From 922ab4144937e056669bf62568cd0f148da34970 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 21 Nov 2019 15:47:43 -0800 Subject: [PATCH] Refactor node factory API, use node factory in parser --- .vscode/tasks.json | 2 +- src/compat/factory.ts | 1925 ++++++ src/compat/tsconfig.json | 12 + src/compiler/binder.ts | 971 +-- src/compiler/checker.ts | 487 +- src/compiler/core.ts | 4 + src/compiler/debug.ts | 150 +- src/compiler/emitter.ts | 18 +- src/compiler/factory.ts | 5551 ---------------- src/compiler/factory/baseNodeFactory.ts | 45 + src/compiler/factory/emitHelpers.ts | 793 +++ src/compiler/factory/emitNode.ts | 270 + src/compiler/factory/nodeConverters.ts | 137 + src/compiler/factory/nodeFactory.ts | 5919 +++++++++++++++++ src/compiler/factory/nodeTests.ts | 763 +++ src/compiler/factory/parenthesizerRules.ts | 426 ++ src/compiler/factory/utilities.ts | 779 +++ src/compiler/moduleNameResolver.ts | 2 - src/compiler/parser.ts | 2538 +++---- src/compiler/program.ts | 4 +- src/compiler/scanner.ts | 6 + src/compiler/transformer.ts | 39 +- src/compiler/transformers/classFields.ts | 68 +- src/compiler/transformers/declarations.ts | 225 +- src/compiler/transformers/destructuring.ts | 148 +- src/compiler/transformers/es2015.ts | 812 ++- src/compiler/transformers/es2016.ts | 33 +- src/compiler/transformers/es2017.ts | 187 +- src/compiler/transformers/es2018.ts | 370 +- src/compiler/transformers/es2019.ts | 7 +- src/compiler/transformers/es5.ts | 9 +- src/compiler/transformers/esnext.ts | 67 +- src/compiler/transformers/generators.ts | 335 +- src/compiler/transformers/jsx.ts | 36 +- src/compiler/transformers/module/es2015.ts | 16 +- src/compiler/transformers/module/module.ts | 397 +- src/compiler/transformers/module/system.ts | 296 +- src/compiler/transformers/ts.ts | 530 +- src/compiler/transformers/utilities.ts | 34 +- src/compiler/tsconfig.json | 9 +- src/compiler/types.ts | 1308 +++- src/compiler/utilities.ts | 1773 +++-- src/compiler/visitor.ts | 410 +- ...dConvertToUnknownForNonOverlappingTypes.ts | 6 +- src/services/codefixes/addMissingAwait.ts | 8 +- .../addMissingInvocationForDecorator.ts | 2 +- .../codefixes/addNameToNamelessParameter.ts | 4 +- .../codefixes/annotateWithTypeFromJSDoc.ts | 32 +- .../codefixes/convertFunctionToEs6Class.ts | 20 +- .../codefixes/convertToAsyncFunction.ts | 68 +- src/services/codefixes/convertToEs6Module.ts | 52 +- .../codefixes/convertToMappedObjectType.ts | 12 +- ...correctQualifiedNameToIndexedAccessType.ts | 6 +- src/services/codefixes/fixAddMissingMember.ts | 22 +- .../codefixes/fixAddMissingNewOperator.ts | 2 +- .../fixAddModuleReferTypeMissingTypeof.ts | 2 +- .../codefixes/fixAwaitInSyncFunction.ts | 2 +- .../fixConstructorForDerivedNeedSuperCall.ts | 2 +- .../fixEnableExperimentalDecorators.ts | 2 +- src/services/codefixes/fixEnableJsxFlag.ts | 2 +- .../fixExtendsInterfaceBecomesImplements.ts | 4 +- .../fixForgottenThisPropertyAccess.ts | 2 +- .../codefixes/fixInvalidImportSyntax.ts | 6 +- src/services/codefixes/fixSpelling.ts | 4 +- .../codefixes/fixStrictClassInitialization.ts | 28 +- src/services/codefixes/fixUnreachableCode.ts | 2 +- src/services/codefixes/fixUnusedIdentifier.ts | 4 +- src/services/codefixes/helpers.ts | 58 +- src/services/codefixes/importFixes.ts | 23 +- src/services/codefixes/inferFromUsage.ts | 22 +- src/services/codefixes/requireInTs.ts | 4 +- src/services/codefixes/useBigintLiteral.ts | 2 +- src/services/getEditsForFileRename.ts | 2 +- src/services/navigationBar.ts | 12 +- src/services/organizeImports.ts | 20 +- .../addOrRemoveBracesToArrowFunction.ts | 8 +- src/services/refactors/convertExport.ts | 18 +- src/services/refactors/convertImport.ts | 18 +- .../convertParamsToDestructuredObject.ts | 35 +- src/services/refactors/extractSymbol.ts | 156 +- src/services/refactors/extractType.ts | 24 +- .../generateGetAccessorAndSetAccessor.ts | 46 +- src/services/refactors/moveToNewFile.ts | 64 +- src/services/signatureHelp.ts | 4 +- src/services/textChanges.ts | 26 +- src/services/transform.ts | 2 +- src/services/utilities.ts | 12 +- src/testRunner/runner.ts | 6 + src/testRunner/tsconfig.json | 3 +- src/testRunner/unittests/asserts.ts | 6 +- src/testRunner/unittests/customTransforms.ts | 6 +- src/testRunner/unittests/debugDeprecation.ts | 88 + src/testRunner/unittests/factory.ts | 44 +- src/testRunner/unittests/printer.ts | 124 +- .../unittests/services/textChanges.ts | 106 +- src/testRunner/unittests/transform.ts | 60 +- src/tsc/executeCommandLine.ts | 6 + src/tsserver/tsconfig.json | 3 +- src/tsserverlibrary/tsconfig.json | 3 +- src/typescriptServices/tsconfig.json | 3 +- ...ocComments.parsesCorrectly.@link tags.json | 4 +- ...ts.parsesCorrectly.Nested @param tags.json | 20 +- ...parsesCorrectly.argSynonymForParamTag.json | 4 +- ...sCorrectly.argumentSynonymForParamTag.json | 4 +- ...less-than and greater-than characters.json | 4 +- ...DocComments.parsesCorrectly.paramTag1.json | 4 +- ...arsesCorrectly.paramTagBracketedName1.json | 4 +- ...arsesCorrectly.paramTagBracketedName2.json | 4 +- ...parsesCorrectly.paramTagNameThenType2.json | 4 +- ...ocComments.parsesCorrectly.returnTag2.json | 4 +- ...Comments.parsesCorrectly.templateTag6.json | 4 +- ...sCorrectly.typedefTagWithChildrenTags.json | 45 +- ...eExpressions.parsesCorrectly.keyword2.json | 12 +- .../reference/api/tsserverlibrary.d.ts | 2437 +++++-- tests/baselines/reference/api/typescript.d.ts | 2437 +++++-- 115 files changed, 21058 insertions(+), 13152 deletions(-) create mode 100644 src/compat/factory.ts create mode 100644 src/compat/tsconfig.json delete mode 100644 src/compiler/factory.ts create mode 100644 src/compiler/factory/baseNodeFactory.ts create mode 100644 src/compiler/factory/emitHelpers.ts create mode 100644 src/compiler/factory/emitNode.ts create mode 100644 src/compiler/factory/nodeConverters.ts create mode 100644 src/compiler/factory/nodeFactory.ts create mode 100644 src/compiler/factory/nodeTests.ts create mode 100644 src/compiler/factory/parenthesizerRules.ts create mode 100644 src/compiler/factory/utilities.ts create mode 100644 src/testRunner/unittests/debugDeprecation.ts diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2f6f528677583..c97770984ac23 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -28,7 +28,7 @@ "command": "gulp", "args": ["tests"], "group": "build", - "problemMatcher": ["$gulp-tsc"] + "problemMatcher": ["$tsc"] } ] } \ No newline at end of file diff --git a/src/compat/factory.ts b/src/compat/factory.ts new file mode 100644 index 0000000000000..e8984bade034a --- /dev/null +++ b/src/compat/factory.ts @@ -0,0 +1,1925 @@ +namespace ts { + // #region Node Factory compat (deprecated since 3.8) + + // #region export const { ... } = factory; + // NOTE: These exports are deprecated in favor of using a `NodeFactory` instance and exist here purely for backwards compatibility reasons. + export const { + /** + * @deprecated Use `factory.createNodeArray` or the factory supplied by your transformation context instead. + */ + createNodeArray, + /** + * @deprecated Use `factory.createNumericLiteral` or the factory supplied by your transformation context instead. + */ + createNumericLiteral, + /** + * @deprecated Use `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + createBigIntLiteral, + /** + * @deprecated Use `factory.createStringLiteral` or the factory supplied by your transformation context instead. + */ + createStringLiteral, + /** + * @deprecated Use `factory.createStringLiteralFromNode` or the factory supplied by your transformation context instead. + */ + createStringLiteralFromNode, + /** + * @deprecated Use `factory.createRegularExpressionLiteral` or the factory supplied by your transformation context instead. + */ + createRegularExpressionLiteral, + /** + * @deprecated Use `factory.createLoopVariable` or the factory supplied by your transformation context instead. + */ + createLoopVariable, + /** + * @deprecated Use `factory.createUniqueName` or the factory supplied by your transformation context instead. + */ + createUniqueName, + /** + * @deprecated Use `factory.createOptimisticUniqueName` or the factory supplied by your transformation context instead. + */ + createOptimisticUniqueName, + /** + * @deprecated Use `factory.createFileLevelUniqueName` or the factory supplied by your transformation context instead. + */ + createFileLevelUniqueName, + /** + * @deprecated Use `factory.createSuper` or the factory supplied by your transformation context instead. + */ + createSuper, + /** + * @deprecated Use `factory.createThis` or the factory supplied by your transformation context instead. + */ + createThis, + /** + * @deprecated Use `factory.createNull` or the factory supplied by your transformation context instead. + */ + createNull, + /** + * @deprecated Use `factory.createTrue` or the factory supplied by your transformation context instead. + */ + createTrue, + /** + * @deprecated Use `factory.createFalse` or the factory supplied by your transformation context instead. + */ + createFalse, + /** + * @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. + */ + createModifier, + /** + * @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. + */ + createModifiersFromModifierFlags, + /** + * @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. + */ + createQualifiedName, + /** + * @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. + */ + updateQualifiedName, + /** + * @deprecated Use `factory.createComputedPropertyName` or the factory supplied by your transformation context instead. + */ + createComputedPropertyName, + /** + * @deprecated Use `factory.updateComputedPropertyName` or the factory supplied by your transformation context instead. + */ + updateComputedPropertyName, + /** + * @deprecated Use `factory.createTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeParameterDeclaration, + /** + * @deprecated Use `factory.updateTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeParameterDeclaration, + /** + * @deprecated Use `factory.createParameterDeclaration` or the factory supplied by your transformation context instead. + */ + createParameterDeclaration: createParameter, + /** + * @deprecated Use `factory.updateParameterDeclaration` or the factory supplied by your transformation context instead. + */ + updateParameterDeclaration: updateParameter, + /** + * @deprecated Use `factory.createDecorator` or the factory supplied by your transformation context instead. + */ + createDecorator, + /** + * @deprecated Use `factory.updateDecorator` or the factory supplied by your transformation context instead. + */ + updateDecorator, + /** + * @deprecated Use `factory.createPropertyDeclaration` or the factory supplied by your transformation context instead. + */ + createPropertyDeclaration: createProperty, + /** + * @deprecated Use `factory.updatePropertyDeclaration` or the factory supplied by your transformation context instead. + */ + updatePropertyDeclaration: updateProperty, + /** + * @deprecated Use `factory.createMethodDeclaration` or the factory supplied by your transformation context instead. + */ + createMethodDeclaration: createMethod, + /** + * @deprecated Use `factory.updateMethodDeclaration` or the factory supplied by your transformation context instead. + */ + updateMethodDeclaration: updateMethod, + /** + * @deprecated Use `factory.createConstructorDeclaration` or the factory supplied by your transformation context instead. + */ + createConstructorDeclaration: createConstructor, + /** + * @deprecated Use `factory.updateConstructorDeclaration` or the factory supplied by your transformation context instead. + */ + updateConstructorDeclaration: updateConstructor, + /** + * @deprecated Use `factory.createGetAccessorDeclaration` or the factory supplied by your transformation context instead. + */ + createGetAccessorDeclaration: createGetAccessor, + /** + * @deprecated Use `factory.updateGetAccessorDeclaration` or the factory supplied by your transformation context instead. + */ + updateGetAccessorDeclaration: updateGetAccessor, + /** + * @deprecated Use `factory.createSetAccessorDeclaration` or the factory supplied by your transformation context instead. + */ + createSetAccessorDeclaration: createSetAccessor, + /** + * @deprecated Use `factory.updateSetAccessorDeclaration` or the factory supplied by your transformation context instead. + */ + updateSetAccessorDeclaration: updateSetAccessor, + /** + * @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. + */ + createCallSignature, + /** + * @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. + */ + updateCallSignature, + /** + * @deprecated Use `factory.createConstructSignature` or the factory supplied by your transformation context instead. + */ + createConstructSignature, + /** + * @deprecated Use `factory.updateConstructSignature` or the factory supplied by your transformation context instead. + */ + updateConstructSignature, + /** + * @deprecated Use `factory.updateIndexSignature` or the factory supplied by your transformation context instead. + */ + updateIndexSignature, + /** + * @deprecated Use `factory.createKeywordTypeNode` or the factory supplied by your transformation context instead. + */ + createKeywordTypeNode, + /** + * @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. + */ + createTypePredicateNode: createTypePredicateNodeWithModifier, + /** + * @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. + */ + updateTypePredicateNode: updateTypePredicateNodeWithModifier, + /** + * @deprecated Use `factory.createTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + createTypeReferenceNode, + /** + * @deprecated Use `factory.updateTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + updateTypeReferenceNode, + /** + * @deprecated Use `factory.createFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + createFunctionTypeNode, + /** + * @deprecated Use `factory.updateFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + updateFunctionTypeNode, + /** + * @deprecated Use `factory.createConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + createConstructorTypeNode, + /** + * @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + updateConstructorTypeNode, + /** + * @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. + */ + createTypeQueryNode, + /** + * @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. + */ + updateTypeQueryNode, + /** + * @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + createTypeLiteralNode, + /** + * @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + updateTypeLiteralNode, + /** + * @deprecated Use `factory.createArrayTypeNode` or the factory supplied by your transformation context instead. + */ + createArrayTypeNode, + /** + * @deprecated Use `factory.updateArrayTypeNode` or the factory supplied by your transformation context instead. + */ + updateArrayTypeNode, + /** + * @deprecated Use `factory.createTupleTypeNode` or the factory supplied by your transformation context instead. + */ + createTupleTypeNode, + /** + * @deprecated Use `factory.updateTupleTypeNode` or the factory supplied by your transformation context instead. + */ + updateTupleTypeNode, + /** + * @deprecated Use `factory.createOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + createOptionalTypeNode, + /** + * @deprecated Use `factory.updateOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateOptionalTypeNode, + /** + * @deprecated Use `factory.createRestTypeNode` or the factory supplied by your transformation context instead. + */ + createRestTypeNode, + /** + * @deprecated Use `factory.updateRestTypeNode` or the factory supplied by your transformation context instead. + */ + updateRestTypeNode, + /** + * @deprecated Use `factory.createUnionTypeNode` or the factory supplied by your transformation context instead. + */ + createUnionTypeNode, + /** + * @deprecated Use `factory.updateUnionTypeNode` or the factory supplied by your transformation context instead. + */ + updateUnionTypeNode, + /** + * @deprecated Use `factory.createIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + createIntersectionTypeNode, + /** + * @deprecated Use `factory.updateIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + updateIntersectionTypeNode, + /** + * @deprecated Use `factory.createConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + createConditionalTypeNode, + /** + * @deprecated Use `factory.updateConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateConditionalTypeNode, + /** + * @deprecated Use `factory.createInferTypeNode` or the factory supplied by your transformation context instead. + */ + createInferTypeNode, + /** + * @deprecated Use `factory.updateInferTypeNode` or the factory supplied by your transformation context instead. + */ + updateInferTypeNode, + /** + * @deprecated Use `factory.createImportTypeNode` or the factory supplied by your transformation context instead. + */ + createImportTypeNode, + /** + * @deprecated Use `factory.updateImportTypeNode` or the factory supplied by your transformation context instead. + */ + updateImportTypeNode, + /** + * @deprecated Use `factory.createParenthesizedType` or the factory supplied by your transformation context instead. + */ + createParenthesizedType, + /** + * @deprecated Use `factory.updateParenthesizedType` or the factory supplied by your transformation context instead. + */ + updateParenthesizedType, + /** + * @deprecated Use `factory.createThisTypeNode` or the factory supplied by your transformation context instead. + */ + createThisTypeNode, + /** + * @deprecated Use `factory.updateTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + updateTypeOperatorNode, + /** + * @deprecated Use `factory.createIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + createIndexedAccessTypeNode, + /** + * @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + updateIndexedAccessTypeNode, + /** + * @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. + */ + createMappedTypeNode, + /** + * @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. + */ + updateMappedTypeNode, + /** + * @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + createLiteralTypeNode, + /** + * @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + updateLiteralTypeNode, + /** + * @deprecated Use `factory.createObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + createObjectBindingPattern, + /** + * @deprecated Use `factory.updateObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + updateObjectBindingPattern, + /** + * @deprecated Use `factory.createArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + createArrayBindingPattern, + /** + * @deprecated Use `factory.updateArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + updateArrayBindingPattern, + /** + * @deprecated Use `factory.createBindingElement` or the factory supplied by your transformation context instead. + */ + createBindingElement, + /** + * @deprecated Use `factory.updateBindingElement` or the factory supplied by your transformation context instead. + */ + updateBindingElement, + /** + * @deprecated Use `factory.createArrayLiteral` or the factory supplied by your transformation context instead. + */ + createArrayLiteral, + /** + * @deprecated Use `factory.updateArrayLiteral` or the factory supplied by your transformation context instead. + */ + updateArrayLiteral, + /** + * @deprecated Use `factory.createObjectLiteral` or the factory supplied by your transformation context instead. + */ + createObjectLiteral, + /** + * @deprecated Use `factory.updateObjectLiteral` or the factory supplied by your transformation context instead. + */ + updateObjectLiteral, + /** + * @deprecated Use `factory.createPropertyAccess` or the factory supplied by your transformation context instead. + */ + createPropertyAccess, + /** + * @deprecated Use `factory.updatePropertyAccess` or the factory supplied by your transformation context instead. + */ + updatePropertyAccess, + /** + * @deprecated Use `factory.createPropertyAccessChain` or the factory supplied by your transformation context instead. + */ + createPropertyAccessChain, + /** + * @deprecated Use `factory.updatePropertyAccessChain` or the factory supplied by your transformation context instead. + */ + updatePropertyAccessChain, + /** + * @deprecated Use `factory.createElementAccess` or the factory supplied by your transformation context instead. + */ + createElementAccess, + /** + * @deprecated Use `factory.updateElementAccess` or the factory supplied by your transformation context instead. + */ + updateElementAccess, + /** + * @deprecated Use `factory.createElementAccessChain` or the factory supplied by your transformation context instead. + */ + createElementAccessChain, + /** + * @deprecated Use `factory.updateElementAccessChain` or the factory supplied by your transformation context instead. + */ + updateElementAccessChain, + /** + * @deprecated Use `factory.createCall` or the factory supplied by your transformation context instead. + */ + createCall, + /** + * @deprecated Use `factory.updateCall` or the factory supplied by your transformation context instead. + */ + updateCall, + /** + * @deprecated Use `factory.createCallChain` or the factory supplied by your transformation context instead. + */ + createCallChain, + /** + * @deprecated Use `factory.updateCallChain` or the factory supplied by your transformation context instead. + */ + updateCallChain, + /** + * @deprecated Use `factory.createNew` or the factory supplied by your transformation context instead. + */ + createNew, + /** + * @deprecated Use `factory.updateNew` or the factory supplied by your transformation context instead. + */ + updateNew, + /** + * @deprecated Use `factory.createTypeAssertion` or the factory supplied by your transformation context instead. + */ + createTypeAssertion, + /** + * @deprecated Use `factory.updateTypeAssertion` or the factory supplied by your transformation context instead. + */ + updateTypeAssertion, + /** + * @deprecated Use `factory.createParen` or the factory supplied by your transformation context instead. + */ + createParen, + /** + * @deprecated Use `factory.updateParen` or the factory supplied by your transformation context instead. + */ + updateParen, + /** + * @deprecated Use `factory.createFunctionExpression` or the factory supplied by your transformation context instead. + */ + createFunctionExpression, + /** + * @deprecated Use `factory.updateFunctionExpression` or the factory supplied by your transformation context instead. + */ + updateFunctionExpression, + /** + * @deprecated Use `factory.createDelete` or the factory supplied by your transformation context instead. + */ + createDelete, + /** + * @deprecated Use `factory.updateDelete` or the factory supplied by your transformation context instead. + */ + updateDelete, + /** + * @deprecated Use `factory.createTypeOf` or the factory supplied by your transformation context instead. + */ + createTypeOf, + /** + * @deprecated Use `factory.updateTypeOf` or the factory supplied by your transformation context instead. + */ + updateTypeOf, + /** + * @deprecated Use `factory.createVoid` or the factory supplied by your transformation context instead. + */ + createVoid, + /** + * @deprecated Use `factory.updateVoid` or the factory supplied by your transformation context instead. + */ + updateVoid, + /** + * @deprecated Use `factory.createAwait` or the factory supplied by your transformation context instead. + */ + createAwait, + /** + * @deprecated Use `factory.updateAwait` or the factory supplied by your transformation context instead. + */ + updateAwait, + /** + * @deprecated Use `factory.createPrefix` or the factory supplied by your transformation context instead. + */ + createPrefix, + /** + * @deprecated Use `factory.updatePrefix` or the factory supplied by your transformation context instead. + */ + updatePrefix, + /** + * @deprecated Use `factory.createPostfix` or the factory supplied by your transformation context instead. + */ + createPostfix, + /** + * @deprecated Use `factory.updatePostfix` or the factory supplied by your transformation context instead. + */ + updatePostfix, + /** + * @deprecated Use `factory.createBinary` or the factory supplied by your transformation context instead. + */ + createBinary, + /** + * @deprecated Use `factory.updateBinary` or the factory supplied by your transformation context instead. + */ + updateBinary, + /** + * @deprecated Use `factory.updateConditional` or the factory supplied by your transformation context instead. + */ + updateConditional, + /** + * @deprecated Use `factory.createTemplateExpression` or the factory supplied by your transformation context instead. + */ + createTemplateExpression, + /** + * @deprecated Use `factory.updateTemplateExpression` or the factory supplied by your transformation context instead. + */ + updateTemplateExpression, + /** + * @deprecated Use `factory.createTemplateHead` or the factory supplied by your transformation context instead. + */ + createTemplateHead, + /** + * @deprecated Use `factory.createTemplateMiddle` or the factory supplied by your transformation context instead. + */ + createTemplateMiddle, + /** + * @deprecated Use `factory.createTemplateTail` or the factory supplied by your transformation context instead. + */ + createTemplateTail, + /** + * @deprecated Use `factory.createNoSubstitutionTemplateLiteral` or the factory supplied by your transformation context instead. + */ + createNoSubstitutionTemplateLiteral, + /** + * @deprecated Use `factory.updateYield` or the factory supplied by your transformation context instead. + */ + updateYield, + /** + * @deprecated Use `factory.createSpread` or the factory supplied by your transformation context instead. + */ + createSpread, + /** + * @deprecated Use `factory.updateSpread` or the factory supplied by your transformation context instead. + */ + updateSpread, + /** + * @deprecated Use `factory.createOmittedExpression` or the factory supplied by your transformation context instead. + */ + createOmittedExpression, + /** + * @deprecated Use `factory.createAsExpression` or the factory supplied by your transformation context instead. + */ + createAsExpression, + /** + * @deprecated Use `factory.updateAsExpression` or the factory supplied by your transformation context instead. + */ + updateAsExpression, + /** + * @deprecated Use `factory.createNonNullExpression` or the factory supplied by your transformation context instead. + */ + createNonNullExpression, + /** + * @deprecated Use `factory.updateNonNullExpression` or the factory supplied by your transformation context instead. + */ + updateNonNullExpression, + /** + * @deprecated Use `factory.createMetaProperty` or the factory supplied by your transformation context instead. + */ + createMetaProperty, + /** + * @deprecated Use `factory.updateMetaProperty` or the factory supplied by your transformation context instead. + */ + updateMetaProperty, + /** + * @deprecated Use `factory.createTemplateSpan` or the factory supplied by your transformation context instead. + */ + createTemplateSpan, + /** + * @deprecated Use `factory.updateTemplateSpan` or the factory supplied by your transformation context instead. + */ + updateTemplateSpan, + /** + * @deprecated Use `factory.createSemicolonClassElement` or the factory supplied by your transformation context instead. + */ + createSemicolonClassElement, + /** + * @deprecated Use `factory.createBlock` or the factory supplied by your transformation context instead. + */ + createBlock, + /** + * @deprecated Use `factory.updateBlock` or the factory supplied by your transformation context instead. + */ + updateBlock, + /** + * @deprecated Use `factory.createVariableStatement` or the factory supplied by your transformation context instead. + */ + createVariableStatement, + /** + * @deprecated Use `factory.updateVariableStatement` or the factory supplied by your transformation context instead. + */ + updateVariableStatement, + /** + * @deprecated Use `factory.createEmptyStatement` or the factory supplied by your transformation context instead. + */ + createEmptyStatement, + /** + * @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. + */ + createExpressionStatement, + /** + * @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. + */ + updateExpressionStatement, + /** @deprecated Use `createExpressionStatement` instead. */ + /** + * @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. + */ + createExpressionStatement: createStatement, + /** @deprecated Use `updateExpressionStatement` instead. */ + /** + * @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. + */ + updateExpressionStatement: updateStatement, + /** + * @deprecated Use `factory.createIf` or the factory supplied by your transformation context instead. + */ + createIf, + /** + * @deprecated Use `factory.updateIf` or the factory supplied by your transformation context instead. + */ + updateIf, + /** + * @deprecated Use `factory.createDo` or the factory supplied by your transformation context instead. + */ + createDo, + /** + * @deprecated Use `factory.updateDo` or the factory supplied by your transformation context instead. + */ + updateDo, + /** + * @deprecated Use `factory.createWhile` or the factory supplied by your transformation context instead. + */ + createWhile, + /** + * @deprecated Use `factory.updateWhile` or the factory supplied by your transformation context instead. + */ + updateWhile, + /** + * @deprecated Use `factory.createFor` or the factory supplied by your transformation context instead. + */ + createFor, + /** + * @deprecated Use `factory.updateFor` or the factory supplied by your transformation context instead. + */ + updateFor, + /** + * @deprecated Use `factory.createForIn` or the factory supplied by your transformation context instead. + */ + createForIn, + /** + * @deprecated Use `factory.updateForIn` or the factory supplied by your transformation context instead. + */ + updateForIn, + /** + * @deprecated Use `factory.createForOf` or the factory supplied by your transformation context instead. + */ + createForOf, + /** + * @deprecated Use `factory.updateForOf` or the factory supplied by your transformation context instead. + */ + updateForOf, + /** + * @deprecated Use `factory.createContinue` or the factory supplied by your transformation context instead. + */ + createContinue, + /** + * @deprecated Use `factory.updateContinue` or the factory supplied by your transformation context instead. + */ + updateContinue, + /** + * @deprecated Use `factory.createBreak` or the factory supplied by your transformation context instead. + */ + createBreak, + /** + * @deprecated Use `factory.updateBreak` or the factory supplied by your transformation context instead. + */ + updateBreak, + /** + * @deprecated Use `factory.createReturn` or the factory supplied by your transformation context instead. + */ + createReturn, + /** + * @deprecated Use `factory.updateReturn` or the factory supplied by your transformation context instead. + */ + updateReturn, + /** + * @deprecated Use `factory.createWith` or the factory supplied by your transformation context instead. + */ + createWith, + /** + * @deprecated Use `factory.updateWith` or the factory supplied by your transformation context instead. + */ + updateWith, + /** + * @deprecated Use `factory.createSwitch` or the factory supplied by your transformation context instead. + */ + createSwitch, + /** + * @deprecated Use `factory.updateSwitch` or the factory supplied by your transformation context instead. + */ + updateSwitch, + /** + * @deprecated Use `factory.createLabel` or the factory supplied by your transformation context instead. + */ + createLabel, + /** + * @deprecated Use `factory.updateLabel` or the factory supplied by your transformation context instead. + */ + updateLabel, + /** + * @deprecated Use `factory.createThrow` or the factory supplied by your transformation context instead. + */ + createThrow, + /** + * @deprecated Use `factory.updateThrow` or the factory supplied by your transformation context instead. + */ + updateThrow, + /** + * @deprecated Use `factory.createTry` or the factory supplied by your transformation context instead. + */ + createTry, + /** + * @deprecated Use `factory.updateTry` or the factory supplied by your transformation context instead. + */ + updateTry, + /** + * @deprecated Use `factory.createDebuggerStatement` or the factory supplied by your transformation context instead. + */ + createDebuggerStatement, + /** + * @deprecated Use `factory.createVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + createVariableDeclarationList, + /** + * @deprecated Use `factory.updateVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + updateVariableDeclarationList, + /** + * @deprecated Use `factory.createFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + createFunctionDeclaration, + /** + * @deprecated Use `factory.updateFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + updateFunctionDeclaration, + /** + * @deprecated Use `factory.createClassDeclaration` or the factory supplied by your transformation context instead. + */ + createClassDeclaration, + /** + * @deprecated Use `factory.updateClassDeclaration` or the factory supplied by your transformation context instead. + */ + updateClassDeclaration, + /** + * @deprecated Use `factory.createInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + createInterfaceDeclaration, + /** + * @deprecated Use `factory.updateInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + updateInterfaceDeclaration, + /** + * @deprecated Use `factory.createTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeAliasDeclaration, + /** + * @deprecated Use `factory.updateTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeAliasDeclaration, + /** + * @deprecated Use `factory.createEnumDeclaration` or the factory supplied by your transformation context instead. + */ + createEnumDeclaration, + /** + * @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. + */ + updateEnumDeclaration, + /** + * @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. + */ + createModuleDeclaration, + /** + * @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. + */ + updateModuleDeclaration, + /** + * @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. + */ + createModuleBlock, + /** + * @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. + */ + updateModuleBlock, + /** + * @deprecated Use `factory.createCaseBlock` or the factory supplied by your transformation context instead. + */ + createCaseBlock, + /** + * @deprecated Use `factory.updateCaseBlock` or the factory supplied by your transformation context instead. + */ + updateCaseBlock, + /** + * @deprecated Use `factory.createNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + createNamespaceExportDeclaration, + /** + * @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateNamespaceExportDeclaration, + /** + * @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + createImportEqualsDeclaration, + /** + * @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportEqualsDeclaration, + /** + * @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. + */ + createImportDeclaration, + /** + * @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportDeclaration, + /** + * @deprecated Use `factory.createImportClause` or the factory supplied by your transformation context instead. + */ + createImportClause, + /** + * @deprecated Use `factory.updateImportClause` or the factory supplied by your transformation context instead. + */ + updateImportClause, + /** + * @deprecated Use `factory.createNamespaceImport` or the factory supplied by your transformation context instead. + */ + createNamespaceImport, + /** + * @deprecated Use `factory.updateNamespaceImport` or the factory supplied by your transformation context instead. + */ + updateNamespaceImport, + /** + * @deprecated Use `factory.createNamedImports` or the factory supplied by your transformation context instead. + */ + createNamedImports, + /** + * @deprecated Use `factory.updateNamedImports` or the factory supplied by your transformation context instead. + */ + updateNamedImports, + /** + * @deprecated Use `factory.createImportSpecifier` or the factory supplied by your transformation context instead. + */ + createImportSpecifier, + /** + * @deprecated Use `factory.updateImportSpecifier` or the factory supplied by your transformation context instead. + */ + updateImportSpecifier, + /** + * @deprecated Use `factory.createExportAssignment` or the factory supplied by your transformation context instead. + */ + createExportAssignment, + /** + * @deprecated Use `factory.updateExportAssignment` or the factory supplied by your transformation context instead. + */ + updateExportAssignment, + /** + * @deprecated Use `factory.createExportDeclaration` or the factory supplied by your transformation context instead. + */ + createExportDeclaration, + /** + * @deprecated Use `factory.updateExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateExportDeclaration, + /** + * @deprecated Use `factory.createNamedExports` or the factory supplied by your transformation context instead. + */ + createNamedExports, + /** + * @deprecated Use `factory.updateNamedExports` or the factory supplied by your transformation context instead. + */ + updateNamedExports, + /** + * @deprecated Use `factory.createExportSpecifier` or the factory supplied by your transformation context instead. + */ + createExportSpecifier, + /** + * @deprecated Use `factory.updateExportSpecifier` or the factory supplied by your transformation context instead. + */ + updateExportSpecifier, + /** + * @deprecated Use `factory.createExternalModuleReference` or the factory supplied by your transformation context instead. + */ + createExternalModuleReference, + /** + * @deprecated Use `factory.updateExternalModuleReference` or the factory supplied by your transformation context instead. + */ + updateExternalModuleReference, + /** + * @deprecated Use `factory.createJSDocTypeExpression` or the factory supplied by your transformation context instead. + */ + createJSDocTypeExpression, + /** + * @deprecated Use `factory.createJSDocTypeTag` or the factory supplied by your transformation context instead. + */ + createJSDocTypeTag, + /** + * @deprecated Use `factory.createJSDocReturnTag` or the factory supplied by your transformation context instead. + */ + createJSDocReturnTag, + /** + * @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. + */ + createJSDocThisTag, + /** + * @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. + */ + createJSDocComment, + /** + * @deprecated Use `factory.createJsxElement` or the factory supplied by your transformation context instead. + */ + createJsxElement, + /** + * @deprecated Use `factory.updateJsxElement` or the factory supplied by your transformation context instead. + */ + updateJsxElement, + /** + * @deprecated Use `factory.createJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxSelfClosingElement, + /** + * @deprecated Use `factory.updateJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxSelfClosingElement, + /** + * @deprecated Use `factory.createJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + createJsxOpeningElement, + /** + * @deprecated Use `factory.updateJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + updateJsxOpeningElement, + /** + * @deprecated Use `factory.createJsxClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxClosingElement, + /** + * @deprecated Use `factory.updateJsxClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxClosingElement, + /** + * @deprecated Use `factory.createJsxFragment` or the factory supplied by your transformation context instead. + */ + createJsxFragment, + /** + * @deprecated Use `factory.createJsxText` or the factory supplied by your transformation context instead. + */ + createJsxText, + /** + * @deprecated Use `factory.updateJsxText` or the factory supplied by your transformation context instead. + */ + updateJsxText, + /** + * @deprecated Use `factory.createJsxOpeningFragment` or the factory supplied by your transformation context instead. + */ + createJsxOpeningFragment, + /** + * @deprecated Use `factory.createJsxJsxClosingFragment` or the factory supplied by your transformation context instead. + */ + createJsxJsxClosingFragment, + /** + * @deprecated Use `factory.updateJsxFragment` or the factory supplied by your transformation context instead. + */ + updateJsxFragment, + /** + * @deprecated Use `factory.createJsxAttribute` or the factory supplied by your transformation context instead. + */ + createJsxAttribute, + /** + * @deprecated Use `factory.updateJsxAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxAttribute, + /** + * @deprecated Use `factory.createJsxAttributes` or the factory supplied by your transformation context instead. + */ + createJsxAttributes, + /** + * @deprecated Use `factory.updateJsxAttributes` or the factory supplied by your transformation context instead. + */ + updateJsxAttributes, + /** + * @deprecated Use `factory.createJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + createJsxSpreadAttribute, + /** + * @deprecated Use `factory.updateJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxSpreadAttribute, + /** + * @deprecated Use `factory.createJsxExpression` or the factory supplied by your transformation context instead. + */ + createJsxExpression, + /** + * @deprecated Use `factory.updateJsxExpression` or the factory supplied by your transformation context instead. + */ + updateJsxExpression, + /** + * @deprecated Use `factory.createCaseClause` or the factory supplied by your transformation context instead. + */ + createCaseClause, + /** + * @deprecated Use `factory.updateCaseClause` or the factory supplied by your transformation context instead. + */ + updateCaseClause, + /** + * @deprecated Use `factory.createDefaultClause` or the factory supplied by your transformation context instead. + */ + createDefaultClause, + /** + * @deprecated Use `factory.updateDefaultClause` or the factory supplied by your transformation context instead. + */ + updateDefaultClause, + /** + * @deprecated Use `factory.createHeritageClause` or the factory supplied by your transformation context instead. + */ + createHeritageClause, + /** + * @deprecated Use `factory.updateHeritageClause` or the factory supplied by your transformation context instead. + */ + updateHeritageClause, + /** + * @deprecated Use `factory.createCatchClause` or the factory supplied by your transformation context instead. + */ + createCatchClause, + /** + * @deprecated Use `factory.updateCatchClause` or the factory supplied by your transformation context instead. + */ + updateCatchClause, + /** + * @deprecated Use `factory.createPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createPropertyAssignment, + /** + * @deprecated Use `factory.updatePropertyAssignment` or the factory supplied by your transformation context instead. + */ + updatePropertyAssignment, + /** + * @deprecated Use `factory.createShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createShorthandPropertyAssignment, + /** + * @deprecated Use `factory.updateShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + updateShorthandPropertyAssignment, + /** + * @deprecated Use `factory.createSpreadAssignment` or the factory supplied by your transformation context instead. + */ + createSpreadAssignment, + /** + * @deprecated Use `factory.updateSpreadAssignment` or the factory supplied by your transformation context instead. + */ + updateSpreadAssignment, + /** + * @deprecated Use `factory.createEnumMember` or the factory supplied by your transformation context instead. + */ + createEnumMember, + /** + * @deprecated Use `factory.updateEnumMember` or the factory supplied by your transformation context instead. + */ + updateEnumMember, + /** + * @deprecated Use `factory.updateSourceFile` or the factory supplied by your transformation context instead. + */ + updateSourceFile: updateSourceFileNode, + /** + * @deprecated Use `factory.createNotEmittedStatement` or the factory supplied by your transformation context instead. + */ + createNotEmittedStatement, + /** + * @deprecated Use `factory.createPartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + createPartiallyEmittedExpression, + /** + * @deprecated Use `factory.updatePartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + updatePartiallyEmittedExpression, + /** + * @deprecated Use `factory.createCommaList` or the factory supplied by your transformation context instead. + */ + createCommaList, + /** + * @deprecated Use `factory.updateCommaList` or the factory supplied by your transformation context instead. + */ + updateCommaList, + /** + * @deprecated Use `factory.createBundle` or the factory supplied by your transformation context instead. + */ + createBundle, + /** + * @deprecated Use `factory.updateBundle` or the factory supplied by your transformation context instead. + */ + updateBundle, + /** + * @deprecated Use `factory.createImmediatelyInvokedFunctionExpression` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedFunctionExpression, + /** + * @deprecated Use `factory.createImmediatelyInvokedArrowFunction` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedArrowFunction, + /** + * @deprecated Use `factory.createVoidZero` or the factory supplied by your transformation context instead. + */ + createVoidZero, + /** + * @deprecated Use `factory.createExportDefault` or the factory supplied by your transformation context instead. + */ + createExportDefault, + /** + * @deprecated Use `factory.createExternalModuleExport` or the factory supplied by your transformation context instead. + */ + createExternalModuleExport + } = factory; + // #endregion export const { ... } = factory; + + /** + * @deprecated Use `factory.createToken` or the factory supplied by your transformation context instead. + */ + export function createToken(kind: TKind): Token { + return factory.createToken(kind); + } + + /** + * @deprecated Use `factory.createIdentifier` or the factory supplied by your transformation context instead. + */ + export function createIdentifier(text: string) { + return factory.createIdentifier(text, /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined); + } + + /** + * @deprecated Use `factory.createTempVariable` or the factory supplied by your transformation context instead. + */ + export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier { + return factory.createTempVariable(recordTempVariable, /*reserveInNestedScopes*/ undefined); + } + + /** + * @deprecated Use `factory.getGeneratedNameForNode` or the factory supplied by your transformation context instead. + */ + export function getGeneratedNameForNode(node: Node | undefined): Identifier { + return factory.getGeneratedNameForNode(node, /*flags*/ undefined); + } + + /** + * @deprecated Use `factory.createIndexSignature` or the factory supplied by your transformation context instead. + */ + export function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration { + return factory.createIndexSignature(decorators, modifiers, parameters, type); + } + + /** + * @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. + */ + export function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode { + return factory.createTypePredicateNode(/*assertsModifier*/ undefined, parameterName, type); + } + + /** + * @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. + */ + export function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode { + return factory.updateTypePredicateNode(node, /*assertsModifier*/ undefined, parameterName, type); + } + + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; + /** + * @deprecated Use `factory.createNumericLiteral` or `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + export function createLiteral(value: number | PseudoBigInt): NumericLiteral; + /** + * @deprecated Use `factory.createTrue` or `factory.createFalse` or the factory supplied by your transformation context instead. + */ + export function createLiteral(value: boolean): BooleanLiteral; + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + export function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; + export function createLiteral(value: string | number | PseudoBigInt | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): PrimaryExpression { + if (typeof value === "number") { + return factory.createNumericLiteral(value); + } + // eslint-disable-next-line no-in-operator + if (typeof value === "object" && "base10Value" in value) { // PseudoBigInt + return factory.createBigIntLiteral(value); + } + if (typeof value === "boolean") { + return value ? factory.createTrue() : factory.createFalse(); + } + if (typeof value === "string") { + return factory.createStringLiteral(value, /*isSingleQuote*/ undefined); + } + return factory.createStringLiteralFromNode(value); + } + + /** + * @deprecated Use `factory.createMethodSignature` or the factory supplied by your transformation context instead. + */ + export function createMethodSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined + ) { + return factory.createMethodSignature(/*modifiers*/ undefined, name, questionToken, typeParameters, parameters, type); + } + + /** + * @deprecated Use `factory.updateMethodSignature` or the factory supplied by your transformation context instead. + */ + export function updateMethodSignature( + node: MethodSignature, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined + ) { + return factory.updateMethodSignature(node, node.modifiers, name, questionToken, typeParameters, parameters, type); + } + + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) { + let operator: TypeOperatorNode["operator"]; + if (type) { + operator = operatorOrType as TypeOperatorNode["operator"]; + } + else { + type = operatorOrType as TypeNode; + operator = SyntaxKind.KeyOfKeyword; + } + return factory.createTypeOperatorNode(operator, type); + } + + /** @deprecated */ + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + export function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: readonly TypeNode[] | TemplateLiteral | undefined, template?: TemplateLiteral) { + let typeArguments: readonly TypeNode[] | undefined; + if (template) { + typeArguments = typeArgumentsOrTemplate as readonly TypeNode[] | undefined; + } + else { + template = typeArgumentsOrTemplate as TemplateLiteral; + } + return factory.createTaggedTemplate(tag, typeArguments, template); + } + + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: readonly TypeNode[] | TemplateLiteral | undefined, template?: TemplateLiteral) { + let typeArguments: readonly TypeNode[] | undefined; + if (template) { + typeArguments = typeArgumentsOrTemplate as readonly TypeNode[] | undefined; + } + else { + template = typeArgumentsOrTemplate as TemplateLiteral; + } + return factory.updateTaggedTemplate(node, tag, typeArguments, template); + } + + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + export function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + export function createConditional(condition: Expression, questionTokenOrWhenTrue: QuestionToken | Expression, whenTrueOrWhenFalse: Expression, colonToken?: ColonToken, whenFalse?: Expression) { + return arguments.length === 5 ? factory.createConditional(condition, questionTokenOrWhenTrue as QuestionToken, whenTrueOrWhenFalse, colonToken!, whenFalse!) : + arguments.length === 3 ? factory.createConditional(condition, factory.createToken(SyntaxKind.QuestionToken), questionTokenOrWhenTrue as Expression, factory.createToken(SyntaxKind.ColonToken), whenTrueOrWhenFalse) : + Debug.fail("Argument count mismatch"); + } + + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + export function createYield(expression?: Expression): YieldExpression; + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + export function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; + export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression | undefined, expression?: Expression) { + let asteriskToken: AsteriskToken | undefined; + if (expression) { + asteriskToken = asteriskTokenOrExpression as AsteriskToken; + } + else { + expression = asteriskTokenOrExpression as Expression; + } + return factory.createYield(asteriskToken, expression); + } + + /** + * @deprecated Use `factory.createClassExpression` or the factory supplied by your transformation context instead. + */ + export function createClassExpression( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + return factory.createClassExpression(/*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); + } + + /** + * @deprecated Use `factory.updateClassExpression` or the factory supplied by your transformation context instead. + */ + export function updateClassExpression( + node: ClassExpression, + modifiers: readonly Modifier[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + return factory.updateClassExpression(node, /*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); + } + + /** + * @deprecated Use `factory.createPropertySignature` or the factory supplied by your transformation context instead. + */ + export function createPropertySignature( + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer?: Expression + ): PropertySignature { + const node = factory.createPropertySignature(modifiers, name, questionToken, type); + node.initializer = initializer; + return node; + } + + /** + * @deprecated Use `factory.updatePropertySignature` or the factory supplied by your transformation context instead. + */ + export function updatePropertySignature( + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) { + return node.modifiers !== modifiers + || node.name !== name + || node.questionToken !== questionToken + || node.type !== type + || node.initializer !== initializer + ? updateNode(createPropertySignature(modifiers, name, questionToken, type, initializer), node) + : node; + } + + /** + * @deprecated Use `factory.createExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + export function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression) { + return factory.createExpressionWithTypeArguments(expression, typeArguments); + } + + /** + * @deprecated Use `factory.updateExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression) { + return factory.updateExpressionWithTypeArguments(node, expression, typeArguments); + } + + /** + * @deprecated Use `factory.createArrowFunction` or the factory supplied by your transformation context instead. + */ + export function createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + /** + * @deprecated Use `factory.createArrowFunction` or the factory supplied by your transformation context instead. + */ + export function createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + export function createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanTokenOrBody: ConciseBody | EqualsGreaterThanToken | undefined, body?: ConciseBody) { + return arguments.length === 6 ? factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody as EqualsGreaterThanToken | undefined, body!) : + arguments.length === 5 ? factory.createArrowFunction(modifiers, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, equalsGreaterThanTokenOrBody as ConciseBody) : + Debug.fail("Argument count mismatch"); + } + + /** + * @deprecated Use `factory.updateArrowFunction` or the factory supplied by your transformation context instead. + */ + export function updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + /** + * @deprecated Use `factory.updateArrowFunction` or the factory supplied by your transformation context instead. + */ + export function updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + export function updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanTokenOrBody: EqualsGreaterThanToken | ConciseBody, body?: ConciseBody) { + return arguments.length === 7 ? factory.updateArrowFunction(node, modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody as EqualsGreaterThanToken, body!) : + arguments.length === 6 ? factory.updateArrowFunction(node, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, equalsGreaterThanTokenOrBody as ConciseBody) : + Debug.fail("Argument count mismatch"); + } + + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + export function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + export function createVariableDeclaration(name: string | BindingName, exclamationTokenOrType?: ExclamationToken | TypeNode, typeOrInitializer?: TypeNode | Expression, initializer?: Expression) { + return arguments.length === 4 ? factory.createVariableDeclaration(name, exclamationTokenOrType as ExclamationToken | undefined, typeOrInitializer as TypeNode | undefined, initializer) : + arguments.length >= 1 && arguments.length <= 3 ? factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, exclamationTokenOrType as TypeNode | undefined, typeOrInitializer as Expression | undefined) : + Debug.fail("Argument count mismatch"); + } + + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationTokenOrType: ExclamationToken | TypeNode | undefined, typeOrInitializer: TypeNode | Expression | undefined, initializer?: Expression | undefined) { + return arguments.length === 5 ? factory.updateVariableDeclaration(node, name, exclamationTokenOrType as ExclamationToken | undefined, typeOrInitializer as TypeNode | undefined, initializer) : + arguments.length === 4 ? factory.updateVariableDeclaration(node, name, node.exclamationToken, exclamationTokenOrType as TypeNode | undefined, typeOrInitializer as Expression | undefined) : + Debug.fail("Argument count mismatch"); + } + + /** + * @deprecated Use `factory.createComma` or the factory supplied by your transformation context instead. + */ + export function createComma(left: Expression, right: Expression): Expression { + return factory.createComma(left, right); + } + + /** + * @deprecated Use `factory.createLessThan` or the factory supplied by your transformation context instead. + */ + export function createLessThan(left: Expression, right: Expression): Expression { + return factory.createLessThan(left, right); + } + + /** + * @deprecated Use `factory.createAssignment` or the factory supplied by your transformation context instead. + */ + export function createAssignment(left: Expression, right: Expression): BinaryExpression { + return factory.createAssignment(left, right); + } + + /** + * @deprecated Use `factory.createStrictEquality` or the factory supplied by your transformation context instead. + */ + export function createStrictEquality(left: Expression, right: Expression): BinaryExpression { + return factory.createStrictEquality(left, right); + } + + /** + * @deprecated Use `factory.createStrictInequality` or the factory supplied by your transformation context instead. + */ + export function createStrictInequality(left: Expression, right: Expression): BinaryExpression { + return factory.createStrictInequality(left, right); + } + + /** + * @deprecated Use `factory.createAdd` or the factory supplied by your transformation context instead. + */ + export function createAdd(left: Expression, right: Expression): BinaryExpression { + return factory.createAdd(left, right); + } + + /** + * @deprecated Use `factory.createSubtract` or the factory supplied by your transformation context instead. + */ + export function createSubtract(left: Expression, right: Expression): BinaryExpression { + return factory.createSubtract(left, right); + } + + /** + * @deprecated Use `factory.createLogicalAnd` or the factory supplied by your transformation context instead. + */ + export function createLogicalAnd(left: Expression, right: Expression): BinaryExpression { + return factory.createLogicalAnd(left, right); + } + + /** + * @deprecated Use `factory.createLogicalOr` or the factory supplied by your transformation context instead. + */ + export function createLogicalOr(left: Expression, right: Expression): BinaryExpression { + return factory.createLogicalOr(left, right); + } + + /** + * @deprecated Use `factory.createPostfixIncrement` or the factory supplied by your transformation context instead. + */ + export function createPostfixIncrement(operand: Expression): PostfixUnaryExpression { + return factory.createPostfixIncrement(operand); + } + + /** + * @deprecated Use `factory.{0}` or the factory supplied by your transformation context instead. + */ + /** + * @deprecated Use `factory.createLogicalNot` or the factory supplied by your transformation context instead. + */ + export function createLogicalNot(operand: Expression): PrefixUnaryExpression { + return factory.createLogicalNot(operand); + } + + Debug.deprecateExports(ts, [ + "createNodeArray", + "createNumericLiteral", + "createBigIntLiteral", + "createStringLiteral", + "createStringLiteralFromNode", + "createRegularExpressionLiteral", + "createLoopVariable", + "createUniqueName", + "createOptimisticUniqueName", + "createFileLevelUniqueName", + "createToken", + "createSuper", + "createThis", + "createNull", + "createTrue", + "createFalse", + "createModifier", + "createModifiersFromModifierFlags", + "createQualifiedName", + "updateQualifiedName", + "createComputedPropertyName", + "updateComputedPropertyName", + "createTypeParameterDeclaration", + "updateTypeParameterDeclaration", + "createDecorator", + "updateDecorator", + "createCallSignature", + "updateCallSignature", + "createConstructSignature", + "updateConstructSignature", + "updateIndexSignature", + "createKeywordTypeNode", + "createTypePredicateNode", + "updateTypePredicateNode", + "createTypeReferenceNode", + "updateTypeReferenceNode", + "createFunctionTypeNode", + "updateFunctionTypeNode", + "createConstructorTypeNode", + "updateConstructorTypeNode", + "createTypeQueryNode", + "updateTypeQueryNode", + "createTypeLiteralNode", + "updateTypeLiteralNode", + "createArrayTypeNode", + "updateArrayTypeNode", + "createTupleTypeNode", + "updateTupleTypeNode", + "createOptionalTypeNode", + "updateOptionalTypeNode", + "createRestTypeNode", + "updateRestTypeNode", + "createUnionTypeNode", + "updateUnionTypeNode", + "createIntersectionTypeNode", + "updateIntersectionTypeNode", + "createConditionalTypeNode", + "updateConditionalTypeNode", + "createInferTypeNode", + "updateInferTypeNode", + "createImportTypeNode", + "updateImportTypeNode", + "createParenthesizedType", + "updateParenthesizedType", + "createThisTypeNode", + "updateTypeOperatorNode", + "createIndexedAccessTypeNode", + "updateIndexedAccessTypeNode", + "createMappedTypeNode", + "updateMappedTypeNode", + "createLiteralTypeNode", + "updateLiteralTypeNode", + "createObjectBindingPattern", + "updateObjectBindingPattern", + "createArrayBindingPattern", + "updateArrayBindingPattern", + "createBindingElement", + "updateBindingElement", + "updateArrayLiteral", + "createObjectLiteral", + "updateObjectLiteral", + "createPropertyAccess", + "updatePropertyAccess", + "createPropertyAccessChain", + "updatePropertyAccessChain", + "createElementAccess", + "updateElementAccess", + "createElementAccessChain", + "updateElementAccessChain", + "createCall", + "updateCall", + "createCallChain", + "updateCallChain", + "createNew", + "updateNew", + "createTypeAssertion", + "updateTypeAssertion", + "createParen", + "updateParen", + "createFunctionExpression", + "updateFunctionExpression", + "createArrowFunction", + "updateArrowFunction", + "createDelete", + "updateDelete", + "createTypeOf", + "updateTypeOf", + "createVoid", + "updateVoid", + "createAwait", + "updateAwait", + "createPrefix", + "updatePrefix", + "createPostfix", + "updatePostfix", + "createBinary", + "updateBinary", + "updateConditional", + "createTemplateExpression", + "updateTemplateExpression", + "createTemplateHead", + "createTemplateMiddle", + "createTemplateTail", + "createNoSubstitutionTemplateLiteral", + "updateYield", + "createSpread", + "updateSpread", + "createOmittedExpression", + "createAsExpression", + "updateAsExpression", + "createNonNullExpression", + "updateNonNullExpression", + "createMetaProperty", + "updateMetaProperty", + "createTemplateSpan", + "updateTemplateSpan", + "createSemicolonClassElement", + "createBlock", + "updateBlock", + "createVariableStatement", + "updateVariableStatement", + "createEmptyStatement", + "createExpressionStatement", + "updateExpressionStatement", + "createIf", + "updateIf", + "createDo", + "updateDo", + "createWhile", + "updateWhile", + "createFor", + "updateFor", + "createForIn", + "updateForIn", + "createForOf", + "updateForOf", + "createContinue", + "updateContinue", + "createBreak", + "updateBreak", + "createReturn", + "updateReturn", + "createWith", + "updateWith", + "createSwitch", + "updateSwitch", + "createLabel", + "updateLabel", + "createThrow", + "updateThrow", + "createTry", + "updateTry", + "createDebuggerStatement", + "createVariableDeclaration", + "updateVariableDeclaration", + "createVariableDeclarationList", + "updateVariableDeclarationList", + "createFunctionDeclaration", + "updateFunctionDeclaration", + "createClassDeclaration", + "updateClassDeclaration", + "createInterfaceDeclaration", + "updateInterfaceDeclaration", + "createTypeAliasDeclaration", + "updateTypeAliasDeclaration", + "createEnumDeclaration", + "updateEnumDeclaration", + "createModuleDeclaration", + "updateModuleDeclaration", + "createModuleBlock", + "updateModuleBlock", + "createCaseBlock", + "updateCaseBlock", + "createNamespaceExportDeclaration", + "updateNamespaceExportDeclaration", + "createImportEqualsDeclaration", + "updateImportEqualsDeclaration", + "createImportDeclaration", + "updateImportDeclaration", + "createImportClause", + "updateImportClause", + "createNamespaceImport", + "updateNamespaceImport", + "createNamedImports", + "updateNamedImports", + "createImportSpecifier", + "updateImportSpecifier", + "createExportAssignment", + "updateExportAssignment", + "createExportDeclaration", + "updateExportDeclaration", + "createNamedExports", + "updateNamedExports", + "createExportSpecifier", + "updateExportSpecifier", + "createExternalModuleReference", + "updateExternalModuleReference", + "createJSDocTypeExpression", + "createJSDocTypeTag", + "createJSDocReturnTag", + "createJSDocThisTag", + "createJSDocComment", + "createJsxElement", + "updateJsxElement", + "createJsxSelfClosingElement", + "updateJsxSelfClosingElement", + "createJsxOpeningElement", + "updateJsxOpeningElement", + "createJsxClosingElement", + "updateJsxClosingElement", + "createJsxFragment", + "createJsxText", + "updateJsxText", + "createJsxOpeningFragment", + "createJsxJsxClosingFragment", + "updateJsxFragment", + "createJsxAttribute", + "updateJsxAttribute", + "createJsxAttributes", + "updateJsxAttributes", + "createJsxSpreadAttribute", + "updateJsxSpreadAttribute", + "createJsxExpression", + "updateJsxExpression", + "createCaseClause", + "updateCaseClause", + "createDefaultClause", + "updateDefaultClause", + "createHeritageClause", + "updateHeritageClause", + "createCatchClause", + "updateCatchClause", + "createPropertyAssignment", + "updatePropertyAssignment", + "createShorthandPropertyAssignment", + "updateShorthandPropertyAssignment", + "createSpreadAssignment", + "updateSpreadAssignment", + "createEnumMember", + "updateEnumMember", + "createNotEmittedStatement", + "createPartiallyEmittedExpression", + "updatePartiallyEmittedExpression", + "createCommaList", + "updateCommaList", + "createBundle", + "updateBundle", + "createImmediatelyInvokedFunctionExpression", + "createImmediatelyInvokedArrowFunction", + "createVoidZero", + "createExportDefault", + "createExternalModuleExport", + "createIdentifier", + "createTempVariable", + "getGeneratedNameForNode", + "createIndexSignature", + "createMethodSignature", + "updateMethodSignature", + "createTypeOperatorNode", + "createTaggedTemplate", + "updateTaggedTemplate", + "createConditional", + "createYield", + "createClassExpression", + "updateClassExpression", + "createPropertySignature", + "updatePropertySignature", + "createExpressionWithTypeArguments", + "updateExpressionWithTypeArguments", + "createComma", + "createLessThan", + "createAssignment", + "createStrictEquality", + "createStrictInequality", + "createAdd", + "createSubtract", + "createLogicalAnd", + "createLogicalOr", + "createPostfixIncrement", + "createLogicalNot", + "createArrayLiteral", + ], { + message: "Use `factory.{0}` or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + Debug.deprecateExports(ts, [ + "createParameter", + "updateParameter", + "createProperty", + "updateProperty", + "createMethod", + "updateMethod", + "createConstructor", + "updateConstructor", + "createGetAccessor", + "updateGetAccessor", + "createSetAccessor", + "updateSetAccessor", + ], { + message: "Use `factory.{0}Declaration` or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + Debug.deprecateExport(ts, "createStatement", { + message: "Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + Debug.deprecateExport(ts, "updateStatement", { + message: "Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + Debug.deprecateExport(ts, "updateSourceFileNode", { + message: "Use `factory.updateSourceFile` or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + Debug.deprecateExport(ts, "createLiteral", { + message: "Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead.", + since: "3.8", + warnAfter: "3.9" + }); + + // #endregion NodeFactory compat (deprecated in 3.8) + + // #region Node Test compat (deprecated since 3.8) + /** + * @deprecated Use `isTypeAssertionExpression` instead. + */ + export function isTypeAssertion(node: Node): node is TypeAssertion { + return node.kind === SyntaxKind.TypeAssertionExpression; + } + + Debug.deprecateExport(ts, "isTypeAssertion", { + message: "Use `isTypeAssertionExpression` instead.", + since: "3.8", + warnAfter: "3.9" + }); + + // #endregion NodeTest compat (deprecated since 3.8) +} \ No newline at end of file diff --git a/src/compat/tsconfig.json b/src/compat/tsconfig.json new file mode 100644 index 0000000000000..6a4a20f900fe0 --- /dev/null +++ b/src/compat/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig-base", + "compilerOptions": { + "outFile": "../../built/local/compat.js" + }, + "references": [ + { "path": "../compiler" } + ], + "files": [ + "factory.ts" + ] +} \ No newline at end of file diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 3372512e0bca1..639b3f9ba3d40 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -692,24 +692,6 @@ namespace ts { blockScopeContainer = savedBlockScopeContainer; } - function bindChildren(node: Node): void { - if (skipTransformFlagAggregation) { - bindChildrenWorker(node); - } - else if (node.transformFlags & TransformFlags.HasComputedFlags) { - skipTransformFlagAggregation = true; - bindChildrenWorker(node); - skipTransformFlagAggregation = false; - subtreeTransformFlags |= node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); - } - else { - const savedSubtreeTransformFlags = subtreeTransformFlags; - subtreeTransformFlags = 0; - bindChildrenWorker(node); - subtreeTransformFlags = savedSubtreeTransformFlags | computeTransformFlagsForNode(node, subtreeTransformFlags); - } - } - function bindEachFunctionsFirst(nodes: NodeArray | undefined): void { bindEach(nodes, n => n.kind === SyntaxKind.FunctionDeclaration ? bind(n) : undefined); bindEach(nodes, n => n.kind !== SyntaxKind.FunctionDeclaration ? bind(n) : undefined); @@ -740,7 +722,7 @@ namespace ts { forEachChild(node, bind, bindEach); } - function bindChildrenWorker(node: Node): void { + function bindChildren(node: Node): void { if (checkUnreachable(node)) { bindEachChild(node); bindJSDoc(node); @@ -2233,8 +2215,7 @@ namespace ts { } parent = saveParent; } - else if (!skipTransformFlagAggregation && (node.transformFlags & TransformFlags.HasComputedFlags) === 0) { - subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); + else { const saveParent = parent; if (node.kind === SyntaxKind.EndOfFileToken) parent = node; bindJSDoc(node); @@ -3261,954 +3242,6 @@ namespace ts { return container.symbol && container.symbol.exports && container.symbol.exports.get(name); } - /** - * Computes the transform flags for a node, given the transform flags of its subtree - * - * @param node The node to analyze - * @param subtreeFlags Transform flags computed for this node's subtree - */ - export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags { - const kind = node.kind; - switch (kind) { - case SyntaxKind.CallExpression: - return computeCallExpression(node, subtreeFlags); - - case SyntaxKind.NewExpression: - return computeNewExpression(node, subtreeFlags); - - case SyntaxKind.ModuleDeclaration: - return computeModuleDeclaration(node, subtreeFlags); - - case SyntaxKind.ParenthesizedExpression: - return computeParenthesizedExpression(node, subtreeFlags); - - case SyntaxKind.BinaryExpression: - return computeBinaryExpression(node, subtreeFlags); - - case SyntaxKind.ExpressionStatement: - return computeExpressionStatement(node, subtreeFlags); - - case SyntaxKind.Parameter: - return computeParameter(node, subtreeFlags); - - case SyntaxKind.ArrowFunction: - return computeArrowFunction(node, subtreeFlags); - - case SyntaxKind.FunctionExpression: - return computeFunctionExpression(node, subtreeFlags); - - case SyntaxKind.FunctionDeclaration: - return computeFunctionDeclaration(node, subtreeFlags); - - case SyntaxKind.VariableDeclaration: - return computeVariableDeclaration(node, subtreeFlags); - - case SyntaxKind.VariableDeclarationList: - return computeVariableDeclarationList(node, subtreeFlags); - - case SyntaxKind.VariableStatement: - return computeVariableStatement(node, subtreeFlags); - - case SyntaxKind.LabeledStatement: - return computeLabeledStatement(node, subtreeFlags); - - case SyntaxKind.ClassDeclaration: - return computeClassDeclaration(node, subtreeFlags); - - case SyntaxKind.ClassExpression: - return computeClassExpression(node, subtreeFlags); - - case SyntaxKind.HeritageClause: - return computeHeritageClause(node, subtreeFlags); - - case SyntaxKind.CatchClause: - return computeCatchClause(node, subtreeFlags); - - case SyntaxKind.ExpressionWithTypeArguments: - return computeExpressionWithTypeArguments(node, subtreeFlags); - - case SyntaxKind.Constructor: - return computeConstructor(node, subtreeFlags); - - case SyntaxKind.PropertyDeclaration: - return computePropertyDeclaration(node, subtreeFlags); - - case SyntaxKind.MethodDeclaration: - return computeMethod(node, subtreeFlags); - - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return computeAccessor(node, subtreeFlags); - - case SyntaxKind.ImportEqualsDeclaration: - return computeImportEquals(node, subtreeFlags); - - case SyntaxKind.PropertyAccessExpression: - return computePropertyAccess(node, subtreeFlags); - - case SyntaxKind.ElementAccessExpression: - return computeElementAccess(node, subtreeFlags); - - default: - return computeOther(node, kind, subtreeFlags); - } - } - - function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - const callee = skipOuterExpressions(node.expression); - const expression = node.expression; - - if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; - } - - if (node.typeArguments) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - if (subtreeFlags & TransformFlags.ContainsRestOrSpread || isSuperOrSuperProperty(callee)) { - // If the this node contains a SpreadExpression, or is a super call, then it is an ES6 - // node. - transformFlags |= TransformFlags.AssertES2015; - if (isSuperProperty(callee)) { - transformFlags |= TransformFlags.ContainsLexicalThis; - } - } - - if (expression.kind === SyntaxKind.ImportKeyword) { - transformFlags |= TransformFlags.ContainsDynamicImport; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes; - } - - function computeNewExpression(node: NewExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - if (node.typeArguments) { - transformFlags |= TransformFlags.AssertTypeScript; - } - if (subtreeFlags & TransformFlags.ContainsRestOrSpread) { - // If the this node contains a SpreadElementExpression then it is an ES6 - // node. - transformFlags |= TransformFlags.AssertES2015; - } - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes; - } - - function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - const operatorTokenKind = node.operatorToken.kind; - const leftKind = node.left.kind; - - if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { - transformFlags |= TransformFlags.AssertESNext; - } - else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { - // Destructuring object assignments with are ES2015 syntax - // and possibly ES2018 if they contain rest - transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment; - } - else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ArrayLiteralExpression) { - // Destructuring assignments are ES2015 syntax. - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment; - } - else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken - || operatorTokenKind === SyntaxKind.AsteriskAsteriskEqualsToken) { - // Exponentiation is ES2016 syntax. - transformFlags |= TransformFlags.AssertES2016; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeParameter(node: ParameterDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - const name = node.name; - const initializer = node.initializer; - const dotDotDotToken = node.dotDotDotToken; - - // The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript - // syntax. - if (node.questionToken - || node.type - || (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax && some(node.decorators)) - || isThisIdentifier(name)) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // If a parameter has an accessibility modifier, then it is TypeScript syntax. - if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) { - transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsTypeScriptClassSyntax; - } - - // parameters with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - // If a parameter has an initializer, a binding pattern or a dotDotDot token, then - // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. - if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) { - transformFlags |= TransformFlags.AssertES2015; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ParameterExcludes; - } - - function computeParenthesizedExpression(node: ParenthesizedExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - const expression = node.expression; - const expressionKind = expression.kind; - - // If the node is synthesized, it means the emitter put the parentheses there, - // not the user. If we didn't want them, the emitter would not have put them - // there. - if (expressionKind === SyntaxKind.AsExpression - || expressionKind === SyntaxKind.TypeAssertionExpression) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.OuterExpressionExcludes; - } - - function computeClassDeclaration(node: ClassDeclaration, subtreeFlags: TransformFlags) { - let transformFlags: TransformFlags; - - if (hasModifier(node, ModifierFlags.Ambient)) { - // An ambient declaration is TypeScript syntax. - transformFlags = TransformFlags.AssertTypeScript; - } - else { - // A ClassDeclaration is ES6 syntax. - transformFlags = subtreeFlags | TransformFlags.AssertES2015; - - // A class with a parameter property assignment or decorator is TypeScript syntax. - // An exported declaration may be TypeScript syntax, but is handled by the visitor - // for a namespace declaration. - if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax) - || node.typeParameters) { - transformFlags |= TransformFlags.AssertTypeScript; - } - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ClassExcludes; - } - - function computeClassExpression(node: ClassExpression, subtreeFlags: TransformFlags) { - // A ClassExpression is ES6 syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - - // A class with a parameter property assignment or decorator is TypeScript syntax. - if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax - || node.typeParameters) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ClassExcludes; - } - - function computeHeritageClause(node: HeritageClause, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - switch (node.token) { - case SyntaxKind.ExtendsKeyword: - // An `extends` HeritageClause is ES6 syntax. - transformFlags |= TransformFlags.AssertES2015; - break; - - case SyntaxKind.ImplementsKeyword: - // An `implements` HeritageClause is TypeScript syntax. - transformFlags |= TransformFlags.AssertTypeScript; - break; - - default: - Debug.fail("Unexpected token for heritage clause"); - break; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - if (!node.variableDeclaration) { - transformFlags |= TransformFlags.AssertES2019; - } - else if (isBindingPattern(node.variableDeclaration.name)) { - transformFlags |= TransformFlags.AssertES2015; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.CatchClauseExcludes; - } - - function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) { - // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the - // extends clause of a class. - let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - - // If an ExpressionWithTypeArguments contains type arguments, then it - // is TypeScript syntax. - if (node.typeArguments) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeConstructor(node: ConstructorDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - // TypeScript-specific modifiers and overloads are TypeScript syntax - if (hasModifier(node, ModifierFlags.TypeScriptModifier) - || !node.body) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // function declarations with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ConstructorExcludes; - } - - function computeMethod(node: MethodDeclaration, subtreeFlags: TransformFlags) { - // A MethodDeclaration is ES6 syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - - // Decorators, TypeScript-specific modifiers, type parameters, type annotations, and - // overloads are TypeScript syntax. - if (node.decorators - || hasModifier(node, ModifierFlags.TypeScriptModifier) - || node.typeParameters - || node.type - || !node.body - || node.questionToken) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // function declarations with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - // An async method declaration is ES2017 syntax. - if (hasModifier(node, ModifierFlags.Async)) { - transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017; - } - - if (node.asteriskToken) { - transformFlags |= TransformFlags.AssertGenerator; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes); - } - - function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - // Decorators, TypeScript-specific modifiers, type annotations, and overloads are - // TypeScript syntax. - if (node.decorators - || hasModifier(node, ModifierFlags.TypeScriptModifier) - || node.type - || !node.body) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // function declarations with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes); - } - - function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags | TransformFlags.ContainsClassFields; - - // Decorators, TypeScript-specific modifiers, and type annotations are TypeScript syntax. - if (some(node.decorators) || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type || node.questionToken) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // Hoisted variables related to class properties should live within the TypeScript class wrapper. - if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { - transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.PropertyExcludes); - } - - function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) { - let transformFlags: TransformFlags; - const modifierFlags = getModifierFlags(node); - const body = node.body; - - if (!body || (modifierFlags & ModifierFlags.Ambient)) { - // An ambient declaration is TypeScript syntax. - // A FunctionDeclaration without a body is an overload and is TypeScript syntax. - transformFlags = TransformFlags.AssertTypeScript; - } - else { - transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion; - - // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript - // syntax. - if (modifierFlags & ModifierFlags.TypeScriptModifier - || node.typeParameters - || node.type) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // An async function declaration is ES2017 syntax. - if (modifierFlags & ModifierFlags.Async) { - transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017; - } - - // function declarations with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - // If a FunctionDeclaration is generator function and is the body of a - // transformed async function, then this node can be transformed to a - // down-level generator. - // Currently we do not support transforming any other generator functions - // down level. - if (node.asteriskToken) { - transformFlags |= TransformFlags.AssertGenerator; - } - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.FunctionExcludes; - } - - function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript - // syntax. - if (hasModifier(node, ModifierFlags.TypeScriptModifier) - || node.typeParameters - || node.type) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // An async function expression is ES2017 syntax. - if (hasModifier(node, ModifierFlags.Async)) { - transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017; - } - - // function expressions with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - // If a FunctionExpression is generator function and is the body of a - // transformed async function, then this node can be transformed to a - // down-level generator. - if (node.asteriskToken) { - transformFlags |= TransformFlags.AssertGenerator; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.FunctionExcludes; - } - - function computeArrowFunction(node: ArrowFunction, subtreeFlags: TransformFlags) { - // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. - let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - - // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript - // syntax. - if (hasModifier(node, ModifierFlags.TypeScriptModifier) - || node.typeParameters - || node.type) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - // An async arrow function is ES2017 syntax. - if (hasModifier(node, ModifierFlags.Async)) { - transformFlags |= TransformFlags.AssertES2017; - } - - // arrow functions with object rest destructuring are ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ArrowFunctionExcludes; - } - - function computePropertyAccess(node: PropertyAccessExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; - } - - // If a PropertyAccessExpression starts with a super keyword, then it is - // ES6 syntax, and requires a lexical `this` binding. - if (node.expression.kind === SyntaxKind.SuperKeyword) { - // super inside of an async function requires hoisting the super access (ES2017). - // same for super inside of an async generator, which is ES2018. - transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.PropertyAccessExcludes; - } - - function computeElementAccess(node: ElementAccessExpression, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; - } - - // If an ElementAccessExpression starts with a super keyword, then it is - // ES6 syntax, and requires a lexical `this` binding. - if (node.expression.kind === SyntaxKind.SuperKeyword) { - // super inside of an async function requires hoisting the super access (ES2017). - // same for super inside of an async generator, which is ES2018. - transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.PropertyAccessExcludes; - } - - function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern; // TODO(rbuckton): Why are these set unconditionally? - - // A VariableDeclaration containing ObjectRest is ES2018 syntax - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018; - } - - // Type annotations are TypeScript syntax. - if (node.type) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeVariableStatement(node: VariableStatement, subtreeFlags: TransformFlags) { - let transformFlags: TransformFlags; - const declarationListTransformFlags = node.declarationList.transformFlags; - - // An ambient declaration is TypeScript syntax. - if (hasModifier(node, ModifierFlags.Ambient)) { - transformFlags = TransformFlags.AssertTypeScript; - } - else { - transformFlags = subtreeFlags; - - if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) { - transformFlags |= TransformFlags.AssertES2015; - } - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeLabeledStatement(node: LabeledStatement, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. - if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding - && isIterationStatement(node, /*lookInLabeledStatements*/ true)) { - transformFlags |= TransformFlags.AssertES2015; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeImportEquals(node: ImportEqualsDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags; - - // An ImportEqualsDeclaration with a namespace reference is TypeScript. - if (!isExternalModuleImportEqualsDeclaration(node)) { - transformFlags |= TransformFlags.AssertTypeScript; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeExpressionStatement(node: ExpressionStatement, subtreeFlags: TransformFlags) { - const transformFlags = subtreeFlags; - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.NodeExcludes; - } - - function computeModuleDeclaration(node: ModuleDeclaration, subtreeFlags: TransformFlags) { - let transformFlags = TransformFlags.AssertTypeScript; - const modifierFlags = getModifierFlags(node); - - if ((modifierFlags & ModifierFlags.Ambient) === 0) { - transformFlags |= subtreeFlags; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.ModuleExcludes; - } - - function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) { - let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion; - - if (subtreeFlags & TransformFlags.ContainsBindingPattern) { - transformFlags |= TransformFlags.AssertES2015; - } - - // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. - if (node.flags & NodeFlags.BlockScoped) { - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBlockScopedBinding; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~TransformFlags.VariableDeclarationListExcludes; - } - - function computeOther(node: Node, kind: SyntaxKind, subtreeFlags: TransformFlags) { - // Mark transformations needed for each node - let transformFlags = subtreeFlags; - let excludeFlags = TransformFlags.NodeExcludes; - - switch (kind) { - case SyntaxKind.AsyncKeyword: - case SyntaxKind.AwaitExpression: - // async/await is ES2017 syntax, but may be ES2018 syntax (for async generators) - transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2017; - break; - - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.PartiallyEmittedExpression: - // These nodes are TypeScript syntax. - transformFlags |= TransformFlags.AssertTypeScript; - excludeFlags = TransformFlags.OuterExpressionExcludes; - break; - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.AbstractKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.ConstKeyword: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.EnumMember: - case SyntaxKind.NonNullExpression: - case SyntaxKind.ReadonlyKeyword: - // These nodes are TypeScript syntax. - transformFlags |= TransformFlags.AssertTypeScript; - break; - - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxOpeningElement: - case SyntaxKind.JsxText: - case SyntaxKind.JsxClosingElement: - case SyntaxKind.JsxFragment: - case SyntaxKind.JsxOpeningFragment: - case SyntaxKind.JsxClosingFragment: - case SyntaxKind.JsxAttribute: - case SyntaxKind.JsxAttributes: - case SyntaxKind.JsxSpreadAttribute: - case SyntaxKind.JsxExpression: - // These nodes are Jsx syntax. - transformFlags |= TransformFlags.AssertJsx; - break; - - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - case SyntaxKind.TemplateExpression: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.StaticKeyword: - case SyntaxKind.MetaProperty: - // These nodes are ES6 syntax. - transformFlags |= TransformFlags.AssertES2015; - break; - - case SyntaxKind.StringLiteral: - if ((node).hasExtendedUnicodeEscape) { - transformFlags |= TransformFlags.AssertES2015; - } - break; - - case SyntaxKind.NumericLiteral: - if ((node).numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { - transformFlags |= TransformFlags.AssertES2015; - } - break; - - case SyntaxKind.BigIntLiteral: - transformFlags |= TransformFlags.AssertESNext; - break; - - case SyntaxKind.ForOfStatement: - // This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of). - if ((node).awaitModifier) { - transformFlags |= TransformFlags.AssertES2018; - } - transformFlags |= TransformFlags.AssertES2015; - break; - - case SyntaxKind.YieldExpression: - // This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async - // generator). - transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.ContainsYield; - break; - - case SyntaxKind.AnyKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.BigIntKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.ObjectKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.VoidKeyword: - case SyntaxKind.TypeParameter: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.TypePredicate: - case SyntaxKind.TypeReference: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - case SyntaxKind.TypeQuery: - case SyntaxKind.TypeLiteral: - case SyntaxKind.ArrayType: - case SyntaxKind.TupleType: - case SyntaxKind.OptionalType: - case SyntaxKind.RestType: - case SyntaxKind.UnionType: - case SyntaxKind.IntersectionType: - case SyntaxKind.ConditionalType: - case SyntaxKind.InferType: - case SyntaxKind.ParenthesizedType: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.ThisType: - case SyntaxKind.TypeOperator: - case SyntaxKind.IndexedAccessType: - case SyntaxKind.MappedType: - case SyntaxKind.LiteralType: - case SyntaxKind.NamespaceExportDeclaration: - // Types and signatures are TypeScript syntax, and exclude all other facts. - transformFlags = TransformFlags.AssertTypeScript; - excludeFlags = TransformFlags.TypeExcludes; - break; - - case SyntaxKind.ComputedPropertyName: - // Even though computed property names are ES6, we don't treat them as such. - // This is so that they can flow through PropertyName transforms unaffected. - // Instead, we mark the container as ES6, so that it can properly handle the transform. - transformFlags |= TransformFlags.ContainsComputedPropertyName; - break; - - case SyntaxKind.SpreadElement: - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsRestOrSpread; - break; - - case SyntaxKind.SpreadAssignment: - transformFlags |= TransformFlags.AssertES2018 | TransformFlags.ContainsObjectRestOrSpread; - break; - - case SyntaxKind.SuperKeyword: - // This node is ES6 syntax. - transformFlags |= TransformFlags.AssertES2015; - excludeFlags = TransformFlags.OuterExpressionExcludes; // must be set to persist `Super` - break; - - case SyntaxKind.ThisKeyword: - // Mark this node and its ancestors as containing a lexical `this` keyword. - transformFlags |= TransformFlags.ContainsLexicalThis; - break; - - case SyntaxKind.ObjectBindingPattern: - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern; - if (subtreeFlags & TransformFlags.ContainsRestOrSpread) { - transformFlags |= TransformFlags.AssertES2018 | TransformFlags.ContainsObjectRestOrSpread; - } - excludeFlags = TransformFlags.BindingPatternExcludes; - break; - - case SyntaxKind.ArrayBindingPattern: - transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern; - excludeFlags = TransformFlags.BindingPatternExcludes; - break; - - case SyntaxKind.BindingElement: - transformFlags |= TransformFlags.AssertES2015; - if ((node).dotDotDotToken) { - transformFlags |= TransformFlags.ContainsRestOrSpread; - } - break; - - case SyntaxKind.Decorator: - // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. - transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsTypeScriptClassSyntax; - break; - - case SyntaxKind.ObjectLiteralExpression: - excludeFlags = TransformFlags.ObjectLiteralExcludes; - if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) { - // If an ObjectLiteralExpression contains a ComputedPropertyName, then it - // is an ES6 node. - transformFlags |= TransformFlags.AssertES2015; - } - - if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) { - // If an ObjectLiteralExpression contains a spread element, then it - // is an ES2018 node. - transformFlags |= TransformFlags.AssertES2018; - } - - break; - - case SyntaxKind.ArrayLiteralExpression: - excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes; - break; - - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - // A loop containing a block scoped binding *may* need to be transformed from ES6. - if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding) { - transformFlags |= TransformFlags.AssertES2015; - } - - break; - - case SyntaxKind.SourceFile: - break; - - case SyntaxKind.ReturnStatement: - // Return statements may require an `await` in ES2018. - transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion | TransformFlags.AssertES2018; - break; - - case SyntaxKind.ContinueStatement: - case SyntaxKind.BreakStatement: - transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion; - break; - } - - node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; - return transformFlags & ~excludeFlags; - } - - function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) { - return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags); - } - - /** - * Gets the transform flags to exclude when unioning the transform flags of a subtree. - * - * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. - * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather - * than calling this function. - */ - export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { - if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) { - return TransformFlags.TypeExcludes; - } - - switch (kind) { - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.ArrayLiteralExpression: - return TransformFlags.ArrayLiteralOrCallOrNewExcludes; - case SyntaxKind.ModuleDeclaration: - return TransformFlags.ModuleExcludes; - case SyntaxKind.Parameter: - return TransformFlags.ParameterExcludes; - case SyntaxKind.ArrowFunction: - return TransformFlags.ArrowFunctionExcludes; - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - return TransformFlags.FunctionExcludes; - case SyntaxKind.VariableDeclarationList: - return TransformFlags.VariableDeclarationListExcludes; - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - return TransformFlags.ClassExcludes; - case SyntaxKind.Constructor: - return TransformFlags.ConstructorExcludes; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return TransformFlags.MethodOrAccessorExcludes; - case SyntaxKind.AnyKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.BigIntKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.ObjectKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.VoidKeyword: - case SyntaxKind.TypeParameter: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - return TransformFlags.TypeExcludes; - case SyntaxKind.ObjectLiteralExpression: - return TransformFlags.ObjectLiteralExcludes; - case SyntaxKind.CatchClause: - return TransformFlags.CatchClauseExcludes; - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - return TransformFlags.BindingPatternExcludes; - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.PartiallyEmittedExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.SuperKeyword: - return TransformFlags.OuterExpressionExcludes; - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - return TransformFlags.PropertyAccessExcludes; - default: - return TransformFlags.NodeExcludes; - } - } - /** * "Binds" JSDoc nodes in TypeScript code. * Since we will never create symbols for JSDoc, we just set parent pointers instead. diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e7befc3a4dce0..5723a32351c6a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -350,8 +350,8 @@ namespace ts { getMergedSymbol, getDiagnostics, getGlobalDiagnostics, - getTypeOfSymbolAtLocation: (symbol, location) => { - location = getParseTreeNode(location); + getTypeOfSymbolAtLocation: (symbol, locationIn) => { + const location = getParseTreeNode(locationIn); return location ? getTypeOfSymbolAtLocation(symbol, location) : errorType; }, getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { @@ -389,16 +389,16 @@ namespace ts { symbolToTypeParameterDeclarations: nodeBuilder.symbolToTypeParameterDeclarations, symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration, typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration, - getSymbolsInScope: (location, meaning) => { - location = getParseTreeNode(location); + getSymbolsInScope: (locationIn, meaning) => { + const location = getParseTreeNode(locationIn); return location ? getSymbolsInScope(location, meaning) : []; }, - getSymbolAtLocation: node => { - node = getParseTreeNode(node); + getSymbolAtLocation: nodeIn => { + const node = getParseTreeNode(nodeIn); return node ? getSymbolAtLocation(node) : undefined; }, - getShorthandAssignmentValueSymbol: node => { - node = getParseTreeNode(node); + getShorthandAssignmentValueSymbol: nodeIn => { + const node = getParseTreeNode(nodeIn); return node ? getShorthandAssignmentValueSymbol(node) : undefined; }, getExportSpecifierLocalTargetSymbol: nodeIn => { @@ -408,8 +408,8 @@ namespace ts { getExportSymbolOfSymbol(symbol) { return getMergedSymbol(symbol.exportSymbol || symbol); }, - getTypeAtLocation: node => { - node = getParseTreeNode(node); + getTypeAtLocation: nodeIn => { + const node = getParseTreeNode(nodeIn); return node ? getTypeOfNode(node) : errorType; }, getTypeOfAssignmentPattern: nodeIn => { @@ -486,9 +486,9 @@ namespace ts { const declaration = getParseTreeNode(declarationIn, isFunctionLike); return declaration ? getSignatureFromDeclaration(declaration) : undefined; }, - isImplementationOfOverload: node => { - const parsed = getParseTreeNode(node, isFunctionLike); - return parsed ? isImplementationOfOverload(parsed) : undefined; + isImplementationOfOverload: nodeIn => { + const node = getParseTreeNode(nodeIn, isFunctionLike); + return node ? isImplementationOfOverload(node) : undefined; }, getImmediateAliasedSymbol, getAliasedSymbol: resolveAlias, @@ -564,15 +564,16 @@ namespace ts { getAccessibleSymbolChain, getTypePredicateOfSignature, resolveExternalModuleSymbol, - tryGetThisTypeAt: (node, includeGlobalThis) => { - node = getParseTreeNode(node); + tryGetThisTypeAt: (nodeIn, includeGlobalThis) => { + const node = getParseTreeNode(nodeIn); return node && tryGetThisTypeAt(node, includeGlobalThis); }, getTypeArgumentConstraint: nodeIn => { const node = getParseTreeNode(nodeIn, isTypeNode); return node && getTypeArgumentConstraint(node); }, - getSuggestionDiagnostics: (file, ct) => { + getSuggestionDiagnostics: (fileIn, ct) => { + const file = getParseTreeNode(fileIn, isSourceFile) || Debug.fail("Could not determine parsed source file."); if (skipTypeChecking(file, compilerOptions, host)) { return emptyArray; } @@ -3683,7 +3684,7 @@ namespace ts { withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)), indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context)), - signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => + signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)), symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)), @@ -3740,26 +3741,26 @@ namespace ts { if (type.flags & TypeFlags.Any) { context.approximateLength += 3; - return createKeywordTypeNode(SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } if (type.flags & TypeFlags.Unknown) { - return createKeywordTypeNode(SyntaxKind.UnknownKeyword); + return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); } if (type.flags & TypeFlags.String) { context.approximateLength += 6; - return createKeywordTypeNode(SyntaxKind.StringKeyword); + return factory.createKeywordTypeNode(SyntaxKind.StringKeyword); } if (type.flags & TypeFlags.Number) { context.approximateLength += 6; - return createKeywordTypeNode(SyntaxKind.NumberKeyword); + return factory.createKeywordTypeNode(SyntaxKind.NumberKeyword); } if (type.flags & TypeFlags.BigInt) { context.approximateLength += 6; - return createKeywordTypeNode(SyntaxKind.BigIntKeyword); + return factory.createKeywordTypeNode(SyntaxKind.BigIntKeyword); } if (type.flags & TypeFlags.Boolean) { context.approximateLength += 7; - return createKeywordTypeNode(SyntaxKind.BooleanKeyword); + return factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword); } if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { const parentSymbol = getParentOfSymbol(type.symbol)!; @@ -3768,7 +3769,7 @@ namespace ts { ? parentName : appendReferenceToType( parentName as TypeReferenceNode | ImportTypeNode, - createTypeReferenceNode(symbolName(type.symbol), /*typeArguments*/ undefined) + factory.createTypeReferenceNode(symbolName(type.symbol), /*typeArguments*/ undefined) ); return enumLiteralName; } @@ -3777,20 +3778,20 @@ namespace ts { } if (type.flags & TypeFlags.StringLiteral) { context.approximateLength += ((type).value.length + 2); - return createLiteralTypeNode(setEmitFlags(createLiteral((type).value), EmitFlags.NoAsciiEscaping)); + return factory.createLiteralTypeNode(setEmitFlags(factory.createStringLiteral((type).value), EmitFlags.NoAsciiEscaping)); } if (type.flags & TypeFlags.NumberLiteral) { const value = (type).value; context.approximateLength += ("" + value).length; - return createLiteralTypeNode(value < 0 ? createPrefix(SyntaxKind.MinusToken, createLiteral(-value)) : createLiteral(value)); + return factory.createLiteralTypeNode(value < 0 ? factory.createPrefix(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : factory.createNumericLiteral(value)); } if (type.flags & TypeFlags.BigIntLiteral) { context.approximateLength += (pseudoBigIntToString((type).value).length) + 1; - return createLiteralTypeNode((createLiteral((type).value))); + return factory.createLiteralTypeNode((factory.createBigIntLiteral((type).value))); } if (type.flags & TypeFlags.BooleanLiteral) { context.approximateLength += (type).intrinsicName.length; - return (type).intrinsicName === "true" ? createTrue() : createFalse(); + return factory.createLiteralTypeNode((type).intrinsicName === "true" ? factory.createTrue() : factory.createFalse()); } if (type.flags & TypeFlags.UniqueESSymbol) { if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { @@ -3803,31 +3804,31 @@ namespace ts { } } context.approximateLength += 13; - return createTypeOperatorNode(SyntaxKind.UniqueKeyword, createKeywordTypeNode(SyntaxKind.SymbolKeyword)); + return factory.createTypeOperatorNode(SyntaxKind.UniqueKeyword, factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword)); } if (type.flags & TypeFlags.Void) { context.approximateLength += 4; - return createKeywordTypeNode(SyntaxKind.VoidKeyword); + return factory.createKeywordTypeNode(SyntaxKind.VoidKeyword); } if (type.flags & TypeFlags.Undefined) { context.approximateLength += 9; - return createKeywordTypeNode(SyntaxKind.UndefinedKeyword); + return factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword); } if (type.flags & TypeFlags.Null) { context.approximateLength += 4; - return createKeywordTypeNode(SyntaxKind.NullKeyword); + return factory.createLiteralTypeNode(factory.createNull()); } if (type.flags & TypeFlags.Never) { context.approximateLength += 5; - return createKeywordTypeNode(SyntaxKind.NeverKeyword); + return factory.createKeywordTypeNode(SyntaxKind.NeverKeyword); } if (type.flags & TypeFlags.ESSymbol) { context.approximateLength += 6; - return createKeywordTypeNode(SyntaxKind.SymbolKeyword); + return factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword); } if (type.flags & TypeFlags.NonPrimitive) { context.approximateLength += 6; - return createKeywordTypeNode(SyntaxKind.ObjectKeyword); + return factory.createKeywordTypeNode(SyntaxKind.ObjectKeyword); } if (isThisTypeParameter(type)) { if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) { @@ -3839,12 +3840,12 @@ namespace ts { } } context.approximateLength += 4; - return createThis(); + return factory.createThisTypeNode(); } if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); - if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return createTypeReferenceNode(createIdentifier(""), typeArgumentNodes); + if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return factory.createTypeReferenceNode(factory.createIdentifier(""), typeArgumentNodes); return symbolToTypeNode(type.aliasSymbol, context, SymbolFlags.Type, typeArgumentNodes); } @@ -3857,19 +3858,19 @@ namespace ts { if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) { if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) { context.approximateLength += (symbolName(type.symbol).length + 6); - return createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, /*constraintNode*/ undefined)); + return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, /*constraintNode*/ undefined)); } if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.flags & TypeFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) { const name = typeParameterToName(type, context); context.approximateLength += idText(name).length; - return createTypeReferenceNode(createIdentifier(idText(name)), /*typeArguments*/ undefined); + return factory.createTypeReferenceNode(factory.createIdentifier(idText(name)), /*typeArguments*/ undefined); } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return type.symbol ? symbolToTypeNode(type.symbol, context, SymbolFlags.Type) - : createTypeReferenceNode(createIdentifier("?"), /*typeArguments*/ undefined); + : factory.createTypeReferenceNode(factory.createIdentifier("?"), /*typeArguments*/ undefined); } if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) { const types = type.flags & TypeFlags.Union ? formatUnionTypes((type).types) : (type).types; @@ -3878,7 +3879,7 @@ namespace ts { } const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true); if (typeNodes && typeNodes.length > 0) { - const unionOrIntersectionTypeNode = createUnionOrIntersectionTypeNode(type.flags & TypeFlags.Union ? SyntaxKind.UnionType : SyntaxKind.IntersectionType, typeNodes); + const unionOrIntersectionTypeNode = type.flags & TypeFlags.Union ? factory.createUnionTypeNode(typeNodes) : factory.createIntersectionTypeNode(typeNodes); return unionOrIntersectionTypeNode; } else { @@ -3897,13 +3898,13 @@ namespace ts { const indexedType = (type).type; context.approximateLength += 6; const indexTypeNode = typeToTypeNodeHelper(indexedType, context); - return createTypeOperatorNode(indexTypeNode); + return factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTypeNode); } if (type.flags & TypeFlags.IndexedAccess) { const objectTypeNode = typeToTypeNodeHelper((type).objectType, context); const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); context.approximateLength += 2; - return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); + return factory.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } if (type.flags & TypeFlags.Conditional) { const checkTypeNode = typeToTypeNodeHelper((type).checkType, context); @@ -3914,7 +3915,7 @@ namespace ts { const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(type), context); const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context); context.approximateLength += 15; - return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); + return factory.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } if (type.flags & TypeFlags.Substitution) { return typeToTypeNodeHelper((type).typeVariable, context); @@ -3924,20 +3925,20 @@ namespace ts { function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); - const readonlyToken = type.declaration.readonlyToken ? createToken(type.declaration.readonlyToken.kind) : undefined; - const questionToken = type.declaration.questionToken ? createToken(type.declaration.questionToken.kind) : undefined; + const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) : undefined; + const questionToken = type.declaration.questionToken ? factory.createToken(type.declaration.questionToken.kind) : undefined; let appropriateConstraintTypeNode: TypeNode; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` - appropriateConstraintTypeNode = createTypeOperatorNode(typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); + appropriateConstraintTypeNode = factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); } else { appropriateConstraintTypeNode = typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context); } const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); const templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); - const mappedTypeNode = createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); + const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); context.approximateLength += 10; return setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); } @@ -4032,7 +4033,7 @@ namespace ts { if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { context.approximateLength += 2; - return setEmitFlags(createTypeLiteralNode(/*members*/ undefined), EmitFlags.SingleLine); + return setEmitFlags(factory.createTypeLiteralNode(/*members*/ undefined), EmitFlags.SingleLine); } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { @@ -4053,7 +4054,7 @@ namespace ts { context.flags |= NodeBuilderFlags.InObjectTypeLiteral; const members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; - const typeLiteralNode = createTypeLiteralNode(members); + const typeLiteralNode = factory.createTypeLiteralNode(members); context.approximateLength += 2; return setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); } @@ -4063,11 +4064,11 @@ namespace ts { if (type.target === globalArrayType || type.target === globalReadonlyArrayType) { if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); - return createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]); + return factory.createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]); } const elementType = typeToTypeNodeHelper(typeArguments[0], context); - const arrayType = createArrayTypeNode(elementType); - return type.target === globalArrayType ? arrayType : createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType); + const arrayType = factory.createArrayTypeNode(elementType); + return type.target === globalArrayType ? arrayType : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { if (typeArguments.length > 0) { @@ -4077,16 +4078,16 @@ namespace ts { if (tupleConstituentNodes) { for (let i = (type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) { tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ? - createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) : - createOptionalTypeNode(tupleConstituentNodes[i]); + factory.createRestTypeNode(factory.createArrayTypeNode(tupleConstituentNodes[i])) : + factory.createOptionalTypeNode(tupleConstituentNodes[i]); } - const tupleTypeNode = createTupleTypeNode(tupleConstituentNodes); - return (type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + const tupleTypeNode = factory.createTupleTypeNode(tupleConstituentNodes); + return (type.target).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; } } if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) { - const tupleTypeNode = createTupleTypeNode([]); - return (type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + const tupleTypeNode = factory.createTupleTypeNode([]); + return (type.target).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; } context.encounteredError = true; return undefined!; // TODO: GH#18217 @@ -4148,7 +4149,7 @@ namespace ts { // then move qualifiers const ids = getAccessStack(ref); for (const id of ids) { - root.qualifier = root.qualifier ? createQualifiedName(root.qualifier, id) : id; + root.qualifier = root.qualifier ? factory.createQualifiedName(root.qualifier, id) : id; } return root; } @@ -4160,7 +4161,7 @@ namespace ts { // then move qualifiers const ids = getAccessStack(ref); for (const id of ids) { - root.typeName = createQualifiedName(root.typeName, id); + root.typeName = factory.createQualifiedName(root.typeName, id); } return root; } @@ -4179,7 +4180,7 @@ namespace ts { function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined { if (checkTruncationLength(context)) { - return [createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)]; + return [factory.createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined)]; } const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { @@ -4220,7 +4221,7 @@ namespace ts { } } if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) { - typeElements.push(createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); + typeElements.push(factory.createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined)); addPropertyToElementList(properties[properties.length - 1], context, typeElements); break; } @@ -4234,9 +4235,9 @@ namespace ts { function createElidedInformationPlaceholder(context: NodeBuilderContext) { context.approximateLength += 3; if (!(context.flags & NodeBuilderFlags.NoTruncation)) { - return createTypeReferenceNode(createIdentifier("..."), /*typeArguments*/ undefined); + return factory.createTypeReferenceNode(factory.createIdentifier("..."), /*typeArguments*/ undefined); } - return createKeywordTypeNode(SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) { @@ -4262,7 +4263,7 @@ namespace ts { context.enclosingDeclaration = saveEnclosingDeclaration; const propertyName = getPropertyNameNodeForSymbol(propertySymbol, context); context.approximateLength += (symbolName(propertySymbol).length + 1); - const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined; + const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol)) { const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), SignatureKind.Call); for (const signature of signatures) { @@ -4280,20 +4281,19 @@ namespace ts { propertyTypeNode = createElidedInformationPlaceholder(context); } else { - propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword); + propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } context.flags = savedFlags; - const modifiers = isReadonlySymbol(propertySymbol) ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined; + const modifiers = isReadonlySymbol(propertySymbol) ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined; if (modifiers) { context.approximateLength += 9; } - const propertySignature = createPropertySignature( + const propertySignature = factory.createPropertySignature( modifiers, propertyName, optionalToken, - propertyTypeNode, - /*initializer*/ undefined); + propertyTypeNode); typeElements.push(preserveCommentsOn(propertySignature)); } @@ -4318,12 +4318,12 @@ namespace ts { if (some(types)) { if (checkTruncationLength(context)) { if (!isBareList) { - return [createTypeReferenceNode("...", /*typeArguments*/ undefined)]; + return [factory.createTypeReferenceNode("...", /*typeArguments*/ undefined)]; } else if (types.length > 2) { return [ typeToTypeNodeHelper(types[0], context), - createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined), + factory.createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined), typeToTypeNodeHelper(types[types.length - 1], context) ]; } @@ -4333,7 +4333,7 @@ namespace ts { for (const type of types) { i++; if (checkTruncationLength(context) && (i + 2 < types.length - 1)) { - result.push(createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined)); + result.push(factory.createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined)); const typeNode = typeToTypeNodeHelper(types[types.length - 1], context); if (typeNode) { result.push(typeNode); @@ -4353,9 +4353,9 @@ namespace ts { function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind, context: NodeBuilderContext): IndexSignatureDeclaration { const name = getNameFromIndexInfo(indexInfo) || "x"; - const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword); + const indexerTypeNode = factory.createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword); - const indexingParameter = createParameter( + const indexingParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -4368,14 +4368,14 @@ namespace ts { context.encounteredError = true; } context.approximateLength += (name.length + 4); - return createIndexSignature( + return factory.createIndexSignature( /*decorators*/ undefined, - indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined, + indexInfo.isReadonly ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined, [indexingParameter], typeNode); } - function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { + function signatureToSignatureDeclarationHelper(signature: Signature, kind: SignatureDeclaration["kind"], context: NodeBuilderContext): SignatureDeclaration { let typeParameters: TypeParameterDeclaration[] | undefined; let typeArguments: TypeNode[] | undefined; if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { @@ -4395,13 +4395,13 @@ namespace ts { const typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? - createToken(SyntaxKind.AssertsKeyword) : + factory.createToken(SyntaxKind.AssertsKeyword) : undefined; const parameterName = typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? - setEmitFlags(createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : - createThisTypeNode(); + setEmitFlags(factory.createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : + factory.createThisTypeNode(); const typeNode = typePredicate.type && typeToTypeNodeHelper(typePredicate.type, context); - returnTypeNode = createTypePredicateNodeWithModifier(assertsModifier, parameterName, typeNode); + returnTypeNode = factory.createTypePredicateNode(assertsModifier, parameterName, typeNode); } else { const returnType = getReturnTypeOfSignature(signature); @@ -4413,10 +4413,14 @@ namespace ts { } } else if (!returnTypeNode) { - returnTypeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword); + returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum - return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); + const node = factory.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); + if (typeArguments) { + node.typeArguments = factory.createNodeArray(typeArguments); + } + return node; } function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration { @@ -4426,7 +4430,7 @@ namespace ts { const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); context.flags = savedContextFlags; - return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode); + return factory.createTypeParameterDeclaration(name, constraintNode, defaultParameterNode); } function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): TypeParameterDeclaration { @@ -4448,7 +4452,7 @@ namespace ts { const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined; const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter; - const dotDotDotToken = isRest ? createToken(SyntaxKind.DotDotDotToken) : undefined; + const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration ? parameterDeclaration.name ? parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) : @@ -4456,8 +4460,8 @@ namespace ts { symbolName(parameterSymbol) : symbolName(parameterSymbol); const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter; - const questionToken = isOptional ? createToken(SyntaxKind.QuestionToken) : undefined; - const parameterNode = createParameter( + const questionToken = isOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; + const parameterNode = factory.createParameterDeclaration( /*decorators*/ undefined, modifiers, dotDotDotToken, @@ -4586,7 +4590,7 @@ namespace ts { let typeParameterNodes: NodeArray | undefined; const targetSymbol = getTargetSymbol(symbol); if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { - typeParameterNodes = createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); + typeParameterNodes = factory.createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); } return typeParameterNodes; } @@ -4695,7 +4699,7 @@ namespace ts { context.tracker.reportLikelyUnsafeImportRequiredError(specifier); } } - const lit = createLiteralTypeNode(createLiteral(specifier)); + const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier)); if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]); context.approximateLength += specifier.length + 10; // specifier + import("") if (!nonRootParts || isEntityName(nonRootParts)) { @@ -4703,12 +4707,12 @@ namespace ts { const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; lastId.typeArguments = undefined; } - return createImportTypeNode(lit, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); + return factory.createImportTypeNode(lit, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); } else { const splitNode = getTopmostIndexedAccessType(nonRootParts); const qualifier = (splitNode.objectType as TypeReferenceNode).typeName; - return createIndexedAccessTypeNode(createImportTypeNode(lit, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType); + return factory.createIndexedAccessTypeNode(factory.createImportTypeNode(lit, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType); } } @@ -4717,13 +4721,13 @@ namespace ts { return entityName; // Indexed accesses can never be `typeof` } if (isTypeOf) { - return createTypeQueryNode(entityName); + return factory.createTypeQueryNode(entityName); } else { const lastId = isIdentifier(entityName) ? entityName : entityName.right; const lastTypeArgs = lastId.typeArguments; lastId.typeArguments = undefined; - return createTypeReferenceNode(entityName, lastTypeArgs as NodeArray); + return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray); } function createAccessFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName | IndexedAccessTypeNode { @@ -4760,14 +4764,14 @@ namespace ts { // Should use an indexed access const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); if (isIndexedAccessTypeNode(LHS)) { - return createIndexedAccessTypeNode(LHS, createLiteralTypeNode(createLiteral(symbolName))); + return factory.createIndexedAccessTypeNode(LHS, factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); } else { - return createIndexedAccessTypeNode(createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), createLiteralTypeNode(createLiteral(symbolName))); + return factory.createIndexedAccessTypeNode(factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); } } - const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; if (index > stopper) { @@ -4775,7 +4779,7 @@ namespace ts { if (!isEntityName(LHS)) { return Debug.fail("Impossible construct - an export of an indexed access cannot be reachable"); } - return createQualifiedName(LHS, identifier); + return factory.createQualifiedName(LHS, identifier); } return identifier; } @@ -4794,7 +4798,7 @@ namespace ts { } let result = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); if (!(result.kind & SyntaxKind.Identifier)) { - return createIdentifier("(Missing type parameter)"); + return factory.createIdentifier("(Missing type parameter)"); } if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { const rawtext = result.escapedText as string; @@ -4805,7 +4809,7 @@ namespace ts { text = `${rawtext}_${i}`; } if (text !== rawtext) { - result = createIdentifier(text, result.typeArguments); + result = factory.createIdentifier(text, result.typeArguments); } (context.typeParameterNames || (context.typeParameterNames = createMap())).set("" + getTypeId(type), result); (context.typeParameterNamesByText || (context.typeParameterNamesByText = createMap())).set(result.escapedText as string, true); @@ -4837,10 +4841,10 @@ namespace ts { context.flags ^= NodeBuilderFlags.InInitialEntityName; } - const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; - return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; } } @@ -4862,14 +4866,14 @@ namespace ts { } let firstChar = symbolName.charCodeAt(0); if (isSingleOrDoubleQuote(firstChar) && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { - return createLiteral(getSpecifierForModuleSymbol(symbol, context)); + return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context)); } const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); if (index === 0 || canUsePropertyAccess) { - const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; - return index > 0 ? createPropertyAccess(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 ? factory.createPropertyAccess(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; } else { if (firstChar === CharacterCodes.openBracket) { @@ -4878,17 +4882,17 @@ namespace ts { } let expression: Expression | undefined; if (isSingleOrDoubleQuote(firstChar)) { - expression = createLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, s => s.substring(1))); + expression = factory.createStringLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, s => s.substring(1))); (expression as StringLiteral).singleQuote = firstChar === CharacterCodes.singleQuote; } else if (("" + +symbolName) === symbolName) { - expression = createLiteral(+symbolName); + expression = factory.createNumericLiteral(+symbolName); } if (!expression) { - expression = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); expression.symbol = symbol; } - return createElementAccess(createExpressionFromSymbolChain(chain, index - 1), expression); + return factory.createElementAccess(createExpressionFromSymbolChain(chain, index - 1), expression); } } } @@ -4911,7 +4915,7 @@ namespace ts { return fromNameType; } if (isKnownSymbol(symbol)) { - return createComputedPropertyName(createPropertyAccess(createIdentifier("Symbol"), (symbol.escapedName as string).substr(3))); + return factory.createComputedPropertyName(factory.createPropertyAccess(factory.createIdentifier("Symbol"), (symbol.escapedName as string).substr(3))); } const rawName = unescapeLeadingUnderscores(symbol.escapedName); return createPropertyNameNodeForIdentifierOrLiteral(rawName, singleQuote); @@ -4924,21 +4928,23 @@ namespace ts { if (nameType.flags & TypeFlags.StringOrNumberLiteral) { const name = "" + (nameType).value; if (!isIdentifierText(name, compilerOptions.target) && !isNumericLiteralName(name)) { - return createLiteral(name, !!singleQuote); + return factory.createStringLiteral(name, !!singleQuote); } if (isNumericLiteralName(name) && startsWith(name, "-")) { - return createComputedPropertyName(createLiteral(+name)); + return factory.createComputedPropertyName(factory.createNumericLiteral(+name)); } return createPropertyNameNodeForIdentifierOrLiteral(name); } if (nameType.flags & TypeFlags.UniqueESSymbol) { - return createComputedPropertyName(symbolToExpression((nameType).symbol, context, SymbolFlags.Value)); + return factory.createComputedPropertyName(symbolToExpression((nameType).symbol, context, SymbolFlags.Value)); } } } function createPropertyNameNodeForIdentifierOrLiteral(name: string, singleQuote?: boolean) { - return isIdentifierText(name, compilerOptions.target) ? createIdentifier(name) : createLiteral(isNumericLiteralName(name) ? +name : name, !!singleQuote); + return isIdentifierText(name, compilerOptions.target) ? factory.createIdentifier(name) : + isNumericLiteralName(name) ? factory.createNumericLiteral(+name) : + factory.createStringLiteral(name, !!singleQuote); } function cloneNodeBuilderContext(context: NodeBuilderContext): NodeBuilderContext { @@ -4968,8 +4974,8 @@ namespace ts { } function symbolTableToDeclarationStatements(symbolTable: SymbolTable, context: NodeBuilderContext, bundled?: boolean): Statement[] { - const serializePropertySymbolForClass = makeSerializePropertySymbol(createProperty, SyntaxKind.MethodDeclaration, /*useAcessors*/ true); - const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol((_decorators, mods, name, question, type, initializer) => createPropertySignature(mods, name, question, type, initializer), SyntaxKind.MethodSignature, /*useAcessors*/ false); + const serializePropertySymbolForClass = makeSerializePropertySymbol(factory.createPropertyDeclaration, SyntaxKind.MethodDeclaration, /*useAcessors*/ true); + const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol((_decorators, mods, name, question, type) => factory.createPropertySignature(mods, name, question, type), SyntaxKind.MethodSignature, /*useAcessors*/ false); // TODO: Use `setOriginalNode` on original declaration names where possible so these declarations see some kind of // declaration mapping @@ -5044,10 +5050,10 @@ namespace ts { // the top-level exports and exporting them in the targeted ns, as can occur when a js file has both typedefs and `module.export` assignments const excessExports = filter(statements, s => !!(getModifierFlags(s) & ModifierFlags.Export)); if (length(excessExports)) { - ns.body.statements = createNodeArray([...ns.body.statements, createExportDeclaration( + ns.body.statements = factory.createNodeArray([...ns.body.statements, factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports(map(flatMap(excessExports, e => getNamesOfDeclaration(e)), id => createExportSpecifier(/*alias*/ undefined, id))), + factory.createNamedExports(map(flatMap(excessExports, e => getNamesOfDeclaration(e)), id => factory.createExportSpecifier(/*alias*/ undefined, id))), /*moduleSpecifier*/ undefined )]); } @@ -5070,10 +5076,10 @@ namespace ts { const exports = filter(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause) as ExportDeclaration[]; if (length(exports) > 1) { const nonExports = filter(statements, d => !isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause); - statements = [...nonExports, createExportDeclaration( + statements = [...nonExports, factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports(flatMap(exports, e => e.exportClause!.elements)), + factory.createNamedExports(flatMap(exports, e => e.exportClause!.elements)), /*moduleSpecifier*/ undefined )]; } @@ -5087,10 +5093,10 @@ namespace ts { // remove group members from statements and then merge group members and add back to statements statements = [ ...filter(statements, s => group.indexOf(s as ExportDeclaration) === -1), - createExportDeclaration( + factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports(flatMap(group, e => e.exportClause!.elements)), + factory.createNamedExports(flatMap(group, e => e.exportClause!.elements)), group[0].moduleSpecifier ) ]; @@ -5123,7 +5129,7 @@ namespace ts { else { // some items filtered, others not - update the export declaration // (mutating because why not, we're building a whole new tree here anyway) - exportDecl.exportClause!.elements = createNodeArray(replacements); + exportDecl.exportClause!.elements = factory.createNodeArray(replacements); } } return statements; @@ -5139,7 +5145,7 @@ namespace ts { if (enclosingDeclaration && ((isSourceFile(enclosingDeclaration) && isExternalOrCommonJsModule(enclosingDeclaration)) || isModuleDeclaration(enclosingDeclaration)) && (!some(statements, isExternalModuleIndicator) || (!hasScopeMarker(statements) && some(statements, needsScopeMarker)))) { - statements.push(createEmptyExports()); + statements.push(createEmptyExports(factory)); } return statements; } @@ -5156,7 +5162,7 @@ namespace ts { function addExportModifier(statement: Statement) { const flags = (getModifierFlags(statement) | ModifierFlags.Export) & ~ModifierFlags.Ambient; - statement.modifiers = createNodeArray(createModifiersFromModifierFlags(flags)); + statement.modifiers = factory.createNodeArray(factory.createModifiersFromModifierFlags(flags)); statement.modifierFlagsCache = 0; } @@ -5275,11 +5281,11 @@ namespace ts { for (const node of symbol.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); if (!resolvedModule) continue; - addResult(createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*exportClause*/ undefined, createLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); + addResult(factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); } } if (needsPostExportDefault) { - addResult(createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportAssignment*/ false, createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None); + addResult(factory.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportAssignment*/ false, factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None); } } @@ -5317,7 +5323,7 @@ namespace ts { newModifierFlags |= ModifierFlags.Default; } if (newModifierFlags) { - node.modifiers = createNodeArray(createModifiersFromModifierFlags(newModifierFlags | getModifierFlags(node))); + node.modifiers = factory.createNodeArray(factory.createModifiersFromModifierFlags(newModifierFlags | getModifierFlags(node))); node.modifierFlagsCache = 0; // Reset computed flags cache } results.push(node); @@ -5332,7 +5338,7 @@ namespace ts { const oldFlags = context.flags; context.flags |= NodeBuilderFlags.InTypeAlias; addResult(setSyntheticLeadingComments( - createTypeAliasDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeToTypeNodeHelper(aliasType, context)), + factory.createTypeAliasDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeToTypeNodeHelper(aliasType, context)), !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }] ), modifierFlags); context.flags = oldFlags; @@ -5349,8 +5355,8 @@ namespace ts { const constructSignatures = serializeSignatures(SignatureKind.Construct, interfaceType, baseType, SyntaxKind.ConstructSignature) as ConstructSignatureDeclaration[]; const indexSignatures = serializeIndexSignatures(interfaceType, baseType); - const heritageClauses = !length(baseTypes) ? undefined : [createHeritageClause(SyntaxKind.ExtendsKeyword, mapDefined(baseTypes, b => trySerializeAsTypeReference(b)))]; - addResult(createInterfaceDeclaration( + const heritageClauses = !length(baseTypes) ? undefined : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, mapDefined(baseTypes, b => trySerializeAsTypeReference(b)))]; + addResult(factory.createInterfaceDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), @@ -5383,23 +5389,23 @@ namespace ts { } if (length(mergedMembers)) { const localName = getInternalSymbolName(symbol, symbolName); - const nsBody = createModuleBlock([createExportDeclaration( + const nsBody = factory.createModuleBlock([factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports(map(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { + factory.createNamedExports(map(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { const name = unescapeLeadingUnderscores(s.escapedName); const localName = getInternalSymbolName(s, name); const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s); const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); includePrivateSymbol(target || s); const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName; - return createExportSpecifier(name === targetName ? undefined : targetName, name); + return factory.createExportSpecifier(name === targetName ? undefined : targetName, name); })) )]); - addResult(createModuleDeclaration( + addResult(factory.createModuleDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createIdentifier(localName), + factory.createIdentifier(localName), nsBody, NodeFlags.Namespace ), ModifierFlags.None); @@ -5407,17 +5413,19 @@ namespace ts { } function serializeEnum(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { - addResult(createEnumDeclaration( + addResult(factory.createEnumDeclaration( /*decorators*/ undefined, - createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ModifierFlags.Const : 0), + factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ModifierFlags.Const : 0), getInternalSymbolName(symbol, symbolName), map(filter(getPropertiesOfType(getTypeOfSymbol(symbol)), p => !!(p.flags & SymbolFlags.EnumMember)), p => { // TODO: Handle computed names // I hate that to get the initialized value we need to walk back to the declarations here; but there's no // other way to get the possible const value of an enum member that I'm aware of, as the value is cached // _on the declaration_, not on the declaration's symbol... - const initializedValue = p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) && getConstantValue(p.declarations[0] as EnumMember); - return createEnumMember(unescapeLeadingUnderscores(p.escapedName), initializedValue === undefined ? undefined : createLiteral(initializedValue)); + const initializedValue = p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) ? getConstantValue(p.declarations[0] as EnumMember) : undefined; + return factory.createEnumMember(unescapeLeadingUnderscores(p.escapedName), initializedValue === undefined ? undefined : + typeof initializedValue === "string" ? factory.createStringLiteral(initializedValue) : + factory.createNumericLiteral(initializedValue)); }) ), modifierFlags); } @@ -5444,8 +5452,8 @@ namespace ts { if (textRange && isVariableDeclarationList(textRange.parent) && textRange.parent.declarations.length === 1) { textRange = textRange.parent.parent; } - const statement = setTextRange(createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([ - createVariableDeclaration(name, serializeTypeForDeclaration(type, symbol)) + const statement = setTextRange(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(type, symbol)) ], flags)), textRange); addResult(statement, name !== localName ? modifierFlags & ~ModifierFlags.Export : modifierFlags); if (name !== localName && !isPrivate) { @@ -5471,10 +5479,10 @@ namespace ts { // ``` // To create an export named `g` that does _not_ shadow the local `g` addResult( - createExportDeclaration( + factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports([createExportSpecifier(name, localName)]) + factory.createNamedExports([factory.createExportSpecifier(name, localName)]) ), ModifierFlags.None ); @@ -5488,7 +5496,7 @@ namespace ts { for (const sig of signatures) { // Each overload becomes a separate function declaration, in order const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context) as FunctionDeclaration; - decl.name = createIdentifier(localName); + decl.name = factory.createIdentifier(localName); addResult(setTextRange(decl, sig.declaration), modifierFlags); } // Module symbol emit will take care of module-y members, provided it has exports @@ -5522,7 +5530,7 @@ namespace ts { // emit akin to the above would be needed. // Add a namespace - const fakespace = createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(localName), createModuleBlock([]), NodeFlags.Namespace); + const fakespace = factory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace); fakespace.flags ^= NodeFlags.Synthesized; // unset synthesized so it is usable as an enclosing declaration fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration; fakespace.locals = createSymbolTable(props); @@ -5544,7 +5552,7 @@ namespace ts { fakespace.parent = undefined!; fakespace.locals = undefined!; fakespace.symbol = undefined!; - fakespace.body = createModuleBlock(declarations); + fakespace.body = factory.createModuleBlock(declarations); addResult(fakespace, modifierFlags); // namespaces can never be default exported } } @@ -5556,7 +5564,7 @@ namespace ts { const baseTypes = getBaseTypes(classType); const staticType = getTypeOfSymbol(symbol); const staticBaseType = getBaseConstructorTypeOfClass(staticType as InterfaceType); - const heritageClauses = !length(baseTypes) ? undefined : [createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))]; + const heritageClauses = !length(baseTypes) ? undefined : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))]; const members = flatMap(getPropertiesOfType(classType), p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0])); // Consider static members empty if symbol also has function or module meaning - function namespacey emit will handle statics const staticMembers = symbol.flags & (SymbolFlags.Function | SymbolFlags.ValueModule) @@ -5573,7 +5581,7 @@ namespace ts { c.typeParameters = undefined; } const indexSignatures = serializeIndexSignatures(classType, baseTypes[0]); - addResult(setTextRange(createClassDeclaration( + addResult(setTextRange(factory.createClassDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, localName, @@ -5605,51 +5613,51 @@ namespace ts { // Could be a local `import localName = ns.member` or // an external `import localName = require("whatever")` const isLocalImport = !(target.flags & SymbolFlags.ValueModule); - addResult(createImportEqualsDeclaration( + addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createIdentifier(localName), + factory.createIdentifier(localName), isLocalImport ? symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) - : createExternalModuleReference(createLiteral(getSpecifierForModuleSymbol(symbol, context))) + : factory.createExternalModuleReference(factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context))) ), isLocalImport ? modifierFlags : ModifierFlags.None); break; case SyntaxKind.NamespaceExportDeclaration: // export as namespace foo // TODO: Not part of a file's local or export symbol tables // Is bound into file.symbol.globalExports instead, which we don't currently traverse - addResult(createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), ModifierFlags.None); + addResult(factory.createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), ModifierFlags.None); break; case SyntaxKind.ImportClause: - addResult(createImportDeclaration( + addResult(factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createImportClause(createIdentifier(localName), /*namedBindings*/ undefined), + factory.createImportClause(factory.createIdentifier(localName), /*namedBindings*/ undefined), // We use `target.parent || target` below as `target.parent` is unset when the target is a module which has been export assigned // And then made into a default by the `esModuleInterop` or `allowSyntheticDefaultImports` flag // In such cases, the `target` refers to the module itself already - createLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) + factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) ), ModifierFlags.None); break; case SyntaxKind.NamespaceImport: - addResult(createImportDeclaration( + addResult(factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createImportClause(/*importClause*/ undefined, createNamespaceImport(createIdentifier(localName))), - createLiteral(getSpecifierForModuleSymbol(target, context)) + factory.createImportClause(/*importClause*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))), + factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)) ), ModifierFlags.None); break; case SyntaxKind.ImportSpecifier: - addResult(createImportDeclaration( + addResult(factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createImportClause(/*importClause*/ undefined, createNamedImports([ - createImportSpecifier( - localName !== verbatimTargetName ? createIdentifier(verbatimTargetName) : undefined, - createIdentifier(localName) + factory.createImportClause(/*importClause*/ undefined, factory.createNamedImports([ + factory.createImportSpecifier( + localName !== verbatimTargetName ? factory.createIdentifier(verbatimTargetName) : undefined, + factory.createIdentifier(localName) ) ])), - createLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) + factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) ), ModifierFlags.None); break; case SyntaxKind.ExportSpecifier: @@ -5661,7 +5669,7 @@ namespace ts { serializeExportSpecifier( unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, - specifier && isStringLiteralLike(specifier) ? createLiteral(specifier.text) : undefined + specifier && isStringLiteralLike(specifier) ? factory.createStringLiteral(specifier.text) : undefined ); break; case SyntaxKind.ExportAssignment: @@ -5685,10 +5693,10 @@ namespace ts { } function serializeExportSpecifier(localName: string, targetName: string, specifier?: Expression) { - addResult(createExportDeclaration( + addResult(factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports([createExportSpecifier(localName !== targetName ? targetName : undefined, localName)]), + factory.createNamedExports([factory.createExportSpecifier(localName !== targetName ? targetName : undefined, localName)]), specifier ), ModifierFlags.None); } @@ -5727,7 +5735,7 @@ namespace ts { const oldTrack = context.tracker.trackSymbol; context.tracker.trackSymbol = noop; if (isExportAssignment) { - results.push(createExportAssignment( + results.push(factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, @@ -5745,10 +5753,10 @@ namespace ts { else { // serialize as `import _Ref = t.arg.et; export { _Ref as name }` const varName = getUnusedName(name, symbol); - addResult(createImportEqualsDeclaration( + addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createIdentifier(varName), + factory.createIdentifier(varName), symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) ), ModifierFlags.None); serializeExportSpecifier(name, varName); @@ -5767,17 +5775,17 @@ namespace ts { serializeAsFunctionNamespaceMerge(typeToSerialize, symbol, varName, isExportAssignment ? ModifierFlags.None : ModifierFlags.Export); } else { - const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([ - createVariableDeclaration(varName, serializeTypeForDeclaration(typeToSerialize, symbol)) + const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(typeToSerialize, symbol)) ], NodeFlags.Const)); addResult(statement, name === varName ? ModifierFlags.Export : ModifierFlags.None); } if (isExportAssignment) { - results.push(createExportAssignment( + results.push(factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, - createIdentifier(varName) + factory.createIdentifier(varName) )); } else if (name !== varName) { @@ -5810,7 +5818,7 @@ namespace ts { questionOrExclamationToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined - ) => T, methodKind: SyntaxKind, useAccessors: true): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]); + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: true): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]); function makeSerializePropertySymbol(createProperty: ( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -5818,7 +5826,7 @@ namespace ts { questionOrExclamationToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined - ) => T, methodKind: SyntaxKind, useAccessors: false): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]); + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: false): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]); function makeSerializePropertySymbol(createProperty: ( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -5826,7 +5834,7 @@ namespace ts { questionOrExclamationToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined - ) => T, methodKind: SyntaxKind, useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) { + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) { return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined) { if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) { // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols @@ -5845,11 +5853,11 @@ namespace ts { if (p.flags & SymbolFlags.Accessor && useAccessors) { const result: AccessorDeclaration[] = []; if (p.flags & SymbolFlags.SetAccessor) { - result.push(setTextRange(createSetAccessor( + result.push(setTextRange(factory.createSetAccessorDeclaration( /*decorators*/ undefined, - createModifiersFromModifierFlags(staticFlag), + factory.createModifiersFromModifierFlags(staticFlag), name, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -5861,9 +5869,9 @@ namespace ts { ), find(p.declarations, isSetAccessor) || firstPropertyLikeDecl)); } if (p.flags & SymbolFlags.GetAccessor) { - result.push(setTextRange(createGetAccessor( + result.push(setTextRange(factory.createGetAccessorDeclaration( /*decorators*/ undefined, - createModifiersFromModifierFlags(staticFlag), + factory.createModifiersFromModifierFlags(staticFlag), name, [], serializeTypeForDeclaration(getTypeOfSymbol(p), p), @@ -5877,9 +5885,9 @@ namespace ts { else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable)) { return setTextRange(createProperty( /*decorators*/ undefined, - createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | staticFlag), + factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | staticFlag), name, - p.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined, + p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, serializeTypeForDeclaration(getTypeOfSymbol(p), p), // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357 // interface members can't have initializers, however class members _can_ @@ -5895,10 +5903,10 @@ namespace ts { const decl = signatureToSignatureDeclarationHelper(sig, methodKind, context) as MethodDeclaration; decl.name = name; // TODO: Clone if (staticFlag) { - decl.modifiers = createNodeArray(createModifiersFromModifierFlags(staticFlag)); + decl.modifiers = factory.createNodeArray(factory.createModifiersFromModifierFlags(staticFlag)); } if (p.flags & SymbolFlags.Optional) { - decl.questionToken = createToken(SyntaxKind.QuestionToken); + decl.questionToken = factory.createToken(SyntaxKind.QuestionToken); } results.push(setTextRange(decl, sig.declaration)); } @@ -5940,25 +5948,25 @@ namespace ts { function visitExistingNodeTreeSymbols(node: T): Node { if (isJSDocAllType(node)) { - return createKeywordTypeNode(SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } if (isJSDocUnknownType(node)) { - return createKeywordTypeNode(SyntaxKind.UnknownKeyword); + return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); } if (isJSDocNullableType(node)) { - return createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), createKeywordTypeNode(SyntaxKind.NullKeyword)]); + return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createLiteralTypeNode(factory.createNull())]); } if (isJSDocOptionalType(node)) { - return createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); + return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); } if (isJSDocNonNullableType(node)) { return visitNode(node.type, visitExistingNodeTreeSymbols); } if ((isExpressionWithTypeArguments(node) || isTypeReferenceNode(node)) && isJSDocIndexSignature(node)) { - return createTypeLiteralNode([createIndexSignature( + return factory.createTypeLiteralNode([factory.createIndexSignature( /*decorators*/ undefined, /*modifiers*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotdotdotToken*/ undefined, @@ -5972,9 +5980,9 @@ namespace ts { if (isJSDocFunctionType(node)) { if (isJSDocConstructSignature(node)) { let newTypeNode: TypeNode | undefined; - return createConstructorTypeNode( + return factory.createConstructorTypeNode( visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), - mapDefined(node.parameters, (p, i) => p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : createParameter( + mapDefined(node.parameters, (p, i) => p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, p.dotDotDotToken, @@ -5987,9 +5995,9 @@ namespace ts { ); } else { - return createFunctionTypeNode( + return factory.createFunctionTypeNode( visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), - map(node.parameters, (p, i) => createParameter( + map(node.parameters, (p, i) => factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, p.dotDotDotToken, @@ -6003,9 +6011,9 @@ namespace ts { } } if (isLiteralImportTypeNode(node)) { - return updateImportTypeNode( + return factory.updateImportTypeNode( node, - updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), + factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), node.qualifier, visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, isTypeNode), node.isTypeOf @@ -6042,7 +6050,7 @@ namespace ts { getCommonSourceDirectory: () => context.tracker.moduleResolverHost!.getCommonSourceDirectory() }; const newName = getResolvedExternalModuleName(resolverHost, targetFile); - return createLiteral(newName); + return factory.createStringLiteral(newName); } } } @@ -6058,7 +6066,7 @@ namespace ts { } } - function serializeSignatures(kind: SignatureKind, input: Type, baseType: Type | undefined, outputKind: SyntaxKind) { + function serializeSignatures(kind: SignatureKind, input: Type, baseType: Type | undefined, outputKind: SignatureDeclaration["kind"]) { const signatures = getSignaturesOfType(input, kind); if (kind === SignatureKind.Construct) { if (!baseType && every(signatures, s => length(s.parameters) === 0)) { @@ -6119,11 +6127,11 @@ namespace ts { return ref; } const tempName = getUnusedName(`${rootName}_base`); - const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([ - createVariableDeclaration(tempName, typeToTypeNodeHelper(staticType, context)) + const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(tempName, /*exclamationToken*/ undefined, typeToTypeNodeHelper(staticType, context)) ], NodeFlags.Const)); addResult(statement, ModifierFlags.None); - return createExpressionWithTypeArguments(/*typeArgs*/ undefined, createIdentifier(tempName)); + return factory.createExpressionWithTypeArguments(factory.createIdentifier(tempName), /*typeArgs*/ undefined); } function trySerializeAsTypeReference(t: Type) { @@ -6139,7 +6147,7 @@ namespace ts { reference = symbolToExpression(t.symbol, context, SymbolFlags.Type); } if (reference) { - return createExpressionWithTypeArguments(typeArgs, reference); + return factory.createExpressionWithTypeArguments(reference, typeArgs); } } @@ -6199,9 +6207,9 @@ namespace ts { return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker); function typePredicateToStringWorker(writer: EmitTextWriter) { - const predicate = createTypePredicateNodeWithModifier( - typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? createToken(SyntaxKind.AssertsKeyword) : undefined, - typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? createIdentifier(typePredicate.parameterName) : createThisTypeNode(), + const predicate = factory.createTypePredicateNode( + typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createToken(SyntaxKind.AssertsKeyword) : undefined, + typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217 ); const printer = createPrinter({ removeComments: true }); @@ -8235,7 +8243,6 @@ namespace ts { case SyntaxKind.ObjectKeyword: case SyntaxKind.VoidKeyword: case SyntaxKind.UndefinedKeyword: - case SyntaxKind.NullKeyword: case SyntaxKind.NeverKeyword: case SyntaxKind.LiteralType: return true; @@ -12690,6 +12697,9 @@ namespace ts { } function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { + if (node.literal.kind === SyntaxKind.NullKeyword) { + return nullType; + } const links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal)); @@ -12771,14 +12781,16 @@ namespace ts { return voidType; case SyntaxKind.UndefinedKeyword: return undefinedType; - case SyntaxKind.NullKeyword: + case SyntaxKind.NullKeyword as TypeNodeSyntaxKind: + // TODO(rbuckton): `NullKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service. return nullType; case SyntaxKind.NeverKeyword: return neverType; case SyntaxKind.ObjectKeyword: return node.flags & NodeFlags.JavaScriptFile ? anyType : nonPrimitiveType; case SyntaxKind.ThisType: - case SyntaxKind.ThisKeyword: + case SyntaxKind.ThisKeyword as TypeNodeSyntaxKind: + // TODO(rbuckton): `ThisKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service and because of `isPartOfTypeNode`. return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode); case SyntaxKind.LiteralType: return getTypeFromLiteralTypeNode(node); @@ -12831,9 +12843,10 @@ namespace ts { case SyntaxKind.ImportType: return getTypeFromImportTypeNode(node); // This function assumes that an identifier or qualified name is a type expression - // Callers should first ensure this by calling isTypeNode - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: + // Callers should first ensure this by calling `isPartOfTypeNode` + // TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s. + case SyntaxKind.Identifier as TypeNodeSyntaxKind: + case SyntaxKind.QualifiedName as TypeNodeSyntaxKind: const symbol = getSymbolAtLocation(node); return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; default: @@ -22275,7 +22288,7 @@ namespace ts { childrenTypes[0] : (getArrayLiteralTupleTypeIfApplicable(childrenTypes, childrenContextualType, /*hasRestElement*/ false) || createArrayType(getUnionType(childrenTypes))); // Fake up a property declaration for the children - childrenPropSymbol.valueDeclaration = createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined); + childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); childrenPropSymbol.valueDeclaration.parent = attributes; childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol; const childPropMap = createSymbolTable(); @@ -24077,14 +24090,14 @@ namespace ts { } if (hasRestParameter || hasSpreadArgument) { - spanArray = createNodeArray(args); + spanArray = factory.createNodeArray(args); if (hasSpreadArgument && argCount) { const nextArg = elementAt(args, getSpreadArgumentIndex(args) + 1) || undefined; - spanArray = createNodeArray(args.slice(max > argCount && nextArg ? args.indexOf(nextArg) : Math.min(max, args.length - 1))); + spanArray = factory.createNodeArray(args.slice(max > argCount && nextArg ? args.indexOf(nextArg) : Math.min(max, args.length - 1))); } } else { - spanArray = createNodeArray(args.slice(max)); + spanArray = factory.createNodeArray(args.slice(max)); } spanArray.pos = first(spanArray).pos; @@ -24993,9 +25006,9 @@ namespace ts { // file would probably be preferable. const typeSymbol = exports && getSymbol(exports, JsxNames.Element, SymbolFlags.Type); const returnNode = typeSymbol && nodeBuilder.symbolToEntityName(typeSymbol, SymbolFlags.Type, node); - const declaration = createFunctionTypeNode(/*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotdotdot*/ undefined, "props", /*questionMark*/ undefined, nodeBuilder.typeToTypeNode(result, node))], - returnNode ? createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : createKeywordTypeNode(SyntaxKind.AnyKeyword) + const declaration = factory.createFunctionTypeNode(/*typeParameters*/ undefined, + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotdotdot*/ undefined, "props", /*questionMark*/ undefined, nodeBuilder.typeToTypeNode(result, node))], + returnNode ? factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ); const parameterSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "props" as __String); parameterSymbol.type = result; @@ -29227,7 +29240,7 @@ namespace ts { if (typeNode.kind === SyntaxKind.NeverKeyword) { continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } const individualEntityName = getEntityNameForDecoratorMetadata(typeNode); @@ -31949,7 +31962,7 @@ namespace ts { } function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) { - const reference = createPropertyAccess(createThis(), propName); + const reference = factory.createPropertyAccess(factory.createThis(), propName); reference.expression.parent = reference; reference.parent = constructor; reference.flowNode = constructor.returnFlowNode; @@ -34232,7 +34245,7 @@ namespace ts { function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { - return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } // Get type of the symbol if this is the valid symbol otherwise get type at location const symbol = getSymbolOfNode(declaration); @@ -34252,7 +34265,7 @@ namespace ts { function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike); if (!signatureDeclaration) { - return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const signature = getSignatureFromDeclaration(signatureDeclaration); return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); @@ -34261,7 +34274,7 @@ namespace ts { function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { const expr = getParseTreeNode(exprIn, isExpression); if (!expr) { - return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const type = getWidenedType(getRegularTypeOfExpression(expr)); return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); @@ -34313,8 +34326,12 @@ namespace ts { function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression { const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) - : type === trueType ? createTrue() : type === falseType && createFalse(); - return enumResult || createLiteral((type as LiteralType).value); + : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse(); + if (enumResult) return enumResult; + const literalValue = (type as LiteralType).value; + return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) : + typeof literalValue === "number" ? factory.createNumericLiteral(literalValue) : + factory.createStringLiteral(literalValue); } function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) { @@ -34346,19 +34363,19 @@ namespace ts { getReferencedImportDeclaration, getReferencedDeclarationWithCollidingName, isDeclarationWithCollidingName, - isValueAliasDeclaration: node => { - node = getParseTreeNode(node); + isValueAliasDeclaration: nodeIn => { + const node = getParseTreeNode(nodeIn); // Synthesized nodes are always treated like values. return node ? isValueAliasDeclaration(node) : true; }, hasGlobalName, - isReferencedAliasDeclaration: (node, checkChildren?) => { - node = getParseTreeNode(node); + isReferencedAliasDeclaration: (nodeIn, checkChildren?) => { + const node = getParseTreeNode(nodeIn); // Synthesized nodes are always treated as referenced. return node ? isReferencedAliasDeclaration(node, checkChildren) : true; }, - getNodeCheckFlags: node => { - node = getParseTreeNode(node); + getNodeCheckFlags: nodeIn => { + const node = getParseTreeNode(nodeIn); return node ? getNodeCheckFlags(node) : 0; }, isTopLevelValueImportEqualsWithEntityName, diff --git a/src/compiler/core.ts b/src/compiler/core.ts index d03b7e1c85c7b..c8d561f190872 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -56,6 +56,7 @@ namespace ts { /** Array that is only intended to be pushed to, never read. */ export interface Push { push(...values: T[]): void; + /* @internal*/ readonly length: number; } /* @internal */ @@ -70,6 +71,9 @@ namespace ts { EqualTo = 0, GreaterThan = 1 } + + /* @internal */ + export type MatchingKeys = K extends (TRecord[K] extends TMatch ? K : never) ? K : never; } /* @internal */ diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 9adc40950548c..9757136e08523 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -1,11 +1,72 @@ /* @internal */ namespace ts { + export enum LogLevel { + Off, + Error, + Warning, + Info, + Verbose + } + + export interface LoggingHost { + log(level: LogLevel, s: string): void; + } + + export interface DeprecationOptions { + message?: string; + error?: boolean; + since?: Version | string; + warnAfter?: Version | string; + errorAfter?: Version | string; + typeScriptVersion?: Version | string; + } + export namespace Debug { + let typeScriptVersion: Version | undefined; + /* eslint-disable prefer-const */ export let currentAssertionLevel = AssertionLevel.None; + export let currentLogLevel = LogLevel.Warning; export let isDebugging = false; + export let loggingHost: LoggingHost | undefined; /* eslint-enable prefer-const */ + export function getTypeScriptVersion() { + return typeScriptVersion ?? (typeScriptVersion = new Version(version)); + } + + export function shouldLog(level: LogLevel): boolean { + return currentLogLevel <= level; + } + + function logMessage(level: LogLevel, s: string): void { + if (loggingHost && shouldLog(level)) { + loggingHost.log(level, s); + } + } + + export function log(s: string): void { + logMessage(LogLevel.Info, s); + } + + export namespace log { + export function error(s: string): void { + logMessage(LogLevel.Error, s); + } + + export function warn(s: string): void { + logMessage(LogLevel.Warning, s); + } + + export function log(s: string): void { + logMessage(LogLevel.Info, s); + } + + export function trace(s: string): void { + logMessage(LogLevel.Verbose, s); + } + } + export function shouldAssert(level: AssertionLevel): boolean { return currentAssertionLevel >= level; } @@ -295,7 +356,7 @@ namespace ts { if (nodeIsSynthesized(this)) return ""; const parseNode = getParseTreeNode(this); const sourceFile = parseNode && getSourceFileOfNode(parseNode); - return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; + return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode!, includeTrivia) : ""; } } }); @@ -320,5 +381,92 @@ namespace ts { isDebugInfoEnabled = true; } + function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { + let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: "; + deprecationMessage += `'${name}' `; + deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated"; + deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : "."; + deprecationMessage += message ? ` ${formatStringFromArgs(message, [name], 0)}` : ""; + return deprecationMessage; + } + + function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { + const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message); + return () => { + throw new TypeError(deprecationMessage); + }; + } + + function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { + let hasWrittenDeprecation = false; + return () => { + if (!hasWrittenDeprecation) { + log.warn(formatDeprecationMessage(name, /*error*/ false, errorAfter, since, message)); + hasWrittenDeprecation = true; + } + }; + } + + function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never; + function createDeprecation(name: string, options?: DeprecationOptions): () => void; + function createDeprecation(name: string, options: DeprecationOptions = {}) { + const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion(); + const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter; + const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter; + const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter; + const error = options.error || errorAfter && version.compareTo(errorAfter) <= 0; + const warn = !warnAfter || version.compareTo(warnAfter) >= 0; + return error ? createErrorDeprecation(name, errorAfter, since, options.message) : + warn ? createWarningDeprecation(name, errorAfter, since, options.message) : + noop; + } + + function wrapFunction any>(deprecation: () => void, func: F): F { + return function (this: unknown) { + deprecation(); + return func.apply(this, arguments); + } as F; + } + + function wrapAccessor(deprecation: () => void, desc: PropertyDescriptor) { + if (desc.configurable) { + const newDesc: PropertyDescriptor = { ...desc, enumerable: false }; + if (desc.get) newDesc.get = wrapFunction(deprecation, desc.get); + if (desc.set) newDesc.set = wrapFunction(deprecation, desc.set); + return newDesc; + } + } + + function wrapValue(deprecation: () => void, desc: PropertyDescriptor) { + if (typeof desc.value === "function" && (desc.configurable || desc.writable)) { + const newDesc: PropertyDescriptor = { ...desc }; + if (desc.configurable) { + desc.enumerable = false; + } + newDesc.value = wrapFunction(deprecation, newDesc.value); + return newDesc; + } + } + + export function deprecateExport any>, string>>(ns: T, key: K, options?: DeprecationOptions) { + const desc = Object.getOwnPropertyDescriptor(ns, key); + if (!desc) return; + const deprecation = createDeprecation(key, options); + const newDesc = desc.get || desc.set ? wrapAccessor(deprecation, desc) : wrapValue(deprecation, desc); + if (newDesc) { + Object.defineProperty(ns, key, newDesc); + } + } + + export function deprecateExports any>, string>>(object: T, keys: readonly K[], options?: DeprecationOptions) { + for (const key of keys) { + deprecateExport(object, key, options); + } + } + + export function deprecateFunction any>(func: F, options?: DeprecationOptions): F { + const deprecation = createDeprecation(getFunctionName(func), options); + return wrapFunction(deprecation, func); + } } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cbff1fb2512f7..7bdac0a20212a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -28,7 +28,7 @@ namespace ts { if (options.outFile || options.out) { const prepends = host.getPrependNodes(); if (sourceFiles.length || prepends.length) { - const bundle = createBundle(sourceFiles, prepends); + const bundle = factory.createBundle(sourceFiles, prepends); const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle); if (result) { return result; @@ -354,7 +354,7 @@ namespace ts { return; } // Transform the source files - const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); const printerOptions: PrinterOptions = { removeComments: compilerOptions.removeComments, @@ -400,13 +400,13 @@ namespace ts { } const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; // Setup and perform the transformation to retrieve declarations from the input files - const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(sourceFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : sourceFiles; + const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [factory.createBundle(sourceFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : sourceFiles; if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) { // Checker wont collect the linked aliases since thats only done when declaration is enabled. // Do that here when emitting only dts files sourceFiles.forEach(collectLinkedAliases); } - const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); + const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics!) { emitterDiagnostics.add(diagnostic); @@ -682,7 +682,7 @@ namespace ts { !host.useCaseSensitiveFileNames() ); sourceFile.text = ""; - sourceFile.statements = createNodeArray(); + sourceFile.statements = factory.createNodeArray(); return sourceFile; }); const jsBundle = Debug.assertDefined(bundle.js); @@ -690,7 +690,7 @@ namespace ts { const sourceFile = sourceFiles[prologueInfo.file]; sourceFile.text = prologueInfo.text; sourceFile.end = prologueInfo.text.length; - sourceFile.statements = createNodeArray(prologueInfo.directives.map(directive => { + sourceFile.statements = factory.createNodeArray(prologueInfo.directives.map(directive => { const statement = createNode(SyntaxKind.ExpressionStatement, directive.pos, directive.end) as PrologueDirective; statement.expression = createNode(SyntaxKind.StringLiteral, directive.expression.pos, directive.expression.end) as StringLiteral; statement.expression.text = directive.expression.text; @@ -3423,15 +3423,15 @@ namespace ts { } function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) { - emitList(lit, createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment); + emitList(lit, factory.createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment); } function emitJSDocSignature(sig: JSDocSignature) { if (sig.typeParameters) { - emitList(sig, createNodeArray(sig.typeParameters), ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.typeParameters), ListFormat.JSDocComment); } if (sig.parameters) { - emitList(sig, createNodeArray(sig.parameters), ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.parameters), ListFormat.JSDocComment); } if (sig.type) { writeLine(); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts deleted file mode 100644 index d54244c083260..0000000000000 --- a/src/compiler/factory.ts +++ /dev/null @@ -1,5551 +0,0 @@ -namespace ts { - function createSynthesizedNode(kind: SyntaxKind): Node { - const node = createNode(kind, -1, -1); - node.flags |= NodeFlags.Synthesized; - return node; - } - - /* @internal */ - export function updateNode(updated: T, original: T): T { - if (updated !== original) { - setOriginalNode(updated, original); - setTextRange(updated, original); - aggregateTransformFlags(updated); - } - return updated; - } - - /* @internal */ export function createNodeArray(elements?: T[], hasTrailingComma?: boolean): MutableNodeArray; - export function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; - /** - * Make `elements` into a `NodeArray`. If `elements` is `undefined`, returns an empty `NodeArray`. - */ - export function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray { - if (!elements || elements === emptyArray) { - elements = []; - } - else if (isNodeArray(elements)) { - return elements; - } - - const array = >elements; - array.pos = -1; - array.end = -1; - array.hasTrailingComma = hasTrailingComma; - return array; - } - - /** - * Creates a shallow, memberwise clone of a node with no source map location. - */ - /* @internal */ - export function getSynthesizedClone(node: T): T { - // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of - // the original node. We also need to exclude specific properties and only include own- - // properties (to skip members already defined on the shared prototype). - - if (node === undefined) { - return node; - } - - const clone = createSynthesizedNode(node.kind); - clone.flags |= node.flags; - setOriginalNode(clone, node); - - for (const key in node) { - if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { - continue; - } - - (clone)[key] = (node)[key]; - } - - return clone; - } - - // Literals - - /* @internal */ export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote: boolean): StringLiteral; // eslint-disable-line @typescript-eslint/unified-signatures - /* @internal */ export function createLiteral(value: string | number, isSingleQuote: boolean): StringLiteral | NumericLiteral; - /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ - export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; - export function createLiteral(value: number | PseudoBigInt): NumericLiteral; - export function createLiteral(value: boolean): BooleanLiteral; - export function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; - export function createLiteral(value: string | number | PseudoBigInt | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote?: boolean): PrimaryExpression { - if (typeof value === "number") { - return createNumericLiteral(value + ""); - } - // eslint-disable-next-line no-in-operator - if (typeof value === "object" && "base10Value" in value) { // PseudoBigInt - return createBigIntLiteral(pseudoBigIntToString(value) + "n"); - } - if (typeof value === "boolean") { - return value ? createTrue() : createFalse(); - } - if (isString(value)) { - const res = createStringLiteral(value); - if (isSingleQuote) res.singleQuote = true; - return res; - } - return createLiteralFromNode(value); - } - - export function createNumericLiteral(value: string, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { - const node = createSynthesizedNode(SyntaxKind.NumericLiteral); - node.text = value; - node.numericLiteralFlags = numericLiteralFlags; - return node; - } - - export function createBigIntLiteral(value: string): BigIntLiteral { - const node = createSynthesizedNode(SyntaxKind.BigIntLiteral); - node.text = value; - return node; - } - - export function createStringLiteral(text: string): StringLiteral { - const node = createSynthesizedNode(SyntaxKind.StringLiteral); - node.text = text; - return node; - } - - export function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { - const node = createSynthesizedNode(SyntaxKind.RegularExpressionLiteral); - node.text = text; - return node; - } - - function createLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { - const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); - node.textSourceNode = sourceNode; - return node; - } - - - // Identifiers - - export function createIdentifier(text: string): Identifier; - /* @internal */ - export function createIdentifier(text: string, typeArguments: readonly (TypeNode | TypeParameterDeclaration)[] | undefined): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures - export function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[]): Identifier { - const node = createSynthesizedNode(SyntaxKind.Identifier); - node.escapedText = escapeLeadingUnderscores(text); - node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; - node.autoGenerateFlags = GeneratedIdentifierFlags.None; - node.autoGenerateId = 0; - if (typeArguments) { - node.typeArguments = createNodeArray(typeArguments as readonly TypeNode[]); - } - return node; - } - - export function updateIdentifier(node: Identifier): Identifier; - /* @internal */ - export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures - export function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { - return node.typeArguments !== typeArguments - ? updateNode(createIdentifier(idText(node), typeArguments), node) - : node; - } - - let nextAutoGenerateId = 0; - - /** Create a unique temporary variable. */ - export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; - /* @internal */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes: boolean): GeneratedIdentifier; - export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { - const name = createIdentifier("") as GeneratedIdentifier; - name.autoGenerateFlags = GeneratedIdentifierFlags.Auto; - name.autoGenerateId = nextAutoGenerateId; - nextAutoGenerateId++; - if (recordTempVariable) { - recordTempVariable(name); - } - if (reservedInNestedScopes) { - name.autoGenerateFlags |= GeneratedIdentifierFlags.ReservedInNestedScopes; - } - return name; - } - - /** Create a unique temporary variable for use in a loop. */ - export function createLoopVariable(): Identifier { - const name = createIdentifier(""); - name.autoGenerateFlags = GeneratedIdentifierFlags.Loop; - name.autoGenerateId = nextAutoGenerateId; - nextAutoGenerateId++; - return name; - } - - /** Create a unique name based on the supplied text. */ - export function createUniqueName(text: string): Identifier { - const name = createIdentifier(text); - name.autoGenerateFlags = GeneratedIdentifierFlags.Unique; - name.autoGenerateId = nextAutoGenerateId; - nextAutoGenerateId++; - return name; - } - - /* @internal */ export function createOptimisticUniqueName(text: string): GeneratedIdentifier; - /** Create a unique name based on the supplied text. */ - export function createOptimisticUniqueName(text: string): Identifier; - export function createOptimisticUniqueName(text: string): GeneratedIdentifier { - const name = createIdentifier(text) as GeneratedIdentifier; - name.autoGenerateFlags = GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic; - name.autoGenerateId = nextAutoGenerateId; - nextAutoGenerateId++; - return name; - } - - /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ - export function createFileLevelUniqueName(text: string): Identifier { - const name = createOptimisticUniqueName(text); - name.autoGenerateFlags |= GeneratedIdentifierFlags.FileLevel; - return name; - } - - /** Create a unique name generated for a node. */ - export function getGeneratedNameForNode(node: Node | undefined): Identifier; - /* @internal */ export function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures - export function getGeneratedNameForNode(node: Node | undefined, flags?: GeneratedIdentifierFlags): Identifier { - const name = createIdentifier(node && isIdentifier(node) ? idText(node) : ""); - name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags!; - name.autoGenerateId = nextAutoGenerateId; - name.original = node; - nextAutoGenerateId++; - return name; - } - - // Punctuation - - export function createToken(token: TKind) { - return >createSynthesizedNode(token); - } - - // Reserved words - - export function createSuper() { - return createSynthesizedNode(SyntaxKind.SuperKeyword); - } - - export function createThis() { - return >createSynthesizedNode(SyntaxKind.ThisKeyword); - } - - export function createNull() { - return >createSynthesizedNode(SyntaxKind.NullKeyword); - } - - export function createTrue() { - return >createSynthesizedNode(SyntaxKind.TrueKeyword); - } - - export function createFalse() { - return >createSynthesizedNode(SyntaxKind.FalseKeyword); - } - - // Modifiers - - export function createModifier(kind: T): Token { - return createToken(kind); - } - - export function createModifiersFromModifierFlags(flags: ModifierFlags) { - const result: Modifier[] = []; - if (flags & ModifierFlags.Export) { result.push(createModifier(SyntaxKind.ExportKeyword)); } - if (flags & ModifierFlags.Ambient) { result.push(createModifier(SyntaxKind.DeclareKeyword)); } - if (flags & ModifierFlags.Default) { result.push(createModifier(SyntaxKind.DefaultKeyword)); } - if (flags & ModifierFlags.Const) { result.push(createModifier(SyntaxKind.ConstKeyword)); } - if (flags & ModifierFlags.Public) { result.push(createModifier(SyntaxKind.PublicKeyword)); } - if (flags & ModifierFlags.Private) { result.push(createModifier(SyntaxKind.PrivateKeyword)); } - if (flags & ModifierFlags.Protected) { result.push(createModifier(SyntaxKind.ProtectedKeyword)); } - if (flags & ModifierFlags.Abstract) { result.push(createModifier(SyntaxKind.AbstractKeyword)); } - if (flags & ModifierFlags.Static) { result.push(createModifier(SyntaxKind.StaticKeyword)); } - if (flags & ModifierFlags.Readonly) { result.push(createModifier(SyntaxKind.ReadonlyKeyword)); } - if (flags & ModifierFlags.Async) { result.push(createModifier(SyntaxKind.AsyncKeyword)); } - return result; - } - - // Names - - export function createQualifiedName(left: EntityName, right: string | Identifier) { - const node = createSynthesizedNode(SyntaxKind.QualifiedName); - node.left = left; - node.right = asName(right); - return node; - } - - export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { - return node.left !== left - || node.right !== right - ? updateNode(createQualifiedName(left, right), node) - : node; - } - - function parenthesizeForComputedName(expression: Expression): Expression { - return isCommaSequence(expression) - ? createParen(expression) - : expression; - } - - export function createComputedPropertyName(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ComputedPropertyName); - node.expression = parenthesizeForComputedName(expression); - return node; - } - - export function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { - return node.expression !== expression - ? updateNode(createComputedPropertyName(expression), node) - : node; - } - - // Signature elements - - export function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration; - node.name = asName(name); - node.constraint = constraint; - node.default = defaultType; - return node; - } - - export function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) { - return node.name !== name - || node.constraint !== constraint - || node.default !== defaultType - ? updateNode(createTypeParameterDeclaration(name, constraint, defaultType), node) - : node; - } - - export function createParameter( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - dotDotDotToken: DotDotDotToken | undefined, - name: string | BindingName, - questionToken?: QuestionToken, - type?: TypeNode, - initializer?: Expression) { - const node = createSynthesizedNode(SyntaxKind.Parameter); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.dotDotDotToken = dotDotDotToken; - node.name = asName(name); - node.questionToken = questionToken; - node.type = type; - node.initializer = initializer ? parenthesizeExpressionForList(initializer) : undefined; - return node; - } - - export function updateParameter( - node: ParameterDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - dotDotDotToken: DotDotDotToken | undefined, - name: string | BindingName, - questionToken: QuestionToken | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.dotDotDotToken !== dotDotDotToken - || node.name !== name - || node.questionToken !== questionToken - || node.type !== type - || node.initializer !== initializer - ? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node) - : node; - } - - export function createDecorator(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.Decorator); - node.expression = parenthesizeForAccess(expression); - return node; - } - - export function updateDecorator(node: Decorator, expression: Expression) { - return node.expression !== expression - ? updateNode(createDecorator(expression), node) - : node; - } - - - // Type Elements - - export function createPropertySignature( - modifiers: readonly Modifier[] | undefined, - name: PropertyName | string, - questionToken: QuestionToken | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined): PropertySignature { - const node = createSynthesizedNode(SyntaxKind.PropertySignature) as PropertySignature; - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.questionToken = questionToken; - node.type = type; - node.initializer = initializer; - return node; - } - - export function updatePropertySignature( - node: PropertySignature, - modifiers: readonly Modifier[] | undefined, - name: PropertyName, - questionToken: QuestionToken | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined) { - return node.modifiers !== modifiers - || node.name !== name - || node.questionToken !== questionToken - || node.type !== type - || node.initializer !== initializer - ? updateNode(createPropertySignature(modifiers, name, questionToken, type, initializer), node) - : node; - } - - export function createProperty( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | PropertyName, - questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined) { - const node = createSynthesizedNode(SyntaxKind.PropertyDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined; - node.type = type; - node.initializer = initializer; - return node; - } - - export function updateProperty( - node: PropertyDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | PropertyName, - questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined) - || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined) - || node.type !== type - || node.initializer !== initializer - ? updateNode(createProperty(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) - : node; - } - - export function createMethodSignature( - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - name: string | PropertyName, - questionToken: QuestionToken | undefined) { - const node = createSignatureDeclaration(SyntaxKind.MethodSignature, typeParameters, parameters, type) as MethodSignature; - node.name = asName(name); - node.questionToken = questionToken; - return node; - } - - export function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined) { - return node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.name !== name - || node.questionToken !== questionToken - ? updateNode(createMethodSignature(typeParameters, parameters, type, name, questionToken), node) - : node; - } - - export function createMethod( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: string | PropertyName, - questionToken: QuestionToken | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.MethodDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.asteriskToken = asteriskToken; - node.name = asName(name); - node.questionToken = questionToken; - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.body = body; - return node; - } - - function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { - return createCall( - createPropertyAccess(object, asName(methodName)), - /*typeArguments*/ undefined, - argumentsList - ); - } - - function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) { - return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList); - } - - /* @internal */ - export function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) { - return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]); - } - - function tryAddPropertyAssignment(properties: Push, propertyName: string, expression: Expression | undefined) { - if (expression) { - properties.push(createPropertyAssignment(propertyName, expression)); - return true; - } - return false; - } - - /* @internal */ - export function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) { - const properties: PropertyAssignment[] = []; - tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable)); - tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable)); - - let isData = tryAddPropertyAssignment(properties, "writable", asExpression(attributes.writable)); - isData = tryAddPropertyAssignment(properties, "value", attributes.value) || isData; - - let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get); - isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor; - - Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); - return createObjectLiteral(properties, !singleLine); - } - - export function updateMethod( - node: MethodDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: PropertyName, - questionToken: QuestionToken | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.asteriskToken !== asteriskToken - || node.name !== name - || node.questionToken !== questionToken - || node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.body !== body - ? updateNode(createMethod(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) - : node; - } - - export function createConstructor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.Constructor); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.typeParameters = undefined; - node.parameters = createNodeArray(parameters); - node.type = undefined; - node.body = body; - return node; - } - - export function updateConstructor( - node: ConstructorDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - parameters: readonly ParameterDeclaration[], - body: Block | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.parameters !== parameters - || node.body !== body - ? updateNode(createConstructor(decorators, modifiers, parameters, body), node) - : node; - } - - export function createGetAccessor( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | PropertyName, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.GetAccessor); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = undefined; - node.parameters = createNodeArray(parameters); - node.type = type; - node.body = body; - return node; - } - - export function updateGetAccessor( - node: GetAccessorDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: PropertyName, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.parameters !== parameters - || node.type !== type - || node.body !== body - ? updateNode(createGetAccessor(decorators, modifiers, name, parameters, type, body), node) - : node; - } - - export function createSetAccessor( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | PropertyName, - parameters: readonly ParameterDeclaration[], - body: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.SetAccessor); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = undefined; - node.parameters = createNodeArray(parameters); - node.body = body; - return node; - } - - export function updateSetAccessor( - node: SetAccessorDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: PropertyName, - parameters: readonly ParameterDeclaration[], - body: Block | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.parameters !== parameters - || node.body !== body - ? updateNode(createSetAccessor(decorators, modifiers, name, parameters, body), node) - : node; - } - - export function createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) { - return createSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type) as CallSignatureDeclaration; - } - - export function updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) { - return createSignatureDeclaration(SyntaxKind.ConstructSignature, typeParameters, parameters, type) as ConstructSignatureDeclaration; - } - - export function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createIndexSignature( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode): IndexSignatureDeclaration { - const node = createSynthesizedNode(SyntaxKind.IndexSignature) as IndexSignatureDeclaration; - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.parameters = createNodeArray(parameters); - node.type = type; - return node; - } - - export function updateIndexSignature( - node: IndexSignatureDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode) { - return node.parameters !== parameters - || node.type !== type - || node.decorators !== decorators - || node.modifiers !== modifiers - ? updateNode(createIndexSignature(decorators, modifiers, parameters, type), node) - : node; - } - - /* @internal */ - export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, typeArguments?: readonly TypeNode[] | undefined) { - const node = createSynthesizedNode(kind) as SignatureDeclaration; - node.typeParameters = asNodeArray(typeParameters); - node.parameters = asNodeArray(parameters); - node.type = type; - node.typeArguments = asNodeArray(typeArguments); - return node; - } - - function updateSignatureDeclaration(node: T, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): T { - return node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - ? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node) - : node; - } - - // Types - - export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]) { - return createSynthesizedNode(kind); - } - - export function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode) { - return createTypePredicateNodeWithModifier(/*assertsModifier*/ undefined, parameterName, type); - } - - export function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) { - const node = createSynthesizedNode(SyntaxKind.TypePredicate) as TypePredicateNode; - node.assertsModifier = assertsModifier; - node.parameterName = asName(parameterName); - node.type = type; - return node; - } - - export function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) { - return updateTypePredicateNodeWithModifier(node, node.assertsModifier, parameterName, type); - } - - export function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) { - return node.assertsModifier !== assertsModifier - || node.parameterName !== parameterName - || node.type !== type - ? updateNode(createTypePredicateNodeWithModifier(assertsModifier, parameterName, type), node) - : node; - } - - export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { - const node = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode; - node.typeName = asName(typeName); - node.typeArguments = typeArguments && parenthesizeTypeParameters(typeArguments); - return node; - } - - export function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { - return node.typeName !== typeName - || node.typeArguments !== typeArguments - ? updateNode(createTypeReferenceNode(typeName, typeArguments), node) - : node; - } - - export function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) { - return createSignatureDeclaration(SyntaxKind.FunctionType, typeParameters, parameters, type) as FunctionTypeNode; - } - - export function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) { - return createSignatureDeclaration(SyntaxKind.ConstructorType, typeParameters, parameters, type) as ConstructorTypeNode; - } - - export function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createTypeQueryNode(exprName: EntityName) { - const node = createSynthesizedNode(SyntaxKind.TypeQuery) as TypeQueryNode; - node.exprName = exprName; - return node; - } - - export function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { - return node.exprName !== exprName - ? updateNode(createTypeQueryNode(exprName), node) - : node; - } - - export function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { - const node = createSynthesizedNode(SyntaxKind.TypeLiteral) as TypeLiteralNode; - node.members = createNodeArray(members); - return node; - } - - export function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray) { - return node.members !== members - ? updateNode(createTypeLiteralNode(members), node) - : node; - } - - export function createArrayTypeNode(elementType: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.ArrayType) as ArrayTypeNode; - node.elementType = parenthesizeArrayTypeMember(elementType); - return node; - } - - export function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { - return node.elementType !== elementType - ? updateNode(createArrayTypeNode(elementType), node) - : node; - } - - export function createTupleTypeNode(elementTypes: readonly TypeNode[]) { - const node = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode; - node.elementTypes = createNodeArray(elementTypes); - return node; - } - - export function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]) { - return node.elementTypes !== elementTypes - ? updateNode(createTupleTypeNode(elementTypes), node) - : node; - } - - export function createOptionalTypeNode(type: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.OptionalType) as OptionalTypeNode; - node.type = parenthesizeArrayTypeMember(type); - return node; - } - - export function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode { - return node.type !== type - ? updateNode(createOptionalTypeNode(type), node) - : node; - } - - export function createRestTypeNode(type: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.RestType) as RestTypeNode; - node.type = type; - return node; - } - - export function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode { - return node.type !== type - ? updateNode(createRestTypeNode(type), node) - : node; - } - - export function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types); - } - - export function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types); - } - - export function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types); - } - - export function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types); - } - - export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) { - const node = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode; - node.types = parenthesizeElementTypeMembers(types); - return node; - } - - function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray): T { - return node.types !== types - ? updateNode(createUnionOrIntersectionTypeNode(node.kind, types), node) - : node; - } - - export function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.ConditionalType) as ConditionalTypeNode; - node.checkType = parenthesizeConditionalTypeMember(checkType); - node.extendsType = parenthesizeConditionalTypeMember(extendsType); - node.trueType = trueType; - node.falseType = falseType; - return node; - } - - export function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { - return node.checkType !== checkType - || node.extendsType !== extendsType - || node.trueType !== trueType - || node.falseType !== falseType - ? updateNode(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node) - : node; - } - - export function createInferTypeNode(typeParameter: TypeParameterDeclaration) { - const node = createSynthesizedNode(SyntaxKind.InferType); - node.typeParameter = typeParameter; - return node; - } - - export function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) { - return node.typeParameter !== typeParameter - ? updateNode(createInferTypeNode(typeParameter), node) - : node; - } - - export function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean) { - const node = createSynthesizedNode(SyntaxKind.ImportType); - node.argument = argument; - node.qualifier = qualifier; - node.typeArguments = parenthesizeTypeParameters(typeArguments); - node.isTypeOf = isTypeOf; - return node; - } - - export function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean) { - return node.argument !== argument - || node.qualifier !== qualifier - || node.typeArguments !== typeArguments - || node.isTypeOf !== isTypeOf - ? updateNode(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node) - : node; - } - - export function createParenthesizedType(type: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.ParenthesizedType); - node.type = type; - return node; - } - - export function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) { - return node.type !== type - ? updateNode(createParenthesizedType(type), node) - : node; - } - - export function createThisTypeNode() { - return createSynthesizedNode(SyntaxKind.ThisType); - } - - export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; - export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode; - node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword; - node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType); - return node; - } - - export function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) { - return node.type !== type ? updateNode(createTypeOperatorNode(node.operator, type), node) : node; - } - - export function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.IndexedAccessType) as IndexedAccessTypeNode; - node.objectType = parenthesizeElementTypeMember(objectType); - node.indexType = indexType; - return node; - } - - export function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { - return node.objectType !== objectType - || node.indexType !== indexType - ? updateNode(createIndexedAccessTypeNode(objectType, indexType), node) - : node; - } - - export function createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { - const node = createSynthesizedNode(SyntaxKind.MappedType) as MappedTypeNode; - node.readonlyToken = readonlyToken; - node.typeParameter = typeParameter; - node.questionToken = questionToken; - node.type = type; - return node; - } - - export function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { - return node.readonlyToken !== readonlyToken - || node.typeParameter !== typeParameter - || node.questionToken !== questionToken - || node.type !== type - ? updateNode(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node) - : node; - } - - export function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { - const node = createSynthesizedNode(SyntaxKind.LiteralType) as LiteralTypeNode; - node.literal = literal; - return node; - } - - export function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) { - return node.literal !== literal - ? updateNode(createLiteralTypeNode(literal), node) - : node; - } - - // Binding Patterns - - export function createObjectBindingPattern(elements: readonly BindingElement[]) { - const node = createSynthesizedNode(SyntaxKind.ObjectBindingPattern); - node.elements = createNodeArray(elements); - return node; - } - - export function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { - return node.elements !== elements - ? updateNode(createObjectBindingPattern(elements), node) - : node; - } - - export function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { - const node = createSynthesizedNode(SyntaxKind.ArrayBindingPattern); - node.elements = createNodeArray(elements); - return node; - } - - export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { - return node.elements !== elements - ? updateNode(createArrayBindingPattern(elements), node) - : node; - } - - export function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { - const node = createSynthesizedNode(SyntaxKind.BindingElement); - node.dotDotDotToken = dotDotDotToken; - node.propertyName = asName(propertyName); - node.name = asName(name); - node.initializer = initializer; - return node; - } - - export function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) { - return node.propertyName !== propertyName - || node.dotDotDotToken !== dotDotDotToken - || node.name !== name - || node.initializer !== initializer - ? updateNode(createBindingElement(dotDotDotToken, propertyName, name, initializer), node) - : node; - } - - // Expression - - export function createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean) { - const node = createSynthesizedNode(SyntaxKind.ArrayLiteralExpression); - node.elements = parenthesizeListElements(createNodeArray(elements)); - if (multiLine) node.multiLine = true; - return node; - } - - export function updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]) { - return node.elements !== elements - ? updateNode(createArrayLiteral(elements, node.multiLine), node) - : node; - } - - export function createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { - const node = createSynthesizedNode(SyntaxKind.ObjectLiteralExpression); - node.properties = createNodeArray(properties); - if (multiLine) node.multiLine = true; - return node; - } - - export function updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { - return node.properties !== properties - ? updateNode(createObjectLiteral(properties, node.multiLine), node) - : node; - } - - export function createPropertyAccess(expression: Expression, name: string | Identifier) { - const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); - node.expression = parenthesizeForAccess(expression); - node.name = asName(name); - setEmitFlags(node, EmitFlags.NoIndentation); - return node; - } - - export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) { - if (isOptionalChain(node)) { - return updatePropertyAccessChain(node, expression, node.questionDotToken, name); - } - // Because we are updating existed propertyAccess we want to inherit its emitFlags - // instead of using the default from createPropertyAccess - return node.expression !== expression - || node.name !== name - ? updateNode(setEmitFlags(createPropertyAccess(expression, name), getEmitFlags(node)), node) - : node; - } - - export function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier) { - const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); - node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizeForAccess(expression); - node.questionDotToken = questionDotToken; - node.name = asName(name); - setEmitFlags(node, EmitFlags.NoIndentation); - return node; - } - - export function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead."); - // Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags - // instead of using the default from createPropertyAccess - return node.expression !== expression - || node.questionDotToken !== questionDotToken - || node.name !== name - ? updateNode(setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), getEmitFlags(node)), node) - : node; - } - - export function createElementAccess(expression: Expression, index: number | Expression) { - const node = createSynthesizedNode(SyntaxKind.ElementAccessExpression); - node.expression = parenthesizeForAccess(expression); - node.argumentExpression = asExpression(index); - return node; - } - - export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { - if (isOptionalChain(node)) { - return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression); - } - return node.expression !== expression - || node.argumentExpression !== argumentExpression - ? updateNode(createElementAccess(expression, argumentExpression), node) - : node; - } - - export function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { - const node = createSynthesizedNode(SyntaxKind.ElementAccessExpression); - node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizeForAccess(expression); - node.questionDotToken = questionDotToken; - node.argumentExpression = asExpression(index); - return node; - } - - export function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update an ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead."); - return node.expression !== expression - || node.questionDotToken !== questionDotToken - || node.argumentExpression !== argumentExpression - ? updateNode(createElementAccessChain(expression, questionDotToken, argumentExpression), node) - : node; - } - - export function createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createSynthesizedNode(SyntaxKind.CallExpression); - node.expression = parenthesizeForAccess(expression); - node.typeArguments = asNodeArray(typeArguments); - node.arguments = parenthesizeListElements(createNodeArray(argumentsArray)); - return node; - } - - export function updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { - if (isOptionalChain(node)) { - return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray); - } - return node.expression !== expression - || node.typeArguments !== typeArguments - || node.arguments !== argumentsArray - ? updateNode(createCall(expression, typeArguments, argumentsArray), node) - : node; - } - - export function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createSynthesizedNode(SyntaxKind.CallExpression); - node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizeForAccess(expression); - node.questionDotToken = questionDotToken; - node.typeArguments = asNodeArray(typeArguments); - node.arguments = parenthesizeListElements(createNodeArray(argumentsArray)); - return node; - } - - export function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead."); - return node.expression !== expression - || node.questionDotToken !== questionDotToken - || node.typeArguments !== typeArguments - || node.arguments !== argumentsArray - ? updateNode(createCallChain(expression, questionDotToken, typeArguments, argumentsArray), node) - : node; - } - - export function createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createSynthesizedNode(SyntaxKind.NewExpression); - node.expression = parenthesizeForNew(expression); - node.typeArguments = asNodeArray(typeArguments); - node.arguments = argumentsArray ? parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; - return node; - } - - export function updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - return node.expression !== expression - || node.typeArguments !== typeArguments - || node.arguments !== argumentsArray - ? updateNode(createNew(expression, typeArguments, argumentsArray), node) - : node; - } - - /** @deprecated */ export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - export function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - /** @internal */ - export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: readonly TypeNode[] | TemplateLiteral | undefined, template?: TemplateLiteral): TaggedTemplateExpression; - export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: readonly TypeNode[] | TemplateLiteral | undefined, template?: TemplateLiteral) { - const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); - node.tag = parenthesizeForAccess(tag); - if (template) { - node.typeArguments = asNodeArray(typeArgumentsOrTemplate as readonly TypeNode[]); - node.template = template; - } - else { - node.typeArguments = undefined; - node.template = typeArgumentsOrTemplate as TemplateLiteral; - } - return node; - } - - /** @deprecated */ export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: readonly TypeNode[] | TemplateLiteral | undefined, template?: TemplateLiteral) { - return node.tag !== tag - || (template - ? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template - : node.typeArguments !== undefined || node.template !== typeArgumentsOrTemplate) - ? updateNode(createTaggedTemplate(tag, typeArgumentsOrTemplate, template), node) - : node; - } - - export function createTypeAssertion(type: TypeNode, expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.TypeAssertionExpression); - node.type = type; - node.expression = parenthesizePrefixOperand(expression); - return node; - } - - export function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { - return node.type !== type - || node.expression !== expression - ? updateNode(createTypeAssertion(type, expression), node) - : node; - } - - export function createParen(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ParenthesizedExpression); - node.expression = expression; - return node; - } - - export function updateParen(node: ParenthesizedExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createParen(expression), node) - : node; - } - - export function createFunctionExpression( - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[] | undefined, - type: TypeNode | undefined, - body: Block) { - const node = createSynthesizedNode(SyntaxKind.FunctionExpression); - node.modifiers = asNodeArray(modifiers); - node.asteriskToken = asteriskToken; - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.body = body; - return node; - } - - export function updateFunctionExpression( - node: FunctionExpression, - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block) { - return node.name !== name - || node.modifiers !== modifiers - || node.asteriskToken !== asteriskToken - || node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.body !== body - ? updateNode(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : node; - } - - export function createArrowFunction( - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken | undefined, - body: ConciseBody) { - const node = createSynthesizedNode(SyntaxKind.ArrowFunction); - node.modifiers = asNodeArray(modifiers); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken); - node.body = parenthesizeConciseBody(body); - return node; - } - export function updateArrowFunction( - node: ArrowFunction, - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: Token, - body: ConciseBody - ): ArrowFunction { - return node.modifiers !== modifiers - || node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.equalsGreaterThanToken !== equalsGreaterThanToken - || node.body !== body - ? updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) - : node; - } - - export function createDelete(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.DeleteExpression); - node.expression = parenthesizePrefixOperand(expression); - return node; - } - - export function updateDelete(node: DeleteExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createDelete(expression), node) - : node; - } - - export function createTypeOf(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.TypeOfExpression); - node.expression = parenthesizePrefixOperand(expression); - return node; - } - - export function updateTypeOf(node: TypeOfExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createTypeOf(expression), node) - : node; - } - - export function createVoid(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.VoidExpression); - node.expression = parenthesizePrefixOperand(expression); - return node; - } - - export function updateVoid(node: VoidExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createVoid(expression), node) - : node; - } - - export function createAwait(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.AwaitExpression); - node.expression = parenthesizePrefixOperand(expression); - return node; - } - - export function updateAwait(node: AwaitExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createAwait(expression), node) - : node; - } - - export function createPrefix(operator: PrefixUnaryOperator, operand: Expression) { - const node = createSynthesizedNode(SyntaxKind.PrefixUnaryExpression); - node.operator = operator; - node.operand = parenthesizePrefixOperand(operand); - return node; - } - - export function updatePrefix(node: PrefixUnaryExpression, operand: Expression) { - return node.operand !== operand - ? updateNode(createPrefix(node.operator, operand), node) - : node; - } - - export function createPostfix(operand: Expression, operator: PostfixUnaryOperator) { - const node = createSynthesizedNode(SyntaxKind.PostfixUnaryExpression); - node.operand = parenthesizePostfixOperand(operand); - node.operator = operator; - return node; - } - - export function updatePostfix(node: PostfixUnaryExpression, operand: Expression) { - return node.operand !== operand - ? updateNode(createPostfix(operand, node.operator), node) - : node; - } - - export function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { - const node = createSynthesizedNode(SyntaxKind.BinaryExpression); - const operatorToken = asToken(operator); - const operatorKind = operatorToken.kind; - node.left = parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); - node.operatorToken = operatorToken; - node.right = parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); - return node; - } - - export function updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken) { - return node.left !== left - || node.right !== right - ? updateNode(createBinary(left, operator || node.operatorToken, right), node) - : node; - } - - /** @deprecated */ export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; - export function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; - export function createConditional(condition: Expression, questionTokenOrWhenTrue: QuestionToken | Expression, whenTrueOrWhenFalse: Expression, colonToken?: ColonToken, whenFalse?: Expression) { - const node = createSynthesizedNode(SyntaxKind.ConditionalExpression); - node.condition = parenthesizeForConditionalHead(condition); - node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(SyntaxKind.QuestionToken); - node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : questionTokenOrWhenTrue); - node.colonToken = whenFalse ? colonToken! : createToken(SyntaxKind.ColonToken); - node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse); - return node; - } - export function updateConditional( - node: ConditionalExpression, - condition: Expression, - questionToken: Token, - whenTrue: Expression, - colonToken: Token, - whenFalse: Expression - ): ConditionalExpression { - return node.condition !== condition - || node.questionToken !== questionToken - || node.whenTrue !== whenTrue - || node.colonToken !== colonToken - || node.whenFalse !== whenFalse - ? updateNode(createConditional(condition, questionToken, whenTrue, colonToken, whenFalse), node) - : node; - } - - export function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { - const node = createSynthesizedNode(SyntaxKind.TemplateExpression); - node.head = head; - node.templateSpans = createNodeArray(templateSpans); - return node; - } - - export function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { - return node.head !== head - || node.templateSpans !== templateSpans - ? updateNode(createTemplateExpression(head, templateSpans), node) - : node; - } - - let rawTextScanner: Scanner | undefined; - const invalidValueSentinel: object = {}; - - function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) { - if (!rawTextScanner) { - rawTextScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard); - } - switch (kind) { - case SyntaxKind.NoSubstitutionTemplateLiteral: - rawTextScanner.setText("`" + rawText + "`"); - break; - case SyntaxKind.TemplateHead: - rawTextScanner.setText("`" + rawText + "${"); - break; - case SyntaxKind.TemplateMiddle: - rawTextScanner.setText("}" + rawText + "${"); - break; - case SyntaxKind.TemplateTail: - rawTextScanner.setText("}" + rawText + "`"); - break; - } - - let token = rawTextScanner.scan(); - if (token === SyntaxKind.CloseBracketToken) { - token = rawTextScanner.reScanTemplateToken(); - } - - if (rawTextScanner.isUnterminated()) { - rawTextScanner.setText(undefined); - return invalidValueSentinel; - } - - let tokenValue: string | undefined; - switch (token) { - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - tokenValue = rawTextScanner.getTokenValue(); - break; - } - - if (rawTextScanner.scan() !== SyntaxKind.EndOfFileToken) { - rawTextScanner.setText(undefined); - return invalidValueSentinel; - } - - rawTextScanner.setText(undefined); - return tokenValue; - } - - function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined) { - const node = createSynthesizedNode(kind); - node.text = text; - if (rawText === undefined || text === rawText) { - node.rawText = rawText; - } - else { - const cooked = getCookedText(kind, rawText); - if (typeof cooked === "object") { - return Debug.fail("Invalid raw text"); - } - - Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); - node.rawText = rawText; - } - return node; - } - - export function createTemplateHead(text: string, rawText?: string) { - const node = createTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText); - node.text = text; - return node; - } - - export function createTemplateMiddle(text: string, rawText?: string) { - const node = createTemplateLiteralLikeNode(SyntaxKind.TemplateMiddle, text, rawText); - node.text = text; - return node; - } - - export function createTemplateTail(text: string, rawText?: string) { - const node = createTemplateLiteralLikeNode(SyntaxKind.TemplateTail, text, rawText); - node.text = text; - return node; - } - - export function createNoSubstitutionTemplateLiteral(text: string, rawText?: string) { - const node = createTemplateLiteralLikeNode(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText); - return node; - } - - export function createYield(expression?: Expression): YieldExpression; - export function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; - export function createYield(asteriskTokenOrExpression?: AsteriskToken | undefined | Expression, expression?: Expression) { - const node = createSynthesizedNode(SyntaxKind.YieldExpression); - node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : undefined; - node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : expression; - return node; - } - - export function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { - return node.expression !== expression - || node.asteriskToken !== asteriskToken - ? updateNode(createYield(asteriskToken, expression), node) - : node; - } - - export function createSpread(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.SpreadElement); - node.expression = parenthesizeExpressionForList(expression); - return node; - } - - export function updateSpread(node: SpreadElement, expression: Expression) { - return node.expression !== expression - ? updateNode(createSpread(expression), node) - : node; - } - - export function createClassExpression( - modifiers: readonly Modifier[] | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly ClassElement[]) { - const node = createSynthesizedNode(SyntaxKind.ClassExpression); - node.decorators = undefined; - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; - } - - export function updateClassExpression( - node: ClassExpression, - modifiers: readonly Modifier[] | undefined, - name: Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly ClassElement[]) { - return node.modifiers !== modifiers - || node.name !== name - || node.typeParameters !== typeParameters - || node.heritageClauses !== heritageClauses - || node.members !== members - ? updateNode(createClassExpression(modifiers, name, typeParameters, heritageClauses, members), node) - : node; - } - - export function createOmittedExpression() { - return createSynthesizedNode(SyntaxKind.OmittedExpression); - } - - export function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ExpressionWithTypeArguments); - node.expression = parenthesizeForAccess(expression); - node.typeArguments = asNodeArray(typeArguments); - return node; - } - - export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression) { - return node.typeArguments !== typeArguments - || node.expression !== expression - ? updateNode(createExpressionWithTypeArguments(typeArguments, expression), node) - : node; - } - - export function createAsExpression(expression: Expression, type: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.AsExpression); - node.expression = expression; - node.type = type; - return node; - } - - export function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { - return node.expression !== expression - || node.type !== type - ? updateNode(createAsExpression(expression, type), node) - : node; - } - - export function createNonNullExpression(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.NonNullExpression); - node.expression = parenthesizeForAccess(expression); - return node; - } - - export function updateNonNullExpression(node: NonNullExpression, expression: Expression) { - return node.expression !== expression - ? updateNode(createNonNullExpression(expression), node) - : node; - } - - export function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { - const node = createSynthesizedNode(SyntaxKind.MetaProperty); - node.keywordToken = keywordToken; - node.name = name; - return node; - } - - export function updateMetaProperty(node: MetaProperty, name: Identifier) { - return node.name !== name - ? updateNode(createMetaProperty(node.keywordToken, name), node) - : node; - } - - // Misc - - export function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { - const node = createSynthesizedNode(SyntaxKind.TemplateSpan); - node.expression = expression; - node.literal = literal; - return node; - } - - export function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { - return node.expression !== expression - || node.literal !== literal - ? updateNode(createTemplateSpan(expression, literal), node) - : node; - } - - export function createSemicolonClassElement() { - return createSynthesizedNode(SyntaxKind.SemicolonClassElement); - } - - // Element - - export function createBlock(statements: readonly Statement[], multiLine?: boolean): Block { - const block = createSynthesizedNode(SyntaxKind.Block); - block.statements = createNodeArray(statements); - if (multiLine) block.multiLine = multiLine; - return block; - } - - export function updateBlock(node: Block, statements: readonly Statement[]) { - return node.statements !== statements - ? updateNode(createBlock(statements, node.multiLine), node) - : node; - } - - export function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { - const node = createSynthesizedNode(SyntaxKind.VariableStatement); - node.decorators = undefined; - node.modifiers = asNodeArray(modifiers); - node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; - return node; - } - - export function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) { - return node.modifiers !== modifiers - || node.declarationList !== declarationList - ? updateNode(createVariableStatement(modifiers, declarationList), node) - : node; - } - - export function createEmptyStatement() { - return createSynthesizedNode(SyntaxKind.EmptyStatement); - } - - export function createExpressionStatement(expression: Expression): ExpressionStatement { - const node = createSynthesizedNode(SyntaxKind.ExpressionStatement); - node.expression = parenthesizeExpressionForExpressionStatement(expression); - return node; - } - - export function updateExpressionStatement(node: ExpressionStatement, expression: Expression) { - return node.expression !== expression - ? updateNode(createExpressionStatement(expression), node) - : node; - } - - /** @deprecated Use `createExpressionStatement` instead. */ - export const createStatement = createExpressionStatement; - /** @deprecated Use `updateExpressionStatement` instead. */ - export const updateStatement = updateExpressionStatement; - - export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { - const node = createSynthesizedNode(SyntaxKind.IfStatement); - node.expression = expression; - node.thenStatement = asEmbeddedStatement(thenStatement); - node.elseStatement = asEmbeddedStatement(elseStatement); - return node; - } - - export function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) { - return node.expression !== expression - || node.thenStatement !== thenStatement - || node.elseStatement !== elseStatement - ? updateNode(createIf(expression, thenStatement, elseStatement), node) - : node; - } - - export function createDo(statement: Statement, expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.DoStatement); - node.statement = asEmbeddedStatement(statement); - node.expression = expression; - return node; - } - - export function updateDo(node: DoStatement, statement: Statement, expression: Expression) { - return node.statement !== statement - || node.expression !== expression - ? updateNode(createDo(statement, expression), node) - : node; - } - - export function createWhile(expression: Expression, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.WhileStatement); - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateWhile(node: WhileStatement, expression: Expression, statement: Statement) { - return node.expression !== expression - || node.statement !== statement - ? updateNode(createWhile(expression, statement), node) - : node; - } - - export function createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.ForStatement); - node.initializer = initializer; - node.condition = condition; - node.incrementor = incrementor; - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { - return node.initializer !== initializer - || node.condition !== condition - || node.incrementor !== incrementor - || node.statement !== statement - ? updateNode(createFor(initializer, condition, incrementor, statement), node) - : node; - } - - export function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.ForInStatement); - node.initializer = initializer; - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { - return node.initializer !== initializer - || node.expression !== expression - || node.statement !== statement - ? updateNode(createForIn(initializer, expression, statement), node) - : node; - } - - export function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.ForOfStatement); - node.awaitModifier = awaitModifier; - node.initializer = initializer; - node.expression = isCommaSequence(expression) ? createParen(expression) : expression; - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { - return node.awaitModifier !== awaitModifier - || node.initializer !== initializer - || node.expression !== expression - || node.statement !== statement - ? updateNode(createForOf(awaitModifier, initializer, expression, statement), node) - : node; - } - - export function createContinue(label?: string | Identifier): ContinueStatement { - const node = createSynthesizedNode(SyntaxKind.ContinueStatement); - node.label = asName(label); - return node; - } - - export function updateContinue(node: ContinueStatement, label: Identifier | undefined) { - return node.label !== label - ? updateNode(createContinue(label), node) - : node; - } - - export function createBreak(label?: string | Identifier): BreakStatement { - const node = createSynthesizedNode(SyntaxKind.BreakStatement); - node.label = asName(label); - return node; - } - - export function updateBreak(node: BreakStatement, label: Identifier | undefined) { - return node.label !== label - ? updateNode(createBreak(label), node) - : node; - } - - export function createReturn(expression?: Expression): ReturnStatement { - const node = createSynthesizedNode(SyntaxKind.ReturnStatement); - node.expression = expression; - return node; - } - - export function updateReturn(node: ReturnStatement, expression: Expression | undefined) { - return node.expression !== expression - ? updateNode(createReturn(expression), node) - : node; - } - - export function createWith(expression: Expression, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.WithStatement); - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateWith(node: WithStatement, expression: Expression, statement: Statement) { - return node.expression !== expression - || node.statement !== statement - ? updateNode(createWith(expression, statement), node) - : node; - } - - export function createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement { - const node = createSynthesizedNode(SyntaxKind.SwitchStatement); - node.expression = parenthesizeExpressionForList(expression); - node.caseBlock = caseBlock; - return node; - } - - export function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { - return node.expression !== expression - || node.caseBlock !== caseBlock - ? updateNode(createSwitch(expression, caseBlock), node) - : node; - } - - export function createLabel(label: string | Identifier, statement: Statement) { - const node = createSynthesizedNode(SyntaxKind.LabeledStatement); - node.label = asName(label); - node.statement = asEmbeddedStatement(statement); - return node; - } - - export function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement) { - return node.label !== label - || node.statement !== statement - ? updateNode(createLabel(label, statement), node) - : node; - } - - export function createThrow(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ThrowStatement); - node.expression = expression; - return node; - } - - export function updateThrow(node: ThrowStatement, expression: Expression) { - return node.expression !== expression - ? updateNode(createThrow(expression), node) - : node; - } - - export function createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.TryStatement); - node.tryBlock = tryBlock; - node.catchClause = catchClause; - node.finallyBlock = finallyBlock; - return node; - } - - export function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { - return node.tryBlock !== tryBlock - || node.catchClause !== catchClause - || node.finallyBlock !== finallyBlock - ? updateNode(createTry(tryBlock, catchClause, finallyBlock), node) - : node; - } - - export function createDebuggerStatement() { - return createSynthesizedNode(SyntaxKind.DebuggerStatement); - } - - export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression) { - const node = createSynthesizedNode(SyntaxKind.VariableDeclaration); - node.name = asName(name); - node.type = type; - node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; - return node; - } - - export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) { - return node.name !== name - || node.type !== type - || node.initializer !== initializer - ? updateNode(createVariableDeclaration(name, type, initializer), node) - : node; - } - - export function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) { - const node = createSynthesizedNode(SyntaxKind.VariableDeclarationList); - node.flags |= flags & NodeFlags.BlockScoped; - node.declarations = createNodeArray(declarations); - return node; - } - - export function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { - return node.declarations !== declarations - ? updateNode(createVariableDeclarationList(declarations, node.flags), node) - : node; - } - - export function createFunctionDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - const node = createSynthesizedNode(SyntaxKind.FunctionDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.asteriskToken = asteriskToken; - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.body = body; - return node; - } - - export function updateFunctionDeclaration( - node: FunctionDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - asteriskToken: AsteriskToken | undefined, - name: Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: Block | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.asteriskToken !== asteriskToken - || node.name !== name - || node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.body !== body - ? updateNode(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : node; - } - - export function createClassDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly ClassElement[]) { - const node = createSynthesizedNode(SyntaxKind.ClassDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; - } - - export function updateClassDeclaration( - node: ClassDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly ClassElement[]) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.typeParameters !== typeParameters - || node.heritageClauses !== heritageClauses - || node.members !== members - ? updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : node; - } - - export function createInterfaceDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | Identifier, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly TypeElement[]) { - const node = createSynthesizedNode(SyntaxKind.InterfaceDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; - } - - export function updateInterfaceDeclaration( - node: InterfaceDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: Identifier, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly TypeElement[]) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.typeParameters !== typeParameters - || node.heritageClauses !== heritageClauses - || node.members !== members - ? updateNode(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : node; - } - - export function createTypeAliasDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | Identifier, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - type: TypeNode) { - const node = createSynthesizedNode(SyntaxKind.TypeAliasDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.type = type; - return node; - } - - export function updateTypeAliasDeclaration( - node: TypeAliasDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: Identifier, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - type: TypeNode) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.typeParameters !== typeParameters - || node.type !== type - ? updateNode(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node) - : node; - } - - export function createEnumDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: string | Identifier, - members: readonly EnumMember[]) { - const node = createSynthesizedNode(SyntaxKind.EnumDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.members = createNodeArray(members); - return node; - } - - export function updateEnumDeclaration( - node: EnumDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - name: Identifier, - members: readonly EnumMember[]) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.members !== members - ? updateNode(createEnumDeclaration(decorators, modifiers, name, members), node) - : node; - } - - export function createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags = NodeFlags.None) { - const node = createSynthesizedNode(SyntaxKind.ModuleDeclaration); - node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = name; - node.body = body; - return node; - } - - export function updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.body !== body - ? updateNode(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) - : node; - } - - export function createModuleBlock(statements: readonly Statement[]) { - const node = createSynthesizedNode(SyntaxKind.ModuleBlock); - node.statements = createNodeArray(statements); - return node; - } - - export function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) { - return node.statements !== statements - ? updateNode(createModuleBlock(statements), node) - : node; - } - - export function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { - const node = createSynthesizedNode(SyntaxKind.CaseBlock); - node.clauses = createNodeArray(clauses); - return node; - } - - export function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) { - return node.clauses !== clauses - ? updateNode(createCaseBlock(clauses), node) - : node; - } - - export function createNamespaceExportDeclaration(name: string | Identifier) { - const node = createSynthesizedNode(SyntaxKind.NamespaceExportDeclaration); - node.name = asName(name); - return node; - } - - export function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { - return node.name !== name - ? updateNode(createNamespaceExportDeclaration(name), node) - : node; - } - - export function createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) { - const node = createSynthesizedNode(SyntaxKind.ImportEqualsDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.name = asName(name); - node.moduleReference = moduleReference; - return node; - } - - export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.name !== name - || node.moduleReference !== moduleReference - ? updateNode(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) - : node; - } - - export function createImportDeclaration( - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - importClause: ImportClause | undefined, - moduleSpecifier: Expression): ImportDeclaration { - const node = createSynthesizedNode(SyntaxKind.ImportDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.importClause = importClause; - node.moduleSpecifier = moduleSpecifier; - return node; - } - - export function updateImportDeclaration( - node: ImportDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - importClause: ImportClause | undefined, - moduleSpecifier: Expression) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.importClause !== importClause - || node.moduleSpecifier !== moduleSpecifier - ? updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) - : node; - } - - export function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { - const node = createSynthesizedNode(SyntaxKind.ImportClause); - node.name = name; - node.namedBindings = namedBindings; - return node; - } - - export function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { - return node.name !== name - || node.namedBindings !== namedBindings - ? updateNode(createImportClause(name, namedBindings), node) - : node; - } - - export function createNamespaceImport(name: Identifier): NamespaceImport { - const node = createSynthesizedNode(SyntaxKind.NamespaceImport); - node.name = name; - return node; - } - - export function updateNamespaceImport(node: NamespaceImport, name: Identifier) { - return node.name !== name - ? updateNode(createNamespaceImport(name), node) - : node; - } - - export function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { - const node = createSynthesizedNode(SyntaxKind.NamedImports); - node.elements = createNodeArray(elements); - return node; - } - - export function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) { - return node.elements !== elements - ? updateNode(createNamedImports(elements), node) - : node; - } - - export function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier) { - const node = createSynthesizedNode(SyntaxKind.ImportSpecifier); - node.propertyName = propertyName; - node.name = name; - return node; - } - - export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) { - return node.propertyName !== propertyName - || node.name !== name - ? updateNode(createImportSpecifier(propertyName, name), node) - : node; - } - - export function createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ExportAssignment); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.isExportEquals = isExportEquals; - node.expression = isExportEquals ? parenthesizeBinaryOperand(SyntaxKind.EqualsToken, expression, /*isLeftSideOfBinary*/ false, /*leftOperand*/ undefined) : parenthesizeDefaultExpression(expression); - return node; - } - - export function updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.expression !== expression - ? updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) - : node; - } - - export function createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression) { - const node = createSynthesizedNode(SyntaxKind.ExportDeclaration); - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); - node.exportClause = exportClause; - node.moduleSpecifier = moduleSpecifier; - return node; - } - - export function updateExportDeclaration( - node: ExportDeclaration, - decorators: readonly Decorator[] | undefined, - modifiers: readonly Modifier[] | undefined, - exportClause: NamedExports | undefined, - moduleSpecifier: Expression | undefined) { - return node.decorators !== decorators - || node.modifiers !== modifiers - || node.exportClause !== exportClause - || node.moduleSpecifier !== moduleSpecifier - ? updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) - : node; - } - - /* @internal */ - export function createEmptyExports() { - return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined); - } - - export function createNamedExports(elements: readonly ExportSpecifier[]) { - const node = createSynthesizedNode(SyntaxKind.NamedExports); - node.elements = createNodeArray(elements); - return node; - } - - export function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) { - return node.elements !== elements - ? updateNode(createNamedExports(elements), node) - : node; - } - - export function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier) { - const node = createSynthesizedNode(SyntaxKind.ExportSpecifier); - node.propertyName = asName(propertyName); - node.name = asName(name); - return node; - } - - export function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) { - return node.propertyName !== propertyName - || node.name !== name - ? updateNode(createExportSpecifier(propertyName, name), node) - : node; - } - - // Module references - - export function createExternalModuleReference(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.ExternalModuleReference); - node.expression = expression; - return node; - } - - export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { - return node.expression !== expression - ? updateNode(createExternalModuleReference(expression), node) - : node; - } - - // JSDoc - - /* @internal */ - export function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { - const node = createSynthesizedNode(SyntaxKind.JSDocTypeExpression) as JSDocTypeExpression; - node.type = type; - return node; - } - - /* @internal */ - export function createJSDocTypeTag(typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag { - const tag = createJSDocTag(SyntaxKind.JSDocTypeTag, "type"); - tag.typeExpression = typeExpression; - tag.comment = comment; - return tag; - } - - /* @internal */ - export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag { - const tag = createJSDocTag(SyntaxKind.JSDocReturnTag, "returns"); - tag.typeExpression = typeExpression; - tag.comment = comment; - return tag; - } - - /** @internal */ - export function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag { - const tag = createJSDocTag(SyntaxKind.JSDocThisTag, "this"); - tag.typeExpression = typeExpression; - return tag; - } - - /* @internal */ - export function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag { - const tag = createJSDocTag(SyntaxKind.JSDocParameterTag, "param"); - tag.typeExpression = typeExpression; - tag.name = name; - tag.isBracketed = isBracketed; - tag.comment = comment; - return tag; - } - - /* @internal */ - export function createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined) { - const node = createSynthesizedNode(SyntaxKind.JSDocComment) as JSDoc; - node.comment = comment; - node.tags = tags; - return node; - } - - /* @internal */ - function createJSDocTag(kind: T["kind"], tagName: string): T { - const node = createSynthesizedNode(kind) as T; - node.tagName = createIdentifier(tagName); - return node; - } - - // JSX - - export function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { - const node = createSynthesizedNode(SyntaxKind.JsxElement); - node.openingElement = openingElement; - node.children = createNodeArray(children); - node.closingElement = closingElement; - return node; - } - - export function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { - return node.openingElement !== openingElement - || node.children !== children - || node.closingElement !== closingElement - ? updateNode(createJsxElement(openingElement, children, closingElement), node) - : node; - } - - export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - const node = createSynthesizedNode(SyntaxKind.JsxSelfClosingElement); - node.tagName = tagName; - node.typeArguments = asNodeArray(typeArguments); - node.attributes = attributes; - return node; - } - - export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - return node.tagName !== tagName - || node.typeArguments !== typeArguments - || node.attributes !== attributes - ? updateNode(createJsxSelfClosingElement(tagName, typeArguments, attributes), node) - : node; - } - - export function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - const node = createSynthesizedNode(SyntaxKind.JsxOpeningElement); - node.tagName = tagName; - node.typeArguments = asNodeArray(typeArguments); - node.attributes = attributes; - return node; - } - - export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - return node.tagName !== tagName - || node.typeArguments !== typeArguments - || node.attributes !== attributes - ? updateNode(createJsxOpeningElement(tagName, typeArguments, attributes), node) - : node; - } - - export function createJsxClosingElement(tagName: JsxTagNameExpression) { - const node = createSynthesizedNode(SyntaxKind.JsxClosingElement); - node.tagName = tagName; - return node; - } - - export function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { - return node.tagName !== tagName - ? updateNode(createJsxClosingElement(tagName), node) - : node; - } - - export function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { - const node = createSynthesizedNode(SyntaxKind.JsxFragment); - node.openingFragment = openingFragment; - node.children = createNodeArray(children); - node.closingFragment = closingFragment; - return node; - } - - export function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { - const node = createSynthesizedNode(SyntaxKind.JsxText); - node.text = text; - node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; - return node; - } - - export function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { - return node.text !== text - || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces - ? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) - : node; - } - - export function createJsxOpeningFragment() { - return createSynthesizedNode(SyntaxKind.JsxOpeningFragment); - } - - export function createJsxJsxClosingFragment() { - return createSynthesizedNode(SyntaxKind.JsxClosingFragment); - } - - export function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { - return node.openingFragment !== openingFragment - || node.children !== children - || node.closingFragment !== closingFragment - ? updateNode(createJsxFragment(openingFragment, children, closingFragment), node) - : node; - } - - export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression) { - const node = createSynthesizedNode(SyntaxKind.JsxAttribute); - node.name = name; - node.initializer = initializer; - return node; - } - - export function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression) { - return node.name !== name - || node.initializer !== initializer - ? updateNode(createJsxAttribute(name, initializer), node) - : node; - } - - export function createJsxAttributes(properties: readonly JsxAttributeLike[]) { - const node = createSynthesizedNode(SyntaxKind.JsxAttributes); - node.properties = createNodeArray(properties); - return node; - } - - export function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { - return node.properties !== properties - ? updateNode(createJsxAttributes(properties), node) - : node; - } - - export function createJsxSpreadAttribute(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.JsxSpreadAttribute); - node.expression = expression; - return node; - } - - export function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { - return node.expression !== expression - ? updateNode(createJsxSpreadAttribute(expression), node) - : node; - } - - export function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) { - const node = createSynthesizedNode(SyntaxKind.JsxExpression); - node.dotDotDotToken = dotDotDotToken; - node.expression = expression; - return node; - } - - export function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { - return node.expression !== expression - ? updateNode(createJsxExpression(node.dotDotDotToken, expression), node) - : node; - } - - // Clauses - - export function createCaseClause(expression: Expression, statements: readonly Statement[]) { - const node = createSynthesizedNode(SyntaxKind.CaseClause); - node.expression = parenthesizeExpressionForList(expression); - node.statements = createNodeArray(statements); - return node; - } - - export function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) { - return node.expression !== expression - || node.statements !== statements - ? updateNode(createCaseClause(expression, statements), node) - : node; - } - - export function createDefaultClause(statements: readonly Statement[]) { - const node = createSynthesizedNode(SyntaxKind.DefaultClause); - node.statements = createNodeArray(statements); - return node; - } - - export function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) { - return node.statements !== statements - ? updateNode(createDefaultClause(statements), node) - : node; - } - - export function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) { - const node = createSynthesizedNode(SyntaxKind.HeritageClause); - node.token = token; - node.types = createNodeArray(types); - return node; - } - - export function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) { - return node.types !== types - ? updateNode(createHeritageClause(node.token, types), node) - : node; - } - - export function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) { - const node = createSynthesizedNode(SyntaxKind.CatchClause); - node.variableDeclaration = isString(variableDeclaration) ? createVariableDeclaration(variableDeclaration) : variableDeclaration; - node.block = block; - return node; - } - - export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { - return node.variableDeclaration !== variableDeclaration - || node.block !== block - ? updateNode(createCatchClause(variableDeclaration, block), node) - : node; - } - - // Property assignments - - export function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { - const node = createSynthesizedNode(SyntaxKind.PropertyAssignment); - node.name = asName(name); - node.questionToken = undefined; - node.initializer = parenthesizeExpressionForList(initializer); - return node; - } - - export function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) { - return node.name !== name - || node.initializer !== initializer - ? updateNode(createPropertyAssignment(name, initializer), node) - : node; - } - - export function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { - const node = createSynthesizedNode(SyntaxKind.ShorthandPropertyAssignment); - node.name = asName(name); - node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; - return node; - } - - export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) { - return node.name !== name - || node.objectAssignmentInitializer !== objectAssignmentInitializer - ? updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) - : node; - } - - export function createSpreadAssignment(expression: Expression) { - const node = createSynthesizedNode(SyntaxKind.SpreadAssignment); - node.expression = parenthesizeExpressionForList(expression); - return node; - } - - export function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { - return node.expression !== expression - ? updateNode(createSpreadAssignment(expression), node) - : node; - } - - // Enum - - export function createEnumMember(name: string | PropertyName, initializer?: Expression) { - const node = createSynthesizedNode(SyntaxKind.EnumMember); - node.name = asName(name); - node.initializer = initializer && parenthesizeExpressionForList(initializer); - return node; - } - - export function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { - return node.name !== name - || node.initializer !== initializer - ? updateNode(createEnumMember(name, initializer), node) - : node; - } - - // Top-level nodes - - export function updateSourceFileNode(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: SourceFile["referencedFiles"], typeReferences?: SourceFile["typeReferenceDirectives"], hasNoDefaultLib?: boolean, libReferences?: SourceFile["libReferenceDirectives"]) { - if ( - node.statements !== statements || - (isDeclarationFile !== undefined && node.isDeclarationFile !== isDeclarationFile) || - (referencedFiles !== undefined && node.referencedFiles !== referencedFiles) || - (typeReferences !== undefined && node.typeReferenceDirectives !== typeReferences) || - (libReferences !== undefined && node.libReferenceDirectives !== libReferences) || - (hasNoDefaultLib !== undefined && node.hasNoDefaultLib !== hasNoDefaultLib) - ) { - const updated = createSynthesizedNode(SyntaxKind.SourceFile); - updated.flags |= node.flags; - updated.statements = createNodeArray(statements); - updated.endOfFileToken = node.endOfFileToken; - updated.fileName = node.fileName; - updated.path = node.path; - updated.text = node.text; - updated.isDeclarationFile = isDeclarationFile === undefined ? node.isDeclarationFile : isDeclarationFile; - updated.referencedFiles = referencedFiles === undefined ? node.referencedFiles : referencedFiles; - updated.typeReferenceDirectives = typeReferences === undefined ? node.typeReferenceDirectives : typeReferences; - updated.hasNoDefaultLib = hasNoDefaultLib === undefined ? node.hasNoDefaultLib : hasNoDefaultLib; - updated.libReferenceDirectives = libReferences === undefined ? node.libReferenceDirectives : libReferences; - if (node.amdDependencies !== undefined) updated.amdDependencies = node.amdDependencies; - if (node.moduleName !== undefined) updated.moduleName = node.moduleName; - if (node.languageVariant !== undefined) updated.languageVariant = node.languageVariant; - if (node.renamedDependencies !== undefined) updated.renamedDependencies = node.renamedDependencies; - if (node.languageVersion !== undefined) updated.languageVersion = node.languageVersion; - if (node.scriptKind !== undefined) updated.scriptKind = node.scriptKind; - if (node.externalModuleIndicator !== undefined) updated.externalModuleIndicator = node.externalModuleIndicator; - if (node.commonJsModuleIndicator !== undefined) updated.commonJsModuleIndicator = node.commonJsModuleIndicator; - if (node.identifiers !== undefined) updated.identifiers = node.identifiers; - if (node.nodeCount !== undefined) updated.nodeCount = node.nodeCount; - if (node.identifierCount !== undefined) updated.identifierCount = node.identifierCount; - if (node.symbolCount !== undefined) updated.symbolCount = node.symbolCount; - if (node.parseDiagnostics !== undefined) updated.parseDiagnostics = node.parseDiagnostics; - if (node.bindDiagnostics !== undefined) updated.bindDiagnostics = node.bindDiagnostics; - if (node.bindSuggestionDiagnostics !== undefined) updated.bindSuggestionDiagnostics = node.bindSuggestionDiagnostics; - if (node.lineMap !== undefined) updated.lineMap = node.lineMap; - if (node.classifiableNames !== undefined) updated.classifiableNames = node.classifiableNames; - if (node.resolvedModules !== undefined) updated.resolvedModules = node.resolvedModules; - if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames; - if (node.imports !== undefined) updated.imports = node.imports; - if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations; - if (node.pragmas !== undefined) updated.pragmas = node.pragmas; - if (node.localJsxFactory !== undefined) updated.localJsxFactory = node.localJsxFactory; - if (node.localJsxNamespace !== undefined) updated.localJsxNamespace = node.localJsxNamespace; - return updateNode(updated, node); - } - - return node; - } - - /** - * Creates a shallow, memberwise clone of a node for mutation. - */ - export function getMutableClone(node: T): T { - const clone = getSynthesizedClone(node); - clone.pos = node.pos; - clone.end = node.end; - clone.parent = node.parent; - return clone; - } - - // Transformation nodes - - /** - * Creates a synthetic statement to act as a placeholder for a not-emitted statement in - * order to preserve comments. - * - * @param original The original statement. - */ - export function createNotEmittedStatement(original: Node) { - const node = createSynthesizedNode(SyntaxKind.NotEmittedStatement); - node.original = original; - setTextRange(node, original); - return node; - } - - /** - * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in - * order to properly emit exports. - */ - /* @internal */ - export function createEndOfDeclarationMarker(original: Node) { - const node = createSynthesizedNode(SyntaxKind.EndOfDeclarationMarker); - node.emitNode = {} as EmitNode; - node.original = original; - return node; - } - - /** - * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in - * order to properly emit exports. - */ - /* @internal */ - export function createMergeDeclarationMarker(original: Node) { - const node = createSynthesizedNode(SyntaxKind.MergeDeclarationMarker); - node.emitNode = {} as EmitNode; - node.original = original; - return node; - } - - /** - * Creates a synthetic expression to act as a placeholder for a not-emitted expression in - * order to preserve comments or sourcemap positions. - * - * @param expression The inner expression to emit. - * @param original The original outer expression. - * @param location The location for the expression. Defaults to the positions from "original" if provided. - */ - export function createPartiallyEmittedExpression(expression: Expression, original?: Node) { - const node = createSynthesizedNode(SyntaxKind.PartiallyEmittedExpression); - node.expression = expression; - node.original = original; - setTextRange(node, original); - return node; - } - - export function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createPartiallyEmittedExpression(expression, node.original), node); - } - return node; - } - - function flattenCommaElements(node: Expression): Expression | readonly Expression[] { - if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { - if (node.kind === SyntaxKind.CommaListExpression) { - return (node).elements; - } - if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { - return [node.left, node.right]; - } - } - return node; - } - - export function createCommaList(elements: readonly Expression[]) { - const node = createSynthesizedNode(SyntaxKind.CommaListExpression); - node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); - return node; - } - - export function updateCommaList(node: CommaListExpression, elements: readonly Expression[]) { - return node.elements !== elements - ? updateNode(createCommaList(elements), node) - : node; - } - - /* @internal */ - export function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) { - const node = createSynthesizedNode(SyntaxKind.SyntheticReferenceExpression); - node.expression = expression; - node.thisArg = thisArg; - return node; - } - - /* @internal */ - export function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) { - return node.expression !== expression - || node.thisArg !== thisArg - ? updateNode(createSyntheticReferenceExpression(expression, thisArg), node) - : node; - } - - export function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { - const node = createNode(SyntaxKind.Bundle); - node.prepends = prepends; - node.sourceFiles = sourceFiles; - return node; - } - - let allUnscopedEmitHelpers: ReadonlyMap | undefined; - function getAllUnscopedEmitHelpers() { - return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([ - valuesHelper, - readHelper, - spreadHelper, - spreadArraysHelper, - restHelper, - decorateHelper, - metadataHelper, - paramHelper, - awaiterHelper, - assignHelper, - awaitHelper, - asyncGeneratorHelper, - asyncDelegator, - asyncValues, - extendsHelper, - templateObjectHelper, - generatorHelper, - importStarHelper, - importDefaultHelper - ], helper => helper.name)); - } - - function createUnparsedSource() { - const node = createNode(SyntaxKind.UnparsedSource); - node.prologues = emptyArray; - node.referencedFiles = emptyArray; - node.libReferenceDirectives = emptyArray; - node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos); - return node; - } - - export function createUnparsedSourceFile(text: string): UnparsedSource; - export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; - export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; - export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource { - const node = createUnparsedSource(); - let stripInternal: boolean | undefined; - let bundleFileInfo: BundleFileInfo | undefined; - if (!isString(textOrInputFiles)) { - Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts"); - node.fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || ""; - node.sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath; - Object.defineProperties(node, { - text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } }, - sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } }, - }); - - - if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) { - node.oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit; - Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean"); - stripInternal = mapTextOrStripInternal as boolean | undefined; - bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts; - if (node.oldFileOfCurrentEmit) { - parseOldFileOfCurrentEmit(node, Debug.assertDefined(bundleFileInfo)); - return node; - } - } - } - else { - node.fileName = ""; - node.text = textOrInputFiles; - node.sourceMapPath = mapPathOrType; - node.sourceMapText = mapTextOrStripInternal as string; - } - Debug.assert(!node.oldFileOfCurrentEmit); - parseUnparsedSourceFile(node, bundleFileInfo, stripInternal); - return node; - } - - function parseUnparsedSourceFile(node: UnparsedSource, bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined) { - let prologues: UnparsedPrologue[] | undefined; - let helpers: UnscopedEmitHelper[] | undefined; - let referencedFiles: FileReference[] | undefined; - let typeReferenceDirectives: string[] | undefined; - let libReferenceDirectives: FileReference[] | undefined; - let texts: UnparsedSourceText[] | undefined; - - for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) { - switch (section.kind) { - case BundleFileSectionKind.Prologue: - (prologues || (prologues = [])).push(createUnparsedNode(section, node) as UnparsedPrologue); - break; - case BundleFileSectionKind.EmitHelpers: - (helpers || (helpers = [])).push(getAllUnscopedEmitHelpers().get(section.data)!); - break; - case BundleFileSectionKind.NoDefaultLib: - node.hasNoDefaultLib = true; - break; - case BundleFileSectionKind.Reference: - (referencedFiles || (referencedFiles = [])).push({ pos: -1, end: -1, fileName: section.data }); - break; - case BundleFileSectionKind.Type: - (typeReferenceDirectives || (typeReferenceDirectives = [])).push(section.data); - break; - case BundleFileSectionKind.Lib: - (libReferenceDirectives || (libReferenceDirectives = [])).push({ pos: -1, end: -1, fileName: section.data }); - break; - case BundleFileSectionKind.Prepend: - const prependNode = createUnparsedNode(section, node) as UnparsedPrepend; - let prependTexts: UnparsedTextLike[] | undefined; - for (const text of section.texts) { - if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) { - (prependTexts || (prependTexts = [])).push(createUnparsedNode(text, node) as UnparsedTextLike); - } - } - prependNode.texts = prependTexts || emptyArray; - (texts || (texts = [])).push(prependNode); - break; - case BundleFileSectionKind.Internal: - if (stripInternal) { - if (!texts) texts = []; - break; - } - // falls through - - case BundleFileSectionKind.Text: - (texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike); - break; - default: - Debug.assertNever(section); - } - } - - node.prologues = prologues || emptyArray; - node.helpers = helpers; - node.referencedFiles = referencedFiles || emptyArray; - node.typeReferenceDirectives = typeReferenceDirectives; - node.libReferenceDirectives = libReferenceDirectives || emptyArray; - node.texts = texts || [createUnparsedNode({ kind: BundleFileSectionKind.Text, pos: 0, end: node.text.length }, node)]; - } - - function parseOldFileOfCurrentEmit(node: UnparsedSource, bundleFileInfo: BundleFileInfo) { - Debug.assert(!!node.oldFileOfCurrentEmit); - let texts: UnparsedTextLike[] | undefined; - let syntheticReferences: UnparsedSyntheticReference[] | undefined; - for (const section of bundleFileInfo.sections) { - switch (section.kind) { - case BundleFileSectionKind.Internal: - case BundleFileSectionKind.Text: - (texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike); - break; - - case BundleFileSectionKind.NoDefaultLib: - case BundleFileSectionKind.Reference: - case BundleFileSectionKind.Type: - case BundleFileSectionKind.Lib: - (syntheticReferences || (syntheticReferences = [])).push(createUnparsedSyntheticReference(section, node)); - break; - - // Ignore - case BundleFileSectionKind.Prologue: - case BundleFileSectionKind.EmitHelpers: - case BundleFileSectionKind.Prepend: - break; - - default: - Debug.assertNever(section); - } - } - node.texts = texts || emptyArray; - node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); - node.syntheticReferences = syntheticReferences; - return node; - } - - function mapBundleFileSectionKindToSyntaxKind(kind: BundleFileSectionKind): SyntaxKind { - switch (kind) { - case BundleFileSectionKind.Prologue: return SyntaxKind.UnparsedPrologue; - case BundleFileSectionKind.Prepend: return SyntaxKind.UnparsedPrepend; - case BundleFileSectionKind.Internal: return SyntaxKind.UnparsedInternalText; - case BundleFileSectionKind.Text: return SyntaxKind.UnparsedText; - - case BundleFileSectionKind.EmitHelpers: - case BundleFileSectionKind.NoDefaultLib: - case BundleFileSectionKind.Reference: - case BundleFileSectionKind.Type: - case BundleFileSectionKind.Lib: - return Debug.fail(`BundleFileSectionKind: ${kind} not yet mapped to SyntaxKind`); - - default: - return Debug.assertNever(kind); - } - } - - function createUnparsedNode(section: BundleFileSection, parent: UnparsedSource): UnparsedNode { - const node = createNode(mapBundleFileSectionKindToSyntaxKind(section.kind), section.pos, section.end) as UnparsedNode; - node.parent = parent; - node.data = section.data; - return node; - } - - function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference, parent: UnparsedSource) { - const node = createNode(SyntaxKind.UnparsedSyntheticReference, section.pos, section.end) as UnparsedSyntheticReference; - node.parent = parent; - node.data = section.data; - node.section = section; - return node; - } - - export function createInputFiles( - javascriptText: string, - declarationText: string - ): InputFiles; - export function createInputFiles( - readFileText: (path: string) => string | undefined, - javascriptPath: string, - javascriptMapPath: string | undefined, - declarationPath: string, - declarationMapPath: string | undefined, - buildInfoPath: string | undefined - ): InputFiles; - export function createInputFiles( - javascriptText: string, - declarationText: string, - javascriptMapPath: string | undefined, - javascriptMapText: string | undefined, - declarationMapPath: string | undefined, - declarationMapText: string | undefined - ): InputFiles; - /*@internal*/ - export function createInputFiles( - javascriptText: string, - declarationText: string, - javascriptMapPath: string | undefined, - javascriptMapText: string | undefined, - declarationMapPath: string | undefined, - declarationMapText: string | undefined, - javascriptPath: string | undefined, - declarationPath: string | undefined, - buildInfoPath?: string | undefined, - buildInfo?: BuildInfo, - oldFileOfCurrentEmit?: boolean - ): InputFiles; - export function createInputFiles( - javascriptTextOrReadFileText: string | ((path: string) => string | undefined), - declarationTextOrJavascriptPath: string, - javascriptMapPath?: string, - javascriptMapTextOrDeclarationPath?: string, - declarationMapPath?: string, - declarationMapTextOrBuildInfoPath?: string, - javascriptPath?: string | undefined, - declarationPath?: string | undefined, - buildInfoPath?: string | undefined, - buildInfo?: BuildInfo, - oldFileOfCurrentEmit?: boolean - ): InputFiles { - const node = createNode(SyntaxKind.InputFiles); - if (!isString(javascriptTextOrReadFileText)) { - const cache = createMap(); - const textGetter = (path: string | undefined) => { - if (path === undefined) return undefined; - let value = cache.get(path); - if (value === undefined) { - value = javascriptTextOrReadFileText(path); - cache.set(path, value !== undefined ? value : false); - } - return value !== false ? value as string : undefined; - }; - const definedTextGetter = (path: string) => { - const result = textGetter(path); - return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`; - }; - let buildInfo: BuildInfo | false; - const getAndCacheBuildInfo = (getText: () => string | undefined) => { - if (buildInfo === undefined) { - const result = getText(); - buildInfo = result !== undefined ? getBuildInfo(result) : false; - } - return buildInfo || undefined; - }; - node.javascriptPath = declarationTextOrJavascriptPath; - node.javascriptMapPath = javascriptMapPath; - node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath); - node.declarationMapPath = declarationMapPath; - node.buildInfoPath = declarationMapTextOrBuildInfoPath; - Object.defineProperties(node, { - javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } }, - javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that - declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, - declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that - buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } } - }); - } - else { - node.javascriptText = javascriptTextOrReadFileText; - node.javascriptMapPath = javascriptMapPath; - node.javascriptMapText = javascriptMapTextOrDeclarationPath; - node.declarationText = declarationTextOrJavascriptPath; - node.declarationMapPath = declarationMapPath; - node.declarationMapText = declarationMapTextOrBuildInfoPath; - node.javascriptPath = javascriptPath; - node.declarationPath = declarationPath; - node.buildInfoPath = buildInfoPath; - node.buildInfo = buildInfo; - node.oldFileOfCurrentEmit = oldFileOfCurrentEmit; - } - return node; - } - - export function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { - if (node.sourceFiles !== sourceFiles || node.prepends !== prepends) { - return createBundle(sourceFiles, prepends); - } - return node; - } - - // Compound nodes - - export function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - export function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - export function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { - return createCall( - createFunctionExpression( - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - /*parameters*/ param ? [param] : [], - /*type*/ undefined, - createBlock(statements, /*multiLine*/ true) - ), - /*typeArguments*/ undefined, - /*argumentsArray*/ paramValue ? [paramValue] : [] - ); - } - - export function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; - export function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - export function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { - return createCall( - createArrowFunction( - /*modifiers*/ undefined, - /*typeParameters*/ undefined, - /*parameters*/ param ? [param] : [], - /*type*/ undefined, - /*equalsGreaterThanToken*/ undefined, - createBlock(statements, /*multiLine*/ true) - ), - /*typeArguments*/ undefined, - /*argumentsArray*/ paramValue ? [paramValue] : [] - ); - } - - - export function createComma(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.CommaToken, right); - } - - export function createLessThan(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.LessThanToken, right); - } - - export function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; - export function createAssignment(left: Expression, right: Expression): BinaryExpression; - export function createAssignment(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.EqualsToken, right); - } - - export function createStrictEquality(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.EqualsEqualsEqualsToken, right); - } - - export function createStrictInequality(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.ExclamationEqualsEqualsToken, right); - } - - export function createAdd(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.PlusToken, right); - } - - export function createSubtract(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.MinusToken, right); - } - - export function createPostfixIncrement(operand: Expression) { - return createPostfix(operand, SyntaxKind.PlusPlusToken); - } - - export function createLogicalAnd(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.AmpersandAmpersandToken, right); - } - - export function createLogicalOr(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.BarBarToken, right); - } - - export function createNullishCoalesce(left: Expression, right: Expression) { - return createBinary(left, SyntaxKind.QuestionQuestionToken, right); - } - - export function createLogicalNot(operand: Expression) { - return createPrefix(SyntaxKind.ExclamationToken, operand); - } - - export function createVoidZero() { - return createVoid(createLiteral(0)); - } - - export function createExportDefault(expression: Expression) { - return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression); - } - - export function createExternalModuleExport(exportName: Identifier) { - return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(/*propertyName*/ undefined, exportName)])); - } - - // Utilities - - function asName(name: string | T): T | Identifier { - return isString(name) ? createIdentifier(name) : name; - } - - function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { - return typeof value === "string" ? createStringLiteral(value) : - typeof value === "number" ? createNumericLiteral(""+value) : - typeof value === "boolean" ? value ? createTrue() : createFalse() : - value; - } - - function asNodeArray(array: readonly T[]): NodeArray; - function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; - function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { - return array ? createNodeArray(array) : undefined; - } - - function asToken(value: TKind | Token): Token { - return typeof value === "number" ? createToken(value) : value; - } - - function asEmbeddedStatement(statement: T): T | EmptyStatement; - function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; - function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { - return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; - } - - /** - * Clears any EmitNode entries from parse-tree nodes. - * @param sourceFile A source file. - */ - export function disposeEmitNodes(sourceFile: SourceFile) { - // During transformation we may need to annotate a parse tree node with transient - // transformation properties. As parse tree nodes live longer than transformation - // nodes, we need to make sure we reclaim any memory allocated for custom ranges - // from these nodes to ensure we do not hold onto entire subtrees just for position - // information. We also need to reset these nodes to a pre-transformation state - // for incremental parsing scenarios so that we do not impact later emit. - sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); - const emitNode = sourceFile && sourceFile.emitNode; - const annotatedNodes = emitNode && emitNode.annotatedNodes; - if (annotatedNodes) { - for (const node of annotatedNodes) { - node.emitNode = undefined; - } - } - } - - /** - * Associates a node with the current transformation, initializing - * various transient transformation properties. - */ - /* @internal */ - export function getOrCreateEmitNode(node: Node): EmitNode { - if (!node.emitNode) { - if (isParseTreeNode(node)) { - // To avoid holding onto transformation artifacts, we keep track of any - // parse tree node we are annotating. This allows us to clean them up after - // all transformations have completed. - if (node.kind === SyntaxKind.SourceFile) { - return node.emitNode = { annotatedNodes: [node] } as EmitNode; - } - - const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))); - getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); - } - - node.emitNode = {} as EmitNode; - } - - return node.emitNode; - } - - /** - * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. - * @internal - */ - export function removeAllComments(node: T): T { - const emitNode = getOrCreateEmitNode(node); - emitNode.flags |= EmitFlags.NoComments; - emitNode.leadingComments = undefined; - emitNode.trailingComments = undefined; - return node; - } - - export function setTextRange(range: T, location: TextRange | undefined): T { - if (location) { - range.pos = location.pos; - range.end = location.end; - } - return range; - } - - /** - * Sets flags that control emit behavior of a node. - */ - export function setEmitFlags(node: T, emitFlags: EmitFlags) { - getOrCreateEmitNode(node).flags = emitFlags; - return node; - } - - /** - * Sets flags that control emit behavior of a node. - */ - /* @internal */ - export function addEmitFlags(node: T, emitFlags: EmitFlags) { - const emitNode = getOrCreateEmitNode(node); - emitNode.flags = emitNode.flags | emitFlags; - return node; - } - - /** - * Gets a custom text range to use when emitting source maps. - */ - export function getSourceMapRange(node: Node): SourceMapRange { - const emitNode = node.emitNode; - return (emitNode && emitNode.sourceMapRange) || node; - } - - /** - * Sets a custom text range to use when emitting source maps. - */ - export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { - getOrCreateEmitNode(node).sourceMapRange = range; - return node; - } - - let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; - - /** - * Create an external source map source file reference - */ - export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource { - return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); - } - - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { - const emitNode = node.emitNode; - const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; - return tokenSourceMapRanges && tokenSourceMapRanges[token]; - } - - /** - * Sets the TextRange to use for source maps for a token of a node. - */ - export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { - const emitNode = getOrCreateEmitNode(node); - const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); - tokenSourceMapRanges[token] = range; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - */ - /*@internal*/ - export function getStartsOnNewLine(node: Node) { - const emitNode = node.emitNode; - return emitNode && emitNode.startsOnNewLine; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - /*@internal*/ - export function setStartsOnNewLine(node: T, newLine: boolean) { - getOrCreateEmitNode(node).startsOnNewLine = newLine; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - */ - export function getCommentRange(node: Node) { - const emitNode = node.emitNode; - return (emitNode && emitNode.commentRange) || node; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - export function setCommentRange(node: T, range: TextRange) { - getOrCreateEmitNode(node).commentRange = range; - return node; - } - - export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.leadingComments; - } - - export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { - getOrCreateEmitNode(node).leadingComments = comments; - return node; - } - - export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); - } - - export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.trailingComments; - } - - export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { - getOrCreateEmitNode(node).trailingComments = comments; - return node; - } - - export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); - } - - export function moveSyntheticComments(node: T, original: Node): T { - setSyntheticLeadingComments(node, getSyntheticLeadingComments(original)); - setSyntheticTrailingComments(node, getSyntheticTrailingComments(original)); - const emit = getOrCreateEmitNode(original); - emit.leadingComments = undefined; - emit.trailingComments = undefined; - return node; - } - - /** - * Gets the constant value to emit for an expression. - */ - export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.constantValue; - } - - /** - * Sets the constant value to emit for an expression. - */ - export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number) { - const emitNode = getOrCreateEmitNode(node); - emitNode.constantValue = value; - return node; - } - - /** - * Adds an EmitHelper to a node. - */ - export function addEmitHelper(node: T, helper: EmitHelper): T { - const emitNode = getOrCreateEmitNode(node); - emitNode.helpers = append(emitNode.helpers, helper); - return node; - } - - /** - * Add EmitHelpers to a node. - */ - export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { - if (some(helpers)) { - const emitNode = getOrCreateEmitNode(node); - for (const helper of helpers) { - emitNode.helpers = appendIfUnique(emitNode.helpers, helper); - } - } - return node; - } - - /** - * Removes an EmitHelper from a node. - */ - export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { - const emitNode = node.emitNode; - if (emitNode) { - const helpers = emitNode.helpers; - if (helpers) { - return orderedRemoveItem(helpers, helper); - } - } - return false; - } - - /** - * Gets the EmitHelpers of a node. - */ - export function getEmitHelpers(node: Node): EmitHelper[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.helpers; - } - - /** - * Moves matching emit helpers from a source node to a target node. - */ - export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { - const sourceEmitNode = source.emitNode; - const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; - if (!some(sourceEmitHelpers)) return; - - const targetEmitNode = getOrCreateEmitNode(target); - let helpersRemoved = 0; - for (let i = 0; i < sourceEmitHelpers.length; i++) { - const helper = sourceEmitHelpers[i]; - if (predicate(helper)) { - helpersRemoved++; - targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); - } - else if (helpersRemoved > 0) { - sourceEmitHelpers[i - helpersRemoved] = helper; - } - } - - if (helpersRemoved > 0) { - sourceEmitHelpers.length -= helpersRemoved; - } - } - - /* @internal */ - export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { - if (x === y) return Comparison.EqualTo; - if (x.priority === y.priority) return Comparison.EqualTo; - if (x.priority === undefined) return Comparison.GreaterThan; - if (y.priority === undefined) return Comparison.LessThan; - return compareValues(x.priority, y.priority); - } - - export function setOriginalNode(node: T, original: Node | undefined): T { - node.original = original; - if (original) { - const emitNode = original.emitNode; - if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); - } - return node; - } - - function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) { - const { - flags, - leadingComments, - trailingComments, - commentRange, - sourceMapRange, - tokenSourceMapRanges, - constantValue, - helpers, - startsOnNewLine, - } = sourceEmitNode; - if (!destEmitNode) destEmitNode = {} as EmitNode; - // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. - if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments); - if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments); - if (flags) destEmitNode.flags = flags; - if (commentRange) destEmitNode.commentRange = commentRange; - if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; - if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!); - if (constantValue !== undefined) destEmitNode.constantValue = constantValue; - if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers); - if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; - return destEmitNode; - } - - function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) { - if (!destRanges) destRanges = []; - for (const key in sourceRanges) { - destRanges[key] = sourceRanges[key]; - } - return destRanges; - } -} - -/* @internal */ -namespace ts { - export const nullTransformationContext: TransformationContext = { - enableEmitNotification: noop, - enableSubstitution: noop, - endLexicalEnvironment: returnUndefined, - getCompilerOptions: notImplemented, - getEmitHost: notImplemented, - getEmitResolver: notImplemented, - hoistFunctionDeclaration: noop, - hoistVariableDeclaration: noop, - isEmitNotificationEnabled: notImplemented, - isSubstitutionEnabled: notImplemented, - onEmitNode: noop, - onSubstituteNode: notImplemented, - readEmitHelpers: notImplemented, - requestEmitHelper: noop, - resumeLexicalEnvironment: noop, - startLexicalEnvironment: noop, - suspendLexicalEnvironment: noop, - addDiagnostic: noop, - }; - - // Compound nodes - - export type TypeOfTag = "undefined" | "number" | "boolean" | "string" | "symbol" | "object" | "function"; - - export function createTypeCheck(value: Expression, tag: TypeOfTag) { - return tag === "undefined" - ? createStrictEquality(value, createVoidZero()) - : createStrictEquality(createTypeOf(value), createLiteral(tag)); - } - - export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { - if (isComputedPropertyName(memberName)) { - return setTextRange(createElementAccess(target, memberName.expression), location); - } - else { - const expression = setTextRange( - isIdentifier(memberName) - ? createPropertyAccess(target, memberName) - : createElementAccess(target, memberName), - memberName - ); - getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; - return expression; - } - } - - export function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: readonly Expression[], location?: TextRange) { - return setTextRange( - createCall( - createPropertyAccess(func, "call"), - /*typeArguments*/ undefined, - [ - thisArg, - ...argumentsList - ]), - location - ); - } - - export function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange) { - return setTextRange( - createCall( - createPropertyAccess(func, "apply"), - /*typeArguments*/ undefined, - [ - thisArg, - argumentsExpression - ] - ), - location - ); - } - - export function createArraySlice(array: Expression, start?: number | Expression) { - const argumentsList: Expression[] = []; - if (start !== undefined) { - argumentsList.push(typeof start === "number" ? createLiteral(start) : start); - } - - return createCall(createPropertyAccess(array, "slice"), /*typeArguments*/ undefined, argumentsList); - } - - export function createArrayConcat(array: Expression, values: readonly Expression[]) { - return createCall( - createPropertyAccess(array, "concat"), - /*typeArguments*/ undefined, - values - ); - } - - export function createMathPow(left: Expression, right: Expression, location?: TextRange) { - return setTextRange( - createCall( - createPropertyAccess(createIdentifier("Math"), "pow"), - /*typeArguments*/ undefined, - [left, right] - ), - location - ); - } - - function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { - // To ensure the emit resolver can properly resolve the namespace, we need to - // treat this identifier as if it were a source tree node by clearing the `Synthesized` - // flag and setting a parent node. - const react = createIdentifier(reactNamespace || "React"); - react.flags &= ~NodeFlags.Synthesized; - // Set the parent that is in parse tree - // this makes sure that parent chain is intact for checker to traverse complete scope tree - react.parent = getParseTreeNode(parent); - return react; - } - - function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - if (isQualifiedName(jsxFactory)) { - const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); - const right = createIdentifier(idText(jsxFactory.right)); - right.escapedText = jsxFactory.right.escapedText; - return createPropertyAccess(left, right); - } - else { - return createReactNamespace(idText(jsxFactory), parent); - } - } - - function createJsxFactoryExpression(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - return jsxFactoryEntity ? - createJsxFactoryExpressionFromEntityName(jsxFactoryEntity, parent) : - createPropertyAccess( - createReactNamespace(reactNamespace, parent), - "createElement" - ); - } - - export function createExpressionForJsxElement(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression, children: readonly Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { - const argumentsList = [tagName]; - if (props) { - argumentsList.push(props); - } - - if (children && children.length > 0) { - if (!props) { - argumentsList.push(createNull()); - } - - if (children.length > 1) { - for (const child of children) { - startOnNewLine(child); - argumentsList.push(child); - } - } - else { - argumentsList.push(children[0]); - } - } - - return setTextRange( - createCall( - createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), - /*typeArguments*/ undefined, - argumentsList - ), - location - ); - } - - export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { - const tagName = createPropertyAccess( - createReactNamespace(reactNamespace, parentElement), - "Fragment" - ); - - const argumentsList = [tagName]; - argumentsList.push(createNull()); - - if (children && children.length > 0) { - if (children.length > 1) { - for (const child of children) { - startOnNewLine(child); - argumentsList.push(child); - } - } - else { - argumentsList.push(children[0]); - } - } - - return setTextRange( - createCall( - createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), - /*typeArguments*/ undefined, - argumentsList - ), - location - ); - } - - // Helpers - - /** - * Gets an identifier for the name of an *unscoped* emit helper. - */ - export function getUnscopedHelperName(name: string) { - return setEmitFlags(createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode); - } - - export const valuesHelper: UnscopedEmitHelper = { - name: "typescript:values", - importName: "__values", - scoped: false, - text: ` - var __values = (this && this.__values) || function(o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) return m.call(o); - if (o && typeof o.length === "number") return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); - };` - }; - - export function createValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) { - context.requestEmitHelper(valuesHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__values"), - /*typeArguments*/ undefined, - [expression] - ), - location - ); - } - - export const readHelper: UnscopedEmitHelper = { - name: "typescript:read", - importName: "__read", - scoped: false, - text: ` - var __read = (this && this.__read) || function (o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); - } - catch (error) { e = { error: error }; } - finally { - try { - if (r && !r.done && (m = i["return"])) m.call(i); - } - finally { if (e) throw e.error; } - } - return ar; - };` - }; - - export function createReadHelper(context: TransformationContext, iteratorRecord: Expression, count: number | undefined, location?: TextRange) { - context.requestEmitHelper(readHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__read"), - /*typeArguments*/ undefined, - count !== undefined - ? [iteratorRecord, createLiteral(count)] - : [iteratorRecord] - ), - location - ); - } - - export const spreadHelper: UnscopedEmitHelper = { - name: "typescript:spread", - importName: "__spread", - scoped: false, - text: ` - var __spread = (this && this.__spread) || function () { - for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); - return ar; - };` - }; - - export function createSpreadHelper(context: TransformationContext, argumentList: readonly Expression[], location?: TextRange) { - context.requestEmitHelper(readHelper); - context.requestEmitHelper(spreadHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__spread"), - /*typeArguments*/ undefined, - argumentList - ), - location - ); - } - - export const spreadArraysHelper: UnscopedEmitHelper = { - name: "typescript:spreadArrays", - importName: "__spreadArrays", - scoped: false, - text: ` - var __spreadArrays = (this && this.__spreadArrays) || function () { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; - };` - }; - - export function createSpreadArraysHelper(context: TransformationContext, argumentList: readonly Expression[], location?: TextRange) { - context.requestEmitHelper(spreadArraysHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__spreadArrays"), - /*typeArguments*/ undefined, - argumentList - ), - location - ); - } - - // Utilities - - export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement { - if (isVariableDeclarationList(node)) { - const firstDeclaration = first(node.declarations); - const updatedDeclaration = updateVariableDeclaration( - firstDeclaration, - firstDeclaration.name, - /*typeNode*/ undefined, - boundValue - ); - return setTextRange( - createVariableStatement( - /*modifiers*/ undefined, - updateVariableDeclarationList(node, [updatedDeclaration]) - ), - /*location*/ node - ); - } - else { - const updatedExpression = setTextRange(createAssignment(node, boundValue), /*location*/ node); - return setTextRange(createStatement(updatedExpression), /*location*/ node); - } - } - - export function insertLeadingStatement(dest: Statement, source: Statement) { - if (isBlock(dest)) { - return updateBlock(dest, setTextRange(createNodeArray([source, ...dest.statements]), dest.statements)); - } - else { - return createBlock(createNodeArray([dest, source]), /*multiLine*/ true); - } - } - - export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { - if (!outermostLabeledStatement) { - return node; - } - const updated = updateLabel( - outermostLabeledStatement, - outermostLabeledStatement.label, - outermostLabeledStatement.statement.kind === SyntaxKind.LabeledStatement - ? restoreEnclosingLabel(node, outermostLabeledStatement.statement) - : node - ); - if (afterRestoreLabelCallback) { - afterRestoreLabelCallback(outermostLabeledStatement); - } - return updated; - } - - export interface CallBinding { - target: LeftHandSideExpression; - thisArg: Expression; - } - - function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean { - const target = skipParentheses(node); - switch (target.kind) { - case SyntaxKind.Identifier: - return cacheIdentifiers; - case SyntaxKind.ThisKeyword: - case SyntaxKind.NumericLiteral: - case SyntaxKind.BigIntLiteral: - case SyntaxKind.StringLiteral: - return false; - case SyntaxKind.ArrayLiteralExpression: - const elements = (target).elements; - if (elements.length === 0) { - return false; - } - return true; - case SyntaxKind.ObjectLiteralExpression: - return (target).properties.length > 0; - default: - return true; - } - } - - export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding { - const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); - let thisArg: Expression; - let target: LeftHandSideExpression; - if (isSuperProperty(callee)) { - thisArg = createThis(); - target = callee; - } - else if (callee.kind === SyntaxKind.SuperKeyword) { - thisArg = createThis(); - target = languageVersion! < ScriptTarget.ES2015 - ? setTextRange(createIdentifier("_super"), callee) - : callee; - } - else if (getEmitFlags(callee) & EmitFlags.HelperName) { - thisArg = createVoidZero(); - target = parenthesizeForAccess(callee); - } - else { - switch (callee.kind) { - case SyntaxKind.PropertyAccessExpression: { - if (shouldBeCapturedInTempVariable((callee).expression, cacheIdentifiers)) { - // for `a.b()` target is `(_a = a).b` and thisArg is `_a` - thisArg = createTempVariable(recordTempVariable); - target = createPropertyAccess( - setTextRange( - createAssignment( - thisArg, - (callee).expression - ), - (callee).expression - ), - (callee).name - ); - setTextRange(target, callee); - } - else { - thisArg = (callee).expression; - target = callee; - } - break; - } - - case SyntaxKind.ElementAccessExpression: { - if (shouldBeCapturedInTempVariable((callee).expression, cacheIdentifiers)) { - // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` - thisArg = createTempVariable(recordTempVariable); - target = createElementAccess( - setTextRange( - createAssignment( - thisArg, - (callee).expression - ), - (callee).expression - ), - (callee).argumentExpression - ); - setTextRange(target, callee); - } - else { - thisArg = (callee).expression; - target = callee; - } - - break; - } - - default: { - // for `a()` target is `a` and thisArg is `void 0` - thisArg = createVoidZero(); - target = parenthesizeForAccess(expression); - break; - } - } - } - - return { target, thisArg }; - } - - export function inlineExpressions(expressions: readonly Expression[]) { - // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call - // stack size exceeded" errors. - return expressions.length > 10 - ? createCommaList(expressions) - : reduceLeft(expressions, createComma)!; - } - - export function createExpressionFromEntityName(node: EntityName | Expression): Expression { - if (isQualifiedName(node)) { - const left = createExpressionFromEntityName(node.left); - const right = getMutableClone(node.right); - return setTextRange(createPropertyAccess(left, right), node); - } - else { - return getMutableClone(node); - } - } - - export function createExpressionForPropertyName(memberName: PropertyName): Expression { - if (isIdentifier(memberName)) { - return createLiteral(memberName); - } - else if (isComputedPropertyName(memberName)) { - return getMutableClone(memberName.expression); - } - else { - return getMutableClone(memberName); - } - } - - export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { - switch (property.kind) { - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); - case SyntaxKind.PropertyAssignment: - return createExpressionForPropertyAssignment(property, receiver); - case SyntaxKind.ShorthandPropertyAssignment: - return createExpressionForShorthandPropertyAssignment(property, receiver); - case SyntaxKind.MethodDeclaration: - return createExpressionForMethodDeclaration(property, receiver); - } - } - - function createExpressionForAccessorDeclaration(properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { - const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); - if (property === firstAccessor) { - const properties: ObjectLiteralElementLike[] = []; - if (getAccessor) { - const getterFunction = createFunctionExpression( - getAccessor.modifiers, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - getAccessor.parameters, - /*type*/ undefined, - getAccessor.body! // TODO: GH#18217 - ); - setTextRange(getterFunction, getAccessor); - setOriginalNode(getterFunction, getAccessor); - const getter = createPropertyAssignment("get", getterFunction); - properties.push(getter); - } - - if (setAccessor) { - const setterFunction = createFunctionExpression( - setAccessor.modifiers, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - setAccessor.parameters, - /*type*/ undefined, - setAccessor.body! // TODO: GH#18217 - ); - setTextRange(setterFunction, setAccessor); - setOriginalNode(setterFunction, setAccessor); - const setter = createPropertyAssignment("set", setterFunction); - properties.push(setter); - } - - properties.push(createPropertyAssignment("enumerable", createTrue())); - properties.push(createPropertyAssignment("configurable", createTrue())); - - const expression = setTextRange( - createCall( - createPropertyAccess(createIdentifier("Object"), "defineProperty"), - /*typeArguments*/ undefined, - [ - receiver, - createExpressionForPropertyName(property.name), - createObjectLiteral(properties, multiLine) - ] - ), - /*location*/ firstAccessor - ); - - return aggregateTransformFlags(expression); - } - - return undefined; - } - - function createExpressionForPropertyAssignment(property: PropertyAssignment, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - createAssignment( - createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - property.initializer - ), - property - ), - property - ) - ); - } - - function createExpressionForShorthandPropertyAssignment(property: ShorthandPropertyAssignment, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - createAssignment( - createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - getSynthesizedClone(property.name) - ), - /*location*/ property - ), - /*original*/ property - ) - ); - } - - function createExpressionForMethodDeclaration(method: MethodDeclaration, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - createAssignment( - createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), - setOriginalNode( - setTextRange( - createFunctionExpression( - method.modifiers, - method.asteriskToken, - /*name*/ undefined, - /*typeParameters*/ undefined, - method.parameters, - /*type*/ undefined, - method.body! // TODO: GH#18217 - ), - /*location*/ method - ), - /*original*/ method - ) - ), - /*location*/ method - ), - /*original*/ method - ) - ); - } - - /** - * Gets the internal name of a declaration. This is primarily used for declarations that can be - * referred to by name in the body of an ES5 class function body. An internal name will *never* - * be prefixed with an module or namespace export modifier like "exports." when emitted as an - * expression. An internal name will also *never* be renamed due to a collision with a block - * scoped variable. - * - * @param node The declaration. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName); - } - - /** - * Gets whether an identifier should only be referred to by its internal name. - */ - export function isInternalName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; - } - - /** - * Gets the local name of a declaration. This is primarily used for declarations that can be - * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A - * local name will *never* be prefixed with an module or namespace export modifier like - * "exports." when emitted as an expression. - * - * @param node The declaration. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName); - } - - /** - * Gets whether an identifier should only be referred to by its local name. - */ - export function isLocalName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; - } - - /** - * Gets the export name of a declaration. This is primarily used for declarations that can be - * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An - * export name will *always* be prefixed with an module or namespace export modifier like - * `"exports."` when emitted as an expression if the name points to an exported symbol. - * - * @param node The declaration. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier { - return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName); - } - - /** - * Gets whether an identifier should only be referred to by its export representation if the - * name points to an exported symbol. - */ - export function isExportName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; - } - - /** - * Gets the name of a declaration for use in declarations. - * - * @param node The declaration. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getDeclarationName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getName(node, allowComments, allowSourceMaps); - } - - function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { - const nodeName = getNameOfDeclaration(node); - if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { - const name = getMutableClone(nodeName); - emitFlags |= getEmitFlags(nodeName); - if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; - if (!allowComments) emitFlags |= EmitFlags.NoComments; - if (emitFlags) setEmitFlags(name, emitFlags); - return name; - } - return getGeneratedNameForNode(node); - } - - /** - * Gets the exported name of a declaration for use in expressions. - * - * An exported name will *always* be prefixed with an module or namespace export modifier like - * "exports." if the name points to an exported symbol. - * - * @param ns The namespace identifier. - * @param node The declaration. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression { - if (ns && hasModifier(node, ModifierFlags.Export)) { - return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); - } - return getExportName(node, allowComments, allowSourceMaps); - } - - /** - * Gets a namespace-qualified name for use in expressions. - * - * @param ns The namespace identifier. - * @param name The name. - * @param allowComments A value indicating whether comments may be emitted for the name. - * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. - */ - export function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { - const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); - setTextRange(qualifiedName, name); - let emitFlags: EmitFlags = 0; - if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; - if (!allowComments) emitFlags |= EmitFlags.NoComments; - if (emitFlags) setEmitFlags(qualifiedName, emitFlags); - return qualifiedName; - } - - export function convertToFunctionBody(node: ConciseBody, multiLine?: boolean): Block { - return isBlock(node) ? node : setTextRange(createBlock([setTextRange(createReturn(node), node)], multiLine), node); - } - - export function convertFunctionDeclarationToExpression(node: FunctionDeclaration) { - if (!node.body) return Debug.fail(); - const updated = createFunctionExpression( - node.modifiers, - node.asteriskToken, - node.name, - node.typeParameters, - node.parameters, - node.type, - node.body - ); - setOriginalNode(updated, node); - setTextRange(updated, node); - if (getStartsOnNewLine(node)) { - setStartsOnNewLine(updated, /*newLine*/ true); - } - aggregateTransformFlags(updated); - return updated; - } - - function isUseStrictPrologue(node: ExpressionStatement): boolean { - return isStringLiteral(node.expression) && node.expression.text === "use strict"; - } - - /** - * Add any necessary prologue-directives into target statement-array. - * The function needs to be called during each transformation step. - * This function needs to be called whenever we transform the statement - * list of a source file, namespace, or function-like body. - * - * @param target: result statements array - * @param source: origin statements array - * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives - * @param visitor: Optional callback used to visit any custom prologue directives. - */ - export function addPrologue(target: Statement[], source: readonly Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number { - const offset = addStandardPrologue(target, source, ensureUseStrict); - return addCustomPrologue(target, source, offset, visitor); - } - - /** - * Add just the standard (string-expression) prologue-directives into target statement-array. - * The function needs to be called during each transformation step. - * This function needs to be called whenever we transform the statement - * list of a source file, namespace, or function-like body. - */ - export function addStandardPrologue(target: Statement[], source: readonly Statement[], ensureUseStrict?: boolean): number { - Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); - let foundUseStrict = false; - let statementOffset = 0; - const numStatements = source.length; - while (statementOffset < numStatements) { - const statement = source[statementOffset]; - if (isPrologueDirective(statement)) { - if (isUseStrictPrologue(statement)) { - foundUseStrict = true; - } - target.push(statement); - } - else { - break; - } - statementOffset++; - } - if (ensureUseStrict && !foundUseStrict) { - target.push(startOnNewLine(createStatement(createLiteral("use strict")))); - } - return statementOffset; - } - - /** - * Add just the custom prologue-directives into target statement-array. - * The function needs to be called during each transformation step. - * This function needs to be called whenever we transform the statement - * list of a source file, namespace, or function-like body. - */ - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number, visitor?: (node: Node) => VisitResult): number; - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined; - export function addCustomPrologue(target: Statement[], source: readonly Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined { - const numStatements = source.length; - while (statementOffset !== undefined && statementOffset < numStatements) { - const statement = source[statementOffset]; - if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { - append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); - } - else { - break; - } - statementOffset++; - } - return statementOffset; - } - - export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined { - for (const statement of statements) { - if (isPrologueDirective(statement)) { - if (isUseStrictPrologue(statement)) { - return statement; - } - } - else { - break; - } - } - return undefined; - } - - export function startsWithUseStrict(statements: readonly Statement[]) { - const firstStatement = firstOrUndefined(statements); - return firstStatement !== undefined - && isPrologueDirective(firstStatement) - && isUseStrictPrologue(firstStatement); - } - - /** - * Ensures "use strict" directive is added - * - * @param statements An array of statements - */ - export function ensureUseStrict(statements: NodeArray): NodeArray { - const foundUseStrict = findUseStrictPrologue(statements); - - if (!foundUseStrict) { - return setTextRange( - createNodeArray([ - startOnNewLine(createStatement(createLiteral("use strict"))), - ...statements - ]), - statements - ); - } - - return statements; - } - - /** - * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended - * order of operations. - * - * @param binaryOperator The operator for the BinaryExpression. - * @param operand The operand for the BinaryExpression. - * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the - * BinaryExpression. - */ - export function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) { - const skipped = skipPartiallyEmittedExpressions(operand); - - // If the resulting expression is already parenthesized, we do not need to do any further processing. - if (skipped.kind === SyntaxKind.ParenthesizedExpression) { - return operand; - } - - return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) - ? createParen(operand) - : operand; - } - - /** - * Determines whether the operand to a BinaryExpression needs to be parenthesized. - * - * @param binaryOperator The operator for the BinaryExpression. - * @param operand The operand for the BinaryExpression. - * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the - * BinaryExpression. - */ - function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) { - // If the operand has lower precedence, then it needs to be parenthesized to preserve the - // intent of the expression. For example, if the operand is `a + b` and the operator is - // `*`, then we need to parenthesize the operand to preserve the intended order of - // operations: `(a + b) * x`. - // - // If the operand has higher precedence, then it does not need to be parenthesized. For - // example, if the operand is `a * b` and the operator is `+`, then we do not need to - // parenthesize to preserve the intended order of operations: `a * b + x`. - // - // If the operand has the same precedence, then we need to check the associativity of - // the operator based on whether this is the left or right operand of the expression. - // - // For example, if `a / d` is on the right of operator `*`, we need to parenthesize - // to preserve the intended order of operations: `x * (a / d)` - // - // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve - // the intended order of operations: `(a ** b) ** c` - const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); - const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); - const emittedOperand = skipPartiallyEmittedExpressions(operand); - if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > 3) { - // We need to parenthesize arrow functions on the right side to avoid it being - // parsed as parenthesized expression: `a && (() => {})` - return true; - } - const operandPrecedence = getExpressionPrecedence(emittedOperand); - switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) { - case Comparison.LessThan: - // If the operand is the right side of a right-associative binary operation - // and is a yield expression, then we do not need parentheses. - if (!isLeftSideOfBinary - && binaryOperatorAssociativity === Associativity.Right - && operand.kind === SyntaxKind.YieldExpression) { - return false; - } - - return true; - - case Comparison.GreaterThan: - return false; - - case Comparison.EqualTo: - if (isLeftSideOfBinary) { - // No need to parenthesize the left operand when the binary operator is - // left associative: - // (a*b)/x -> a*b/x - // (a**b)/x -> a**b/x - // - // Parentheses are needed for the left operand when the binary operator is - // right associative: - // (a/b)**x -> (a/b)**x - // (a**b)**x -> (a**b)**x - return binaryOperatorAssociativity === Associativity.Right; - } - else { - if (isBinaryExpression(emittedOperand) - && emittedOperand.operatorToken.kind === binaryOperator) { - // No need to parenthesize the right operand when the binary operator and - // operand are the same and one of the following: - // x*(a*b) => x*a*b - // x|(a|b) => x|a|b - // x&(a&b) => x&a&b - // x^(a^b) => x^a^b - if (operatorHasAssociativeProperty(binaryOperator)) { - return false; - } - - // No need to parenthesize the right operand when the binary operator - // is plus (+) if both the left and right operands consist solely of either - // literals of the same kind or binary plus (+) expressions for literals of - // the same kind (recursively). - // "a"+(1+2) => "a"+(1+2) - // "a"+("b"+"c") => "a"+"b"+"c" - if (binaryOperator === SyntaxKind.PlusToken) { - const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown; - if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { - return false; - } - } - } - - // No need to parenthesize the right operand when the operand is right - // associative: - // x/(a**b) -> x/a**b - // x**(a**b) -> x**a**b - // - // Parentheses are needed for the right operand when the operand is left - // associative: - // x/(a*b) -> x/(a*b) - // x**(a/b) -> x**(a/b) - const operandAssociativity = getExpressionAssociativity(emittedOperand); - return operandAssociativity === Associativity.Left; - } - } - } - - /** - * Determines whether a binary operator is mathematically associative. - * - * @param binaryOperator The binary operator. - */ - function operatorHasAssociativeProperty(binaryOperator: SyntaxKind) { - // The following operators are associative in JavaScript: - // (a*b)*c -> a*(b*c) -> a*b*c - // (a|b)|c -> a|(b|c) -> a|b|c - // (a&b)&c -> a&(b&c) -> a&b&c - // (a^b)^c -> a^(b^c) -> a^b^c - // - // While addition is associative in mathematics, JavaScript's `+` is not - // guaranteed to be associative as it is overloaded with string concatenation. - return binaryOperator === SyntaxKind.AsteriskToken - || binaryOperator === SyntaxKind.BarToken - || binaryOperator === SyntaxKind.AmpersandToken - || binaryOperator === SyntaxKind.CaretToken; - } - - interface BinaryPlusExpression extends BinaryExpression { - cachedLiteralKind: SyntaxKind; - } - - /** - * This function determines whether an expression consists of a homogeneous set of - * literal expressions or binary plus expressions that all share the same literal kind. - * It is used to determine whether the right-hand operand of a binary plus expression can be - * emitted without parentheses. - */ - function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind { - node = skipPartiallyEmittedExpressions(node); - - if (isLiteralKind(node.kind)) { - return node.kind; - } - - if (node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.PlusToken) { - if ((node).cachedLiteralKind !== undefined) { - return (node).cachedLiteralKind; - } - - const leftKind = getLiteralKindOfBinaryPlusOperand((node).left); - const literalKind = isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand((node).right) ? leftKind : - SyntaxKind.Unknown; - - (node).cachedLiteralKind = literalKind; - return literalKind; - } - - return SyntaxKind.Unknown; - } - - export function parenthesizeForConditionalHead(condition: Expression) { - const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken); - const emittedCondition = skipPartiallyEmittedExpressions(condition); - const conditionPrecedence = getExpressionPrecedence(emittedCondition); - if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) { - return createParen(condition); - } - return condition; - } - - export function parenthesizeSubexpressionOfConditionalExpression(e: Expression): Expression { - // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions - // so in case when comma expression is introduced as a part of previous transformations - // if should be wrapped in parens since comma operator has the lowest precedence - const emittedExpression = skipPartiallyEmittedExpressions(e); - return isCommaSequence(emittedExpression) - ? createParen(e) - : e; - } - - /** - * [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but - * has a lookahead restriction for `function`, `async function`, and `class`. - * - * Basically, that means we need to parenthesize in the following cases: - * - * - BinaryExpression of CommaToken - * - CommaList (synthetic list of multiple comma expressions) - * - FunctionExpression - * - ClassExpression - */ - export function parenthesizeDefaultExpression(e: Expression) { - const check = skipPartiallyEmittedExpressions(e); - let needsParens = isCommaSequence(check); - if (!needsParens) { - switch (getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) { - case SyntaxKind.ClassExpression: - case SyntaxKind.FunctionExpression: - needsParens = true; - } - } - return needsParens ? createParen(e) : e; - } - - /** - * Wraps an expression in parentheses if it is needed in order to use the expression - * as the expression of a NewExpression node. - * - * @param expression The Expression node. - */ - export function parenthesizeForNew(expression: Expression): LeftHandSideExpression { - const leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); - switch (leftmostExpr.kind) { - case SyntaxKind.CallExpression: - return createParen(expression); - - case SyntaxKind.NewExpression: - return !(leftmostExpr as NewExpression).arguments - ? createParen(expression) - : expression; - } - - return parenthesizeForAccess(expression); - } - - /** - * Wraps an expression in parentheses if it is needed in order to use the expression for - * property or element access. - * - * @param expr The expression node. - */ - export function parenthesizeForAccess(expression: Expression): LeftHandSideExpression { - // isLeftHandSideExpression is almost the correct criterion for when it is not necessary - // to parenthesize the expression before a dot. The known exception is: - // - // NewExpression: - // new C.x -> not the same as (new C).x - // - const emittedExpression = skipPartiallyEmittedExpressions(expression); - if (isLeftHandSideExpression(emittedExpression) - && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments)) { - return expression; - } - - return setTextRange(createParen(expression), expression); - } - - export function parenthesizePostfixOperand(operand: Expression) { - return isLeftHandSideExpression(operand) - ? operand - : setTextRange(createParen(operand), operand); - } - - export function parenthesizePrefixOperand(operand: Expression) { - return isUnaryExpression(operand) - ? operand - : setTextRange(createParen(operand), operand); - } - - export function parenthesizeListElements(elements: NodeArray) { - let result: Expression[] | undefined; - for (let i = 0; i < elements.length; i++) { - const element = parenthesizeExpressionForList(elements[i]); - if (result !== undefined || element !== elements[i]) { - if (result === undefined) { - result = elements.slice(0, i); - } - - result.push(element); - } - } - - if (result !== undefined) { - return setTextRange(createNodeArray(result, elements.hasTrailingComma), elements); - } - - return elements; - } - - export function parenthesizeExpressionForList(expression: Expression) { - const emittedExpression = skipPartiallyEmittedExpressions(expression); - const expressionPrecedence = getExpressionPrecedence(emittedExpression); - const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); - return expressionPrecedence > commaPrecedence - ? expression - : setTextRange(createParen(expression), expression); - } - - export function parenthesizeExpressionForExpressionStatement(expression: Expression) { - const emittedExpression = skipPartiallyEmittedExpressions(expression); - if (isCallExpression(emittedExpression)) { - const callee = emittedExpression.expression; - const kind = skipPartiallyEmittedExpressions(callee).kind; - if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) { - const mutableCall = getMutableClone(emittedExpression); - mutableCall.expression = setTextRange(createParen(callee), callee); - return recreateOuterExpressions(expression, mutableCall, OuterExpressionKinds.PartiallyEmittedExpressions); - } - } - - const leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; - if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) { - return setTextRange(createParen(expression), expression); - } - - return expression; - } - - export function parenthesizeConditionalTypeMember(member: TypeNode) { - return member.kind === SyntaxKind.ConditionalType ? createParenthesizedType(member) : member; - } - - export function parenthesizeElementTypeMember(member: TypeNode) { - switch (member.kind) { - case SyntaxKind.UnionType: - case SyntaxKind.IntersectionType: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - return createParenthesizedType(member); - } - return parenthesizeConditionalTypeMember(member); - } - - export function parenthesizeArrayTypeMember(member: TypeNode) { - switch (member.kind) { - case SyntaxKind.TypeQuery: - case SyntaxKind.TypeOperator: - case SyntaxKind.InferType: - return createParenthesizedType(member); - } - return parenthesizeElementTypeMember(member); - } - - export function parenthesizeElementTypeMembers(members: readonly TypeNode[]) { - return createNodeArray(sameMap(members, parenthesizeElementTypeMember)); - } - - export function parenthesizeTypeParameters(typeParameters: readonly TypeNode[] | undefined) { - if (some(typeParameters)) { - const params: TypeNode[] = []; - for (let i = 0; i < typeParameters.length; ++i) { - const entry = typeParameters[i]; - params.push(i === 0 && isFunctionOrConstructorTypeNode(entry) && entry.typeParameters ? - createParenthesizedType(entry) : - entry); - } - - return createNodeArray(params); - } - } - - export function getLeftmostExpression(node: Expression, stopAtCallExpressions: boolean) { - while (true) { - switch (node.kind) { - case SyntaxKind.PostfixUnaryExpression: - node = (node).operand; - continue; - - case SyntaxKind.BinaryExpression: - node = (node).left; - continue; - - case SyntaxKind.ConditionalExpression: - node = (node).condition; - continue; - - case SyntaxKind.TaggedTemplateExpression: - node = (node).tag; - continue; - - case SyntaxKind.CallExpression: - if (stopAtCallExpressions) { - return node; - } - // falls through - case SyntaxKind.AsExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.NonNullExpression: - case SyntaxKind.PartiallyEmittedExpression: - node = (node).expression; - continue; - } - - return node; - } - - } - - export function parenthesizeConciseBody(body: ConciseBody): ConciseBody { - if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { - return setTextRange(createParen(body), body); - } - - return body; - } - - export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token} | CommaListExpression { - return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.CommaToken || - node.kind === SyntaxKind.CommaListExpression; - } - - export const enum OuterExpressionKinds { - Parentheses = 1 << 0, - Assertions = 1 << 1, - PartiallyEmittedExpressions = 1 << 2, - - All = Parentheses | Assertions | PartiallyEmittedExpressions - } - - export type OuterExpression = ParenthesizedExpression | TypeAssertion | AsExpression | NonNullExpression | PartiallyEmittedExpression; - - export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { - switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: - return (kinds & OuterExpressionKinds.Parentheses) !== 0; - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.NonNullExpression: - return (kinds & OuterExpressionKinds.Assertions) !== 0; - case SyntaxKind.PartiallyEmittedExpression: - return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; - } - return false; - } - - export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; - export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; - export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { - let previousNode: Node; - do { - previousNode = node; - if (kinds & OuterExpressionKinds.Parentheses) { - node = skipParentheses(node); - } - - if (kinds & OuterExpressionKinds.Assertions) { - node = skipAssertions(node); - } - - if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) { - node = skipPartiallyEmittedExpressions(node); - } - } - while (previousNode !== node); - - return node; - } - - export function skipAssertions(node: Expression): Expression; - export function skipAssertions(node: Node): Node; - export function skipAssertions(node: Node): Node { - while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) { - node = (node).expression; - } - - return node; - } - - function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) { - switch (outerExpression.kind) { - case SyntaxKind.ParenthesizedExpression: return updateParen(outerExpression, expression); - case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression); - case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type); - case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression); - case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); - } - } - - /** - * Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions. - * - * A parenthesized expression can be ignored when all of the following are true: - * - * - It's `pos` and `end` are not -1 - * - It does not have a custom source map range - * - It does not have a custom comment range - * - It does not have synthetic leading or trailing comments - * - * If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around - * the expression to maintain precedence, a new parenthesized expression should be created automatically when - * the containing expression is created/updated. - */ - function isIgnorableParen(node: Expression) { - return node.kind === SyntaxKind.ParenthesizedExpression - && nodeIsSynthesized(node) - && nodeIsSynthesized(getSourceMapRange(node)) - && nodeIsSynthesized(getCommentRange(node)) - && !some(getSyntheticLeadingComments(node)) - && !some(getSyntheticTrailingComments(node)); - } - - export function recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression { - if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { - return updateOuterExpression( - outerExpression, - recreateOuterExpressions(outerExpression.expression, innerExpression) - ); - } - return innerExpression; - } - - export function startOnNewLine(node: T): T { - return setStartsOnNewLine(node, /*newLine*/ true); - } - - export function getExternalHelpersModuleName(node: SourceFile) { - const parseNode = getOriginalNode(node, isSourceFile); - const emitNode = parseNode && parseNode.emitNode; - return emitNode && emitNode.externalHelpersModuleName; - } - - export function hasRecordedExternalHelpers(sourceFile: SourceFile) { - const parseNode = getOriginalNode(sourceFile, isSourceFile); - const emitNode = parseNode && parseNode.emitNode; - return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); - } - - export function createExternalHelpersImportDeclarationIfNeeded(sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { - if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { - let namedBindings: NamedImportBindings | undefined; - const moduleKind = getEmitModuleKind(compilerOptions); - if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) { - // use named imports - const helpers = getEmitHelpers(sourceFile); - if (helpers) { - const helperNames: string[] = []; - for (const helper of helpers) { - if (!helper.scoped) { - const importName = (helper as UnscopedEmitHelper).importName; - if (importName) { - pushIfUnique(helperNames, importName); - } - } - } - if (some(helperNames)) { - helperNames.sort(compareStringsCaseSensitive); - // Alias the imports if the names are used somewhere in the file. - // NOTE: We don't need to care about global import collisions as this is a module. - namedBindings = createNamedImports( - map(helperNames, name => isFileLevelUniqueName(sourceFile, name) - ? createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name)) - : createImportSpecifier(createIdentifier(name), getUnscopedHelperName(name)) - ) - ); - const parseNode = getOriginalNode(sourceFile, isSourceFile); - const emitNode = getOrCreateEmitNode(parseNode); - emitNode.externalHelpers = true; - } - } - } - else { - // use a namespace import - const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault); - if (externalHelpersModuleName) { - namedBindings = createNamespaceImport(externalHelpersModuleName); - } - } - if (namedBindings) { - const externalHelpersImportDeclaration = createImportDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, - createImportClause(/*name*/ undefined, namedBindings), - createLiteral(externalHelpersModuleNameText) - ); - addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper); - return externalHelpersImportDeclaration; - } - } - } - - export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { - if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { - const externalHelpersModuleName = getExternalHelpersModuleName(node); - if (externalHelpersModuleName) { - return externalHelpersModuleName; - } - - const moduleKind = getEmitModuleKind(compilerOptions); - let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault)) - && moduleKind !== ModuleKind.System - && moduleKind !== ModuleKind.ES2015 - && moduleKind !== ModuleKind.ESNext; - if (!create) { - const helpers = getEmitHelpers(node); - if (helpers) { - for (const helper of helpers) { - if (!helper.scoped) { - create = true; - break; - } - } - } - } - - if (create) { - const parseNode = getOriginalNode(node, isSourceFile); - const emitNode = getOrCreateEmitNode(parseNode); - return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText)); - } - } - } - - /** - * Get the name of that target module from an import or export declaration - */ - export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { - const namespaceDeclaration = getNamespaceDeclarationNode(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - const name = namespaceDeclaration.name; - return isGeneratedIdentifier(name) ? name : createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); - } - if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { - return getGeneratedNameForNode(node); - } - if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) { - return getGeneratedNameForNode(node); - } - return undefined; - } - - /** - * Get the name of a target module from an import/export declaration as should be written in the emitted output. - * The emitted output name can be different from the input if: - * 1. The module has a /// - * 2. --out or --outFile is used, making the name relative to the rootDir - * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). - * Otherwise, a new StringLiteral node representing the module name will be returned. - */ - export function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { - const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 - if (moduleName.kind === SyntaxKind.StringLiteral) { - return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) - || tryRenameExternalModule(moduleName, sourceFile) - || getSynthesizedClone(moduleName); - } - - return undefined; - } - - /** - * Some bundlers (SystemJS builder) sometimes want to rename dependencies. - * Here we check if alternative name was provided for a given moduleName and return it if possible. - */ - function tryRenameExternalModule(moduleName: LiteralExpression, sourceFile: SourceFile) { - const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); - return rename && createLiteral(rename); - } - - /** - * Get the name of a module as should be written in the emitted output. - * The emitted output name can be different from the input if: - * 1. The module has a /// - * 2. --out or --outFile is used, making the name relative to the rootDir - * Otherwise, a new StringLiteral node representing the module name will be returned. - */ - export function tryGetModuleNameFromFile(file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { - if (!file) { - return undefined; - } - if (file.moduleName) { - return createLiteral(file.moduleName); - } - if (!file.isDeclarationFile && (options.out || options.outFile)) { - return createLiteral(getExternalModuleNameFromPath(host, file.fileName)); - } - return undefined; - } - - function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { - return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); - } - - /** - * Gets the initializer of an BindingOrAssignmentElement. - */ - export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { - if (isDeclarationBindingElement(bindingElement)) { - // `1` in `let { a = 1 } = ...` - // `1` in `let { a: b = 1 } = ...` - // `1` in `let { a: {b} = 1 } = ...` - // `1` in `let { a: [b] = 1 } = ...` - // `1` in `let [a = 1] = ...` - // `1` in `let [{a} = 1] = ...` - // `1` in `let [[a] = 1] = ...` - return bindingElement.initializer; - } - - if (isPropertyAssignment(bindingElement)) { - // `1` in `({ a: b = 1 } = ...)` - // `1` in `({ a: {b} = 1 } = ...)` - // `1` in `({ a: [b] = 1 } = ...)` - const initializer = bindingElement.initializer; - return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) - ? initializer.right - : undefined; - } - - if (isShorthandPropertyAssignment(bindingElement)) { - // `1` in `({ a = 1 } = ...)` - return bindingElement.objectAssignmentInitializer; - } - - if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { - // `1` in `[a = 1] = ...` - // `1` in `[{a} = 1] = ...` - // `1` in `[[a] = 1] = ...` - return bindingElement.right; - } - - if (isSpreadElement(bindingElement)) { - // Recovery consistent with existing emit. - return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); - } - } - - /** - * Gets the name of an BindingOrAssignmentElement. - */ - export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { - if (isDeclarationBindingElement(bindingElement)) { - // `a` in `let { a } = ...` - // `a` in `let { a = 1 } = ...` - // `b` in `let { a: b } = ...` - // `b` in `let { a: b = 1 } = ...` - // `a` in `let { ...a } = ...` - // `{b}` in `let { a: {b} } = ...` - // `{b}` in `let { a: {b} = 1 } = ...` - // `[b]` in `let { a: [b] } = ...` - // `[b]` in `let { a: [b] = 1 } = ...` - // `a` in `let [a] = ...` - // `a` in `let [a = 1] = ...` - // `a` in `let [...a] = ...` - // `{a}` in `let [{a}] = ...` - // `{a}` in `let [{a} = 1] = ...` - // `[a]` in `let [[a]] = ...` - // `[a]` in `let [[a] = 1] = ...` - return bindingElement.name; - } - - if (isObjectLiteralElementLike(bindingElement)) { - switch (bindingElement.kind) { - case SyntaxKind.PropertyAssignment: - // `b` in `({ a: b } = ...)` - // `b` in `({ a: b = 1 } = ...)` - // `{b}` in `({ a: {b} } = ...)` - // `{b}` in `({ a: {b} = 1 } = ...)` - // `[b]` in `({ a: [b] } = ...)` - // `[b]` in `({ a: [b] = 1 } = ...)` - // `b.c` in `({ a: b.c } = ...)` - // `b.c` in `({ a: b.c = 1 } = ...)` - // `b[0]` in `({ a: b[0] } = ...)` - // `b[0]` in `({ a: b[0] = 1 } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); - - case SyntaxKind.ShorthandPropertyAssignment: - // `a` in `({ a } = ...)` - // `a` in `({ a = 1 } = ...)` - return bindingElement.name; - - case SyntaxKind.SpreadAssignment: - // `a` in `({ ...a } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression); - } - - // no target - return undefined; - } - - if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { - // `a` in `[a = 1] = ...` - // `{a}` in `[{a} = 1] = ...` - // `[a]` in `[[a] = 1] = ...` - // `a.b` in `[a.b = 1] = ...` - // `a[0]` in `[a[0] = 1] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.left); - } - - if (isSpreadElement(bindingElement)) { - // `a` in `[...a] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression); - } - - // `a` in `[a] = ...` - // `{a}` in `[{a}] = ...` - // `[a]` in `[[a]] = ...` - // `a.b` in `[a.b] = ...` - // `a[0]` in `[a[0]] = ...` - return bindingElement; - } - - /** - * Determines whether an BindingOrAssignmentElement is a rest element. - */ - export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { - switch (bindingElement.kind) { - case SyntaxKind.Parameter: - case SyntaxKind.BindingElement: - // `...` in `let [...a] = ...` - return bindingElement.dotDotDotToken; - - case SyntaxKind.SpreadElement: - case SyntaxKind.SpreadAssignment: - // `...` in `[...a] = ...` - return bindingElement; - } - - return undefined; - } - - /** - * Gets the property name of a BindingOrAssignmentElement - */ - export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { - const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement); - Debug.assert(!!propertyName || isSpreadAssignment(bindingElement), "Invalid property name for binding element."); - return propertyName; - } - - export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { - switch (bindingElement.kind) { - case SyntaxKind.BindingElement: - // `a` in `let { a: b } = ...` - // `[a]` in `let { [a]: b } = ...` - // `"a"` in `let { "a": b } = ...` - // `1` in `let { 1: b } = ...` - if (bindingElement.propertyName) { - const propertyName = bindingElement.propertyName; - return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) - ? propertyName.expression - : propertyName; - } - - break; - - case SyntaxKind.PropertyAssignment: - // `a` in `({ a: b } = ...)` - // `[a]` in `({ [a]: b } = ...)` - // `"a"` in `({ "a": b } = ...)` - // `1` in `({ 1: b } = ...)` - if (bindingElement.name) { - const propertyName = bindingElement.name; - return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) - ? propertyName.expression - : propertyName; - } - - break; - - case SyntaxKind.SpreadAssignment: - // `a` in `({ ...a } = ...)` - return bindingElement.name; - } - - const target = getTargetOfBindingOrAssignmentElement(bindingElement); - if (target && isPropertyName(target)) { - return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression) - ? target.expression - : target; - } - } - - function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral { - const kind = node.kind; - return kind === SyntaxKind.StringLiteral - || kind === SyntaxKind.NumericLiteral; - } - - /** - * Gets the elements of a BindingOrAssignmentPattern - */ - export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { - switch (name.kind) { - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ArrayLiteralExpression: - // `a` in `{a}` - // `a` in `[a]` - return name.elements; - - case SyntaxKind.ObjectLiteralExpression: - // `a` in `{a}` - return name.properties; - } - } - - export function convertToArrayAssignmentElement(element: BindingOrAssignmentElement) { - if (isBindingElement(element)) { - if (element.dotDotDotToken) { - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(createSpread(element.name), element), element); - } - const expression = convertToAssignmentElementTarget(element.name); - return element.initializer - ? setOriginalNode( - setTextRange( - createAssignment(expression, element.initializer), - element - ), - element - ) - : expression; - } - Debug.assertNode(element, isExpression); - return element; - } - - export function convertToObjectAssignmentElement(element: BindingOrAssignmentElement) { - if (isBindingElement(element)) { - if (element.dotDotDotToken) { - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(createSpreadAssignment(element.name), element), element); - } - if (element.propertyName) { - const expression = convertToAssignmentElementTarget(element.name); - return setOriginalNode(setTextRange(createPropertyAssignment(element.propertyName, element.initializer ? createAssignment(expression, element.initializer) : expression), element), element); - } - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(createShorthandPropertyAssignment(element.name, element.initializer), element), element); - } - Debug.assertNode(element, isObjectLiteralElementLike); - return element; - } - - export function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern { - switch (node.kind) { - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ArrayLiteralExpression: - return convertToArrayAssignmentPattern(node); - - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ObjectLiteralExpression: - return convertToObjectAssignmentPattern(node); - } - } - - export function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { - if (isObjectBindingPattern(node)) { - return setOriginalNode( - setTextRange( - createObjectLiteral(map(node.elements, convertToObjectAssignmentElement)), - node - ), - node - ); - } - Debug.assertNode(node, isObjectLiteralExpression); - return node; - } - - export function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { - if (isArrayBindingPattern(node)) { - return setOriginalNode( - setTextRange( - createArrayLiteral(map(node.elements, convertToArrayAssignmentElement)), - node - ), - node - ); - } - Debug.assertNode(node, isArrayLiteralExpression); - return node; - } - - export function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression { - if (isBindingPattern(node)) { - return convertToAssignmentPattern(node); - } - - Debug.assertNode(node, isExpression); - return node; - } -} diff --git a/src/compiler/factory/baseNodeFactory.ts b/src/compiler/factory/baseNodeFactory.ts new file mode 100644 index 0000000000000..9d4a25ea305b1 --- /dev/null +++ b/src/compiler/factory/baseNodeFactory.ts @@ -0,0 +1,45 @@ +/* @internal */ +namespace ts { + /* @internal */ + export interface BaseNodeFactory { + createBaseSourceFileNode(kind: SyntaxKind): Node; + createBaseIdentifierNode(kind: SyntaxKind): Node; + createBaseTokenNode(kind: SyntaxKind): Node; + createBaseNode(kind: SyntaxKind): Node; + } + + /** + * Creates a `BaseNodeFactory` which can be used to create `Nodes` from the constructors provided by the object allocator. + */ + export function createBaseNodeFactory(): BaseNodeFactory { + // tslint:disable variable-name + let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + // tslint:enable variable-name + + return { + createBaseSourceFileNode, + createBaseIdentifierNode, + createBaseTokenNode, + createBaseNode + }; + + function createBaseSourceFileNode(kind: SyntaxKind): Node { + return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseIdentifierNode(kind: SyntaxKind): Node { + return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseTokenNode(kind: SyntaxKind): Node { + return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseNode(kind: SyntaxKind): Node { + return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + } +} \ No newline at end of file diff --git a/src/compiler/factory/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts new file mode 100644 index 0000000000000..db8a0f82c13f6 --- /dev/null +++ b/src/compiler/factory/emitHelpers.ts @@ -0,0 +1,793 @@ +/* @internal */ +namespace ts { + export interface EmitHelperFactory { + getUnscopedHelperName(name: string): Identifier; + // TypeScript Helpers + createDecorateHelper(decoratorExpressions: readonly Expression[], target: Expression, memberName?: Expression, descriptor?: Expression): Expression; + createMetadataHelper(metadataKey: string, metadataValue: Expression): Expression; + createParamHelper(expression: Expression, parameterOffset: number): Expression; + // ES2018 Helpers + createAssignHelper(attributesSegments: readonly Expression[]): Expression; + createAwaitHelper(expression: Expression): Expression; + createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean): Expression; + createAsyncDelegatorHelper(expression: Expression): Expression; + createAsyncValuesHelper(expression: Expression): Expression; + // ES2018 Destructuring Helpers + createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[]): Expression; + // ES2017 Helpers + createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block): Expression; + // ES2015 Helpers + createExtendsHelper(name: Identifier): Expression; + createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression): Expression; + createSpreadHelper(argumentList: readonly Expression[]): Expression; + createSpreadArraysHelper(argumentList: readonly Expression[]): Expression; + // ES2015 Destructuring Helpers + createValuesHelper(expression: Expression): Expression; + createReadHelper(iteratorRecord: Expression, count: number | undefined): Expression; + // ES2015 Generator Helpers + createGeneratorHelper(body: FunctionExpression): Expression; + // ES Module Helpers + createImportStarHelper(expression: Expression): Expression; + createImportStarCallbackHelper(): Expression; + createImportDefaultHelper(expression: Expression): Expression; + } + + export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory { + const factory = context.factory; + return { + getUnscopedHelperName, + // TypeScript Helpers + createDecorateHelper, + createMetadataHelper, + createParamHelper, + // ES2018 Helpers + createAssignHelper, + createAwaitHelper, + createAsyncGeneratorHelper, + createAsyncDelegatorHelper, + createAsyncValuesHelper, + // ES2018 Destructuring Helpers + createRestHelper, + // ES2017 Helpers + createAwaiterHelper, + // ES2015 Helpers + createExtendsHelper, + createTemplateObjectHelper, + createSpreadHelper, + createSpreadArraysHelper, + // ES2015 Destructuring Helpers + createValuesHelper, + createReadHelper, + // ES2015 Generator Helpers + createGeneratorHelper, + // ES Module Helpers + createImportStarHelper, + createImportStarCallbackHelper, + createImportDefaultHelper, + }; + + /** + * Gets an identifier for the name of an *unscoped* emit helper. + */ + function getUnscopedHelperName(name: string) { + return setEmitFlags(factory.createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode); + } + + // TypeScript Helpers + + function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) { + context.requestEmitHelper(decorateHelper); + + const argumentsArray: Expression[] = []; + argumentsArray.push(factory.createArrayLiteral(decoratorExpressions, /*multiLine*/ true)); + argumentsArray.push(target); + if (memberName) { + argumentsArray.push(memberName); + if (descriptor) { + argumentsArray.push(descriptor); + } + } + + return factory.createCall( + getUnscopedHelperName("__decorate"), + /*typeArguments*/ undefined, + argumentsArray + ); + } + + function createMetadataHelper(metadataKey: string, metadataValue: Expression) { + context.requestEmitHelper(metadataHelper); + return factory.createCall( + getUnscopedHelperName("__metadata"), + /*typeArguments*/ undefined, + [ + factory.createStringLiteral(metadataKey), + metadataValue + ] + ); + } + + function createParamHelper(expression: Expression, parameterOffset: number, location?: TextRange) { + context.requestEmitHelper(paramHelper); + return setTextRange( + factory.createCall( + getUnscopedHelperName("__param"), + /*typeArguments*/ undefined, + [ + factory.createNumericLiteral(parameterOffset + ""), + expression + ] + ), + location + ); + } + + // ES2018 Helpers + + function createAssignHelper(attributesSegments: Expression[]) { + if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) { + return factory.createCall(factory.createPropertyAccess(factory.createIdentifier("Object"), "assign"), + /*typeArguments*/ undefined, + attributesSegments); + } + context.requestEmitHelper(assignHelper); + return factory.createCall( + getUnscopedHelperName("__assign"), + /*typeArguments*/ undefined, + attributesSegments + ); + } + + function createAwaitHelper(expression: Expression) { + context.requestEmitHelper(awaitHelper); + return factory.createCall(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]); + } + + function createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean) { + context.requestEmitHelper(awaitHelper); + context.requestEmitHelper(asyncGeneratorHelper); + + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody; + + return factory.createCall( + getUnscopedHelperName("__asyncGenerator"), + /*typeArguments*/ undefined, + [ + hasLexicalThis ? factory.createThis() : factory.createVoidZero(), + factory.createIdentifier("arguments"), + generatorFunc + ] + ); + } + + function createAsyncDelegatorHelper(expression: Expression) { + context.requestEmitHelper(awaitHelper); + context.requestEmitHelper(asyncDelegator); + return factory.createCall( + getUnscopedHelperName("__asyncDelegator"), + /*typeArguments*/ undefined, + [expression] + ); + } + + function createAsyncValuesHelper(expression: Expression) { + context.requestEmitHelper(asyncValues); + return factory.createCall( + getUnscopedHelperName("__asyncValues"), + /*typeArguments*/ undefined, + [expression] + ); + } + + // ES2018 Destructuring Helpers + + /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement + * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` + */ + function createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[]): Expression { + context.requestEmitHelper(restHelper); + const propertyNames: Expression[] = []; + let computedTempVariableOffset = 0; + for (let i = 0; i < elements.length - 1; i++) { + const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); + if (propertyName) { + if (isComputedPropertyName(propertyName)) { + const temp = computedTempVariables[computedTempVariableOffset]; + computedTempVariableOffset++; + // typeof _tmp === "symbol" ? _tmp : _tmp + "" + propertyNames.push( + factory.createConditional( + factory.createTypeCheck(temp, "symbol"), + /*questionToken*/ undefined, + temp, + /*colonToken*/ undefined, + factory.createAdd(temp, factory.createStringLiteral("")) + ) + ); + } + else { + propertyNames.push(factory.createStringLiteralFromNode(propertyName)); + } + } + } + return factory.createCall( + getUnscopedHelperName("__rest"), + /*typeArguments*/ undefined, + [value, factory.createArrayLiteral(propertyNames)] + ); + } + + // ES2017 Helpers + + function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) { + context.requestEmitHelper(awaiterHelper); + + const generatorFunc = factory.createFunctionExpression( + /*modifiers*/ undefined, + factory.createToken(SyntaxKind.AsteriskToken), + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, + body + ); + + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; + + return factory.createCall( + getUnscopedHelperName("__awaiter"), + /*typeArguments*/ undefined, + [ + hasLexicalThis ? factory.createThis() : factory.createVoidZero(), + hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZero(), + promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(), + generatorFunc + ] + ); + } + + // ES2015 Helpers + + function createExtendsHelper(name: Identifier) { + context.requestEmitHelper(extendsHelper); + return factory.createCall( + getUnscopedHelperName("__extends"), + /*typeArguments*/ undefined, + [name, factory.createFileLevelUniqueName("_super")] + ); + } + + function createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) { + context.requestEmitHelper(templateObjectHelper); + return factory.createCall( + getUnscopedHelperName("__makeTemplateObject"), + /*typeArguments*/ undefined, + [cooked, raw] + ); + } + + function createSpreadHelper(argumentList: readonly Expression[]) { + context.requestEmitHelper(readHelper); + context.requestEmitHelper(spreadHelper); + return factory.createCall( + getUnscopedHelperName("__spread"), + /*typeArguments*/ undefined, + argumentList + ); + } + + function createSpreadArraysHelper(argumentList: readonly Expression[]) { + context.requestEmitHelper(spreadArraysHelper); + return factory.createCall( + getUnscopedHelperName("__spreadArrays"), + /*typeArguments*/ undefined, + argumentList + ); + } + + // ES2015 Destructuring Helpers + + function createValuesHelper(expression: Expression) { + context.requestEmitHelper(valuesHelper); + return factory.createCall( + getUnscopedHelperName("__values"), + /*typeArguments*/ undefined, + [expression] + ); + } + + function createReadHelper(iteratorRecord: Expression, count: number | undefined) { + context.requestEmitHelper(readHelper); + return factory.createCall( + getUnscopedHelperName("__read"), + /*typeArguments*/ undefined, + count !== undefined + ? [iteratorRecord, factory.createNumericLiteral(count + "")] + : [iteratorRecord] + ); + } + + // ES2015 Generator Helpers + + function createGeneratorHelper(body: FunctionExpression) { + context.requestEmitHelper(generatorHelper); + return factory.createCall( + getUnscopedHelperName("__generator"), + /*typeArguments*/ undefined, + [factory.createThis(), body]); + } + + // ES Module Helpers + + function createImportStarHelper(expression: Expression) { + context.requestEmitHelper(importStarHelper); + return factory.createCall( + getUnscopedHelperName("__importStar"), + /*typeArguments*/ undefined, + [expression] + ); + } + + function createImportStarCallbackHelper() { + context.requestEmitHelper(importStarHelper); + return getUnscopedHelperName("__importStar"); + } + + function createImportDefaultHelper(expression: Expression) { + context.requestEmitHelper(importDefaultHelper); + return factory.createCall( + getUnscopedHelperName("__importDefault"), + /*typeArguments*/ undefined, + [expression] + ); + } + } + + /* @internal */ + export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { + if (x === y) return Comparison.EqualTo; + if (x.priority === y.priority) return Comparison.EqualTo; + if (x.priority === undefined) return Comparison.GreaterThan; + if (y.priority === undefined) return Comparison.LessThan; + return compareValues(x.priority, y.priority); + } + + /** + * @param input Template string input strings + * @param args Names which need to be made file-level unique + */ + export function helperString(input: TemplateStringsArray, ...args: string[]) { + return (uniqueName: EmitHelperUniqueNameCallback) => { + let result = ""; + for (let i = 0; i < args.length; i++) { + result += input[i]; + result += uniqueName(args[i]); + } + result += input[input.length - 1]; + return result; + }; + } + + // TypeScript Helpers + + export const decorateHelper: UnscopedEmitHelper = { + name: "typescript:decorate", + importName: "__decorate", + scoped: false, + priority: 2, + text: ` + var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + };` + }; + + export const metadataHelper: UnscopedEmitHelper = { + name: "typescript:metadata", + importName: "__metadata", + scoped: false, + priority: 3, + text: ` + var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); + };` + }; + + export const paramHelper: UnscopedEmitHelper = { + name: "typescript:param", + importName: "__param", + scoped: false, + priority: 4, + text: ` + var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + };` + }; + + // ES2018 Helpers + + export const assignHelper: UnscopedEmitHelper = { + name: "typescript:assign", + importName: "__assign", + scoped: false, + priority: 1, + text: ` + var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + };` + }; + + export const awaitHelper: UnscopedEmitHelper = { + name: "typescript:await", + importName: "__await", + scoped: false, + text: ` + var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }` + }; + + export const asyncGeneratorHelper: UnscopedEmitHelper = { + name: "typescript:asyncGenerator", + importName: "__asyncGenerator", + scoped: false, + text: ` + var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + };` + }; + + export const asyncDelegator: UnscopedEmitHelper = { + name: "typescript:asyncDelegator", + importName: "__asyncDelegator", + scoped: false, + text: ` + var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } + };` + }; + + export const asyncValues: UnscopedEmitHelper = { + name: "typescript:asyncValues", + importName: "__asyncValues", + scoped: false, + text: ` + var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + };` + }; + + // ES2018 Destructuring Helpers + + export const restHelper: UnscopedEmitHelper = { + name: "typescript:rest", + importName: "__rest", + scoped: false, + text: ` + var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + };` + }; + + // ES2017 Helpers + + export const awaiterHelper: UnscopedEmitHelper = { + name: "typescript:awaiter", + importName: "__awaiter", + scoped: false, + priority: 5, + text: ` + var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + };` + }; + + // ES2015 Helpers + + export const extendsHelper: UnscopedEmitHelper = { + name: "typescript:extends", + importName: "__extends", + scoped: false, + priority: 0, + text: ` + var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })();` + }; + + export const templateObjectHelper: UnscopedEmitHelper = { + name: "typescript:makeTemplateObject", + importName: "__makeTemplateObject", + scoped: false, + priority: 0, + text: ` + var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + };` + }; + + export const spreadHelper: UnscopedEmitHelper = { + name: "typescript:spread", + importName: "__spread", + scoped: false, + text: ` + var __spread = (this && this.__spread) || function () { + for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); + return ar; + };` + }; + + export const spreadArraysHelper: UnscopedEmitHelper = { + name: "typescript:spreadArrays", + importName: "__spreadArrays", + scoped: false, + text: ` + var __spreadArrays = (this && this.__spreadArrays) || function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + };` + }; + + // ES2015 Destructuring Helpers + + export const valuesHelper: UnscopedEmitHelper = { + name: "typescript:values", + importName: "__values", + scoped: false, + text: ` + var __values = (this && this.__values) || function(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + };` + }; + + export const readHelper: UnscopedEmitHelper = { + name: "typescript:read", + importName: "__read", + scoped: false, + text: ` + var __read = (this && this.__read) || function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + };` + }; + + // ES2015 Generator Helpers + + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // @param thisArg The value to use as the `this` binding for the transformed generator body. + // @param body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts + export const generatorHelper: UnscopedEmitHelper = { + name: "typescript:generator", + importName: "__generator", + scoped: false, + priority: 6, + text: ` + var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + };` + }; + + // ES Module Helpers + + // emit helper for `import * as Name from "foo"` + export const importStarHelper: UnscopedEmitHelper = { + name: "typescript:commonjsimportstar", + importName: "__importStar", + scoped: false, + text: ` + var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; + };` + }; + + // emit helper for `import Name from "foo"` + export const importDefaultHelper: UnscopedEmitHelper = { + name: "typescript:commonjsimportdefault", + importName: "__importDefault", + scoped: false, + text: ` + var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + };` + }; + + let allUnscopedEmitHelpers: ReadonlyMap | undefined; + + export function getAllUnscopedEmitHelpers() { + return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([ + decorateHelper, + metadataHelper, + paramHelper, + assignHelper, + awaitHelper, + asyncGeneratorHelper, + asyncDelegator, + asyncValues, + restHelper, + awaiterHelper, + extendsHelper, + templateObjectHelper, + spreadHelper, + spreadArraysHelper, + valuesHelper, + readHelper, + generatorHelper, + importStarHelper, + importDefaultHelper + ], helper => helper.name)); + } + + export const asyncSuperHelper: EmitHelper = { + name: "typescript:async-super", + scoped: true, + text: helperString` + const ${"_superIndex"} = name => super[name];` + }; + + export const advancedAsyncSuperHelper: EmitHelper = { + name: "typescript:advanced-async-super", + scoped: true, + text: helperString` + const ${"_superIndex"} = (function (geti, seti) { + const cache = Object.create(null); + return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + })(name => super[name], (name, value) => super[name] = value);` + }; +} \ No newline at end of file diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts new file mode 100644 index 0000000000000..d4b35d99aea99 --- /dev/null +++ b/src/compiler/factory/emitNode.ts @@ -0,0 +1,270 @@ +namespace ts { + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + export function disposeEmitNodes(sourceFile: SourceFile | undefined) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); + const emitNode = sourceFile && sourceFile.emitNode; + const annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (const node of annotatedNodes) { + node.emitNode = undefined; + } + } + } + + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + */ + /* @internal */ + export function getOrCreateEmitNode(node: Node): EmitNode { + if (!node.emitNode) { + if (isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === SyntaxKind.SourceFile) { + return node.emitNode = { annotatedNodes: [node] } as EmitNode; + } + + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) || Debug.fail("Could not determine parsed source file."); + getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); + } + + node.emitNode = {} as EmitNode; + } + + return node.emitNode; + } + + /** + * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. + * @internal + */ + export function removeAllComments(node: T): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags |= EmitFlags.NoComments; + emitNode.leadingComments = undefined; + emitNode.trailingComments = undefined; + return node; + } + + /** + * Sets flags that control emit behavior of a node. + */ + export function setEmitFlags(node: T, emitFlags: EmitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + + /** + * Sets flags that control emit behavior of a node. + */ + /* @internal */ + export function addEmitFlags(node: T, emitFlags: EmitFlags) { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags = emitNode.flags | emitFlags; + return node; + } + + /** + * Gets a custom text range to use when emitting source maps. + */ + export function getSourceMapRange(node: Node): SourceMapRange { + const emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + + /** + * Sets a custom text range to use when emitting source maps. + */ + export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + + /** + * Gets the TextRange to use for source maps for a token of a node. + */ + export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { + const emitNode = node.emitNode; + const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } + + /** + * Sets the TextRange to use for source maps for a token of a node. + */ + export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { + const emitNode = getOrCreateEmitNode(node); + const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); + tokenSourceMapRanges[token] = range; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function getStartsOnNewLine(node: Node) { + const emitNode = node.emitNode; + return emitNode && emitNode.startsOnNewLine; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function setStartsOnNewLine(node: T, newLine: boolean) { + getOrCreateEmitNode(node).startsOnNewLine = newLine; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + */ + export function getCommentRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + export function setCommentRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + + export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.leadingComments; + } + + export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { + getOrCreateEmitNode(node).leadingComments = comments; + return node; + } + + export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); + } + + export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.trailingComments; + } + + export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { + getOrCreateEmitNode(node).trailingComments = comments; + return node; + } + + export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); + } + + export function moveSyntheticComments(node: T, original: Node): T { + setSyntheticLeadingComments(node, getSyntheticLeadingComments(original)); + setSyntheticTrailingComments(node, getSyntheticTrailingComments(original)); + const emit = getOrCreateEmitNode(original); + emit.leadingComments = undefined; + emit.trailingComments = undefined; + return node; + } + + /** + * Gets the constant value to emit for an expression. + */ + export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.constantValue; + } + + /** + * Sets the constant value to emit for an expression. + */ + export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number) { + const emitNode = getOrCreateEmitNode(node); + emitNode.constantValue = value; + return node; + } + + /** + * Adds an EmitHelper to a node. + */ + export function addEmitHelper(node: T, helper: EmitHelper): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.helpers = append(emitNode.helpers, helper); + return node; + } + + /** + * Add EmitHelpers to a node. + */ + export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { + if (some(helpers)) { + const emitNode = getOrCreateEmitNode(node); + for (const helper of helpers) { + emitNode.helpers = appendIfUnique(emitNode.helpers, helper); + } + } + return node; + } + + /** + * Removes an EmitHelper from a node. + */ + export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { + const emitNode = node.emitNode; + if (emitNode) { + const helpers = emitNode.helpers; + if (helpers) { + return orderedRemoveItem(helpers, helper); + } + } + return false; + } + + /** + * Gets the EmitHelpers of a node. + */ + export function getEmitHelpers(node: Node): EmitHelper[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.helpers; + } + + /** + * Moves matching emit helpers from a source node to a target node. + */ + export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { + const sourceEmitNode = source.emitNode; + const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; + if (!some(sourceEmitHelpers)) return; + + const targetEmitNode = getOrCreateEmitNode(target); + let helpersRemoved = 0; + for (let i = 0; i < sourceEmitHelpers.length; i++) { + const helper = sourceEmitHelpers[i]; + if (predicate(helper)) { + helpersRemoved++; + targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); + } + else if (helpersRemoved > 0) { + sourceEmitHelpers[i - helpersRemoved] = helper; + } + } + + if (helpersRemoved > 0) { + sourceEmitHelpers.length -= helpersRemoved; + } + } +} \ No newline at end of file diff --git a/src/compiler/factory/nodeConverters.ts b/src/compiler/factory/nodeConverters.ts new file mode 100644 index 0000000000000..7697117895f59 --- /dev/null +++ b/src/compiler/factory/nodeConverters.ts @@ -0,0 +1,137 @@ +/* @internal */ +namespace ts { + export function createNodeConverters(factory: NodeFactory): NodeConverters { + return { + convertToFunctionBlock, + convertToFunctionExpression, + convertToArrayAssignmentElement, + convertToObjectAssignmentElement, + convertToAssignmentPattern, + convertToObjectAssignmentPattern, + convertToArrayAssignmentPattern, + convertToAssignmentElementTarget, + }; + + function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block { + if (isBlock(node)) return node; + const returnStatement = factory.createReturn(node); + setTextRange(returnStatement, node); + const body = factory.createBlock([returnStatement], multiLine); + setTextRange(body, node); + return body; + } + + function convertToFunctionExpression(node: FunctionDeclaration) { + if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`); + const updated = factory.createFunctionExpression( + node.modifiers, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + node.body + ); + setOriginalNode(updated, node); + setTextRange(updated, node); + if (getStartsOnNewLine(node)) { + setStartsOnNewLine(updated, /*newLine*/ true); + } + return updated; + } + + function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) { + if (isBindingElement(element)) { + if (element.dotDotDotToken) { + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpread(element.name), element), element); + } + const expression = convertToAssignmentElementTarget(element.name); + return element.initializer + ? setOriginalNode( + setTextRange( + factory.createAssignment(expression, element.initializer), + element + ), + element + ) + : expression; + } + return cast(element, isExpression); + } + + function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) { + if (isBindingElement(element)) { + if (element.dotDotDotToken) { + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element); + } + if (element.propertyName) { + const expression = convertToAssignmentElementTarget(element.name); + return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); + } + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); + } + + return cast(element, isObjectLiteralElementLike); + } + + function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern { + switch (node.kind) { + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + return convertToArrayAssignmentPattern(node); + + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ObjectLiteralExpression: + return convertToObjectAssignmentPattern(node); + } + } + + function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { + if (isObjectBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createObjectLiteral(map(node.elements, convertToObjectAssignmentElement)), + node + ), + node + ); + } + return cast(node, isObjectLiteralExpression); + } + + function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { + if (isArrayBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createArrayLiteral(map(node.elements, convertToArrayAssignmentElement)), + node + ), + node + ); + } + return cast(node, isArrayLiteralExpression); + } + + function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression { + if (isBindingPattern(node)) { + return convertToAssignmentPattern(node); + } + + return cast(node, isExpression); + } + } + + export const nullNodeConverters: NodeConverters = { + convertToFunctionBlock: notImplemented, + convertToFunctionExpression: notImplemented, + convertToArrayAssignmentElement: notImplemented, + convertToObjectAssignmentElement: notImplemented, + convertToAssignmentPattern: notImplemented, + convertToObjectAssignmentPattern: notImplemented, + convertToArrayAssignmentPattern: notImplemented, + convertToAssignmentElementTarget: notImplemented, + }; +} \ No newline at end of file diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts new file mode 100644 index 0000000000000..e03006c2767b8 --- /dev/null +++ b/src/compiler/factory/nodeFactory.ts @@ -0,0 +1,5919 @@ +namespace ts { + let nextAutoGenerateId = 0; + + /* @internal */ + export const enum NodeFactoryFlags { + None = 0, + // Disables the parenthesizer rules for the factory. + NoParenthesizerRules = 1 << 0, + // Disables the node converters for the factory. + NoNodeConverters = 1 << 1, + // Ensures new `PropertyAccessExpression` nodes are created with the `NoIndentation` emit flag set. + NoIndentationOnFreshPropertyAccess = 1 << 2, + } + + /* @internal */ + export interface TreeStateObserver { + /** + * Observes the creation of a new `Node`. + */ + onCreateNode?(node: Node): void; + /** + * Observes when a child `Node` is attached to a parent `Node`. + * - This is not raised when a child is `undefined`. + * - This is raised *after* the child has been attached to the parent. + * - This is raised *before* the transform flags of the child have been aggregated into the parent. + * - The `parent` pointer for the child will likely be `undefined`. + */ + onSetChild?(parent: Node, child: Node): void; + /** + * Observes when a `NodeArray` of children is attached to a parent `Node`. + * - This is not raised when the array of children is `undefined`. + * - This is raised *after* the array of children has been attached to the parent. + * - This is raised *before* the transform flags of the child have been aggregated into the parent. + * - The `parent` pointer for each child in the array will likely be `undefined`. + */ + onSetChildren?(parent: Node, children: NodeArray): void; + /** + * Observes when a `Node` is "finished" (i.e. its child nodes have been attached). + * - This is raised *after* transform flags for the node have been aggregated. + * - The core members of the node should be considered immutable. + */ + onFinishNode?(node: Node): void; + /** + * Observes when a `Node` has been replaced with a node of the same `kind` in the syntax tree. + * - This is raised *before* the `original` pointer has been set for `updated`. + */ + onUpdateNode?(updated: Node, original: Node): void; + /** + * Observes when a `Node` has been reused in the syntax tree (i.e. after an `update` call). + */ + onReuseNode?(node: Node): void; + } + + /** + * Creates a `NodeFactory` that can be used to create and update a syntax tree. + * @param flags Flags that control factory behavior. + * @param baseFactory A `BaseNodeFactory` used to create the base `Node` objects. + * @param treeStateObserver An object that can be used to observe syntax tree creation. + */ + /* @internal */ + export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory, treeStateObserver?: TreeStateObserver): NodeFactory { + // TODO(rbuckton): This exists to avoid collectiong transform flags when parsing a declaration file or JSDoc comment. + // This is so that we can avoid executing code for those cases to improve performance. We should measure + // this and determine if it worthwhile to keep this optimization. + let skipTransformationFlags = false; + + // Lazily load the parenthesizer, node converters, and some factory methods until they are used. + const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); + const converters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); + const lazyFactory = memoize(() => createLazyFactoryMembers(factory, asExpression)); + + // Add tree state observers to base methods. + const createNode = observeResult(baseFactory.createBaseNode, treeStateObserver && treeStateObserver.onCreateNode); + const createTokenNode = observeResult(baseFactory.createBaseTokenNode, treeStateObserver && treeStateObserver.onCreateNode); + const createIdentifierNode = observeResult(baseFactory.createBaseIdentifierNode, treeStateObserver && treeStateObserver.onCreateNode); + const createSourceFileNode = observeResult(baseFactory.createBaseSourceFileNode, treeStateObserver && treeStateObserver.onCreateNode); + const setChild = observeArguments(setChildWorker, treeStateObserver && treeStateObserver.onSetChild); + const setChildren = observeArguments(setChildrenWorker, treeStateObserver && treeStateObserver.onSetChildren); + const finish = observeResult(finishWorker, treeStateObserver && treeStateObserver.onFinishNode); + const finishJSDoc = observeResult(identity, treeStateObserver && treeStateObserver.onFinishNode); + const update = observeArguments(updateWorker, treeStateObserver && treeStateObserver.onUpdateNode); + const reuse = observeResult(reuseWorker, treeStateObserver && treeStateObserver.onReuseNode); + + const factory: NodeFactory = { + get parenthesizer() { return parenthesizerRules(); }, + get converters() { return converters(); }, + setSkipTransformationFlags: value => { + const oldValue = skipTransformationFlags; + skipTransformationFlags = value; + return oldValue; + }, + trackExtraneousChildNode: setChild, + trackExtraneousChildNodes: setChildren, + createNodeArray, + createNumericLiteral, + createBigIntLiteral, + createStringLiteral, + createStringLiteralFromNode, + createRegularExpressionLiteral, + createLiteralLikeNode, + createIdentifier, + updateIdentifier, + createTempVariable, + createLoopVariable, + createUniqueName, + createOptimisticUniqueName, + createFileLevelUniqueName, + getGeneratedNameForNode, + createToken, + createSuper, + createThis, + createNull, + createTrue, + createFalse, + createModifier, + createModifiersFromModifierFlags, + createQualifiedName, + updateQualifiedName, + createComputedPropertyName, + updateComputedPropertyName, + createTypeParameterDeclaration, + updateTypeParameterDeclaration, + createParameterDeclaration, + updateParameterDeclaration, + createDecorator, + updateDecorator, + createPropertySignature, + updatePropertySignature, + createPropertyDeclaration, + updatePropertyDeclaration, + createMethodSignature, + updateMethodSignature, + createMethodDeclaration, + updateMethodDeclaration, + createConstructorDeclaration, + updateConstructorDeclaration, + createGetAccessorDeclaration, + updateGetAccessorDeclaration, + createSetAccessorDeclaration, + updateSetAccessorDeclaration, + createCallSignature, + updateCallSignature, + createConstructSignature, + updateConstructSignature, + createIndexSignature, + updateIndexSignature, + createKeywordTypeNode, + createTypePredicateNode, + updateTypePredicateNode, + createTypeReferenceNode, + updateTypeReferenceNode, + createFunctionTypeNode, + updateFunctionTypeNode, + createConstructorTypeNode, + updateConstructorTypeNode, + createTypeQueryNode, + updateTypeQueryNode, + createTypeLiteralNode, + updateTypeLiteralNode, + createArrayTypeNode, + updateArrayTypeNode, + createTupleTypeNode, + updateTupleTypeNode, + createOptionalTypeNode, + updateOptionalTypeNode, + createRestTypeNode, + updateRestTypeNode, + createUnionTypeNode, + updateUnionTypeNode, + createIntersectionTypeNode, + updateIntersectionTypeNode, + createConditionalTypeNode, + updateConditionalTypeNode, + createInferTypeNode, + updateInferTypeNode, + createImportTypeNode, + updateImportTypeNode, + createParenthesizedType, + updateParenthesizedType, + createThisTypeNode, + createTypeOperatorNode, + updateTypeOperatorNode, + createIndexedAccessTypeNode, + updateIndexedAccessTypeNode, + createMappedTypeNode, + updateMappedTypeNode, + createLiteralTypeNode, + updateLiteralTypeNode, + createObjectBindingPattern, + updateObjectBindingPattern, + createArrayBindingPattern, + updateArrayBindingPattern, + createBindingElement, + updateBindingElement, + createArrayLiteral: createArrayLiteralExpression, + updateArrayLiteral: updateArrayLiteralExpression, + createObjectLiteral: createObjectLiteralExpression, + updateObjectLiteral: updateObjectLiteralExpression, + createPropertyAccess: (expression, name) => { + const node = createPropertyAccessExpression(expression, name); + if (flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess) { + setEmitFlags(node, EmitFlags.NoIndentation); + } + return node; + }, + updatePropertyAccess: updatePropertyAccessExpression, + createPropertyAccessChain: (expression, questionDotToken, name) => { + const node = createPropertyAccessChain(expression, questionDotToken, name); + if (flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess) { + setEmitFlags(node, EmitFlags.NoIndentation); + } + return node; + }, + updatePropertyAccessChain, + createElementAccess: createElementAccessExpression, + updateElementAccess: updateElementAccessExpression, + createElementAccessChain, + updateElementAccessChain, + createCall: createCallExpression, + updateCall: updateCallExpression, + createCallChain, + updateCallChain, + createNew: createNewExpression, + updateNew: updateNewExpression, + createTaggedTemplate: createTaggedTemplateExpression, + updateTaggedTemplate: updateTaggedTemplateExpression, + createTypeAssertion, + updateTypeAssertion, + createParen: createParenthesizedExpression, + updateParen: updateParenthesizedExpression, + createFunctionExpression, + updateFunctionExpression, + createArrowFunction, + updateArrowFunction, + createDelete: createDeleteExpression, + updateDelete: updateDeleteExpression, + createTypeOf: createTypeOfExpression, + updateTypeOf: updateTypeOfExpression, + createVoid: createVoidExpression, + updateVoid: updateVoidExpression, + createAwait: createAwaitExpression, + updateAwait: updateAwaitExpression, + createPrefix: createPrefixUnaryExpression, + updatePrefix: updatePrefixUnaryExpression, + createPostfix: createPostfixUnaryExpression, + updatePostfix: updatePostfixUnaryExpression, + createBinary: createBinaryExpression, + updateBinary: updateBinaryExpression, + createConditional: createConditionalExpression, + updateConditional: updateConditionalExpression, + createTemplateExpression, + updateTemplateExpression, + createTemplateHead, + createTemplateMiddle, + createTemplateTail, + createNoSubstitutionTemplateLiteral, + createTemplateLiteralLikeNode, + createYield: createYieldExpression, + updateYield: updateYieldExpression, + createSpread: createSpreadElement, + updateSpread: updateSpreadElement, + createClassExpression, + updateClassExpression, + createOmittedExpression, + createExpressionWithTypeArguments, + updateExpressionWithTypeArguments, + createAsExpression, + updateAsExpression, + createNonNullExpression, + updateNonNullExpression, + createMetaProperty, + updateMetaProperty, + createTemplateSpan, + updateTemplateSpan, + createSemicolonClassElement, + createBlock, + updateBlock, + createVariableStatement, + updateVariableStatement, + createEmptyStatement, + createExpressionStatement, + updateExpressionStatement, + createIf: createIfStatement, + updateIf: updateIfStatement, + createDo: createDoStatement, + updateDo: updateDoStatement, + createWhile: createWhileStatement, + updateWhile: updateWhileStatement, + createFor: createForStatement, + updateFor: updateForStatement, + createForIn: createForInStatement, + updateForIn: updateForInStatement, + createForOf: createForOfStatement, + updateForOf: updateForOfStatement, + createContinue: createContinueStatement, + updateContinue: updateContinueStatement, + createBreak: createBreakStatement, + updateBreak: updateBreakStatement, + createReturn: createReturnStatement, + updateReturn: updateReturnStatement, + createWith: createWithStatement, + updateWith: updateWithStatement, + createSwitch: createSwitchStatement, + updateSwitch: updateSwitchStatement, + createLabel: createLabeledStatement, + updateLabel: updateLabeledStatement, + createThrow: createThrowStatement, + updateThrow: updateThrowStatement, + createTry: createTryStatement, + updateTry: updateTryStatement, + createDebuggerStatement, + createVariableDeclaration, + updateVariableDeclaration, + createVariableDeclarationList, + updateVariableDeclarationList, + createFunctionDeclaration, + updateFunctionDeclaration, + createClassDeclaration, + updateClassDeclaration, + createInterfaceDeclaration, + updateInterfaceDeclaration, + createTypeAliasDeclaration, + updateTypeAliasDeclaration, + createEnumDeclaration, + updateEnumDeclaration, + createModuleDeclaration, + updateModuleDeclaration, + createModuleBlock, + updateModuleBlock, + createCaseBlock, + updateCaseBlock, + createNamespaceExportDeclaration, + updateNamespaceExportDeclaration, + createImportEqualsDeclaration, + updateImportEqualsDeclaration, + createImportDeclaration, + updateImportDeclaration, + createImportClause, + updateImportClause, + createNamespaceImport, + updateNamespaceImport, + createNamedImports, + updateNamedImports, + createImportSpecifier, + updateImportSpecifier, + createExportAssignment, + updateExportAssignment, + createExportDeclaration, + updateExportDeclaration, + createNamedExports, + updateNamedExports, + createExportSpecifier, + updateExportSpecifier, + createMissingDeclaration, + createExternalModuleReference, + updateExternalModuleReference, + createJSDocAllType, + createJSDocUnknownType, + createJSDocNonNullableType, + createJSDocNullableType, + createJSDocOptionalType, + createJSDocFunctionType, + createJSDocVariadicType, + createJSDocNamepathType, + createJSDocTypeLiteral, + createJSDocTypeExpression, + createJSDocSignature, + createJSDocTemplateTag, + createJSDocTypeTag, + createJSDocTypedefTag, + createJSDocReturnTag, + createJSDocThisTag, + createJSDocParameterTag, + createJSDocPropertyTag, + createJSDocAuthorTag, + createJSDocAugmentsTag, + createJSDocCallbackTag, + createJSDocClassTag, + createJSDocEnumTag, + createJSDocUnknownTag, + createJSDocComment, + createJsxElement, + updateJsxElement, + createJsxSelfClosingElement, + updateJsxSelfClosingElement, + createJsxOpeningElement, + updateJsxOpeningElement, + createJsxClosingElement, + updateJsxClosingElement, + createJsxFragment, + createJsxText, + updateJsxText, + createJsxOpeningFragment, + createJsxJsxClosingFragment, + updateJsxFragment, + createJsxAttribute, + updateJsxAttribute, + createJsxAttributes, + updateJsxAttributes, + createJsxSpreadAttribute, + updateJsxSpreadAttribute, + createJsxExpression, + updateJsxExpression, + createCaseClause, + updateCaseClause, + createDefaultClause, + updateDefaultClause, + createHeritageClause, + updateHeritageClause, + createCatchClause, + updateCatchClause, + createPropertyAssignment, + updatePropertyAssignment, + createShorthandPropertyAssignment, + updateShorthandPropertyAssignment, + createSpreadAssignment, + updateSpreadAssignment, + createEnumMember, + updateEnumMember, + createSourceFile, + updateSourceFile, + createBundle, + updateBundle, + createNotEmittedStatement, + createPartiallyEmittedExpression, + updatePartiallyEmittedExpression, + createCommaList: createCommaListExpression, + updateCommaList: updateCommaListExpression, + createEndOfDeclarationMarker, + createMergeDeclarationMarker, + createSyntheticReferenceExpression, + updateSyntheticReferenceExpression, + + // Lazily load factory methods for common operator factories and utilities + get createSignatureDeclaration() { return lazyFactory().createSignatureDeclaration; }, + get createComma() { return lazyFactory().createComma; }, + get createAssignment() { return lazyFactory().createAssignment; }, + get createLogicalOr() { return lazyFactory().createLogicalOr; }, + get createLogicalAnd() { return lazyFactory().createLogicalAnd; }, + get createBitwiseOr() { return lazyFactory().createBitwiseOr; }, + get createBitwiseXor() { return lazyFactory().createBitwiseXor; }, + get createBitwiseAnd() { return lazyFactory().createBitwiseAnd; }, + get createStrictEquality() { return lazyFactory().createStrictEquality; }, + get createStrictInequality() { return lazyFactory().createStrictInequality; }, + get createEquality() { return lazyFactory().createEquality; }, + get createInequality() { return lazyFactory().createInequality; }, + get createLessThan() { return lazyFactory().createLessThan; }, + get createLessThanEquals() { return lazyFactory().createLessThanEquals; }, + get createGreaterThan() { return lazyFactory().createGreaterThan; }, + get createGreaterThanEquals() { return lazyFactory().createGreaterThanEquals; }, + get createLeftShift() { return lazyFactory().createLeftShift; }, + get createRightShift() { return lazyFactory().createRightShift; }, + get createUnsignedRightShift() { return lazyFactory().createUnsignedRightShift; }, + get createAdd() { return lazyFactory().createAdd; }, + get createSubtract() { return lazyFactory().createSubtract; }, + get createMultiply() { return lazyFactory().createMultiply; }, + get createDivide() { return lazyFactory().createDivide; }, + get createModulo() { return lazyFactory().createModulo; }, + get createExponent() { return lazyFactory().createExponent; }, + get createPrefixPlus() { return lazyFactory().createPrefixPlus; }, + get createPrefixMinus() { return lazyFactory().createPrefixMinus; }, + get createPrefixIncrement() { return lazyFactory().createPrefixIncrement; }, + get createPrefixDecrement() { return lazyFactory().createPrefixDecrement; }, + get createBitwiseNot() { return lazyFactory().createBitwiseNot; }, + get createLogicalNot() { return lazyFactory().createLogicalNot; }, + get createPostfixIncrement() { return lazyFactory().createPostfixIncrement; }, + get createPostfixDecrement() { return lazyFactory().createPostfixDecrement; }, + get createImmediatelyInvokedFunctionExpression() { return lazyFactory().createImmediatelyInvokedFunctionExpression; }, + get createImmediatelyInvokedArrowFunction() { return lazyFactory().createImmediatelyInvokedArrowFunction; }, + get createVoidZero() { return lazyFactory().createVoidZero; }, + get createExportDefault() { return lazyFactory().createExportDefault; }, + get createExternalModuleExport() { return lazyFactory().createExternalModuleExport; }, + get createTypeCheck() { return lazyFactory().createTypeCheck; }, + get createMethodCall() { return lazyFactory().createMethodCall; }, + get createGlobalMethodCall() { return lazyFactory().createGlobalMethodCall; }, + get createFunctionBindCall() { return lazyFactory().createFunctionBindCall; }, + get createFunctionCallCall() { return lazyFactory().createFunctionCallCall; }, + get createFunctionApplyCall() { return lazyFactory().createFunctionApplyCall; }, + get createArraySliceCall() { return lazyFactory().createArraySliceCall; }, + get createArrayConcatCall() { return lazyFactory().createArrayConcatCall; }, + get createObjectDefinePropertyCall() { return lazyFactory().createObjectDefinePropertyCall; }, + get createPropertyDescriptor() { return lazyFactory().createPropertyDescriptor; }, + get createCallBinding() { return lazyFactory().createCallBinding; }, + get inlineExpressions() { return lazyFactory().inlineExpressions; }, + get getInternalName() { return lazyFactory().getInternalName; }, + get getLocalName() { return lazyFactory().getLocalName; }, + get getExportName() { return lazyFactory().getExportName; }, + get getDeclarationName() { return lazyFactory().getDeclarationName; }, + get getNamespaceMemberName() { return lazyFactory().getNamespaceMemberName; }, + get getExternalModuleOrNamespaceExportName() { return lazyFactory().getExternalModuleOrNamespaceExportName; }, + get restoreOuterExpressions() { return lazyFactory().recreateOuterExpressions; }, + get restoreEnclosingLabel() { return lazyFactory().restoreEnclosingLabel; }, + get createUseStrictPrologue() { return lazyFactory().createUseStrictPrologue; }, + get copyPrologue() { return lazyFactory().copyPrologue; }, + get copyStandardPrologue() { return lazyFactory().copyStandardPrologue; }, + get copyCustomPrologue() { return lazyFactory().copyCustomPrologue; }, + get ensureUseStrict() { return lazyFactory().ensureUseStrict; }, + get liftToBlock() { return lazyFactory().liftToBlock; }, + }; + + return factory; + + // @api + function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray { + if (elements === undefined || elements === emptyArray) { + elements = []; + } + else if (isNodeArray(elements)) { + if (!skipTransformationFlags) { + // Ensure the transform flags have been aggregated for this NodeArray + if (elements.transformFlags === undefined) { + aggregateChildrenFlags(elements); + } + } + return elements; + } + + // Since the element list of a node array is typically created by starting with an empty array and + // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for + // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. + const length = elements.length; + const array = >(length >= 1 && length <= 4 ? elements.slice() : elements); + array.pos = -1; + array.end = -1; + if (hasTrailingComma) { + array.hasTrailingComma = hasTrailingComma; + } + if (!skipTransformationFlags) { + aggregateChildrenFlags(array); + } + return array; + } + + function createBaseNode(kind: T["kind"]): T { + return createNode(kind) as T; + } + + function createBaseDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined + ) { + const node = createBaseNode(kind); + setChildren(node, node.decorators = asNodeArray(decorators)); + setChildren(node, node.modifiers = asNodeArray(modifiers)); + return node; + } + + function createBaseNamedDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined + ) { + const node = createBaseDeclaration( + kind, + decorators, + modifiers + ); + setChild(node, node.name = asName(name)); + return node; + } + + function createBaseGenericNamedDeclaration }>( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined + ) { + const node = createBaseNamedDeclaration( + kind, + decorators, + modifiers, + name + ); + setChildren(node, node.typeParameters = asNodeArray(typeParameters)); + if (!skipTransformationFlags) { + if (typeParameters) { + markTypeScript(node); + } + } + return node; + } + + function createBaseSignatureDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined + ) { + const node = createBaseGenericNamedDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters + ); + setChildren(node, node.parameters = createNodeArray(parameters)); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + if (type) markTypeScript(node); + } + return node; + } + + function updateBaseSignatureDeclaration(updated: T, original: T) { + if (original.typeArguments) updated.typeArguments = original.typeArguments; + return update(updated, original); + } + + function createBaseFunctionLikeDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: T["body"] + ) { + const node = createBaseSignatureDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters, + parameters, + type + ); + setChild(node, node.body = body); + if (!skipTransformationFlags) { + if (!body) markTypeScript(node); + } + return node; + } + + function updateBaseFunctionLikeDeclaration(updated: T, original: T) { + if (original.exclamationToken) updated.exclamationToken = original.exclamationToken; + if (original.typeArguments) updated.typeArguments = original.typeArguments; + return updateBaseSignatureDeclaration(updated, original); + } + + function createBaseInterfaceOrClassLikeDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined + ) { + const node = createBaseGenericNamedDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters + ); + setChildren(node, node.heritageClauses = asNodeArray(heritageClauses)); + return node; + } + + function createBaseClassLikeDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + const node = createBaseInterfaceOrClassLikeDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters, + heritageClauses + ); + setChildren(node, node.members = createNodeArray(members)); + return node; + } + + function createBaseBindingLikeDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | T["name"] | undefined, + initializer: Expression | undefined + ) { + const node = createBaseNamedDeclaration( + kind, + decorators, + modifiers, + name + ); + setChild(node, node.initializer = initializer); + return node; + } + + function createBaseVariableLikeDeclaration( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | T["name"] | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) { + const node = createBaseBindingLikeDeclaration( + kind, + decorators, + modifiers, + name, + initializer + ); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + if (type) markTypeScript(node); + } + return node; + } + + // + // Literals + // + + function createBaseLiteral( + kind: T["kind"], + text: string + ) { + const node = createTokenNode(kind) as T; + node.text = text; + node.hasExtendedUnicodeEscape = undefined; + node.isUnterminated = undefined; + return node; + } + + // @api + function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { + const node = createBaseLiteral(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value); + node.numericLiteralFlags = numericLiteralFlags; + if (!skipTransformationFlags) { + if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) markES2015(node); + } + return finish(node); + } + + // @api + function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { + const node = createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); + if (!skipTransformationFlags) { + markESNext(node); + } + return finish(node); + } + + function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { + const node = createBaseLiteral(SyntaxKind.StringLiteral, text); + node.singleQuote = isSingleQuote; + return node; + } + + // @api + function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral { + const node = createBaseStringLiteral(text, isSingleQuote); + node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + if (!skipTransformationFlags) { + if (hasExtendedUnicodeEscape) markES2015(node); + } + return finish(node); + } + + // @api + function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { + const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); + node.textSourceNode = sourceNode; + return finish(node); + } + + // @api + function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { + const node = createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); + return finish(node); + } + + // @api + function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken { + switch (kind) { + case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); + case SyntaxKind.BigIntLiteral: return createBigIntLiteral(text); + case SyntaxKind.StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined); + case SyntaxKind.JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false); + case SyntaxKind.JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true); + case SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text); + case SyntaxKind.NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined) as NoSubstitutionTemplateLiteral; + } + } + + // + // Identifiers + // + + function createBaseIdentifier(text: string, originalKeywordKind: SyntaxKind | undefined): Identifier { + if (originalKeywordKind === undefined && text) { + originalKeywordKind = stringToToken(text); + } + if (originalKeywordKind === SyntaxKind.Identifier) { + originalKeywordKind = undefined; + } + const node = createIdentifierNode(SyntaxKind.Identifier) as Identifier; + node.originalKeywordKind = originalKeywordKind; + node.escapedText = escapeLeadingUnderscores(text); + return node; + } + + function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags) { + const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as GeneratedIdentifier; + node.autoGenerateFlags = autoGenerateFlags; + node.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return node; + } + + // @api + function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier { + const node = createBaseIdentifier(text, originalKeywordKind); + if (typeArguments) { + // NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations + node.typeArguments = createNodeArray(typeArguments); + if (treeStateObserver && treeStateObserver.onSetChildren) { + treeStateObserver.onSetChildren(node, node.typeArguments); + } + } + return finish(node); + } + + // @api + function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { + return node.typeArguments !== typeArguments + ? update(createIdentifier(idText(node), typeArguments), node) + : reuse(node); + } + + // @api + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { + let flags = GeneratedIdentifierFlags.Auto; + if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; + const name = finish(createBaseGeneratedIdentifier("", flags)); + if (recordTempVariable) { + recordTempVariable(name); + } + return name; + } + + /** Create a unique temporary variable for use in a loop. */ + // @api + function createLoopVariable(): Identifier { + return finish(createBaseGeneratedIdentifier("", GeneratedIdentifierFlags.Loop)); + } + + /** Create a unique name based on the supplied text. */ + // @api + function createUniqueName(text: string): Identifier { + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique)); + } + + // @api + function createOptimisticUniqueName(text: string): Identifier { + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic)); + } + + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ + // @api + function createFileLevelUniqueName(text: string): Identifier { + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)); + } + + /** Create a unique name generated for a node. */ + // @api + function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0): Identifier { + const name = createBaseGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags); + name.original = node; + return finish(name); + } + + // + // Punctuation + // + + // @api + function createToken(token: SyntaxKind.SuperKeyword): SuperExpression; + function createToken(token: SyntaxKind.ThisKeyword): ThisExpression; + function createToken(token: SyntaxKind.NullKeyword): NullLiteral; + function createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; + function createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + function createToken(token: TKind): PunctuationToken; + function createToken(token: TKind): KeywordTypeNode; + function createToken(token: TKind): ModifierToken; + function createToken(token: TKind): KeywordToken; + function createToken(token: TKind): Token; + function createToken(token: TKind): Token; + function createToken(token: TKind) { + Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); + Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); + Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); + Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); + const node = createTokenNode(token) as Token; + if (!skipTransformationFlags) { + switch (token) { + case SyntaxKind.AsyncKeyword: + // 'async' modifier is ES2017 (async functions) or ES2018 (async generators) + markES2017(node); + markES2018(node); + break; + + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.UnknownKeyword: + case SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case. + markTypeScript(node); + break; + case SyntaxKind.StaticKeyword: + case SyntaxKind.SuperKeyword: + markES2015(node); + break; + case SyntaxKind.ThisKeyword: + // 'this' indicates a lexical 'this' + markLexicalThis(node); + break; + } + } + return finish(node); + } + + // + // Reserved words + // + + // @api + function createSuper() { + return createToken(SyntaxKind.SuperKeyword); + } + + // @api + function createThis() { + return createToken(SyntaxKind.ThisKeyword); + } + + // @api + function createNull() { + return createToken(SyntaxKind.NullKeyword); + } + + // @api + function createTrue() { + return createToken(SyntaxKind.TrueKeyword); + } + + // @api + function createFalse() { + return createToken(SyntaxKind.FalseKeyword); + } + + // + // Modifiers + // + + // @api + function createModifier(kind: T) { + return createToken(kind); + } + + // @api + function createModifiersFromModifierFlags(flags: ModifierFlags) { + const result: Modifier[] = []; + if (flags & ModifierFlags.Export) { result.push(createModifier(SyntaxKind.ExportKeyword)); } + if (flags & ModifierFlags.Ambient) { result.push(createModifier(SyntaxKind.DeclareKeyword)); } + if (flags & ModifierFlags.Default) { result.push(createModifier(SyntaxKind.DefaultKeyword)); } + if (flags & ModifierFlags.Const) { result.push(createModifier(SyntaxKind.ConstKeyword)); } + if (flags & ModifierFlags.Public) { result.push(createModifier(SyntaxKind.PublicKeyword)); } + if (flags & ModifierFlags.Private) { result.push(createModifier(SyntaxKind.PrivateKeyword)); } + if (flags & ModifierFlags.Protected) { result.push(createModifier(SyntaxKind.ProtectedKeyword)); } + if (flags & ModifierFlags.Abstract) { result.push(createModifier(SyntaxKind.AbstractKeyword)); } + if (flags & ModifierFlags.Static) { result.push(createModifier(SyntaxKind.StaticKeyword)); } + if (flags & ModifierFlags.Readonly) { result.push(createModifier(SyntaxKind.ReadonlyKeyword)); } + if (flags & ModifierFlags.Async) { result.push(createModifier(SyntaxKind.AsyncKeyword)); } + return result; + } + + // + // Names + // + + // @api + function createQualifiedName(left: EntityName, right: string | Identifier) { + const node = createBaseNode(SyntaxKind.QualifiedName); + setChild(node, node.left = left); + setChild(node, node.right = asName(right)); + return finish(node); + } + + // @api + function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { + return node.left !== left + || node.right !== right + ? update(createQualifiedName(left, right), node) + : reuse(node); + } + + // @api + function createComputedPropertyName(expression: Expression) { + const node = createBaseNode(SyntaxKind.ComputedPropertyName); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression)); + if (!skipTransformationFlags) { + markES2015(node); + markComputedPropertyName(node); + } + return finish(node); + } + + // @api + function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { + return node.expression !== expression + ? update(createComputedPropertyName(expression), node) + : reuse(node); + } + + // + // Signature elements + // + + // @api + function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) { + const node = createBaseNamedDeclaration( + SyntaxKind.TypeParameter, + /*decorators*/ undefined, + /*modifiers*/ undefined, + name + ); + setChild(node, node.constraint = constraint); + setChild(node, node.default = defaultType); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) { + return node.name !== name + || node.constraint !== constraint + || node.default !== defaultType + ? update(createTypeParameterDeclaration(name, constraint, defaultType), node) + : reuse(node); + } + + // @api + function createParameterDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression + ) { + const node = createBaseVariableLikeDeclaration( + SyntaxKind.Parameter, + decorators, + modifiers, + name, + type, + initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) + ); + setChild(node, node.dotDotDotToken = dotDotDotToken); + setChild(node, node.questionToken = questionToken); + if (!skipTransformationFlags) { + if (isThisIdentifier(node.name)) { + markTypeScriptOnly(node); + } + else { + if (questionToken) markTypeScript(node); + if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) markTypeScriptClassSyntax(node); + if (initializer || dotDotDotToken) markES2015(node); + } + } + return finish(node); + } + + // @api + function updateParameterDeclaration( + node: ParameterDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.dotDotDotToken !== dotDotDotToken + || node.name !== name + || node.questionToken !== questionToken + || node.type !== type + || node.initializer !== initializer + ? update(createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node) + : reuse(node); + } + + // @api + function createDecorator(expression: Expression) { + const node = createBaseNode(SyntaxKind.Decorator); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + if (!skipTransformationFlags) { + markTypeScript(node); + markTypeScriptClassSyntax(node); + } + return finish(node); + } + + // @api + function updateDecorator(node: Decorator, expression: Expression) { + return node.expression !== expression + ? update(createDecorator(expression), node) + : reuse(node); + } + + // + // Type Elements + // + + // @api + function createPropertySignature( + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined + ): PropertySignature { + const node = createBaseNamedDeclaration( + SyntaxKind.PropertySignature, + /*decorators*/ undefined, + modifiers, + name + ); + setChild(node, node.type = type); + setChild(node, node.questionToken = questionToken); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updatePropertySignature( + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined + ) { + return node.modifiers !== modifiers + || node.name !== name + || node.questionToken !== questionToken + || node.type !== type + ? update(createPropertySignature(modifiers, name, questionToken, type), node) + : reuse(node); + } + + // @api + function createPropertyDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) { + const node = createBaseVariableLikeDeclaration( + SyntaxKind.PropertyDeclaration, + decorators, + modifiers, + name, + type, + initializer + ); + setChild(node, node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined); + setChild(node, node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined); + if (!skipTransformationFlags) { + if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { + markTypeScriptClassSyntax(node); + } + markClassFields(node); + if (questionOrExclamationToken) { + markTypeScript(node); + } + } + return finish(node); + } + + // @api + function updatePropertyDeclaration( + node: PropertyDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined) + || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined) + || node.type !== type + || node.initializer !== initializer + ? update(createPropertyDeclaration(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) + : reuse(node); + } + + // @api + function createMethodSignature( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ) { + const node = createBaseSignatureDeclaration( + SyntaxKind.MethodSignature, + /*decorators*/ undefined, + modifiers, + name, + typeParameters, + parameters, + type + ); + setChild(node, node.questionToken = questionToken); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateMethodSignature( + node: MethodSignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined + ) { + return node.modifiers !== modifiers + || node.name !== name + || node.questionToken !== questionToken + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node) + : reuse(node); + } + + // @api + function createMethodDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.MethodDeclaration, + decorators, + modifiers, + name, + typeParameters, + parameters, + type, + body + ); + setChild(node, node.asteriskToken = asteriskToken); + setChild(node, node.questionToken = questionToken); + if (!skipTransformationFlags) { + if (questionToken) { + markTypeScript(node); + } + if (hasModifier(node, ModifierFlags.Async)) { + if (asteriskToken) { + markES2018(node); + } + else { + markES2017(node); + } + } + else if (asteriskToken) { + markGenerator(node); + } + markES2015(node); + } + return finish(node); + } + + // @api + function updateMethodDeclaration( + node: MethodDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.asteriskToken !== asteriskToken + || node.name !== name + || node.questionToken !== questionToken + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) + : reuse(node); + } + + // @api + function createConstructorDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.Constructor, + decorators, + modifiers, + /*name*/ undefined, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + body + ); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function updateConstructorDeclaration( + node: ConstructorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.parameters !== parameters + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createConstructorDeclaration(decorators, modifiers, parameters, body), node) + : reuse(node); + } + + // @api + function createGetAccessorDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.GetAccessor, + decorators, + modifiers, + name, + /*typeParameters*/ undefined, + parameters, + type, + body + ); + return finish(node); + } + + // @api + function updateGetAccessorDeclaration( + node: GetAccessorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node) + : reuse(node); + } + + // @api + function createSetAccessorDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.SetAccessor, + decorators, + modifiers, + name, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + body + ); + return finish(node); + } + + // @api + function updateSetAccessorDeclaration( + node: SetAccessorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node) + : reuse(node); + } + + // @api + function createCallSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): CallSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.CallSignature, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateCallSignature( + node: CallSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined + ) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createCallSignature(typeParameters, parameters, type), node) + : reuse(node); + } + + // @api + function createConstructSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): ConstructSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.ConstructSignature, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateConstructSignature( + node: ConstructSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined + ) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createConstructSignature(typeParameters, parameters, type), node) + : reuse(node); + } + + // @api + function createIndexSignature( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): IndexSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.IndexSignature, + decorators, + modifiers, + /*name*/ undefined, + /*typeParameters*/ undefined, + parameters, + type + ); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateIndexSignature( + node: IndexSignatureDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode + ) { + return node.parameters !== parameters + || node.type !== type + || node.decorators !== decorators + || node.modifiers !== modifiers + ? updateBaseSignatureDeclaration(createIndexSignature(decorators, modifiers, parameters, type), node) + : reuse(node); + } + + // + // Types + // + + // @api + function createKeywordTypeNode(kind: TKind) { + return createToken(kind); + } + + // @api + function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) { + const node = createBaseNode(SyntaxKind.TypePredicate); + setChild(node, node.assertsModifier = assertsModifier); + setChild(node, node.parameterName = asName(parameterName)); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) { + return node.assertsModifier !== assertsModifier + || node.parameterName !== parameterName + || node.type !== type + ? update(createTypePredicateNode(assertsModifier, parameterName, type), node) + : reuse(node); + } + + // @api + function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { + const node = createBaseNode(SyntaxKind.TypeReference); + setChild(node, node.typeName = asName(typeName)); + setChildren(node, node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments))); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { + return node.typeName !== typeName + || node.typeArguments !== typeArguments + ? update(createTypeReferenceNode(typeName, typeArguments), node) + : reuse(node); + } + + // @api + function createFunctionTypeNode( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): FunctionTypeNode { + const node = createBaseSignatureDeclaration( + SyntaxKind.FunctionType, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined + ) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createFunctionTypeNode(typeParameters, parameters, type), node) + : reuse(node); + } + + // @api + function createConstructorTypeNode( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): ConstructorTypeNode { + const node = createBaseSignatureDeclaration( + SyntaxKind.ConstructorType, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateConstructorTypeNode( + node: ConstructorTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined + ) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createConstructorTypeNode(typeParameters, parameters, type), node) + : reuse(node); + } + + // @api + function createTypeQueryNode(exprName: EntityName) { + const node = createBaseNode(SyntaxKind.TypeQuery); + setChild(node, node.exprName = exprName); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { + return node.exprName !== exprName + ? update(createTypeQueryNode(exprName), node) + : reuse(node); + } + + // @api + function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { + const node = createBaseNode(SyntaxKind.TypeLiteral); + setChildren(node, node.members = createNodeArray(members)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray) { + return node.members !== members + ? update(createTypeLiteralNode(members), node) + : reuse(node); + } + + // @api + function createArrayTypeNode(elementType: TypeNode) { + const node = createBaseNode(SyntaxKind.ArrayType); + setChild(node, node.elementType = parenthesizerRules().parenthesizeElementTypeOfArrayType(elementType)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { + return node.elementType !== elementType + ? update(createArrayTypeNode(elementType), node) + : reuse(node); + } + + // @api + function createTupleTypeNode(elementTypes: readonly TypeNode[]) { + const node = createBaseNode(SyntaxKind.TupleType); + setChildren(node, node.elementTypes = createNodeArray(elementTypes)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]) { + return node.elementTypes !== elementTypes + ? update(createTupleTypeNode(elementTypes), node) + : reuse(node); + } + + // @api + function createOptionalTypeNode(type: TypeNode) { + const node = createBaseNode(SyntaxKind.OptionalType); + setChild(node, node.type = parenthesizerRules().parenthesizeElementTypeOfArrayType(type)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode { + return node.type !== type + ? update(createOptionalTypeNode(type), node) + : reuse(node); + } + + // @api + function createRestTypeNode(type: TypeNode) { + const node = createBaseNode(SyntaxKind.RestType); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode { + return node.type !== type + ? update(createRestTypeNode(type), node) + : reuse(node); + } + + function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) { + const node = createBaseNode(kind); + setChildren(node, node.types = parenthesizerRules().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types))); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray): T { + return node.types !== types + ? update(createUnionOrIntersectionTypeNode(node.kind, types), node) + : reuse(node); + } + + // @api + function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { + return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types); + } + + // @api + function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { + return updateUnionOrIntersectionTypeNode(node, types); + } + + // @api + function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { + return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types); + } + + // @api + function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { + return updateUnionOrIntersectionTypeNode(node, types); + } + + // @api + function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { + const node = createBaseNode(SyntaxKind.ConditionalType); + setChild(node, node.checkType = parenthesizerRules().parenthesizeMemberOfConditionalType(checkType)); + setChild(node, node.extendsType = parenthesizerRules().parenthesizeMemberOfConditionalType(extendsType)); + setChild(node, node.trueType = trueType); + setChild(node, node.falseType = falseType); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { + return node.checkType !== checkType + || node.extendsType !== extendsType + || node.trueType !== trueType + || node.falseType !== falseType + ? update(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node) + : reuse(node); + } + + // @api + function createInferTypeNode(typeParameter: TypeParameterDeclaration) { + const node = createBaseNode(SyntaxKind.InferType); + setChild(node, node.typeParameter = typeParameter); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) { + return node.typeParameter !== typeParameter + ? update(createInferTypeNode(typeParameter), node) + : reuse(node); + } + + // @api + function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean) { + const node = createBaseNode(SyntaxKind.ImportType); + setChild(node, node.argument = argument); + setChild(node, node.qualifier = qualifier); + setChildren(node, node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments))); + node.isTypeOf = isTypeOf; + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean) { + return node.argument !== argument + || node.qualifier !== qualifier + || node.typeArguments !== typeArguments + || node.isTypeOf !== isTypeOf + ? update(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node) + : reuse(node); + } + + // @api + function createParenthesizedType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.ParenthesizedType); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) { + return node.type !== type + ? update(createParenthesizedType(type), node) + : reuse(node); + } + + // @api + function createThisTypeNode() { + const node = createBaseNode(SyntaxKind.ThisType); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode { + const node = createBaseNode(SyntaxKind.TypeOperator); + node.operator = operator; + setChild(node, node.type = parenthesizerRules().parenthesizeMemberOfElementType(type)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) { + return node.type !== type + ? update(createTypeOperatorNode(node.operator, type), node) + : reuse(node); + } + + // @api + function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { + const node = createBaseNode(SyntaxKind.IndexedAccessType); + setChild(node, node.objectType = parenthesizerRules().parenthesizeMemberOfElementType(objectType)); + setChild(node, node.indexType = indexType); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { + return node.objectType !== objectType + || node.indexType !== indexType + ? update(createIndexedAccessTypeNode(objectType, indexType), node) + : reuse(node); + } + + // @api + function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + const node = createBaseNode(SyntaxKind.MappedType); + setChild(node, node.readonlyToken = readonlyToken); + setChild(node, node.typeParameter = typeParameter); + setChild(node, node.questionToken = questionToken); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + return node.readonlyToken !== readonlyToken + || node.typeParameter !== typeParameter + || node.questionToken !== questionToken + || node.type !== type + ? update(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node) + : reuse(node); + } + + // @api + function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { + const node = createBaseNode(SyntaxKind.LiteralType); + setChild(node, node.literal = literal); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) { + return node.literal !== literal + ? update(createLiteralTypeNode(literal), node) + : reuse(node); + } + + // + // Binding Patterns + // + + // @api + function createObjectBindingPattern(elements: readonly BindingElement[]) { + const node = createBaseNode(SyntaxKind.ObjectBindingPattern); + setChildren(node, node.elements = createNodeArray(elements)); + if (!skipTransformationFlags) { + markES2015(node); + markBindingPattern(node); + if (node.transformFlags & TransformFlags.ContainsRestOrSpread) { + markES2018(node); + markObjectRestOrSpread(node); + } + } + return finish(node); + } + + // @api + function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { + return node.elements !== elements + ? update(createObjectBindingPattern(elements), node) + : reuse(node); + } + + // @api + function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { + const node = createBaseNode(SyntaxKind.ArrayBindingPattern); + setChildren(node, node.elements = createNodeArray(elements)); + if (!skipTransformationFlags) { + markES2015(node); + markBindingPattern(node); + } + return finish(node); + } + + // @api + function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { + return node.elements !== elements + ? update(createArrayBindingPattern(elements), node) + : reuse(node); + } + + // @api + function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { + const node = createBaseBindingLikeDeclaration( + SyntaxKind.BindingElement, + /*decorators*/ undefined, + /*modifiers*/ undefined, + name, + initializer + ); + setChild(node, node.propertyName = asName(propertyName)); + setChild(node, node.dotDotDotToken = dotDotDotToken); + if (!skipTransformationFlags) { + if (dotDotDotToken) markRestOrSpread(node); + markES2015(node); + } + return finish(node); + } + + // @api + function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) { + return node.propertyName !== propertyName + || node.dotDotDotToken !== dotDotDotToken + || node.name !== name + || node.initializer !== initializer + ? update(createBindingElement(dotDotDotToken, propertyName, name, initializer), node) + : reuse(node); + } + + // + // Expression + // + + // @api + function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) { + const node = createBaseNode(SyntaxKind.ArrayLiteralExpression); + setChildren(node, node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements))); + if (multiLine) node.multiLine = true; + return finish(node); + } + + // @api + function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) { + return node.elements !== elements + ? update(createArrayLiteralExpression(elements, node.multiLine), node) + : reuse(node); + } + + // @api + function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { + const node = createBaseNode(SyntaxKind.ObjectLiteralExpression); + setChildren(node, node.properties = createNodeArray(properties)); + if (multiLine) node.multiLine = true; + return finish(node); + } + + // @api + function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { + return node.properties !== properties + ? update(createObjectLiteralExpression(properties, node.multiLine), node) + : reuse(node); + } + + // @api + function createPropertyAccessExpression(expression: Expression, name: string | Identifier) { + const node = createBaseNode(SyntaxKind.PropertyAccessExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.name = asName(name)); + if (!skipTransformationFlags) { + // super method calls require a lexical 'this' + // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators + if (expression.kind === SyntaxKind.SuperKeyword) { + markES2017(node); + markES2018(node); + } + } + return finish(node); + } + + // @api + function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier) { + if (isOptionalChain(node)) { + return updatePropertyAccessChain(node, expression, node.questionDotToken, name); + } + return node.expression !== expression + || node.name !== name + ? update(createPropertyAccessExpression(expression, name), node) + : reuse(node); + } + + // @api + function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier) { + const node = createBaseNode(SyntaxKind.PropertyAccessExpression); + node.flags |= NodeFlags.OptionalChain; + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.questionDotToken = questionDotToken); + setChild(node, node.name = asName(name)); + if (!skipTransformationFlags) { + markESNext(node); + } + return finish(node); + } + + // @api + function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead."); + // Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags + // instead of using the default from createPropertyAccess + return node.expression !== expression + || node.questionDotToken !== questionDotToken + || node.name !== name + ? update(createPropertyAccessChain(expression, questionDotToken, name), node) + : node; + } + + // @api + function createElementAccessExpression(expression: Expression, index: number | Expression) { + const node = createBaseNode(SyntaxKind.ElementAccessExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.argumentExpression = asExpression(index)); + if (!skipTransformationFlags) { + // super method calls require a lexical 'this' + // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators + if (expression.kind === SyntaxKind.SuperKeyword) { + markES2017(node); + markES2018(node); + } + } + return finish(node); + } + + // @api + function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { + if (isOptionalChain(node)) { + return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression); + } + return node.expression !== expression + || node.argumentExpression !== argumentExpression + ? update(createElementAccessExpression(expression, argumentExpression), node) + : reuse(node); + } + + // @api + function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { + const node = createBaseNode(SyntaxKind.ElementAccessExpression); + node.flags |= NodeFlags.OptionalChain; + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.questionDotToken = questionDotToken); + setChild(node, node.argumentExpression = asExpression(index)); + if (!skipTransformationFlags) { + markESNext(node); + } + return finish(node); + } + + // @api + function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead."); + // Because we are updating an existing ElementAccessChain we want to inherit its emitFlags + // instead of using the default from createElementAccess + return node.expression !== expression + || node.questionDotToken !== questionDotToken + || node.argumentExpression !== argumentExpression + ? update(createElementAccessChain(expression, questionDotToken, argumentExpression), node) + : node; + } + + // @api + function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseNode(SyntaxKind.CallExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChildren(node, node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); + if (!skipTransformationFlags) { + if (typeArguments) { + markTypeScript(node); + } + if (expression.kind === SyntaxKind.ImportKeyword) { + markDynamicImport(node); + } + if (isSuperProperty(expression)) { + markLexicalThis(node); + } + } + return finish(node); + } + + // @api + function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + if (isOptionalChain(node)) { + return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray); + } + return node.expression !== expression + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? update(createCallExpression(expression, typeArguments, argumentsArray), node) + : reuse(node); + } + + // @api + function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseNode(SyntaxKind.CallExpression); + node.flags |= NodeFlags.OptionalChain; + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.questionDotToken = questionDotToken); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChildren(node, node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); + if (!skipTransformationFlags) { + markESNext(node); + if (typeArguments) { + markTypeScript(node); + } + if (isSuperProperty(expression)) { + markLexicalThis(node); + } + } + return finish(node); + } + + // @api + function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead."); + return node.expression !== expression + || node.questionDotToken !== questionDotToken + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? update(createCallChain(expression, questionDotToken, typeArguments, argumentsArray), node) + : node; + } + + // @api + function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseNode(SyntaxKind.NewExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChildren(node, node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) : undefined); + if (!skipTransformationFlags) { + if (typeArguments) { + markTypeScript(node); + } + } + return finish(node); + } + + // @api + function updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + return node.expression !== expression + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? update(createNewExpression(expression, typeArguments, argumentsArray), node) + : reuse(node); + } + + // @api + function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + const node = createBaseNode(SyntaxKind.TaggedTemplateExpression); + setChild(node, node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.template = template); + if (!skipTransformationFlags) { + markES2015(node); + if (typeArguments) { + markTypeScript(node); + } + } + return finish(node); + } + + // @api + function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + return node.tag !== tag + || node.typeArguments !== typeArguments + || node.template !== template + ? update(createTaggedTemplateExpression(tag, typeArguments, template), node) + : reuse(node); + } + + // @api + function createTypeAssertion(type: TypeNode, expression: Expression) { + const node = createBaseNode(SyntaxKind.TypeAssertionExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { + return node.type !== type + || node.expression !== expression + ? update(createTypeAssertion(type, expression), node) + : reuse(node); + } + + // @api + function createParenthesizedExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.ParenthesizedExpression); + setChild(node, node.expression = expression); + return finish(node); + } + + // @api + function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) { + return node.expression !== expression + ? update(createParenthesizedExpression(expression), node) + : reuse(node); + } + + // @api + function createFunctionExpression( + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: Block + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionExpression, + /*decorators*/ undefined, + modifiers, + name, + typeParameters, + parameters, + type, + body + ); + setChild(node, node.asteriskToken = asteriskToken); + if (!skipTransformationFlags) { + if (typeParameters) { + markTypeScript(node); + } + if (hasModifier(node, ModifierFlags.Async)) { + if (asteriskToken) { + markES2018(node); + } + else { + markES2017(node); + } + } + else if (asteriskToken) { + markGenerator(node); + } + } + return finish(node); + } + + // @api + function updateFunctionExpression( + node: FunctionExpression, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block + ) { + return node.name !== name + || node.modifiers !== modifiers + || node.asteriskToken !== asteriskToken + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + : reuse(node); + } + + // @api + function createArrowFunction( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken | undefined, + body: ConciseBody + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.ArrowFunction, + /*decorators*/ undefined, + modifiers, + /*name*/ undefined, + typeParameters, + parameters, + type, + parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body) + ); + setChild(node, node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken)); + if (!skipTransformationFlags) { + if (hasModifier(node, ModifierFlags.Async)) markES2017(node); + markES2015(node); + } + return finish(node); + } + + // @api + function updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken, + body: ConciseBody + ): ArrowFunction { + return node.modifiers !== modifiers + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.equalsGreaterThanToken !== equalsGreaterThanToken + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) + : reuse(node); + } + + // @api + function createDeleteExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.DeleteExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression)); + return finish(node); + } + + // @api + function updateDeleteExpression(node: DeleteExpression, expression: Expression) { + return node.expression !== expression + ? update(createDeleteExpression(expression), node) + : reuse(node); + } + + // @api + function createTypeOfExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.TypeOfExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression)); + return finish(node); + } + + // @api + function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) { + return node.expression !== expression + ? update(createTypeOfExpression(expression), node) + : reuse(node); + } + + // @api + function createVoidExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.VoidExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression)); + return finish(node); + } + + // @api + function updateVoidExpression(node: VoidExpression, expression: Expression) { + return node.expression !== expression + ? update(createVoidExpression(expression), node) + : reuse(node); + } + + // @api + function createAwaitExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.AwaitExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression)); + if (!skipTransformationFlags) { + markES2017(node); + markES2018(node); + } + return finish(node); + } + + // @api + function updateAwaitExpression(node: AwaitExpression, expression: Expression) { + return node.expression !== expression + ? update(createAwaitExpression(expression), node) + : reuse(node); + } + + // @api + function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { + const node = createBaseNode(SyntaxKind.PrefixUnaryExpression); + node.operator = operator; + setChild(node, node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand)); + return finish(node); + } + + // @api + function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) { + return node.operand !== operand + ? update(createPrefixUnaryExpression(node.operator, operand), node) + : reuse(node); + } + + // @api + function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { + const node = createBaseNode(SyntaxKind.PostfixUnaryExpression); + node.operator = operator; + setChild(node, node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand)); + return finish(node); + } + + // @api + function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) { + return node.operand !== operand + ? update(createPostfixUnaryExpression(operand, node.operator), node) + : reuse(node); + } + + // @api + function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { + const node = createBaseNode(SyntaxKind.BinaryExpression); + const operatorToken = asToken(operator); + const operatorKind = operatorToken.kind; + setChild(node, node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left)); + setChild(node, node.operatorToken = operatorToken); + setChild(node, node.right = parenthesizerRules().parenthesizeRightSideOfBinary(operatorKind, node.left, right)); + if (!skipTransformationFlags) { + if (operatorKind === SyntaxKind.QuestionQuestionToken) { + markESNext(node); + } + else if (operatorKind === SyntaxKind.EqualsToken) { + if (node.left.kind === SyntaxKind.ObjectLiteralExpression) { + markES2015(node); + markES2018(node); + markDestructuringAssignment(node); + } + else if (node.left.kind === SyntaxKind.ArrayLiteralExpression) { + markES2015(node); + markDestructuringAssignment(node); + } + } + else if (operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken) { + markES2016(node); + } + } + return finish(node); + } + + // @api + function updateBinaryExpression(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken) { + return node.left !== left + || node.right !== right + ? update(createBinaryExpression(left, operator || node.operatorToken, right), node) + : reuse(node); + } + + // @api + function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) { + const node = createBaseNode(SyntaxKind.ConditionalExpression); + setChild(node, node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition)); + setChild(node, node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken)); + setChild(node, node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue)); + setChild(node, node.colonToken = colonToken ?? createToken(SyntaxKind.ColonToken)); + setChild(node, node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse)); + return finish(node); + } + + // @api + function updateConditionalExpression( + node: ConditionalExpression, + condition: Expression, + questionToken: Token, + whenTrue: Expression, + colonToken: Token, + whenFalse: Expression + ): ConditionalExpression { + return node.condition !== condition + || node.questionToken !== questionToken + || node.whenTrue !== whenTrue + || node.colonToken !== colonToken + || node.whenFalse !== whenFalse + ? update(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node) + : reuse(node); + } + + // @api + function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { + const node = createBaseNode(SyntaxKind.TemplateExpression); + setChild(node, node.head = head); + setChildren(node, node.templateSpans = createNodeArray(templateSpans)); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { + return node.head !== head + || node.templateSpans !== templateSpans + ? update(createTemplateExpression(head, templateSpans), node) + : reuse(node); + } + + function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined) { + // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`. + // eslint-disable-next-line no-undef-init + let cooked: string | object | undefined = undefined; + if (rawText !== undefined && rawText !== text) { + cooked = getCookedText(kind, rawText); + if (typeof cooked === "object") { + return Debug.fail("Invalid raw text"); + } + } + if (text === undefined) { + if (cooked === undefined) { + return Debug.fail("Arguments 'text' and 'rawText' may not both be undefined."); + } + text = cooked; + } + else if (cooked !== undefined) { + Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); + } + return createTemplateLiteralLikeNode(kind, text, rawText); + } + + // @api + function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined) { + const node = createTokenNode(kind) as TemplateLiteralLikeNode; + node.text = text; + node.rawText = rawText; + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function createTemplateHead(text: string | undefined, rawText?: string) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateHead, text, rawText); + } + + // @api + function createTemplateMiddle(text: string | undefined, rawText?: string) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateMiddle, text, rawText); + } + + // @api + function createTemplateTail(text: string | undefined, rawText?: string) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateTail, text, rawText); + } + + // @api + function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText); + } + + // @api + function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { + Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); + const node = createBaseNode(SyntaxKind.YieldExpression); + setChild(node, node.expression = expression); + setChild(node, node.asteriskToken = asteriskToken); + if (!skipTransformationFlags) { + markES2015(node); + markES2018(node); + markYield(node); + } + return finish(node); + } + + // @api + function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { + return node.expression !== expression + || node.asteriskToken !== asteriskToken + ? update(createYieldExpression(asteriskToken, expression), node) + : reuse(node); + } + + // @api + function createSpreadElement(expression: Expression) { + const node = createBaseNode(SyntaxKind.SpreadElement); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression)); + if (!skipTransformationFlags) { + markES2015(node); + markRestOrSpread(node); + } + return finish(node); + } + + // @api + function updateSpreadElement(node: SpreadElement, expression: Expression) { + return node.expression !== expression + ? update(createSpreadElement(expression), node) + : reuse(node); + } + + // @api + function createClassExpression( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassExpression, + decorators, + modifiers, + name, + typeParameters, + heritageClauses, + members + ); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function updateClassExpression( + node: ClassExpression, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.heritageClauses !== heritageClauses + || node.members !== members + ? update(createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); + } + + // @api + function createOmittedExpression() { + return finish(createBaseNode(SyntaxKind.OmittedExpression)); + } + + // @api + function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) { + const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + setChildren(node, node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments)); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) { + return node.expression !== expression + || node.typeArguments !== typeArguments + ? update(createExpressionWithTypeArguments(expression, typeArguments), node) + : reuse(node); + } + + // @api + function createAsExpression(expression: Expression, type: TypeNode) { + const node = createBaseNode(SyntaxKind.AsExpression); + setChild(node, node.expression = expression); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { + return node.expression !== expression + || node.type !== type + ? update(createAsExpression(expression, type), node) + : reuse(node); + } + + // @api + function createNonNullExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.NonNullExpression); + setChild(node, node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression)); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updateNonNullExpression(node: NonNullExpression, expression: Expression) { + return node.expression !== expression + ? update(createNonNullExpression(expression), node) + : reuse(node); + } + + // @api + function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { + const node = createBaseNode(SyntaxKind.MetaProperty); + node.keywordToken = keywordToken; + setChild(node, node.name = name); + if (!skipTransformationFlags) { + switch (keywordToken) { + case SyntaxKind.NewKeyword: + markES2015(node); + break; + case SyntaxKind.ImportKeyword: + markESNext(node); + break; + default: + return Debug.assertNever(keywordToken); + } + } + return finish(node); + } + + // @api + function updateMetaProperty(node: MetaProperty, name: Identifier) { + return node.name !== name + ? update(createMetaProperty(node.keywordToken, name), node) + : reuse(node); + } + + // + // Misc + // + + // @api + function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { + const node = createBaseNode(SyntaxKind.TemplateSpan); + setChild(node, node.expression = expression); + setChild(node, node.literal = literal); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + // @api + function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { + return node.expression !== expression + || node.literal !== literal + ? update(createTemplateSpan(expression, literal), node) + : reuse(node); + } + + // @api + function createSemicolonClassElement() { + const node = createBaseNode(SyntaxKind.SemicolonClassElement); + markES2015(node); + return finish(node); + } + + // + // Element + // + + // @api + function createBlock(statements: readonly Statement[], multiLine?: boolean): Block { + const node = createBaseNode(SyntaxKind.Block); + setChildren(node, node.statements = createNodeArray(statements)); + if (multiLine) node.multiLine = multiLine; + return finish(node); + } + + // @api + function updateBlock(node: Block, statements: readonly Statement[]) { + return node.statements !== statements + ? update(createBlock(statements, node.multiLine), node) + : reuse(node); + } + + // @api + function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { + const node = createBaseDeclaration(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers); + setChild(node, node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList); + if (!skipTransformationFlags) { + if (hasModifier(node, ModifierFlags.Ambient)) { + markTypeScriptOnly(node); + } + } + return finish(node); + } + + // @api + function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) { + return node.modifiers !== modifiers + || node.declarationList !== declarationList + ? update(createVariableStatement(modifiers, declarationList), node) + : reuse(node); + } + + // @api + function createEmptyStatement() { + return finish(createBaseNode(SyntaxKind.EmptyStatement)); + } + + // @api + function createExpressionStatement(expression: Expression): ExpressionStatement { + const node = createBaseNode(SyntaxKind.ExpressionStatement); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression)); + return finish(node); + } + + // @api + function updateExpressionStatement(node: ExpressionStatement, expression: Expression) { + return node.expression !== expression + ? update(createExpressionStatement(expression), node) + : reuse(node); + } + + // @api + function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { + const node = createBaseNode(SyntaxKind.IfStatement); + setChild(node, node.expression = expression); + setChild(node, node.thenStatement = asEmbeddedStatement(thenStatement)); + setChild(node, node.elseStatement = asEmbeddedStatement(elseStatement)); + return finish(node); + } + + // @api + function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) { + return node.expression !== expression + || node.thenStatement !== thenStatement + || node.elseStatement !== elseStatement + ? update(createIfStatement(expression, thenStatement, elseStatement), node) + : reuse(node); + } + + // @api + function createDoStatement(statement: Statement, expression: Expression) { + const node = createBaseNode(SyntaxKind.DoStatement); + setChild(node, node.statement = asEmbeddedStatement(statement)); + setChild(node, node.expression = expression); + return finish(node); + } + + // @api + function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) { + return node.statement !== statement + || node.expression !== expression + ? update(createDoStatement(statement, expression), node) + : reuse(node); + } + + // @api + function createWhileStatement(expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.WhileStatement); + setChild(node, node.expression = expression); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finish(node); + } + + // @api + function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) { + return node.expression !== expression + || node.statement !== statement + ? update(createWhileStatement(expression, statement), node) + : reuse(node); + } + + // @api + function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForStatement); + setChild(node, node.initializer = initializer); + setChild(node, node.condition = condition); + setChild(node, node.incrementor = incrementor); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finish(node); + } + + // @api + function updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + return node.initializer !== initializer + || node.condition !== condition + || node.incrementor !== incrementor + || node.statement !== statement + ? update(createForStatement(initializer, condition, incrementor, statement), node) + : reuse(node); + } + + // @api + function createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForInStatement); + setChild(node, node.initializer = initializer); + setChild(node, node.expression = expression); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finish(node); + } + + // @api + function updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { + return node.initializer !== initializer + || node.expression !== expression + || node.statement !== statement + ? update(createForInStatement(initializer, expression, statement), node) + : reuse(node); + } + + // @api + function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForOfStatement); + setChild(node, node.awaitModifier = awaitModifier); + setChild(node, node.initializer = initializer); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.statement = asEmbeddedStatement(statement)); + if (!skipTransformationFlags) { + if (awaitModifier) markES2018(node); + markES2015(node); + } + return finish(node); + } + + // @api + function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + return node.awaitModifier !== awaitModifier + || node.initializer !== initializer + || node.expression !== expression + || node.statement !== statement + ? update(createForOfStatement(awaitModifier, initializer, expression, statement), node) + : reuse(node); + } + + // @api + function createContinueStatement(label?: string | Identifier): ContinueStatement { + const node = createBaseNode(SyntaxKind.ContinueStatement); + setChild(node, node.label = asName(label)); + if (!skipTransformationFlags) { + markHoistedDeclarationOrCompletion(node); + } + return finish(node); + } + + // @api + function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) { + return node.label !== label + ? update(createContinueStatement(label), node) + : reuse(node); + } + + // @api + function createBreakStatement(label?: string | Identifier): BreakStatement { + const node = createBaseNode(SyntaxKind.BreakStatement); + setChild(node, node.label = asName(label)); + if (!skipTransformationFlags) { + markHoistedDeclarationOrCompletion(node); + } + return finish(node); + } + + // @api + function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) { + return node.label !== label + ? update(createBreakStatement(label), node) + : reuse(node); + } + + // @api + function createReturnStatement(expression?: Expression): ReturnStatement { + const node = createBaseNode(SyntaxKind.ReturnStatement); + setChild(node, node.expression = expression); + if (!skipTransformationFlags) { + // return in an ES2018 async generator must be awaited + markES2018(node); + markHoistedDeclarationOrCompletion(node); + } + return finish(node); + } + + // @api + function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) { + return node.expression !== expression + ? update(createReturnStatement(expression), node) + : reuse(node); + } + + // @api + function createWithStatement(expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.WithStatement); + setChild(node, node.expression = expression); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finish(node); + } + + // @api + function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) { + return node.expression !== expression + || node.statement !== statement + ? update(createWithStatement(expression, statement), node) + : reuse(node); + } + + // @api + function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement { + const node = createBaseNode(SyntaxKind.SwitchStatement); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.caseBlock = caseBlock); + return finish(node); + } + + // @api + function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { + return node.expression !== expression + || node.caseBlock !== caseBlock + ? update(createSwitchStatement(expression, caseBlock), node) + : reuse(node); + } + + // @api + function createLabeledStatement(label: string | Identifier, statement: Statement) { + const node = createBaseNode(SyntaxKind.LabeledStatement); + setChild(node, node.label = asName(label)); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finish(node); + } + + // @api + function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) { + return node.label !== label + || node.statement !== statement + ? update(createLabeledStatement(label, statement), node) + : reuse(node); + } + + // @api + function createThrowStatement(expression: Expression) { + const node = createBaseNode(SyntaxKind.ThrowStatement); + setChild(node, node.expression = expression); + return finish(node); + } + + // @api + function updateThrowStatement(node: ThrowStatement, expression: Expression) { + return node.expression !== expression + ? update(createThrowStatement(expression), node) + : reuse(node); + } + + // @api + function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + const node = createBaseNode(SyntaxKind.TryStatement); + setChild(node, node.tryBlock = tryBlock); + setChild(node, node.catchClause = catchClause); + setChild(node, node.finallyBlock = finallyBlock); + return finish(node); + } + + // @api + function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + return node.tryBlock !== tryBlock + || node.catchClause !== catchClause + || node.finallyBlock !== finallyBlock + ? update(createTryStatement(tryBlock, catchClause, finallyBlock), node) + : reuse(node); + } + + // @api + function createDebuggerStatement() { + return finish(createBaseNode(SyntaxKind.DebuggerStatement)); + } + + // @api + function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + const node = createBaseVariableLikeDeclaration( + SyntaxKind.VariableDeclaration, + /*decorators*/ undefined, + /*modifiers*/ undefined, + name, + type, + initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) + ); + setChild(node, node.exclamationToken = exclamationToken); + if (!skipTransformationFlags) { + if (exclamationToken) { + markTypeScript(node); + } + } + return finish(node); + } + + // @api + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + return node.name !== name + || node.type !== type + || node.exclamationToken !== exclamationToken + || node.initializer !== initializer + ? update(createVariableDeclaration(name, exclamationToken, type, initializer), node) + : reuse(node); + } + + // @api + function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) { + const node = createBaseNode(SyntaxKind.VariableDeclarationList); + node.flags |= flags & NodeFlags.BlockScoped; + setChildren(node, node.declarations = createNodeArray(declarations)); + if (!skipTransformationFlags) { + markHoistedDeclarationOrCompletion(node); + if (flags & NodeFlags.BlockScoped) { + markES2015(node); + markBlockScopedBinding(node); + } + } + return finish(node); + } + + // @api + function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { + return node.declarations !== declarations + ? update(createVariableDeclarationList(declarations, node.flags), node) + : reuse(node); + } + + // @api + function createFunctionDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionDeclaration, + decorators, + modifiers, + name, + typeParameters, + parameters, + type, + body + ); + setChild(node, node.asteriskToken = asteriskToken); + if (!skipTransformationFlags) { + if (!body || hasModifier(node, ModifierFlags.Ambient)) { + markTypeScriptOnly(node); + } + else { + markHoistedDeclarationOrCompletion(node); + if (hasModifier(node, ModifierFlags.Async)) { + if (asteriskToken) { + markES2018(node); + } + else { + markES2017(node); + } + } + else if (asteriskToken) { + markGenerator(node); + } + } + } + return finish(node); + } + + // @api + function updateFunctionDeclaration( + node: FunctionDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.asteriskToken !== asteriskToken + || node.name !== name + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateBaseFunctionLikeDeclaration(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + : reuse(node); + } + + // @api + function createClassDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassDeclaration, + decorators, + modifiers, + name, + typeParameters, + heritageClauses, + members + ); + if (!skipTransformationFlags) { + if (hasModifier(node, ModifierFlags.Ambient)) { + markTypeScriptOnly(node); + } + else { + markES2015(node); + if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) { + markTypeScript(node); + } + } + } + return finish(node); + } + + // @api + function updateClassDeclaration( + node: ClassDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.heritageClauses !== heritageClauses + || node.members !== members + ? update(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); + } + + // @api + function createInterfaceDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[] + ) { + const node = createBaseInterfaceOrClassLikeDeclaration( + SyntaxKind.InterfaceDeclaration, + decorators, + modifiers, + name, + typeParameters, + heritageClauses + ); + setChildren(node, node.members = createNodeArray(members)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateInterfaceDeclaration( + node: InterfaceDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[] + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.heritageClauses !== heritageClauses + || node.members !== members + ? update(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); + } + + // @api + function createTypeAliasDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode + ) { + const node = createBaseGenericNamedDeclaration( + SyntaxKind.TypeAliasDeclaration, + decorators, + modifiers, + name, + typeParameters + ); + setChild(node, node.type = type); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateTypeAliasDeclaration( + node: TypeAliasDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.type !== type + ? update(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node) + : reuse(node); + } + + // @api + function createEnumDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + members: readonly EnumMember[] + ) { + const node = createBaseNamedDeclaration( + SyntaxKind.EnumDeclaration, + decorators, + modifiers, + name + ); + setChildren(node, node.members = createNodeArray(members)); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updateEnumDeclaration( + node: EnumDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + members: readonly EnumMember[]) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.members !== members + ? update(createEnumDeclaration(decorators, modifiers, name, members), node) + : reuse(node); + } + + // @api + function createModuleDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags = NodeFlags.None + ) { + const node = createBaseDeclaration( + SyntaxKind.ModuleDeclaration, + decorators, + modifiers + ); + node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); + setChild(node, node.name = name); + setChild(node, node.body = body); + if (!skipTransformationFlags) { + if (hasModifier(node, ModifierFlags.Ambient)) { + markTypeScriptOnly(node); + } + else { + markTypeScript(node); + } + } + return finish(node); + } + + // @api + function updateModuleDeclaration( + node: ModuleDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.body !== body + ? update(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) + : reuse(node); + } + + // @api + function createModuleBlock(statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.ModuleBlock); + setChildren(node, node.statements = createNodeArray(statements)); + return finish(node); + } + + // @api + function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) { + return node.statements !== statements + ? update(createModuleBlock(statements), node) + : reuse(node); + } + + // @api + function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { + const node = createBaseNode(SyntaxKind.CaseBlock); + setChildren(node, node.clauses = createNodeArray(clauses)); + return finish(node); + } + + // @api + function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) { + return node.clauses !== clauses + ? update(createCaseBlock(clauses), node) + : reuse(node); + } + + // @api + function createNamespaceExportDeclaration(name: string | Identifier) { + const node = createBaseNode(SyntaxKind.NamespaceExportDeclaration); + setChild(node, node.name = asName(name)); + if (!skipTransformationFlags) { + markTypeScriptOnly(node); + } + return finish(node); + } + + // @api + function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { + return node.name !== name + ? update(createNamespaceExportDeclaration(name), node) + : reuse(node); + } + + // @api + function createImportEqualsDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + moduleReference: ModuleReference + ) { + const node = createBaseNamedDeclaration( + SyntaxKind.ImportEqualsDeclaration, + decorators, + modifiers, + name + ); + setChild(node, node.moduleReference = moduleReference); + if (!skipTransformationFlags) { + if (moduleReference.kind !== SyntaxKind.ExternalModuleReference) markTypeScript(node); + } + return finish(node); + } + + // @api + function updateImportEqualsDeclaration( + node: ImportEqualsDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + moduleReference: ModuleReference + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.moduleReference !== moduleReference + ? update(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) + : reuse(node); + } + + // @api + function createImportDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression + ): ImportDeclaration { + const node = createBaseDeclaration( + SyntaxKind.ImportDeclaration, + decorators, + modifiers + ); + setChild(node, node.importClause = importClause); + setChild(node, node.moduleSpecifier = moduleSpecifier); + return finish(node); + } + + // @api + function updateImportDeclaration( + node: ImportDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.importClause !== importClause + || node.moduleSpecifier !== moduleSpecifier + ? update(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) + : reuse(node); + } + + // @api + function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { + const node = createBaseNode(SyntaxKind.ImportClause); + setChild(node, node.name = name); + setChild(node, node.namedBindings = namedBindings); + return finish(node); + } + + // @api + function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { + return node.name !== name + || node.namedBindings !== namedBindings + ? update(createImportClause(name, namedBindings), node) + : reuse(node); + } + + // @api + function createNamespaceImport(name: Identifier): NamespaceImport { + const node = createBaseNode(SyntaxKind.NamespaceImport); + setChild(node, node.name = name); + return finish(node); + } + + // @api + function updateNamespaceImport(node: NamespaceImport, name: Identifier) { + return node.name !== name + ? update(createNamespaceImport(name), node) + : reuse(node); + } + + // @api + function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { + const node = createBaseNode(SyntaxKind.NamedImports); + setChildren(node, node.elements = createNodeArray(elements)); + return finish(node); + } + + // @api + function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) { + return node.elements !== elements + ? update(createNamedImports(elements), node) + : reuse(node); + } + + // @api + function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier) { + const node = createBaseNode(SyntaxKind.ImportSpecifier); + setChild(node, node.propertyName = propertyName); + setChild(node, node.name = name); + return finish(node); + } + + // @api + function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) { + return node.propertyName !== propertyName + || node.name !== name + ? update(createImportSpecifier(propertyName, name), node) + : reuse(node); + } + + // @api + function createExportAssignment( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + isExportEquals: boolean | undefined, + expression: Expression + ) { + const node = createBaseDeclaration( + SyntaxKind.ExportAssignment, + decorators, + modifiers + ); + node.isExportEquals = isExportEquals; + setChild(node, node.expression = isExportEquals + ? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) + : parenthesizerRules().parenthesizeExpressionOfExportDefault(expression)); + return finish(node); + } + + // @api + function updateExportAssignment( + node: ExportAssignment, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + expression: Expression + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.expression !== expression + ? update(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) + : reuse(node); + } + + // @api + function createExportDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + exportClause: NamedExports | undefined, + moduleSpecifier?: Expression + ) { + const node = createBaseDeclaration( + SyntaxKind.ExportDeclaration, + decorators, + modifiers + ); + setChild(node, node.exportClause = exportClause); + setChild(node, node.moduleSpecifier = moduleSpecifier); + return finish(node); + } + + // @api + function updateExportDeclaration( + node: ExportDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + exportClause: NamedExports | undefined, + moduleSpecifier: Expression | undefined + ) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.exportClause !== exportClause + || node.moduleSpecifier !== moduleSpecifier + ? update(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) + : reuse(node); + } + + // @api + function createNamedExports(elements: readonly ExportSpecifier[]) { + const node = createBaseNode(SyntaxKind.NamedExports); + setChildren(node, node.elements = createNodeArray(elements)); + return finish(node); + } + + // @api + function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) { + return node.elements !== elements + ? update(createNamedExports(elements), node) + : reuse(node); + } + + // @api + function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier) { + const node = createBaseNode(SyntaxKind.ExportSpecifier); + setChild(node, node.propertyName = asName(propertyName)); + setChild(node, node.name = asName(name)); + return finish(node); + } + + // @api + function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) { + return node.propertyName !== propertyName + || node.name !== name + ? update(createExportSpecifier(propertyName, name), node) + : reuse(node); + } + + // @api + function createMissingDeclaration() { + const node = createBaseDeclaration( + SyntaxKind.MissingDeclaration, + /*decorators*/ undefined, + /*modifiers*/ undefined + ); + return finish(node); + } + + // + // Module references + // + + // @api + function createExternalModuleReference(expression: Expression) { + const node = createBaseNode(SyntaxKind.ExternalModuleReference); + setChild(node, node.expression = expression); + return finish(node); + } + + // @api + function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { + return node.expression !== expression + ? update(createExternalModuleReference(expression), node) + : reuse(node); + } + + // + // JSDoc + // + + // @api + function createJSDocAllType() { + const node = createBaseNode(SyntaxKind.JSDocAllType); + return finishJSDoc(node); + } + + // @api + function createJSDocUnknownType() { + const node = createBaseNode(SyntaxKind.JSDocUnknownType); + return finishJSDoc(node); + } + + // @api + function createJSDocNonNullableType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.JSDocNonNullableType); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocNullableType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.JSDocNullableType); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocOptionalType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.JSDocOptionalType); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { + const node = createBaseSignatureDeclaration( + SyntaxKind.JSDocFunctionType, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + parameters, + type + ); + return finishJSDoc(node); + } + + // @api + function createJSDocVariadicType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.JSDocVariadicType); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocNamepathType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.JSDocNamepathType); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral { + const node = createBaseNode(SyntaxKind.JSDocTypeLiteral); + setChildren(node, node.jsDocPropertyTags = asNodeArray(propertyTags)); + node.isArrayType = isArrayType; + return finishJSDoc(node); + } + + // @api + function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { + const node = createBaseNode(SyntaxKind.JSDocTypeExpression); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { + const node = createBaseNode(SyntaxKind.JSDocSignature); + setChildren(node, node.typeParameters = asNodeArray(typeParameters)); + setChildren(node, node.parameters = createNodeArray(parameters)); + setChild(node, node.type = type); + return finishJSDoc(node); + } + + // @api + function createBaseJSDocTag(kind: T["kind"], tagName: Identifier, comment: string | undefined) { + const node = createBaseNode(kind); + setChild(node, node.tagName = tagName); + node.comment = comment; + return node; + } + + // @api + function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[]): JSDocTemplateTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName || createIdentifier("template"), /*comment*/ undefined); + setChild(node, node.constraint = constraint); + setChildren(node, node.typeParameters = createNodeArray(typeParameters)); + return finishJSDoc(node); + } + + // @api + function createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTypeTag, tagName || createIdentifier("type"), comment); + setChild(node, node.typeExpression = typeExpression); + return finishJSDoc(node); + } + + // @api + function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocTypedefTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTypedefTag, tagName || createIdentifier("typedef"), comment); + setChild(node, node.typeExpression = typeExpression); + setChild(node, node.fullName = fullName); + setChild(node, node.name = getJSDocTypeAliasName(fullName)); + return finishJSDoc(node); + } + + // @api + function createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocReturnTag, tagName || createIdentifier("returns"), comment); + setChild(node, node.typeExpression = typeExpression); + return finishJSDoc(node); + } + + // @api + function createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocThisTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocThisTag, tagName || createIdentifier("this"), /*comment*/ undefined); + setChild(node, node.typeExpression = typeExpression); + return finishJSDoc(node); + } + + // @api + function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocParameterTag, tagName || createIdentifier("param"), comment); + setChild(node, node.typeExpression = typeExpression); + setChild(node, node.name = name); + node.isNameFirst = !!isNameFirst; + node.isBracketed = isBracketed; + return finishJSDoc(node); + } + + // @api + function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocPropertyTag, tagName || createIdentifier("prop"), comment); + setChild(node, node.typeExpression = typeExpression); + setChild(node, node.name = name); + node.isNameFirst = !!isNameFirst; + node.isBracketed = isBracketed; + return finishJSDoc(node); + } + + // @api + function createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocAuthorTag, tagName || createIdentifier("author"), comment); + return finishJSDoc(node); + } + + // @api + function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"]): JSDocAugmentsTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName || createIdentifier("augments"), /*comment*/ undefined); + setChild(node, node.class = className); + return finishJSDoc(node); + } + + // @api + function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocCallbackTag, tagName || createIdentifier("callback"), comment); + setChild(node, node.typeExpression = typeExpression); + setChild(node, node.fullName = fullName); + node.name = getJSDocTypeAliasName(fullName); + return finishJSDoc(node); + } + + // @api + function createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class"), /*comment*/ undefined); + return finishJSDoc(node); + } + + // @api + function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocEnumTag, tagName || createIdentifier("enum"), /*comment*/ undefined); + setChild(node, node.typeExpression = typeExpression); + return finishJSDoc(node); + } + + // @api + function createJSDocUnknownTag(tagName: Identifier): JSDocUnknownTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTag, tagName, /*comment*/ undefined); + return finishJSDoc(node); + } + + // @api + function createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined) { + const node = createBaseNode(SyntaxKind.JSDocComment); + node.comment = comment; + setChildren(node, node.tags = tags); + return finishJSDoc(node); + } + + // + // JSX + // + + // @api + function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { + const node = createBaseNode(SyntaxKind.JsxElement); + setChild(node, node.openingElement = openingElement); + setChildren(node, node.children = createNodeArray(children)); + setChild(node, node.closingElement = closingElement); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { + return node.openingElement !== openingElement + || node.children !== children + || node.closingElement !== closingElement + ? update(createJsxElement(openingElement, children, closingElement), node) + : reuse(node); + } + + // @api + function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + const node = createBaseNode(SyntaxKind.JsxSelfClosingElement); + setChild(node, node.tagName = tagName); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.attributes = attributes); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + return node.tagName !== tagName + || node.typeArguments !== typeArguments + || node.attributes !== attributes + ? update(createJsxSelfClosingElement(tagName, typeArguments, attributes), node) + : reuse(node); + } + + // @api + function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + const node = createBaseNode(SyntaxKind.JsxOpeningElement); + setChild(node, node.tagName = tagName); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.attributes = attributes); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + return node.tagName !== tagName + || node.typeArguments !== typeArguments + || node.attributes !== attributes + ? update(createJsxOpeningElement(tagName, typeArguments, attributes), node) + : reuse(node); + } + + // @api + function createJsxClosingElement(tagName: JsxTagNameExpression) { + const node = createBaseNode(SyntaxKind.JsxClosingElement); + setChild(node, node.tagName = tagName); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { + return node.tagName !== tagName + ? update(createJsxClosingElement(tagName), node) + : reuse(node); + } + + // @api + function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { + const node = createBaseNode(SyntaxKind.JsxFragment); + setChild(node, node.openingFragment = openingFragment); + setChildren(node, node.children = createNodeArray(children)); + setChild(node, node.closingFragment = closingFragment); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { + return node.openingFragment !== openingFragment + || node.children !== children + || node.closingFragment !== closingFragment + ? update(createJsxFragment(openingFragment, children, closingFragment), node) + : reuse(node); + } + + // @api + function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + const node = createBaseNode(SyntaxKind.JsxText); + node.text = text; + node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + return node.text !== text + || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces + ? update(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) + : reuse(node); + } + + // @api + function createJsxOpeningFragment() { + const node = createBaseNode(SyntaxKind.JsxOpeningFragment); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function createJsxJsxClosingFragment() { + const node = createBaseNode(SyntaxKind.JsxClosingFragment); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined) { + const node = createBaseNode(SyntaxKind.JsxAttribute); + setChild(node, node.name = name); + setChild(node, node.initializer = initializer); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) { + return node.name !== name + || node.initializer !== initializer + ? update(createJsxAttribute(name, initializer), node) + : reuse(node); + } + + // @api + function createJsxAttributes(properties: readonly JsxAttributeLike[]) { + const node = createBaseNode(SyntaxKind.JsxAttributes); + setChildren(node, node.properties = createNodeArray(properties)); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { + return node.properties !== properties + ? update(createJsxAttributes(properties), node) + : reuse(node); + } + + // @api + function createJsxSpreadAttribute(expression: Expression) { + const node = createBaseNode(SyntaxKind.JsxSpreadAttribute); + setChild(node, node.expression = expression); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { + return node.expression !== expression + ? update(createJsxSpreadAttribute(expression), node) + : reuse(node); + } + + // @api + function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) { + const node = createBaseNode(SyntaxKind.JsxExpression); + setChild(node, node.dotDotDotToken = dotDotDotToken); + setChild(node, node.expression = expression); + if (!skipTransformationFlags) { + markJsx(node); + } + return finish(node); + } + + // @api + function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { + return node.expression !== expression + ? update(createJsxExpression(node.dotDotDotToken, expression), node) + : reuse(node); + } + + // + // Clauses + // + + // @api + function createCaseClause(expression: Expression, statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.CaseClause); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression)); + setChildren(node, node.statements = createNodeArray(statements)); + return finish(node); + } + + // @api + function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) { + return node.expression !== expression + || node.statements !== statements + ? update(createCaseClause(expression, statements), node) + : reuse(node); + } + + // @api + function createDefaultClause(statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.DefaultClause); + setChildren(node, node.statements = createNodeArray(statements)); + return finish(node); + } + + // @api + function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) { + return node.statements !== statements + ? update(createDefaultClause(statements), node) + : reuse(node); + } + + // @api + function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) { + const node = createBaseNode(SyntaxKind.HeritageClause); + node.token = token; + setChildren(node, node.types = createNodeArray(types)); + if (!skipTransformationFlags) { + switch (token) { + case SyntaxKind.ExtendsKeyword: + markES2015(node); + break; + case SyntaxKind.ImplementsKeyword: + markTypeScript(node); + break; + default: + return Debug.assertNever(token); + } + } + return finish(node); + } + + // @api + function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) { + return node.types !== types + ? update(createHeritageClause(node.token, types), node) + : reuse(node); + } + + // @api + function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) { + const node = createBaseNode(SyntaxKind.CatchClause); + variableDeclaration = !isString(variableDeclaration) ? variableDeclaration : createVariableDeclaration( + variableDeclaration, + /*exclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ); + setChild(node, node.variableDeclaration = variableDeclaration); + setChild(node, node.block = block); + if (!skipTransformationFlags) { + if (!variableDeclaration) markES2019(node); + } + return finish(node); + } + + // @api + function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { + return node.variableDeclaration !== variableDeclaration + || node.block !== block + ? update(createCatchClause(variableDeclaration, block), node) + : reuse(node); + } + + // + // Property assignments + // + + // @api + function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { + const node = createBaseNode(SyntaxKind.PropertyAssignment); + setChild(node, node.name = asName(name)); + setChild(node, node.questionToken = undefined); + setChild(node, node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)); + return finish(node); + } + + function finishUpdatePropertyAssignment(updated: PropertyAssignment, original: PropertyAssignment) { + if (original.decorators) updated.decorators = original.decorators; + if (original.modifiers) updated.modifiers = original.modifiers; + if (original.questionToken) updated.questionToken = original.questionToken; + if (original.exclamationToken) updated.exclamationToken = original.exclamationToken; + return update(updated, original); + } + + // @api + function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) { + return node.name !== name + || node.initializer !== initializer + ? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node) + : reuse(node); + } + + // @api + function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { + const node = createBaseNamedDeclaration( + SyntaxKind.ShorthandPropertyAssignment, + /*decorators*/ undefined, + /*modifiers*/ undefined, + name + ); + setChild(node, node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined + ? parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) + : undefined); + if (!skipTransformationFlags) { + markES2015(node); + } + return finish(node); + } + + function finishUpdateShorthandPropertyAssignment(updated: ShorthandPropertyAssignment, original: ShorthandPropertyAssignment) { + if (original.decorators) updated.decorators = original.decorators; + if (original.modifiers) updated.modifiers = original.modifiers; + if (original.equalsToken) updated.equalsToken = original.equalsToken; + if (original.questionToken) updated.questionToken = original.questionToken; + if (original.exclamationToken) updated.exclamationToken = original.exclamationToken; + return update(updated, original); + } + + // @api + function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) { + return node.name !== name + || node.objectAssignmentInitializer !== objectAssignmentInitializer + ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) + : reuse(node); + } + + // @api + function createSpreadAssignment(expression: Expression) { + const node = createBaseNode(SyntaxKind.SpreadAssignment); + setChild(node, node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression)); + if (!skipTransformationFlags) { + markES2018(node); + markObjectRestOrSpread(node); + } + return finish(node); + } + + // @api + function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { + return node.expression !== expression + ? update(createSpreadAssignment(expression), node) + : reuse(node); + } + + // + // Enum + // + + // @api + function createEnumMember(name: string | PropertyName, initializer?: Expression) { + const node = createBaseNode(SyntaxKind.EnumMember); + setChild(node, node.name = asName(name)); + setChild(node, node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { + return node.name !== name + || node.initializer !== initializer + ? update(createEnumMember(name, initializer), node) + : reuse(node); + } + + // + // Top-level nodes + // + + // @api + function createSourceFile( + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + ) { + const node = createSourceFileNode(SyntaxKind.SourceFile) as SourceFile; + setChildren(node, node.statements = createNodeArray(statements)); + setChild(node, node.endOfFileToken = endOfFileToken); + node.fileName = ""; + node.text = ""; + node.languageVersion = 0; + node.languageVariant = 0; + node.scriptKind = 0; + node.isDeclarationFile = false; + node.hasNoDefaultLib = false; + return finish(node); + } + + function cloneSourceFileWithChanges( + source: SourceFile, + statements: readonly Statement[], + isDeclarationFile: boolean, + referencedFiles: readonly FileReference[], + typeReferences: readonly FileReference[], + hasNoDefaultLib: boolean, + libReferences: readonly FileReference[] + ) { + const node = createBaseNode(SyntaxKind.SourceFile); + for (const p in source) { + if (p === "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue; + (node as any)[p] = (source as any)[p]; + } + node.flags |= source.flags; + setChildren(node, node.statements = createNodeArray(statements)); + setChild(node, node.endOfFileToken); + node.isDeclarationFile = isDeclarationFile; + node.referencedFiles = referencedFiles; + node.typeReferenceDirectives = typeReferences; + node.hasNoDefaultLib = hasNoDefaultLib; + node.libReferenceDirectives = libReferences; + return finish(node); + } + + // @api + function updateSourceFile( + node: SourceFile, + statements: readonly Statement[], + isDeclarationFile = node.isDeclarationFile, + referencedFiles = node.referencedFiles, + typeReferenceDirectives = node.typeReferenceDirectives, + hasNoDefaultLib = node.hasNoDefaultLib, + libReferenceDirectives = node.libReferenceDirectives + ) { + return node.statements !== statements + || node.isDeclarationFile !== isDeclarationFile + || node.referencedFiles !== referencedFiles + || node.typeReferenceDirectives !== typeReferenceDirectives + || node.hasNoDefaultLib !== hasNoDefaultLib + || node.libReferenceDirectives !== libReferenceDirectives + ? update(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node) + : reuse(node); + } + + // @api + function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { + const node = createBaseNode(SyntaxKind.Bundle); + node.prepends = prepends; + node.sourceFiles = sourceFiles; + return finish(node); + } + + // @api + function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { + return node.sourceFiles !== sourceFiles + || node.prepends !== prepends + ? update(createBundle(sourceFiles, prepends), node) + : reuse(node); + } + + // + // Transformation nodes + // + + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ + // @api + function createNotEmittedStatement(original: Node) { + const node = createBaseNode(SyntaxKind.NotEmittedStatement); + node.original = original; + setTextRange(node, original); + return finish(node); + } + + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + */ + // @api + function createPartiallyEmittedExpression(expression: Expression, original?: Node) { + const node = createBaseNode(SyntaxKind.PartiallyEmittedExpression); + setChild(node, node.expression = expression); + node.original = original; + setTextRange(node, original); + if (!skipTransformationFlags) { + markTypeScript(node); + } + return finish(node); + } + + // @api + function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { + return node.expression !== expression + ? update(createPartiallyEmittedExpression(expression, node.original), node) + : reuse(node); + } + + function flattenCommaElements(node: Expression): Expression | readonly Expression[] { + if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { + if (node.kind === SyntaxKind.CommaListExpression) { + return (node).elements; + } + if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { + return [node.left, node.right]; + } + } + return node; + } + + // @api + function createCommaListExpression(elements: readonly Expression[]) { + const node = createBaseNode(SyntaxKind.CommaListExpression); + setChildren(node, node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements))); + return finish(node); + } + + // @api + function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) { + return node.elements !== elements + ? update(createCommaListExpression(elements), node) + : reuse(node); + } + + /** + * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in + * order to properly emit exports. + */ + // @api + function createEndOfDeclarationMarker(original: Node) { + const node = createBaseNode(SyntaxKind.EndOfDeclarationMarker); + node.emitNode = {} as EmitNode; + node.original = original; + return finish(node); + } + + /** + * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in + * order to properly emit exports. + */ + // @api + function createMergeDeclarationMarker(original: Node) { + const node = createBaseNode(SyntaxKind.MergeDeclarationMarker); + node.emitNode = {} as EmitNode; + node.original = original; + return finish(node); + } + + // @api + function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) { + const node = createBaseNode(SyntaxKind.SyntheticReferenceExpression); + setChild(node, node.expression = expression); + setChild(node, node.thisArg = thisArg); + return node; + } + + // @api + function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) { + return node.expression !== expression + || node.thisArg !== thisArg + ? updateNode(createSyntheticReferenceExpression(expression, thisArg), node) + : node; + } + + function asNodeArray(array: readonly T[]): NodeArray; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { + return array ? createNodeArray(array) : undefined; + } + + function asName(name: string | T): T | Identifier { + return typeof name === "string" ? createIdentifier(name) : + name; + } + + function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { + return typeof value === "string" ? createStringLiteral(value) : + typeof value === "number" ? createNumericLiteral(value) : + typeof value === "boolean" ? value ? createTrue() : createFalse() : + value; + } + + function asToken(value: TKind | Token): Token { + return typeof value === "number" ? createToken(value) : value; + } + + function asEmbeddedStatement(statement: T): T | EmptyStatement; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { + return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; + } + + function setChildWorker(parent: Node, child: Node | undefined): void { + if (!skipTransformationFlags) { + if (child) { + parent.transformFlags |= propagateChildFlags(child); + } + } + } + + function setChildrenWorker(parent: Node, children: NodeArray | undefined): void { + if (!skipTransformationFlags) { + if (children) { + parent.transformFlags |= propagateChildrenFlags(children); + } + } + } + + function finishWorker(node: T) { + if (!skipTransformationFlags) { + node.transformFlags |= TransformFlags.HasComputedFlags; + } + return node; + } + + function updateWorker(updated: T, original: T) { + return updateNode(updated, original); + } + + function reuseWorker(node: T) { + return node; + } + } + + function createLazyFactoryMembers( + factory: NodeFactory, + asExpression: (value: string | number | boolean | T) => T | StringLiteral | NumericLiteral | BooleanLiteral, + ) { + // lazy initializaton of common operator factories + let lazyBinaryFactories: ((left: Expression, right: Expression) => BinaryExpression)[] | undefined; + let lazyPrefixUnaryFactories: ((operand: Expression) => PrefixUnaryExpression)[] | undefined; + let lazyPostfixUnaryFactories: ((operand: Expression) => PostfixUnaryExpression)[] | undefined; + + return { + get createComma() { return getBinaryFactory(SyntaxKind.CommaToken); }, + get createAssignment() { return getBinaryFactory(SyntaxKind.EqualsToken) as NodeFactory["createAssignment"]; }, + get createLogicalOr() { return getBinaryFactory(SyntaxKind.BarBarToken); }, + get createLogicalAnd() { return getBinaryFactory(SyntaxKind.AmpersandAmpersandToken); }, + get createBitwiseOr() { return getBinaryFactory(SyntaxKind.BarToken); }, + get createBitwiseXor() { return getBinaryFactory(SyntaxKind.CaretToken); }, + get createBitwiseAnd() { return getBinaryFactory(SyntaxKind.AmpersandToken); }, + get createStrictEquality() { return getBinaryFactory(SyntaxKind.EqualsEqualsEqualsToken); }, + get createStrictInequality() { return getBinaryFactory(SyntaxKind.ExclamationEqualsEqualsToken); }, + get createEquality() { return getBinaryFactory(SyntaxKind.EqualsEqualsToken); }, + get createInequality() { return getBinaryFactory(SyntaxKind.ExclamationEqualsToken); }, + get createLessThan() { return getBinaryFactory(SyntaxKind.LessThanToken); }, + get createLessThanEquals() { return getBinaryFactory(SyntaxKind.LessThanEqualsToken); }, + get createGreaterThan() { return getBinaryFactory(SyntaxKind.GreaterThanToken); }, + get createGreaterThanEquals() { return getBinaryFactory(SyntaxKind.GreaterThanEqualsToken); }, + get createLeftShift() { return getBinaryFactory(SyntaxKind.LessThanLessThanToken); }, + get createRightShift() { return getBinaryFactory(SyntaxKind.GreaterThanGreaterThanToken); }, + get createUnsignedRightShift() { return getBinaryFactory(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); }, + get createAdd() { return getBinaryFactory(SyntaxKind.PlusToken); }, + get createSubtract() { return getBinaryFactory(SyntaxKind.MinusToken); }, + get createMultiply() { return getBinaryFactory(SyntaxKind.AsteriskToken); }, + get createDivide() { return getBinaryFactory(SyntaxKind.SlashToken); }, + get createModulo() { return getBinaryFactory(SyntaxKind.PercentToken); }, + get createExponent() { return getBinaryFactory(SyntaxKind.AsteriskAsteriskToken); }, + get createPrefixPlus() { return getPrefixUnaryFactory(SyntaxKind.PlusToken); }, + get createPrefixMinus() { return getPrefixUnaryFactory(SyntaxKind.MinusToken); }, + get createPrefixIncrement() { return getPrefixUnaryFactory(SyntaxKind.PlusPlusToken); }, + get createPrefixDecrement() { return getPrefixUnaryFactory(SyntaxKind.MinusMinusToken); }, + get createBitwiseNot() { return getPrefixUnaryFactory(SyntaxKind.TildeToken); }, + get createLogicalNot() { return getPrefixUnaryFactory(SyntaxKind.ExclamationToken); }, + get createPostfixIncrement() { return getPostfixUnaryFactory(SyntaxKind.PlusPlusToken); }, + get createPostfixDecrement() { return getPostfixUnaryFactory(SyntaxKind.MinusMinusToken); }, + + createSignatureDeclaration, + createImmediatelyInvokedFunctionExpression, + createImmediatelyInvokedArrowFunction, + createVoidZero, + createExportDefault, + createExternalModuleExport, + createTypeCheck, + createMethodCall, + createGlobalMethodCall, + createFunctionBindCall, + createFunctionCallCall, + createFunctionApplyCall, + createArraySliceCall, + createArrayConcatCall, + createObjectDefinePropertyCall, + createPropertyDescriptor, + createCallBinding, + inlineExpressions, + getInternalName, + getLocalName, + getExportName, + getDeclarationName, + getNamespaceMemberName, + getExternalModuleOrNamespaceExportName, + recreateOuterExpressions, + restoreEnclosingLabel, + createUseStrictPrologue, + copyPrologue, + copyStandardPrologue, + copyCustomPrologue, + ensureUseStrict, + liftToBlock, + }; + + function getBinaryFactory(operator: BinaryOperator) { + const factories = lazyBinaryFactories || []; + return factories[operator] || (factories[operator] = (left, right) => factory.createBinary(left, operator, right)); + } + + function getPrefixUnaryFactory(operator: PrefixUnaryOperator) { + const factories = lazyPrefixUnaryFactories || []; + return factories[operator] || (factories[operator] = operand => factory.createPrefix(operator, operand)); + } + + function getPostfixUnaryFactory(operator: PostfixUnaryOperator) { + const factories = lazyPostfixUnaryFactories || []; + return factories[operator] || (factories[operator] = operand => factory.createPostfix(operand, operator)); + } + + // Route signature creation to the appropriate factory method. Used by the NodeBuilder in the checker. + function createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; + function createSignatureDeclaration(kind: SignatureDeclaration["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): SignatureDeclaration { + switch (kind) { + case SyntaxKind.CallSignature: + return factory.createCallSignature(typeParameters, parameters, type); + case SyntaxKind.ConstructSignature: + return factory.createConstructSignature(typeParameters, parameters, type); + case SyntaxKind.MethodSignature: + // NOTE: This creates an *invalid* method signature since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createMethodSignature(/*modifiers*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type); + case SyntaxKind.MethodDeclaration: + // NOTE: This creates an *invalid* method declaration since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createMethodDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type, /*body*/ undefined); + case SyntaxKind.Constructor: + return factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined); + case SyntaxKind.GetAccessor: + // NOTE: This creates an *invalid* get accessor since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createGetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, type, /*body*/ undefined); + case SyntaxKind.SetAccessor: + // NOTE: This creates an *invalid* set accessor since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createSetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, /*body*/ undefined); + case SyntaxKind.IndexSignature: + return factory.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, type); + case SyntaxKind.JSDocFunctionType: + return factory.createJSDocFunctionType(parameters, type); + case SyntaxKind.FunctionType: + return factory.createFunctionTypeNode(typeParameters, parameters, type); + case SyntaxKind.ConstructorType: + return factory.createConstructorTypeNode(typeParameters, parameters, type); + case SyntaxKind.FunctionDeclaration: + return factory.createFunctionDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined); + case SyntaxKind.FunctionExpression: + // NOTE: This creates an *invalid* function expression since `body` is `undefined`, but this is preserved to support existing behavior. + return factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined!); + case SyntaxKind.ArrowFunction: + // NOTE: This creates an *invalid* arrow function since `body` is `undefined`, but this is preserved to support existing behavior. + return factory.createArrowFunction(/*modifiers*/ undefined, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, /*body*/ undefined!); + default: + return Debug.assertNever(kind); + } + } + + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { + return factory.createCall( + factory.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, + factory.createBlock(statements, /*multiLine*/ true) + ), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : [] + ); + } + + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { + return factory.createCall( + factory.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, + factory.createBlock(statements, /*multiLine*/ true) + ), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : [] + ); + } + + function createVoidZero() { + return factory.createVoid(factory.createNumericLiteral("0")); + } + + function createExportDefault(expression: Expression) { + return factory.createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, + expression); + } + + function createExternalModuleExport(exportName: Identifier) { + return factory.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + factory.createNamedExports([ + factory.createExportSpecifier(/*propertyName*/ undefined, exportName) + ]) + ); + } + + // + // Utilities + // + + function createTypeCheck(value: Expression, tag: TypeOfTag) { + return tag === "undefined" + ? factory.createStrictEquality(value, createVoidZero()) + : factory.createStrictEquality(factory.createTypeOf(value), factory.createStringLiteral(tag)); + } + + function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { + return factory.createCall( + factory.createPropertyAccess(object, methodName), + /*typeArguments*/ undefined, + argumentsList + ); + } + + function createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) { + return createMethodCall(target, "bind", [thisArg, ...argumentsList]); + } + + function createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) { + return createMethodCall(target, "call", [thisArg, ...argumentsList]); + } + + function createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression) { + return createMethodCall(target, "apply", [thisArg, argumentsExpression]); + } + + function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) { + return createMethodCall(factory.createIdentifier(globalObjectName), methodName, argumentsList); + } + + function createArraySliceCall(array: Expression, start?: number | Expression) { + return createMethodCall(array, "slice", start === undefined ? [] : [asExpression(start)]); + } + + function createArrayConcatCall(array: Expression, argumentsList: readonly Expression[]) { + return createMethodCall(array, "concat", argumentsList); + } + + function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) { + return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]); + } + + function tryAddPropertyAssignment(properties: Push, propertyName: string, expression: Expression | undefined) { + if (expression) { + properties.push(factory.createPropertyAssignment(propertyName, expression)); + return true; + } + return false; + } + + function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) { + const properties: PropertyAssignment[] = []; + tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable)); + tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable)); + + let isData = tryAddPropertyAssignment(properties, "writable", asExpression(attributes.writable)); + isData = tryAddPropertyAssignment(properties, "value", attributes.value) || isData; + + let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get); + isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor; + + Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); + return factory.createObjectLiteral(properties, !singleLine); + } + + function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) { + switch (outerExpression.kind) { + case SyntaxKind.ParenthesizedExpression: return factory.updateParen(outerExpression, expression); + case SyntaxKind.TypeAssertionExpression: return factory.updateTypeAssertion(outerExpression, outerExpression.type, expression); + case SyntaxKind.AsExpression: return factory.updateAsExpression(outerExpression, expression, outerExpression.type); + case SyntaxKind.NonNullExpression: return factory.updateNonNullExpression(outerExpression, expression); + case SyntaxKind.PartiallyEmittedExpression: return factory.updatePartiallyEmittedExpression(outerExpression, expression); + } + } + + /** + * Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions. + * + * A parenthesized expression can be ignored when all of the following are true: + * + * - It's `pos` and `end` are not -1 + * - It does not have a custom source map range + * - It does not have a custom comment range + * - It does not have synthetic leading or trailing comments + * + * If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around + * the expression to maintain precedence, a new parenthesized expression should be created automatically when + * the containing expression is created/updated. + */ + function isIgnorableParen(node: Expression) { + return node.kind === SyntaxKind.ParenthesizedExpression + && nodeIsSynthesized(node) + && nodeIsSynthesized(getSourceMapRange(node)) + && nodeIsSynthesized(getCommentRange(node)) + && !some(getSyntheticLeadingComments(node)) + && !some(getSyntheticTrailingComments(node)); + } + + function recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression { + if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { + return updateOuterExpression( + outerExpression, + recreateOuterExpressions(outerExpression.expression, innerExpression) + ); + } + return innerExpression; + } + + function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { + if (!outermostLabeledStatement) { + return node; + } + const updated = factory.updateLabel( + outermostLabeledStatement, + outermostLabeledStatement.label, + outermostLabeledStatement.statement.kind === SyntaxKind.LabeledStatement + ? restoreEnclosingLabel(node, outermostLabeledStatement.statement) + : node + ); + if (afterRestoreLabelCallback) { + afterRestoreLabelCallback(outermostLabeledStatement); + } + return updated; + } + + function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean { + const target = skipParentheses(node); + switch (target.kind) { + case SyntaxKind.Identifier: + return cacheIdentifiers; + case SyntaxKind.ThisKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + return false; + case SyntaxKind.ArrayLiteralExpression: + const elements = (target).elements; + if (elements.length === 0) { + return false; + } + return true; + case SyntaxKind.ObjectLiteralExpression: + return (target).properties.length > 0; + default: + return true; + } + } + + function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding { + const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); + let thisArg: Expression; + let target: LeftHandSideExpression; + if (isSuperProperty(callee)) { + thisArg = factory.createThis(); + target = callee; + } + else if (callee.kind === SyntaxKind.SuperKeyword) { + thisArg = factory.createThis(); + target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015 + ? setTextRange(factory.createIdentifier("_super"), callee) + : callee; + } + else if (getEmitFlags(callee) & EmitFlags.HelperName) { + thisArg = createVoidZero(); + target = factory.parenthesizer.parenthesizeLeftSideOfAccess(callee); + } + else if (isPropertyAccessExpression(callee)) { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` + thisArg = factory.createTempVariable(recordTempVariable); + target = factory.createPropertyAccess( + setTextRange( + factory.createAssignment( + thisArg, + callee.expression + ), + callee.expression + ), + callee.name + ); + setTextRange(target, callee); + } + else { + thisArg = callee.expression; + target = callee; + } + } + else if (isElementAccessExpression(callee)) { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` + thisArg = factory.createTempVariable(recordTempVariable); + target = factory.createElementAccess( + setTextRange( + factory.createAssignment( + thisArg, + callee.expression + ), + callee.expression + ), + callee.argumentExpression + ); + setTextRange(target, callee); + } + else { + thisArg = callee.expression; + target = callee; + } + } + else { + // for `a()` target is `a` and thisArg is `void 0` + thisArg = createVoidZero(); + target = factory.parenthesizer.parenthesizeLeftSideOfAccess(expression); + } + + return { target, thisArg }; + } + + function inlineExpressions(expressions: readonly Expression[]) { + // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call + // stack size exceeded" errors. + return expressions.length > 10 + ? factory.createCommaList(expressions) + : reduceLeft(expressions, factory.createComma)!; + } + + function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { + const nodeName = getNameOfDeclaration(node); + if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { + const name = getMutableClone(nodeName); + emitFlags |= getEmitFlags(nodeName); + if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags |= EmitFlags.NoComments; + if (emitFlags) setEmitFlags(name, emitFlags); + return name; + } + return factory.getGeneratedNameForNode(node); + } + + /** + * Gets the internal name of a declaration. This is primarily used for declarations that can be + * referred to by name in the body of an ES5 class function body. An internal name will *never* + * be prefixed with an module or namespace export modifier like "exports." when emitted as an + * expression. An internal name will also *never* be renamed due to a collision with a block + * scoped variable. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { + return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName); + } + + /** + * Gets the local name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A + * local name will *never* be prefixed with an module or namespace export modifier like + * "exports." when emitted as an expression. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { + return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName); + } + + /** + * Gets the export name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An + * export name will *always* be prefixed with an module or namespace export modifier like + * `"exports."` when emitted as an expression if the name points to an exported symbol. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier { + return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName); + } + + /** + * Gets the name of a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getDeclarationName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { + return getName(node, allowComments, allowSourceMaps); + } + + /** + * Gets a namespace-qualified name for use in expressions. + * + * @param ns The namespace identifier. + * @param name The name. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { + const qualifiedName = factory.createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); + setTextRange(qualifiedName, name); + let emitFlags: EmitFlags = 0; + if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags |= EmitFlags.NoComments; + if (emitFlags) setEmitFlags(qualifiedName, emitFlags); + return qualifiedName; + } + + /** + * Gets the exported name of a declaration for use in expressions. + * + * An exported name will *always* be prefixed with an module or namespace export modifier like + * "exports." if the name points to an exported symbol. + * + * @param ns The namespace identifier. + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression { + if (ns && hasModifier(node, ModifierFlags.Export)) { + return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); + } + return getExportName(node, allowComments, allowSourceMaps); + } + + /** + * Copies any necessary standard and custom prologue-directives into target array. + * @param source origin statements array + * @param target result statements array + * @param ensureUseStrict boolean determining whether the function need to add prologue-directives + * @param visitor Optional callback used to visit any custom prologue directives. + */ + function copyPrologue(source: readonly Statement[], target: Push, ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number { + const offset = copyStandardPrologue(source, target, ensureUseStrict); + return copyCustomPrologue(source, target, offset, visitor); + } + + function isUseStrictPrologue(node: ExpressionStatement): boolean { + return isStringLiteral(node.expression) && node.expression.text === "use strict"; + } + + function createUseStrictPrologue() { + return startOnNewLine(factory.createExpressionStatement(factory.createStringLiteral("use strict"))) as PrologueDirective; + } + + /** + * Copies only the standard (string-expression) prologue-directives into the target statement-array. + * @param source origin statements array + * @param target result statements array + * @param ensureUseStrict boolean determining whether the function need to add prologue-directives + */ + function copyStandardPrologue(source: readonly Statement[], target: Push, ensureUseStrict?: boolean): number { + Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); + let foundUseStrict = false; + let statementOffset = 0; + const numStatements = source.length; + while (statementOffset < numStatements) { + const statement = source[statementOffset]; + if (isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement)) { + foundUseStrict = true; + } + target.push(statement); + } + else { + break; + } + statementOffset++; + } + if (ensureUseStrict && !foundUseStrict) { + target.push(createUseStrictPrologue()); + } + return statementOffset; + } + + /** + * Copies only the custom prologue-directives into target statement-array. + * @param source origin statements array + * @param target result statements array + * @param statementOffset The offset at which to begin the copy. + * @param visitor Optional callback used to visit any custom prologue directives. + */ + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number, visitor?: (node: Node) => VisitResult): number; + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined; + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined { + const numStatements = source.length; + while (statementOffset !== undefined && statementOffset < numStatements) { + const statement = source[statementOffset]; + if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { + append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); + } + else { + break; + } + statementOffset++; + } + return statementOffset; + } + + /** + * Ensures "use strict" directive is added + * + * @param statements An array of statements + */ + function ensureUseStrict(statements: NodeArray): NodeArray { + const foundUseStrict = findUseStrictPrologue(statements); + + if (!foundUseStrict) { + return setTextRange(factory.createNodeArray([createUseStrictPrologue(), ...statements]), statements); + } + + return statements; + } + + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ + function liftToBlock(nodes: readonly Node[]): Statement { + Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block."); + return singleOrUndefined(nodes) || factory.createBlock(nodes); + } + } + + // Language-edition and feature specific node markers + const markBindingPattern = createFlagMarker(TransformFlags.ContainsBindingPattern); + const markBlockScopedBinding = createFlagMarker(TransformFlags.ContainsBlockScopedBinding); + const markRestOrSpread = createFlagMarker(TransformFlags.ContainsRestOrSpread); + const markObjectRestOrSpread = createFlagMarker(TransformFlags.ContainsObjectRestOrSpread); + const markDestructuringAssignment = createFlagMarker(TransformFlags.ContainsDestructuringAssignment); + const markComputedPropertyName = createFlagMarker(TransformFlags.ContainsComputedPropertyName); + const markLexicalThis = createFlagMarker(TransformFlags.ContainsLexicalThis); + const markDynamicImport = createFlagMarker(TransformFlags.ContainsDynamicImport); + const markGenerator = createFlagMarker(TransformFlags.ContainsGenerator); + const markYield = createFlagMarker(TransformFlags.ContainsYield); + const markHoistedDeclarationOrCompletion = createFlagMarker(TransformFlags.ContainsHoistedDeclarationOrCompletion); + const markClassFields = createFlagMarker(TransformFlags.ContainsClassFields); + const markES2015 = createFlagMarker(TransformFlags.ContainsES2015); + const markES2016 = createFlagMarker(TransformFlags.ContainsES2016); + const markES2017 = createFlagMarker(TransformFlags.ContainsES2017); + const markES2018 = createFlagMarker(TransformFlags.ContainsES2018); + const markES2019 = createFlagMarker(TransformFlags.ContainsES2019); + const markESNext = createFlagMarker(TransformFlags.ContainsESNext); + const markTypeScript = createFlagMarker(TransformFlags.ContainsTypeScript); + const markTypeScriptOnly = createFlagMarker(TransformFlags.ContainsTypeScript, /*excludeSubtree*/ true); + const markTypeScriptClassSyntax = createFlagMarker(TransformFlags.ContainsTypeScriptClassSyntax); + const markJsx = createFlagMarker(TransformFlags.ContainsJsx); + + function createFlagMarker(transformFlags: TransformFlags, excludeSubtree?: boolean) { + return excludeSubtree ? (node: Node) => { node.transformFlags = transformFlags; } : + (node: Node) => { node.transformFlags |= transformFlags; }; + } + + function observeArguments(action: (arg1: U, arg2: U) => U, observer: ((arg1: T, arg2: T) => void) | undefined): (arg1: U, arg2: U) => U; + function observeArguments(action: (arg1: T, arg2: U | undefined) => R, observer: ((arg1: T, arg2: U) => void) | undefined): (arg1: T, arg2: U | undefined) => R; + function observeArguments(action: (arg1: T, arg2: U) => R, observer: ((arg1: T, arg2: U) => void) | undefined): (arg1: T, arg2: U) => R { + return !observer ? action : (arg1, arg2) => { + if (arg2 !== undefined) { + observer(arg1, arg2); + } + return action(arg1, arg2); + }; + } + + function observeResult(action: (arg: U) => U, observer: ((result: T) => void) | undefined): (arg: U) => U; + function observeResult(action: (arg: T) => R, observer: ((result: R) => void) | undefined): (arg: T) => R; + function observeResult(action: (arg: T) => R, observer: ((result: R) => void) | undefined): (arg: T) => R { + return !observer ? action : arg => { + const result = action(arg); + observer(result); + return result; + }; + } + + let rawTextScanner: Scanner | undefined; + const invalidValueSentinel: object = { }; + + function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) { + if (!rawTextScanner) { + rawTextScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard); + } + switch (kind) { + case SyntaxKind.NoSubstitutionTemplateLiteral: + rawTextScanner.setText("`" + rawText + "`"); + break; + case SyntaxKind.TemplateHead: + // tslint:disable-next-line no-invalid-template-strings + rawTextScanner.setText("`" + rawText + "${"); + break; + case SyntaxKind.TemplateMiddle: + // tslint:disable-next-line no-invalid-template-strings + rawTextScanner.setText("}" + rawText + "${"); + break; + case SyntaxKind.TemplateTail: + rawTextScanner.setText("}" + rawText + "`"); + break; + } + + let token = rawTextScanner.scan(); + if (token === SyntaxKind.CloseBracketToken) { + token = rawTextScanner.reScanTemplateToken(); + } + + if (rawTextScanner.isUnterminated()) { + rawTextScanner.setText(undefined); + return invalidValueSentinel; + } + + let tokenValue: string | undefined; + switch (token) { + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + tokenValue = rawTextScanner.getTokenValue(); + break; + } + + if (tokenValue === undefined || rawTextScanner.scan() !== SyntaxKind.EndOfFileToken) { + rawTextScanner.setText(undefined); + return invalidValueSentinel; + } + + rawTextScanner.setText(undefined); + return tokenValue; + } + + function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) { + return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags); + } + + function propagateChildFlags(child: Node): TransformFlags { + const childFlags = child.transformFlags & ~TransformFlags.HasComputedFlags & ~getTransformFlagsSubtreeExclusions(child.kind); + return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlags(child.name, childFlags) : childFlags; + } + + function propagateChildrenFlags(children: NodeArray): TransformFlags { + return children.transformFlags & ~TransformFlags.HasComputedFlags; + } + + function aggregateChildrenFlags(children: NodeArray) { + let subtreeFlags = TransformFlags.None; + for (const child of children) { + subtreeFlags |= propagateChildFlags(child); + } + children.transformFlags = subtreeFlags | TransformFlags.HasComputedFlags; + } + + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + */ + /* @internal */ + export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { + if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) { + return TransformFlags.TypeExcludes; + } + + switch (kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ArrayLiteralExpression: + return TransformFlags.ArrayLiteralOrCallOrNewExcludes; + case SyntaxKind.ModuleDeclaration: + return TransformFlags.ModuleExcludes; + case SyntaxKind.Parameter: + return TransformFlags.ParameterExcludes; + case SyntaxKind.ArrowFunction: + return TransformFlags.ArrowFunctionExcludes; + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + return TransformFlags.FunctionExcludes; + case SyntaxKind.VariableDeclarationList: + return TransformFlags.VariableDeclarationListExcludes; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return TransformFlags.ClassExcludes; + case SyntaxKind.Constructor: + return TransformFlags.ConstructorExcludes; + case SyntaxKind.PropertyDeclaration: + return TransformFlags.PropertyExcludes; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return TransformFlags.MethodOrAccessorExcludes; + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + return TransformFlags.TypeExcludes; + case SyntaxKind.ObjectLiteralExpression: + return TransformFlags.ObjectLiteralExcludes; + case SyntaxKind.CatchClause: + return TransformFlags.CatchClauseExcludes; + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return TransformFlags.BindingPatternExcludes; + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.PartiallyEmittedExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.SuperKeyword: + return TransformFlags.OuterExpressionExcludes; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + return TransformFlags.PropertyAccessExcludes; + default: + return TransformFlags.NodeExcludes; + } + } + + export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, createBaseNodeFactory(), { + onCreateNode: node => node.flags |= NodeFlags.Synthesized + }); + + /* @internal */ + export function createSynthesizedNode(kind: SyntaxKind): Node { + const node = createNode(kind, -1, -1); + node.flags |= NodeFlags.Synthesized; + return node; + } + + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + /* @internal */ + export function getSynthesizedClone(node: T): T { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). + + if (node === undefined) { + return node; + } + + const clone = createSynthesizedNode(node.kind); + clone.flags |= node.flags; + setOriginalNode(clone, node); + + for (const key in node) { + if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { + continue; + } + + (clone)[key] = (node)[key]; + } + + return clone; + } + + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + export function getMutableClone(node: T): T { + const clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + clone.parent = node.parent; + return clone; + } + + /* @internal */ + export function updateNode(updated: T, original: T): T { + if (updated !== original) { + setOriginalNode(updated, original); + setTextRange(updated, original); + } + return updated; + } + + // TODO(rbuckton): Move this to factory + function createUnparsedSource() { + const node = createNode(SyntaxKind.UnparsedSource); + node.prologues = emptyArray; + node.referencedFiles = emptyArray; + node.libReferenceDirectives = emptyArray; + node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos); + return node; + } + + export function createUnparsedSourceFile(text: string): UnparsedSource; + export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; + export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; + export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource { + const node = createUnparsedSource(); + let stripInternal: boolean | undefined; + let bundleFileInfo: BundleFileInfo | undefined; + if (!isString(textOrInputFiles)) { + Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts"); + node.fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || ""; + node.sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath; + Object.defineProperties(node, { + text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } }, + sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } }, + }); + + + if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) { + node.oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit; + Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean"); + stripInternal = mapTextOrStripInternal as boolean | undefined; + bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts; + if (node.oldFileOfCurrentEmit) { + parseOldFileOfCurrentEmit(node, Debug.assertDefined(bundleFileInfo)); + return node; + } + } + } + else { + node.fileName = ""; + node.text = textOrInputFiles; + node.sourceMapPath = mapPathOrType; + node.sourceMapText = mapTextOrStripInternal as string; + } + Debug.assert(!node.oldFileOfCurrentEmit); + parseUnparsedSourceFile(node, bundleFileInfo, stripInternal); + return node; + } + + function parseUnparsedSourceFile(node: UnparsedSource, bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined) { + let prologues: UnparsedPrologue[] | undefined; + let helpers: UnscopedEmitHelper[] | undefined; + let referencedFiles: FileReference[] | undefined; + let typeReferenceDirectives: string[] | undefined; + let libReferenceDirectives: FileReference[] | undefined; + let texts: UnparsedSourceText[] | undefined; + + for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) { + switch (section.kind) { + case BundleFileSectionKind.Prologue: + (prologues || (prologues = [])).push(createUnparsedNode(section, node) as UnparsedPrologue); + break; + case BundleFileSectionKind.EmitHelpers: + (helpers || (helpers = [])).push(getAllUnscopedEmitHelpers().get(section.data)!); + break; + case BundleFileSectionKind.NoDefaultLib: + node.hasNoDefaultLib = true; + break; + case BundleFileSectionKind.Reference: + (referencedFiles || (referencedFiles = [])).push({ pos: -1, end: -1, fileName: section.data }); + break; + case BundleFileSectionKind.Type: + (typeReferenceDirectives || (typeReferenceDirectives = [])).push(section.data); + break; + case BundleFileSectionKind.Lib: + (libReferenceDirectives || (libReferenceDirectives = [])).push({ pos: -1, end: -1, fileName: section.data }); + break; + case BundleFileSectionKind.Prepend: + const prependNode = createUnparsedNode(section, node) as UnparsedPrepend; + let prependTexts: UnparsedTextLike[] | undefined; + for (const text of section.texts) { + if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) { + (prependTexts || (prependTexts = [])).push(createUnparsedNode(text, node) as UnparsedTextLike); + } + } + prependNode.texts = prependTexts || emptyArray; + (texts || (texts = [])).push(prependNode); + break; + case BundleFileSectionKind.Internal: + if (stripInternal) { + if (!texts) texts = []; + break; + } + // falls through + + case BundleFileSectionKind.Text: + (texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike); + break; + default: + Debug.assertNever(section); + } + } + + node.prologues = prologues || emptyArray; + node.helpers = helpers; + node.referencedFiles = referencedFiles || emptyArray; + node.typeReferenceDirectives = typeReferenceDirectives; + node.libReferenceDirectives = libReferenceDirectives || emptyArray; + node.texts = texts || [createUnparsedNode({ kind: BundleFileSectionKind.Text, pos: 0, end: node.text.length }, node)]; + } + + function parseOldFileOfCurrentEmit(node: UnparsedSource, bundleFileInfo: BundleFileInfo) { + Debug.assert(!!node.oldFileOfCurrentEmit); + let texts: UnparsedTextLike[] | undefined; + let syntheticReferences: UnparsedSyntheticReference[] | undefined; + for (const section of bundleFileInfo.sections) { + switch (section.kind) { + case BundleFileSectionKind.Internal: + case BundleFileSectionKind.Text: + (texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike); + break; + + case BundleFileSectionKind.NoDefaultLib: + case BundleFileSectionKind.Reference: + case BundleFileSectionKind.Type: + case BundleFileSectionKind.Lib: + (syntheticReferences || (syntheticReferences = [])).push(createUnparsedSyntheticReference(section, node)); + break; + + // Ignore + case BundleFileSectionKind.Prologue: + case BundleFileSectionKind.EmitHelpers: + case BundleFileSectionKind.Prepend: + break; + + default: + Debug.assertNever(section); + } + } + node.texts = texts || emptyArray; + node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); + node.syntheticReferences = syntheticReferences; + return node; + } + + function mapBundleFileSectionKindToSyntaxKind(kind: BundleFileSectionKind): SyntaxKind { + switch (kind) { + case BundleFileSectionKind.Prologue: return SyntaxKind.UnparsedPrologue; + case BundleFileSectionKind.Prepend: return SyntaxKind.UnparsedPrepend; + case BundleFileSectionKind.Internal: return SyntaxKind.UnparsedInternalText; + case BundleFileSectionKind.Text: return SyntaxKind.UnparsedText; + + case BundleFileSectionKind.EmitHelpers: + case BundleFileSectionKind.NoDefaultLib: + case BundleFileSectionKind.Reference: + case BundleFileSectionKind.Type: + case BundleFileSectionKind.Lib: + return Debug.fail(`BundleFileSectionKind: ${kind} not yet mapped to SyntaxKind`); + + default: + return Debug.assertNever(kind); + } + } + + // TODO(rbuckton): Move this to factory + function createUnparsedNode(section: BundleFileSection, parent: UnparsedSource): UnparsedNode { + const node = createNode(mapBundleFileSectionKindToSyntaxKind(section.kind), section.pos, section.end) as UnparsedNode; + node.parent = parent; + node.data = section.data; + return node; + } + + // TODO(rbuckton): Move this to factory + function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference, parent: UnparsedSource) { + const node = createNode(SyntaxKind.UnparsedSyntheticReference, section.pos, section.end) as UnparsedSyntheticReference; + node.parent = parent; + node.data = section.data; + node.section = section; + return node; + } + + // TODO(rbuckton): Move part of this to factory + export function createInputFiles( + javascriptText: string, + declarationText: string + ): InputFiles; + export function createInputFiles( + readFileText: (path: string) => string | undefined, + javascriptPath: string, + javascriptMapPath: string | undefined, + declarationPath: string, + declarationMapPath: string | undefined, + buildInfoPath: string | undefined + ): InputFiles; + export function createInputFiles( + javascriptText: string, + declarationText: string, + javascriptMapPath: string | undefined, + javascriptMapText: string | undefined, + declarationMapPath: string | undefined, + declarationMapText: string | undefined + ): InputFiles; + /*@internal*/ + export function createInputFiles( + javascriptText: string, + declarationText: string, + javascriptMapPath: string | undefined, + javascriptMapText: string | undefined, + declarationMapPath: string | undefined, + declarationMapText: string | undefined, + javascriptPath: string | undefined, + declarationPath: string | undefined, + buildInfoPath?: string | undefined, + buildInfo?: BuildInfo, + oldFileOfCurrentEmit?: boolean + ): InputFiles; + export function createInputFiles( + javascriptTextOrReadFileText: string | ((path: string) => string | undefined), + declarationTextOrJavascriptPath: string, + javascriptMapPath?: string, + javascriptMapTextOrDeclarationPath?: string, + declarationMapPath?: string, + declarationMapTextOrBuildInfoPath?: string, + javascriptPath?: string | undefined, + declarationPath?: string | undefined, + buildInfoPath?: string | undefined, + buildInfo?: BuildInfo, + oldFileOfCurrentEmit?: boolean + ): InputFiles { + const node = createNode(SyntaxKind.InputFiles); + if (!isString(javascriptTextOrReadFileText)) { + const cache = createMap(); + const textGetter = (path: string | undefined) => { + if (path === undefined) return undefined; + let value = cache.get(path); + if (value === undefined) { + value = javascriptTextOrReadFileText(path); + cache.set(path, value !== undefined ? value : false); + } + return value !== false ? value as string : undefined; + }; + const definedTextGetter = (path: string) => { + const result = textGetter(path); + return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`; + }; + let buildInfo: BuildInfo | false; + const getAndCacheBuildInfo = (getText: () => string | undefined) => { + if (buildInfo === undefined) { + const result = getText(); + buildInfo = result !== undefined ? getBuildInfo(result) : false; + } + return buildInfo || undefined; + }; + node.javascriptPath = declarationTextOrJavascriptPath; + node.javascriptMapPath = javascriptMapPath; + node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath); + node.declarationMapPath = declarationMapPath; + node.buildInfoPath = declarationMapTextOrBuildInfoPath; + Object.defineProperties(node, { + javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } }, + javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that + declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } }, + declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that + buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } } + }); + } + else { + node.javascriptText = javascriptTextOrReadFileText; + node.javascriptMapPath = javascriptMapPath; + node.javascriptMapText = javascriptMapTextOrDeclarationPath; + node.declarationText = declarationTextOrJavascriptPath; + node.declarationMapPath = declarationMapPath; + node.declarationMapText = declarationMapTextOrBuildInfoPath; + node.javascriptPath = javascriptPath; + node.declarationPath = declarationPath; + node.buildInfoPath = buildInfoPath; + node.buildInfo = buildInfo; + node.oldFileOfCurrentEmit = oldFileOfCurrentEmit; + } + return node; + } + + // tslint:disable-next-line variable-name + let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; + + /** + * Create an external source map source file reference + */ + export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource { + return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); + } + + // Utilities + + export function setOriginalNode(node: T, original: Node | undefined): T { + node.original = original; + if (original) { + const emitNode = original.emitNode; + if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); + } + return node; + } + + function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) { + const { + flags, + leadingComments, + trailingComments, + commentRange, + sourceMapRange, + tokenSourceMapRanges, + constantValue, + helpers, + startsOnNewLine, + } = sourceEmitNode; + if (!destEmitNode) destEmitNode = {} as EmitNode; + // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. + if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments); + if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments); + if (flags) destEmitNode.flags = flags; + if (commentRange) destEmitNode.commentRange = commentRange; + if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; + if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!); + if (constantValue !== undefined) destEmitNode.constantValue = constantValue; + if (helpers) { + for (const helper of helpers) { + destEmitNode.helpers = appendIfUnique(destEmitNode.helpers, helper); + } + } + if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; + return destEmitNode; + } + + function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) { + if (!destRanges) destRanges = []; + for (const key in sourceRanges) { + destRanges[key] = sourceRanges[key]; + } + return destRanges; + } +} + diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts new file mode 100644 index 0000000000000..957dde1109b0e --- /dev/null +++ b/src/compiler/factory/nodeTests.ts @@ -0,0 +1,763 @@ +namespace ts { + // Literals + + export function isNumericLiteral(node: Node): node is NumericLiteral { + return node.kind === SyntaxKind.NumericLiteral; + } + + export function isBigIntLiteral(node: Node): node is BigIntLiteral { + return node.kind === SyntaxKind.BigIntLiteral; + } + + export function isStringLiteral(node: Node): node is StringLiteral { + return node.kind === SyntaxKind.StringLiteral; + } + + export function isJsxText(node: Node): node is JsxText { + return node.kind === SyntaxKind.JsxText; + } + + export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral { + return node.kind === SyntaxKind.RegularExpressionLiteral; + } + + export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral { + return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; + } + + // Pseudo-literals + + export function isTemplateHead(node: Node): node is TemplateHead { + return node.kind === SyntaxKind.TemplateHead; + } + + export function isTemplateMiddle(node: Node): node is TemplateMiddle { + return node.kind === SyntaxKind.TemplateMiddle; + } + + export function isTemplateTail(node: Node): node is TemplateTail { + return node.kind === SyntaxKind.TemplateTail; + } + + // Identifiers + + export function isIdentifier(node: Node): node is Identifier { + return node.kind === SyntaxKind.Identifier; + } + + // Names + + export function isQualifiedName(node: Node): node is QualifiedName { + return node.kind === SyntaxKind.QualifiedName; + } + + export function isComputedPropertyName(node: Node): node is ComputedPropertyName { + return node.kind === SyntaxKind.ComputedPropertyName; + } + + // Signature elements + + export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { + return node.kind === SyntaxKind.TypeParameter; + } + + // TODO(rbuckton): Rename to 'isParameterDeclaration' + export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter; + } + + export function isDecorator(node: Node): node is Decorator { + return node.kind === SyntaxKind.Decorator; + } + + // TypeMember + + export function isPropertySignature(node: Node): node is PropertySignature { + return node.kind === SyntaxKind.PropertySignature; + } + + export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { + return node.kind === SyntaxKind.PropertyDeclaration; + } + + export function isMethodSignature(node: Node): node is MethodSignature { + return node.kind === SyntaxKind.MethodSignature; + } + + export function isMethodDeclaration(node: Node): node is MethodDeclaration { + return node.kind === SyntaxKind.MethodDeclaration; + } + + export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { + return node.kind === SyntaxKind.Constructor; + } + + export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { + return node.kind === SyntaxKind.GetAccessor; + } + + export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor; + } + + export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { + return node.kind === SyntaxKind.CallSignature; + } + + export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration { + return node.kind === SyntaxKind.ConstructSignature; + } + + export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration { + return node.kind === SyntaxKind.IndexSignature; + } + + // Type + + export function isTypePredicateNode(node: Node): node is TypePredicateNode { + return node.kind === SyntaxKind.TypePredicate; + } + + export function isTypeReferenceNode(node: Node): node is TypeReferenceNode { + return node.kind === SyntaxKind.TypeReference; + } + + export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { + return node.kind === SyntaxKind.FunctionType; + } + + export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode { + return node.kind === SyntaxKind.ConstructorType; + } + + export function isTypeQueryNode(node: Node): node is TypeQueryNode { + return node.kind === SyntaxKind.TypeQuery; + } + + export function isTypeLiteralNode(node: Node): node is TypeLiteralNode { + return node.kind === SyntaxKind.TypeLiteral; + } + + export function isArrayTypeNode(node: Node): node is ArrayTypeNode { + return node.kind === SyntaxKind.ArrayType; + } + + export function isTupleTypeNode(node: Node): node is TupleTypeNode { + return node.kind === SyntaxKind.TupleType; + } + + export function isOptionalTypeNode(node: Node): node is OptionalTypeNode { + return node.kind === SyntaxKind.OptionalType; + } + + export function isRestTypeNode(node: Node): node is RestTypeNode { + return node.kind === SyntaxKind.RestType; + } + + export function isUnionTypeNode(node: Node): node is UnionTypeNode { + return node.kind === SyntaxKind.UnionType; + } + + export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode { + return node.kind === SyntaxKind.IntersectionType; + } + + export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode { + return node.kind === SyntaxKind.ConditionalType; + } + + export function isInferTypeNode(node: Node): node is InferTypeNode { + return node.kind === SyntaxKind.InferType; + } + + export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode { + return node.kind === SyntaxKind.ParenthesizedType; + } + + export function isThisTypeNode(node: Node): node is ThisTypeNode { + return node.kind === SyntaxKind.ThisType; + } + + export function isTypeOperatorNode(node: Node): node is TypeOperatorNode { + return node.kind === SyntaxKind.TypeOperator; + } + + export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode { + return node.kind === SyntaxKind.IndexedAccessType; + } + + export function isMappedTypeNode(node: Node): node is MappedTypeNode { + return node.kind === SyntaxKind.MappedType; + } + + export function isLiteralTypeNode(node: Node): node is LiteralTypeNode { + return node.kind === SyntaxKind.LiteralType; + } + + export function isImportTypeNode(node: Node): node is ImportTypeNode { + return node.kind === SyntaxKind.ImportType; + } + + // Binding patterns + + export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { + return node.kind === SyntaxKind.ObjectBindingPattern; + } + + export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { + return node.kind === SyntaxKind.ArrayBindingPattern; + } + + export function isBindingElement(node: Node): node is BindingElement { + return node.kind === SyntaxKind.BindingElement; + } + + // Expression + + export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { + return node.kind === SyntaxKind.ArrayLiteralExpression; + } + + export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { + return node.kind === SyntaxKind.ObjectLiteralExpression; + } + + export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node.kind === SyntaxKind.PropertyAccessExpression; + } + + export function isElementAccessExpression(node: Node): node is ElementAccessExpression { + return node.kind === SyntaxKind.ElementAccessExpression; + } + + export function isCallExpression(node: Node): node is CallExpression { + return node.kind === SyntaxKind.CallExpression; + } + + export function isNewExpression(node: Node): node is NewExpression { + return node.kind === SyntaxKind.NewExpression; + } + + export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { + return node.kind === SyntaxKind.TaggedTemplateExpression; + } + + export function isTypeAssertionExpression(node: Node): node is TypeAssertion { + return node.kind === SyntaxKind.TypeAssertionExpression; + } + + export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { + return node.kind === SyntaxKind.ParenthesizedExpression; + } + + export function isFunctionExpression(node: Node): node is FunctionExpression { + return node.kind === SyntaxKind.FunctionExpression; + } + + export function isArrowFunction(node: Node): node is ArrowFunction { + return node.kind === SyntaxKind.ArrowFunction; + } + + export function isDeleteExpression(node: Node): node is DeleteExpression { + return node.kind === SyntaxKind.DeleteExpression; + } + + export function isTypeOfExpression(node: Node): node is TypeOfExpression { + return node.kind === SyntaxKind.TypeOfExpression; + } + + export function isVoidExpression(node: Node): node is VoidExpression { + return node.kind === SyntaxKind.VoidExpression; + } + + export function isAwaitExpression(node: Node): node is AwaitExpression { + return node.kind === SyntaxKind.AwaitExpression; + } + + export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { + return node.kind === SyntaxKind.PrefixUnaryExpression; + } + + export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { + return node.kind === SyntaxKind.PostfixUnaryExpression; + } + + export function isBinaryExpression(node: Node): node is BinaryExpression { + return node.kind === SyntaxKind.BinaryExpression; + } + + export function isConditionalExpression(node: Node): node is ConditionalExpression { + return node.kind === SyntaxKind.ConditionalExpression; + } + + export function isTemplateExpression(node: Node): node is TemplateExpression { + return node.kind === SyntaxKind.TemplateExpression; + } + + export function isYieldExpression(node: Node): node is YieldExpression { + return node.kind === SyntaxKind.YieldExpression; + } + + export function isSpreadElement(node: Node): node is SpreadElement { + return node.kind === SyntaxKind.SpreadElement; + } + + export function isClassExpression(node: Node): node is ClassExpression { + return node.kind === SyntaxKind.ClassExpression; + } + + export function isOmittedExpression(node: Node): node is OmittedExpression { + return node.kind === SyntaxKind.OmittedExpression; + } + + export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { + return node.kind === SyntaxKind.ExpressionWithTypeArguments; + } + + export function isAsExpression(node: Node): node is AsExpression { + return node.kind === SyntaxKind.AsExpression; + } + + export function isNonNullExpression(node: Node): node is NonNullExpression { + return node.kind === SyntaxKind.NonNullExpression; + } + + export function isMetaProperty(node: Node): node is MetaProperty { + return node.kind === SyntaxKind.MetaProperty; + } + + export function isSyntheticExpression(node: Node): node is SyntheticExpression { + return node.kind === SyntaxKind.SyntheticExpression; + } + + export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression { + return node.kind === SyntaxKind.PartiallyEmittedExpression; + } + + export function isCommaListExpression(node: Node): node is CommaListExpression { + return node.kind === SyntaxKind.CommaListExpression; + } + + // Misc + + export function isTemplateSpan(node: Node): node is TemplateSpan { + return node.kind === SyntaxKind.TemplateSpan; + } + + export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { + return node.kind === SyntaxKind.SemicolonClassElement; + } + + // Elements + + export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block; + } + + export function isVariableStatement(node: Node): node is VariableStatement { + return node.kind === SyntaxKind.VariableStatement; + } + + export function isEmptyStatement(node: Node): node is EmptyStatement { + return node.kind === SyntaxKind.EmptyStatement; + } + + export function isExpressionStatement(node: Node): node is ExpressionStatement { + return node.kind === SyntaxKind.ExpressionStatement; + } + + export function isIfStatement(node: Node): node is IfStatement { + return node.kind === SyntaxKind.IfStatement; + } + + export function isDoStatement(node: Node): node is DoStatement { + return node.kind === SyntaxKind.DoStatement; + } + + export function isWhileStatement(node: Node): node is WhileStatement { + return node.kind === SyntaxKind.WhileStatement; + } + + export function isForStatement(node: Node): node is ForStatement { + return node.kind === SyntaxKind.ForStatement; + } + + export function isForInStatement(node: Node): node is ForInStatement { + return node.kind === SyntaxKind.ForInStatement; + } + + export function isForOfStatement(node: Node): node is ForOfStatement { + return node.kind === SyntaxKind.ForOfStatement; + } + + export function isContinueStatement(node: Node): node is ContinueStatement { + return node.kind === SyntaxKind.ContinueStatement; + } + + export function isBreakStatement(node: Node): node is BreakStatement { + return node.kind === SyntaxKind.BreakStatement; + } + + export function isReturnStatement(node: Node): node is ReturnStatement { + return node.kind === SyntaxKind.ReturnStatement; + } + + export function isWithStatement(node: Node): node is WithStatement { + return node.kind === SyntaxKind.WithStatement; + } + + export function isSwitchStatement(node: Node): node is SwitchStatement { + return node.kind === SyntaxKind.SwitchStatement; + } + + export function isLabeledStatement(node: Node): node is LabeledStatement { + return node.kind === SyntaxKind.LabeledStatement; + } + + export function isThrowStatement(node: Node): node is ThrowStatement { + return node.kind === SyntaxKind.ThrowStatement; + } + + export function isTryStatement(node: Node): node is TryStatement { + return node.kind === SyntaxKind.TryStatement; + } + + export function isDebuggerStatement(node: Node): node is DebuggerStatement { + return node.kind === SyntaxKind.DebuggerStatement; + } + + export function isVariableDeclaration(node: Node): node is VariableDeclaration { + return node.kind === SyntaxKind.VariableDeclaration; + } + + export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { + return node.kind === SyntaxKind.VariableDeclarationList; + } + + export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { + return node.kind === SyntaxKind.FunctionDeclaration; + } + + export function isClassDeclaration(node: Node): node is ClassDeclaration { + return node.kind === SyntaxKind.ClassDeclaration; + } + + export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { + return node.kind === SyntaxKind.InterfaceDeclaration; + } + + export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { + return node.kind === SyntaxKind.TypeAliasDeclaration; + } + + export function isEnumDeclaration(node: Node): node is EnumDeclaration { + return node.kind === SyntaxKind.EnumDeclaration; + } + + export function isModuleDeclaration(node: Node): node is ModuleDeclaration { + return node.kind === SyntaxKind.ModuleDeclaration; + } + + export function isModuleBlock(node: Node): node is ModuleBlock { + return node.kind === SyntaxKind.ModuleBlock; + } + + export function isCaseBlock(node: Node): node is CaseBlock { + return node.kind === SyntaxKind.CaseBlock; + } + + export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration { + return node.kind === SyntaxKind.NamespaceExportDeclaration; + } + + export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { + return node.kind === SyntaxKind.ImportEqualsDeclaration; + } + + export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node.kind === SyntaxKind.ImportDeclaration; + } + + export function isImportClause(node: Node): node is ImportClause { + return node.kind === SyntaxKind.ImportClause; + } + + export function isNamespaceImport(node: Node): node is NamespaceImport { + return node.kind === SyntaxKind.NamespaceImport; + } + + export function isNamedImports(node: Node): node is NamedImports { + return node.kind === SyntaxKind.NamedImports; + } + + export function isImportSpecifier(node: Node): node is ImportSpecifier { + return node.kind === SyntaxKind.ImportSpecifier; + } + + export function isExportAssignment(node: Node): node is ExportAssignment { + return node.kind === SyntaxKind.ExportAssignment; + } + + export function isExportDeclaration(node: Node): node is ExportDeclaration { + return node.kind === SyntaxKind.ExportDeclaration; + } + + export function isNamedExports(node: Node): node is NamedExports { + return node.kind === SyntaxKind.NamedExports; + } + + export function isExportSpecifier(node: Node): node is ExportSpecifier { + return node.kind === SyntaxKind.ExportSpecifier; + } + + export function isMissingDeclaration(node: Node): node is MissingDeclaration { + return node.kind === SyntaxKind.MissingDeclaration; + } + + export function isNotEmittedStatement(node: Node): node is NotEmittedStatement { + return node.kind === SyntaxKind.NotEmittedStatement; + } + + /* @internal */ + export function isSyntheticReference(node: Node): node is SyntheticReferenceExpression { + return node.kind === SyntaxKind.SyntheticReferenceExpression; + } + + /* @internal */ + export function isMergeDeclarationMarker(node: Node): node is MergeDeclarationMarker { + return node.kind === SyntaxKind.MergeDeclarationMarker; + } + + /* @internal */ + export function isEndOfDeclarationMarker(node: Node): node is EndOfDeclarationMarker { + return node.kind === SyntaxKind.EndOfDeclarationMarker; + } + + // Module References + + export function isExternalModuleReference(node: Node): node is ExternalModuleReference { + return node.kind === SyntaxKind.ExternalModuleReference; + } + + // JSX + + export function isJsxElement(node: Node): node is JsxElement { + return node.kind === SyntaxKind.JsxElement; + } + + export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { + return node.kind === SyntaxKind.JsxSelfClosingElement; + } + + export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { + return node.kind === SyntaxKind.JsxOpeningElement; + } + + export function isJsxClosingElement(node: Node): node is JsxClosingElement { + return node.kind === SyntaxKind.JsxClosingElement; + } + + export function isJsxFragment(node: Node): node is JsxFragment { + return node.kind === SyntaxKind.JsxFragment; + } + + export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { + return node.kind === SyntaxKind.JsxOpeningFragment; + } + + export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { + return node.kind === SyntaxKind.JsxClosingFragment; + } + + export function isJsxAttribute(node: Node): node is JsxAttribute { + return node.kind === SyntaxKind.JsxAttribute; + } + + export function isJsxAttributes(node: Node): node is JsxAttributes { + return node.kind === SyntaxKind.JsxAttributes; + } + + export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { + return node.kind === SyntaxKind.JsxSpreadAttribute; + } + + export function isJsxExpression(node: Node): node is JsxExpression { + return node.kind === SyntaxKind.JsxExpression; + } + + // Clauses + + export function isCaseClause(node: Node): node is CaseClause { + return node.kind === SyntaxKind.CaseClause; + } + + export function isDefaultClause(node: Node): node is DefaultClause { + return node.kind === SyntaxKind.DefaultClause; + } + + export function isHeritageClause(node: Node): node is HeritageClause { + return node.kind === SyntaxKind.HeritageClause; + } + + export function isCatchClause(node: Node): node is CatchClause { + return node.kind === SyntaxKind.CatchClause; + } + + // Property assignments + + export function isPropertyAssignment(node: Node): node is PropertyAssignment { + return node.kind === SyntaxKind.PropertyAssignment; + } + + export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { + return node.kind === SyntaxKind.ShorthandPropertyAssignment; + } + + export function isSpreadAssignment(node: Node): node is SpreadAssignment { + return node.kind === SyntaxKind.SpreadAssignment; + } + + // Enum + + export function isEnumMember(node: Node): node is EnumMember { + return node.kind === SyntaxKind.EnumMember; + } + + // Unparsed + + // TODO(rbuckton): isUnparsedPrologue + + export function isUnparsedPrepend(node: Node): node is UnparsedPrepend { + return node.kind === SyntaxKind.UnparsedPrepend; + } + + // TODO(rbuckton): isUnparsedText + // TODO(rbuckton): isUnparsedInternalText + // TODO(rbuckton): isUnparsedSyntheticReference + + // Top-level nodes + export function isSourceFile(node: Node): node is SourceFile { + return node.kind === SyntaxKind.SourceFile; + } + + export function isBundle(node: Node): node is Bundle { + return node.kind === SyntaxKind.Bundle; + } + + export function isUnparsedSource(node: Node): node is UnparsedSource { + return node.kind === SyntaxKind.UnparsedSource; + } + + // TODO(rbuckton): isInputFiles + + // JSDoc Elements + + export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { + return node.kind === SyntaxKind.JSDocTypeExpression; + } + + export function isJSDocAllType(node: Node): node is JSDocAllType { + return node.kind === SyntaxKind.JSDocAllType; + } + + export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { + return node.kind === SyntaxKind.JSDocUnknownType; + } + + export function isJSDocNullableType(node: Node): node is JSDocNullableType { + return node.kind === SyntaxKind.JSDocNullableType; + } + + export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { + return node.kind === SyntaxKind.JSDocNonNullableType; + } + + export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { + return node.kind === SyntaxKind.JSDocOptionalType; + } + + export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { + return node.kind === SyntaxKind.JSDocFunctionType; + } + + export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { + return node.kind === SyntaxKind.JSDocVariadicType; + } + + export function isJSDocNamepathType(node: Node): node is JSDocNamepathType { + return node.kind === SyntaxKind.JSDocNamepathType; + } + + export function isJSDoc(node: Node): node is JSDoc { + return node.kind === SyntaxKind.JSDocComment; + } + + export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { + return node.kind === SyntaxKind.JSDocTypeLiteral; + } + + export function isJSDocSignature(node: Node): node is JSDocSignature { + return node.kind === SyntaxKind.JSDocSignature; + } + + // JSDoc Tags + + export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { + return node.kind === SyntaxKind.JSDocAugmentsTag; + } + + export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { + return node.kind === SyntaxKind.JSDocAuthorTag; + } + + export function isJSDocClassTag(node: Node): node is JSDocClassTag { + return node.kind === SyntaxKind.JSDocClassTag; + } + + export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag { + return node.kind === SyntaxKind.JSDocCallbackTag; + } + + export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { + return node.kind === SyntaxKind.JSDocEnumTag; + } + + export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { + return node.kind === SyntaxKind.JSDocParameterTag; + } + + export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { + return node.kind === SyntaxKind.JSDocReturnTag; + } + + export function isJSDocThisTag(node: Node): node is JSDocThisTag { + return node.kind === SyntaxKind.JSDocThisTag; + } + + export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { + return node.kind === SyntaxKind.JSDocTypeTag; + } + + export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { + return node.kind === SyntaxKind.JSDocTemplateTag; + } + + export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { + return node.kind === SyntaxKind.JSDocTypedefTag; + } + + export function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag { + return node.kind === SyntaxKind.JSDocTag; + } + + export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag { + return node.kind === SyntaxKind.JSDocPropertyTag; + } + + // Synthesized list + + /* @internal */ + export function isSyntaxList(n: Node): n is SyntaxList { + return n.kind === SyntaxKind.SyntaxList; + } +} diff --git a/src/compiler/factory/parenthesizerRules.ts b/src/compiler/factory/parenthesizerRules.ts new file mode 100644 index 0000000000000..7a62c11385bcd --- /dev/null +++ b/src/compiler/factory/parenthesizerRules.ts @@ -0,0 +1,426 @@ +/* @internal */ +namespace ts { + export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRules { + interface BinaryPlusExpression extends BinaryExpression { + cachedLiteralKind: SyntaxKind; + } + + return { + parenthesizeLeftSideOfBinary, + parenthesizeRightSideOfBinary, + parenthesizeExpressionOfComputedPropertyName, + parenthesizeConditionOfConditionalExpression, + parenthesizeBranchOfConditionalExpression, + parenthesizeExpressionOfExportDefault, + parenthesizeExpressionOfNew, + parenthesizeLeftSideOfAccess, + parenthesizeOperandOfPostfixUnary, + parenthesizeOperandOfPrefixUnary, + parenthesizeExpressionsOfCommaDelimitedList, + parenthesizeExpressionForDisallowedComma, + parenthesizeExpressionOfExpressionStatement, + parenthesizeConciseBodyOfArrowFunction, + parenthesizeMemberOfConditionalType, + parenthesizeMemberOfElementType, + parenthesizeElementTypeOfArrayType, + parenthesizeConstituentTypesOfUnionOrIntersectionType, + parenthesizeTypeArguments, + }; + + /** + * Determines whether the operand to a BinaryExpression needs to be parenthesized. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) { + // If the operand has lower precedence, then it needs to be parenthesized to preserve the + // intent of the expression. For example, if the operand is `a + b` and the operator is + // `*`, then we need to parenthesize the operand to preserve the intended order of + // operations: `(a + b) * x`. + // + // If the operand has higher precedence, then it does not need to be parenthesized. For + // example, if the operand is `a * b` and the operator is `+`, then we do not need to + // parenthesize to preserve the intended order of operations: `a * b + x`. + // + // If the operand has the same precedence, then we need to check the associativity of + // the operator based on whether this is the left or right operand of the expression. + // + // For example, if `a / d` is on the right of operator `*`, we need to parenthesize + // to preserve the intended order of operations: `x * (a / d)` + // + // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve + // the intended order of operations: `(a ** b) ** c` + const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); + const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); + const emittedOperand = skipPartiallyEmittedExpressions(operand); + if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) { + // We need to parenthesize arrow functions on the right side to avoid it being + // parsed as parenthesized expression: `a && (() => {})` + return true; + } + const operandPrecedence = getExpressionPrecedence(emittedOperand); + switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) { + case Comparison.LessThan: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. + if (!isLeftSideOfBinary + && binaryOperatorAssociativity === Associativity.Right + && operand.kind === SyntaxKind.YieldExpression) { + return false; + } + + return true; + + case Comparison.GreaterThan: + return false; + + case Comparison.EqualTo: + if (isLeftSideOfBinary) { + // No need to parenthesize the left operand when the binary operator is + // left associative: + // (a*b)/x -> a*b/x + // (a**b)/x -> a**b/x + // + // Parentheses are needed for the left operand when the binary operator is + // right associative: + // (a/b)**x -> (a/b)**x + // (a**b)**x -> (a**b)**x + return binaryOperatorAssociativity === Associativity.Right; + } + else { + if (isBinaryExpression(emittedOperand) + && emittedOperand.operatorToken.kind === binaryOperator) { + // No need to parenthesize the right operand when the binary operator and + // operand are the same and one of the following: + // x*(a*b) => x*a*b + // x|(a|b) => x|a|b + // x&(a&b) => x&a&b + // x^(a^b) => x^a^b + if (operatorHasAssociativeProperty(binaryOperator)) { + return false; + } + + // No need to parenthesize the right operand when the binary operator + // is plus (+) if both the left and right operands consist solely of either + // literals of the same kind or binary plus (+) expressions for literals of + // the same kind (recursively). + // "a"+(1+2) => "a"+(1+2) + // "a"+("b"+"c") => "a"+"b"+"c" + if (binaryOperator === SyntaxKind.PlusToken) { + const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown; + if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { + return false; + } + } + } + + // No need to parenthesize the right operand when the operand is right + // associative: + // x/(a**b) -> x/a**b + // x**(a**b) -> x**a**b + // + // Parentheses are needed for the right operand when the operand is left + // associative: + // x/(a*b) -> x/(a*b) + // x**(a/b) -> x**(a/b) + const operandAssociativity = getExpressionAssociativity(emittedOperand); + return operandAssociativity === Associativity.Left; + } + } + } + + /** + * Determines whether a binary operator is mathematically associative. + * + * @param binaryOperator The binary operator. + */ + function operatorHasAssociativeProperty(binaryOperator: SyntaxKind) { + // The following operators are associative in JavaScript: + // (a*b)*c -> a*(b*c) -> a*b*c + // (a|b)|c -> a|(b|c) -> a|b|c + // (a&b)&c -> a&(b&c) -> a&b&c + // (a^b)^c -> a^(b^c) -> a^b^c + // + // While addition is associative in mathematics, JavaScript's `+` is not + // guaranteed to be associative as it is overloaded with string concatenation. + return binaryOperator === SyntaxKind.AsteriskToken + || binaryOperator === SyntaxKind.BarToken + || binaryOperator === SyntaxKind.AmpersandToken + || binaryOperator === SyntaxKind.CaretToken; + } + + /** + * This function determines whether an expression consists of a homogeneous set of + * literal expressions or binary plus expressions that all share the same literal kind. + * It is used to determine whether the right-hand operand of a binary plus expression can be + * emitted without parentheses. + */ + function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind { + node = skipPartiallyEmittedExpressions(node); + + if (isLiteralKind(node.kind)) { + return node.kind; + } + + if (node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.PlusToken) { + if ((node).cachedLiteralKind !== undefined) { + return (node).cachedLiteralKind; + } + + const leftKind = getLiteralKindOfBinaryPlusOperand((node).left); + const literalKind = isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand((node).right) + ? leftKind + : SyntaxKind.Unknown; + + (node).cachedLiteralKind = literalKind; + return literalKind; + } + + return SyntaxKind.Unknown; + } + + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) { + const skipped = skipPartiallyEmittedExpressions(operand); + + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (skipped.kind === SyntaxKind.ParenthesizedExpression) { + return operand; + } + + return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) + ? factory.createParen(operand) + : operand; + } + + + function parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression { + return parenthesizeBinaryOperand(binaryOperator, leftSide, /*isLeftSideOfBinary*/ true); + } + + function parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression, rightSide: Expression): Expression { + return parenthesizeBinaryOperand(binaryOperator, rightSide, /*isLeftSideOfBinary*/ false, leftSide); + } + + function parenthesizeExpressionOfComputedPropertyName(expression: Expression): Expression { + return isCommaSequence(expression) ? factory.createParen(expression) : expression; + } + + function parenthesizeConditionOfConditionalExpression(condition: Expression): Expression { + const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken); + const emittedCondition = skipPartiallyEmittedExpressions(condition); + const conditionPrecedence = getExpressionPrecedence(emittedCondition); + if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) { + return factory.createParen(condition); + } + return condition; + } + + function parenthesizeBranchOfConditionalExpression(branch: Expression): Expression { + // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions + // so in case when comma expression is introduced as a part of previous transformations + // if should be wrapped in parens since comma operator has the lowest precedence + const emittedExpression = skipPartiallyEmittedExpressions(branch); + return isCommaSequence(emittedExpression) + ? factory.createParen(branch) + : branch; + } + + /** + * [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but + * has a lookahead restriction for `function`, `async function`, and `class`. + * + * Basically, that means we need to parenthesize in the following cases: + * + * - BinaryExpression of CommaToken + * - CommaList (synthetic list of multiple comma expressions) + * - FunctionExpression + * - ClassExpression + */ + function parenthesizeExpressionOfExportDefault(expression: Expression): Expression { + const check = skipPartiallyEmittedExpressions(expression); + let needsParens = isCommaSequence(check); + if (!needsParens) { + switch (getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) { + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: + needsParens = true; + } + } + return needsParens ? factory.createParen(expression) : expression; + } + + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a `NewExpression` node. + */ + function parenthesizeExpressionOfNew(expression: Expression): LeftHandSideExpression { + const leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); + switch (leftmostExpr.kind) { + case SyntaxKind.CallExpression: + return factory.createParen(expression); + + case SyntaxKind.NewExpression: + return !(leftmostExpr as NewExpression).arguments + ? factory.createParen(expression) + : expression as LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds + } + + return parenthesizeLeftSideOfAccess(expression); + } + + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + */ + function parenthesizeLeftSideOfAccess(expression: Expression): LeftHandSideExpression { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exception is: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments)) { + // TODO(rbuckton): Verify whether this assertion holds. + return expression as LeftHandSideExpression; + } + + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return setTextRange(factory.createParen(expression), expression); + } + + function parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return isLeftHandSideExpression(operand) ? operand : setTextRange(factory.createParen(operand), operand); + } + + function parenthesizeOperandOfPrefixUnary(operand: Expression): UnaryExpression { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return isUnaryExpression(operand) ? operand : setTextRange(factory.createParen(operand), operand); + } + + function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray): NodeArray { + const result = sameMap(elements, parenthesizeExpressionForDisallowedComma); + return setTextRange(factory.createNodeArray(result, elements.hasTrailingComma), elements); + } + + function parenthesizeExpressionForDisallowedComma(expression: Expression): Expression { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + const expressionPrecedence = getExpressionPrecedence(emittedExpression); + const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return expressionPrecedence > commaPrecedence ? expression : setTextRange(factory.createParen(expression), expression); + } + + function parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isCallExpression(emittedExpression)) { + const callee = emittedExpression.expression; + const kind = skipPartiallyEmittedExpressions(callee).kind; + if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + const updated = factory.updateCall( + emittedExpression, + setTextRange(factory.createParen(callee), callee), + emittedExpression.typeArguments, + emittedExpression.arguments + ); + return factory.restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); + } + } + + const leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; + if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return setTextRange(factory.createParen(expression), expression); + } + + return expression; + } + + function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody { + if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return setTextRange(factory.createParen(body), body); + } + + return body; + } + + function parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode { + return member.kind === SyntaxKind.ConditionalType ? factory.createParenthesizedType(member) : member; + } + + function parenthesizeMemberOfElementType(member: TypeNode): TypeNode { + switch (member.kind) { + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return factory.createParenthesizedType(member); + } + return parenthesizeMemberOfConditionalType(member); + } + + function parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode { + switch (member.kind) { + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeOperator: + case SyntaxKind.InferType: + return factory.createParenthesizedType(member); + } + return parenthesizeMemberOfElementType(member); + } + + function parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray { + return factory.createNodeArray(sameMap(members, parenthesizeMemberOfElementType)); + + } + + function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) { + return i === 0 && isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node; + } + + function parenthesizeTypeArguments(typeArguments: NodeArray | undefined): NodeArray | undefined { + if (some(typeArguments)) { + return factory.createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); + } + } + } + + export const nullParenthesizerRules: ParenthesizerRules = { + parenthesizeLeftSideOfBinary: (_binaryOperator, leftSide) => leftSide, + parenthesizeRightSideOfBinary: (_binaryOperator, _leftSide, rightSide) => rightSide, + parenthesizeExpressionOfComputedPropertyName: identity, + parenthesizeConditionOfConditionalExpression: identity, + parenthesizeBranchOfConditionalExpression: identity, + parenthesizeExpressionOfExportDefault: identity, + parenthesizeExpressionOfNew: expression => cast(expression, isLeftHandSideExpression), + parenthesizeLeftSideOfAccess: expression => cast(expression, isLeftHandSideExpression), + parenthesizeOperandOfPostfixUnary: operand => cast(operand, isLeftHandSideExpression), + parenthesizeOperandOfPrefixUnary: operand => cast(operand, isUnaryExpression), + parenthesizeExpressionsOfCommaDelimitedList: nodes => cast(nodes, isNodeArray), + parenthesizeExpressionForDisallowedComma: identity, + parenthesizeExpressionOfExpressionStatement: identity, + parenthesizeConciseBodyOfArrowFunction: identity, + parenthesizeMemberOfConditionalType: identity, + parenthesizeMemberOfElementType: identity, + parenthesizeElementTypeOfArrayType: identity, + parenthesizeConstituentTypesOfUnionOrIntersectionType: nodes => cast(nodes, isNodeArray), + parenthesizeTypeArguments: nodes => nodes && cast(nodes, isNodeArray), + }; +} \ No newline at end of file diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts new file mode 100644 index 0000000000000..98c6d395c7a4e --- /dev/null +++ b/src/compiler/factory/utilities.ts @@ -0,0 +1,779 @@ +/* @internal */ +namespace ts { + + // Compound nodes + + export function createEmptyExports(factory: NodeFactory) { + return factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createNamedExports([]), /*moduleSpecifier*/ undefined); + } + + export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { + if (isComputedPropertyName(memberName)) { + return setTextRange(factory.createElementAccess(target, memberName.expression), location); + } + else { + const expression = setTextRange( + isIdentifier(memberName) + ? factory.createPropertyAccess(target, memberName) + : factory.createElementAccess(target, memberName), + memberName + ); + getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; + return expression; + } + } + + function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. + const react = parseNodeFactory.createIdentifier(reactNamespace || "React"); + // Set the parent that is in parse tree + // this makes sure that parent chain is intact for checker to traverse complete scope tree + react.parent = getParseTreeNode(parent)!; + return react; + } + + function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + if (isQualifiedName(jsxFactory)) { + const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent); + const right = factory.createIdentifier(idText(jsxFactory.right)); + right.escapedText = jsxFactory.right.escapedText; + return factory.createPropertyAccess(left, right); + } + else { + return createReactNamespace(idText(jsxFactory), parent); + } + } + + function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + return jsxFactoryEntity ? + createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) : + factory.createPropertyAccess( + createReactNamespace(reactNamespace, parent), + "createElement" + ); + } + + export function createExpressionForJsxElement(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { + const argumentsList = [tagName]; + if (props) { + argumentsList.push(props); + } + + if (children && children.length > 0) { + if (!props) { + argumentsList.push(factory.createNull()); + } + + if (children.length > 1) { + for (const child of children) { + startOnNewLine(child); + argumentsList.push(child); + } + } + else { + argumentsList.push(children[0]); + } + } + + return setTextRange( + factory.createCall( + createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), + location + ); + } + + export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { + const tagName = factory.createPropertyAccess( + createReactNamespace(reactNamespace, parentElement), + "Fragment" + ); + + const argumentsList = [tagName]; + argumentsList.push(factory.createNull()); + + if (children && children.length > 0) { + if (children.length > 1) { + for (const child of children) { + startOnNewLine(child); + argumentsList.push(child); + } + } + else { + argumentsList.push(children[0]); + } + } + + return setTextRange( + factory.createCall( + createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), + location + ); + } + + // Utilities + + export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement { + if (isVariableDeclarationList(node)) { + const firstDeclaration = first(node.declarations); + const updatedDeclaration = factory.updateVariableDeclaration( + firstDeclaration, + firstDeclaration.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + boundValue + ); + return setTextRange( + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.updateVariableDeclarationList(node, [updatedDeclaration]) + ), + /*location*/ node + ); + } + else { + const updatedExpression = setTextRange(factory.createAssignment(node, boundValue), /*location*/ node); + return setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node); + } + } + + export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement) { + if (isBlock(dest)) { + return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); + } + else { + return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true); + } + } + + export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression { + if (isQualifiedName(node)) { + const left = createExpressionFromEntityName(factory, node.left); + const right = getMutableClone(node.right); + return setTextRange(factory.createPropertyAccess(left, right), node); + } + else { + return getMutableClone(node); + } + } + + export function createExpressionForPropertyName(factory: NodeFactory, memberName: PropertyName): Expression { + if (isIdentifier(memberName)) { + return factory.createStringLiteralFromNode(memberName); + } + else if (isComputedPropertyName(memberName)) { + return getMutableClone(memberName.expression); + } + else { + return getMutableClone(memberName); + } + } + + function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { + const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); + if (property === firstAccessor) { + return setTextRange( + factory.createObjectDefinePropertyCall( + receiver, + createExpressionForPropertyName(factory, property.name), + factory.createPropertyDescriptor({ + enumerable: true, + configurable: true, + get: getAccessor && setTextRange( + setOriginalNode( + factory.createFunctionExpression( + getAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + getAccessor.parameters, + /*type*/ undefined, + getAccessor.body! // TODO: GH#18217 + ), + getAccessor + ), + getAccessor + ), + set: setAccessor && setTextRange( + setOriginalNode( + factory.createFunctionExpression( + setAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + setAccessor.parameters, + /*type*/ undefined, + setAccessor.body! // TODO: GH#18217 + ), + setAccessor + ), + setAccessor + ) + }, !multiLine) + ), + firstAccessor + ); + } + + return undefined; + } + + function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) { + return setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), + property.initializer + ), + property + ), + property + ); + } + + function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) { + return setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), + getSynthesizedClone(property.name) + ), + /*location*/ property + ), + /*original*/ property + ); + } + + function createExpressionForMethodDeclaration(factory: NodeFactory, method: MethodDeclaration, receiver: Expression) { + return setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, method.name, /*location*/ method.name), + setOriginalNode( + setTextRange( + factory.createFunctionExpression( + method.modifiers, + method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, + method.parameters, + /*type*/ undefined, + method.body! // TODO: GH#18217 + ), + /*location*/ method + ), + /*original*/ method + ) + ), + /*location*/ method + ), + /*original*/ method + ); + } + + export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { + switch (property.kind) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return createExpressionForAccessorDeclaration(factory, node.properties, property, receiver, !!node.multiLine); + case SyntaxKind.PropertyAssignment: + return createExpressionForPropertyAssignment(factory, property, receiver); + case SyntaxKind.ShorthandPropertyAssignment: + return createExpressionForShorthandPropertyAssignment(factory, property, receiver); + case SyntaxKind.MethodDeclaration: + return createExpressionForMethodDeclaration(factory, property, receiver); + } + } + + /** + * Gets whether an identifier should only be referred to by its internal name. + */ + export function isInternalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; + } + + /** + * Gets whether an identifier should only be referred to by its local name. + */ + export function isLocalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; + } + + /** + * Gets whether an identifier should only be referred to by its export representation if the + * name points to an exported symbol. + */ + export function isExportName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; + } + + function isUseStrictPrologue(node: ExpressionStatement): boolean { + return isStringLiteral(node.expression) && node.expression.text === "use strict"; + } + + export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined { + for (const statement of statements) { + if (isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement)) { + return statement; + } + } + else { + break; + } + } + return undefined; + } + + export function startsWithUseStrict(statements: readonly Statement[]) { + const firstStatement = firstOrUndefined(statements); + return firstStatement !== undefined + && isPrologueDirective(firstStatement) + && isUseStrictPrologue(firstStatement); + } + + export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token} | CommaListExpression { + return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.CommaToken || + node.kind === SyntaxKind.CommaListExpression; + } + + export type OuterExpression = ParenthesizedExpression | TypeAssertion | AsExpression | NonNullExpression | PartiallyEmittedExpression; + + export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { + switch (node.kind) { + case SyntaxKind.ParenthesizedExpression: + return (kinds & OuterExpressionKinds.Parentheses) !== 0; + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + return (kinds & OuterExpressionKinds.Assertions) !== 0; + case SyntaxKind.PartiallyEmittedExpression: + return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; + } + return false; + } + + export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; + export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; + export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { + let previousNode: Node; + do { + previousNode = node; + if (kinds & OuterExpressionKinds.Parentheses) { + node = skipParentheses(node); + } + + if (kinds & OuterExpressionKinds.Assertions) { + node = skipAssertions(node); + } + + if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) { + node = skipPartiallyEmittedExpressions(node); + } + } + while (previousNode !== node); + + return node; + } + + export function skipAssertions(node: Expression): Expression; + export function skipAssertions(node: Node): Node; + export function skipAssertions(node: Node): Node { + while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) { + node = (node).expression; + } + + return node; + } + + export function startOnNewLine(node: T): T { + return setStartsOnNewLine(node, /*newLine*/ true); + } + + export function getExternalHelpersModuleName(node: SourceFile) { + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = parseNode && parseNode.emitNode; + return emitNode && emitNode.externalHelpersModuleName; + } + + export function hasRecordedExternalHelpers(sourceFile: SourceFile) { + const parseNode = getOriginalNode(sourceFile, isSourceFile); + const emitNode = parseNode && parseNode.emitNode; + return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); + } + + export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { + let namedBindings: NamedImportBindings | undefined; + const moduleKind = getEmitModuleKind(compilerOptions); + if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) { + // use named imports + const helpers = getEmitHelpers(sourceFile); + if (helpers) { + const helperNames: string[] = []; + for (const helper of helpers) { + if (!helper.scoped) { + const importName = (helper as UnscopedEmitHelper).importName; + if (importName) { + pushIfUnique(helperNames, importName); + } + } + } + if (some(helperNames)) { + helperNames.sort(compareStringsCaseSensitive); + // Alias the imports if the names are used somewhere in the file. + // NOTE: We don't need to care about global import collisions as this is a module. + namedBindings = nodeFactory.createNamedImports( + map(helperNames, name => isFileLevelUniqueName(sourceFile, name) + ? nodeFactory.createImportSpecifier(/*propertyName*/ undefined, nodeFactory.createIdentifier(name)) + : nodeFactory.createImportSpecifier(nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name)) + ) + ); + const parseNode = getOriginalNode(sourceFile, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + emitNode.externalHelpers = true; + } + } + } + else { + // use a namespace import + const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(nodeFactory, sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault); + if (externalHelpersModuleName) { + namedBindings = nodeFactory.createNamespaceImport(externalHelpersModuleName); + } + } + if (namedBindings) { + const externalHelpersImportDeclaration = nodeFactory.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + nodeFactory.createImportClause(/*name*/ undefined, namedBindings), + nodeFactory.createStringLiteral(externalHelpersModuleNameText) + ); + addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper); + return externalHelpersImportDeclaration; + } + } + } + + export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { + const externalHelpersModuleName = getExternalHelpersModuleName(node); + if (externalHelpersModuleName) { + return externalHelpersModuleName; + } + + const moduleKind = getEmitModuleKind(compilerOptions); + let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault)) + && moduleKind !== ModuleKind.System + && moduleKind !== ModuleKind.ES2015 + && moduleKind !== ModuleKind.ESNext; + if (!create) { + const helpers = getEmitHelpers(node); + if (helpers) { + for (const helper of helpers) { + if (!helper.scoped) { + create = true; + break; + } + } + } + } + + if (create) { + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); + } + } + } + + /** + * Get the name of that target module from an import or export declaration + */ + export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { + const namespaceDeclaration = getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !isDefaultImport(node)) { + const name = namespaceDeclaration.name; + return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); + } + if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { + return factory.getGeneratedNameForNode(node); + } + if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) { + return factory.getGeneratedNameForNode(node); + } + return undefined; + } + + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { + const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 + if (moduleName.kind === SyntaxKind.StringLiteral) { + return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) + || tryRenameExternalModule(factory, moduleName, sourceFile) + || getSynthesizedClone(moduleName); + } + + return undefined; + } + + /** + * Some bundlers (SystemJS builder) sometimes want to rename dependencies. + * Here we check if alternative name was provided for a given moduleName and return it if possible. + */ + function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) { + const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); + return rename && factory.createStringLiteral(rename); + } + + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { + if (!file) { + return undefined; + } + if (file.moduleName) { + return factory.createStringLiteral(file.moduleName); + } + if (!file.isDeclarationFile && (options.out || options.outFile)) { + return factory.createStringLiteral(getExternalModuleNameFromPath(host, file.fileName)); + } + return undefined; + } + + function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { + return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); + } + + /** + * Gets the initializer of an BindingOrAssignmentElement. + */ + export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { + if (isDeclarationBindingElement(bindingElement)) { + // `1` in `let { a = 1 } = ...` + // `1` in `let { a: b = 1 } = ...` + // `1` in `let { a: {b} = 1 } = ...` + // `1` in `let { a: [b] = 1 } = ...` + // `1` in `let [a = 1] = ...` + // `1` in `let [{a} = 1] = ...` + // `1` in `let [[a] = 1] = ...` + return bindingElement.initializer; + } + + if (isPropertyAssignment(bindingElement)) { + // `1` in `({ a: b = 1 } = ...)` + // `1` in `({ a: {b} = 1 } = ...)` + // `1` in `({ a: [b] = 1 } = ...)` + const initializer = bindingElement.initializer; + return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) + ? initializer.right + : undefined; + } + + if (isShorthandPropertyAssignment(bindingElement)) { + // `1` in `({ a = 1 } = ...)` + return bindingElement.objectAssignmentInitializer; + } + + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `1` in `[a = 1] = ...` + // `1` in `[{a} = 1] = ...` + // `1` in `[[a] = 1] = ...` + return bindingElement.right; + } + + if (isSpreadElement(bindingElement)) { + // Recovery consistent with existing emit. + return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); + } + } + + /** + * Gets the name of an BindingOrAssignmentElement. + */ + export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { + if (isDeclarationBindingElement(bindingElement)) { + // `a` in `let { a } = ...` + // `a` in `let { a = 1 } = ...` + // `b` in `let { a: b } = ...` + // `b` in `let { a: b = 1 } = ...` + // `a` in `let { ...a } = ...` + // `{b}` in `let { a: {b} } = ...` + // `{b}` in `let { a: {b} = 1 } = ...` + // `[b]` in `let { a: [b] } = ...` + // `[b]` in `let { a: [b] = 1 } = ...` + // `a` in `let [a] = ...` + // `a` in `let [a = 1] = ...` + // `a` in `let [...a] = ...` + // `{a}` in `let [{a}] = ...` + // `{a}` in `let [{a} = 1] = ...` + // `[a]` in `let [[a]] = ...` + // `[a]` in `let [[a] = 1] = ...` + return bindingElement.name; + } + + if (isObjectLiteralElementLike(bindingElement)) { + switch (bindingElement.kind) { + case SyntaxKind.PropertyAssignment: + // `b` in `({ a: b } = ...)` + // `b` in `({ a: b = 1 } = ...)` + // `{b}` in `({ a: {b} } = ...)` + // `{b}` in `({ a: {b} = 1 } = ...)` + // `[b]` in `({ a: [b] } = ...)` + // `[b]` in `({ a: [b] = 1 } = ...)` + // `b.c` in `({ a: b.c } = ...)` + // `b.c` in `({ a: b.c = 1 } = ...)` + // `b[0]` in `({ a: b[0] } = ...)` + // `b[0]` in `({ a: b[0] = 1 } = ...)` + return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); + + case SyntaxKind.ShorthandPropertyAssignment: + // `a` in `({ a } = ...)` + // `a` in `({ a = 1 } = ...)` + return bindingElement.name; + + case SyntaxKind.SpreadAssignment: + // `a` in `({ ...a } = ...)` + return getTargetOfBindingOrAssignmentElement(bindingElement.expression); + } + + // no target + return undefined; + } + + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `a` in `[a = 1] = ...` + // `{a}` in `[{a} = 1] = ...` + // `[a]` in `[[a] = 1] = ...` + // `a.b` in `[a.b = 1] = ...` + // `a[0]` in `[a[0] = 1] = ...` + return getTargetOfBindingOrAssignmentElement(bindingElement.left); + } + + if (isSpreadElement(bindingElement)) { + // `a` in `[...a] = ...` + return getTargetOfBindingOrAssignmentElement(bindingElement.expression); + } + + // `a` in `[a] = ...` + // `{a}` in `[{a}] = ...` + // `[a]` in `[[a]] = ...` + // `a.b` in `[a.b] = ...` + // `a[0]` in `[a[0]] = ...` + return bindingElement; + } + + /** + * Determines whether an BindingOrAssignmentElement is a rest element. + */ + export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { + switch (bindingElement.kind) { + case SyntaxKind.Parameter: + case SyntaxKind.BindingElement: + // `...` in `let [...a] = ...` + return bindingElement.dotDotDotToken; + + case SyntaxKind.SpreadElement: + case SyntaxKind.SpreadAssignment: + // `...` in `[...a] = ...` + return bindingElement; + } + + return undefined; + } + + /** + * Gets the property name of a BindingOrAssignmentElement + */ + export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { + const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement); + Debug.assert(!!propertyName || isSpreadAssignment(bindingElement), "Invalid property name for binding element."); + return propertyName; + } + + export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { + switch (bindingElement.kind) { + case SyntaxKind.BindingElement: + // `a` in `let { a: b } = ...` + // `[a]` in `let { [a]: b } = ...` + // `"a"` in `let { "a": b } = ...` + // `1` in `let { 1: b } = ...` + if (bindingElement.propertyName) { + const propertyName = bindingElement.propertyName; + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + ? propertyName.expression + : propertyName; + } + + break; + + case SyntaxKind.PropertyAssignment: + // `a` in `({ a: b } = ...)` + // `[a]` in `({ [a]: b } = ...)` + // `"a"` in `({ "a": b } = ...)` + // `1` in `({ 1: b } = ...)` + if (bindingElement.name) { + const propertyName = bindingElement.name; + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + ? propertyName.expression + : propertyName; + } + + break; + + case SyntaxKind.SpreadAssignment: + // `a` in `({ ...a } = ...)` + return bindingElement.name; + } + + const target = getTargetOfBindingOrAssignmentElement(bindingElement); + if (target && isPropertyName(target)) { + return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression) + ? target.expression + : target; + } + } + + function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral { + const kind = node.kind; + return kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral; + } + + /** + * Gets the elements of a BindingOrAssignmentPattern + */ + export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { + switch (name.kind) { + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + // `a` in `{a}` + // `a` in `[a]` + return name.elements; + + case SyntaxKind.ObjectLiteralExpression: + // `a` in `{a}` + return name.properties; + } + } +} \ No newline at end of file diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 7e0aa5e5b15ad..a27f608546c99 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -118,8 +118,6 @@ namespace ts { version?: string; } - type MatchingKeys = K extends (TRecord[K] extends TMatch ? K : never) ? K : never; - function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; function readPackageJsonField(jsonContent: PackageJson, fieldName: K, typeOfTag: "string" | "object", state: ModuleResolutionState): PackageJson[K] | undefined { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 49cdea63d58a2..2c1948d3e2ba9 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -28,6 +28,14 @@ namespace ts { } } + /* @internal */ + export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.None, { + createBaseSourceFileNode: createNode, + createBaseIdentifierNode: createNode, + createBaseTokenNode: createNode, + createBaseNode: createNode + }); + function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); } @@ -590,20 +598,64 @@ namespace ts { // Share a single scanner across all calls to parse a source file. This helps speed things // up by avoiding the cost of creating/compiling scanners over and over again. const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; // capture constructors in 'initializeState' to avoid null checks + // tslint:disable variable-name let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + // tslint:enable variable-name + + // Rather than using `createBaseNodeFactory` here, we establish a `BaseNodeFactory` that closes over the + // constructors above, which are reset each time `initializeState` is called. + const baseNodeFactory: BaseNodeFactory = { + createBaseSourceFileNode: kind => new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseIdentifierNode: kind => new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseTokenNode: kind => new TokenConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseNode: kind => new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0) + }; + + const factoryWithParentPointers = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters, baseNodeFactory, { + onSetChild(parent, child) { + child.parent = parent; + }, + onSetChildren(parent, children) { + for (const child of children) { + child.parent = parent; + } + }, + onFinishNode(node) { + if (hasJSDocNodes(node)) { + for (const jsDoc of node.jsDoc!) { + jsDoc.parent = node; + } + } + }, + onCreateNode(_) { + nodeCount++; + } + }); + + const factoryWithoutParentPointers = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters, baseNodeFactory, { + onCreateNode(_) { + nodeCount++; + } + }); - let sourceFile: SourceFile; - let parseDiagnostics: DiagnosticWithLocation[]; + let factory = factoryWithoutParentPointers; + let sourceFlags: NodeFlags; + let sourceText: string; + let languageVersion: ScriptTarget; + let scriptKind: ScriptKind; + let languageVariant: LanguageVariant; + let parseDiagnostics: DiagnosticWithDetachedLocation[]; + let jsDocDiagnostics: DiagnosticWithDetachedLocation[]; let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; let currentToken: SyntaxKind; - let sourceText: string; let nodeCount: number; let identifiers: Map; let identifierCount: number; @@ -703,7 +755,7 @@ namespace ts { return result; } - initializeState(sourceText, languageVersion, syntaxCursor, scriptKind); + initializeState(sourceText, languageVersion, syntaxCursor, scriptKind, setParentNodes); const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); @@ -714,7 +766,7 @@ namespace ts { export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined { // Choice of `isDeclarationFile` should be arbitrary - initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); + initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS, /*setParentNodes*/ false); // Prime the scanner. nextToken(); const entityName = parseEntityName(/*allowReservedWords*/ true); @@ -723,54 +775,60 @@ namespace ts { return isInvalid ? entityName : undefined; } - export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): JsonSourceFile { - initializeState(sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); - // Set source file so that errors will be reported with this file name - sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false); - sourceFile.flags = contextFlags; + export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { + initializeState(sourceText, languageVersion, syntaxCursor, ScriptKind.JSON, setParentNodes); + sourceFlags = contextFlags; // Prime the scanner. nextToken(); const pos = getNodePos(); + let statements, endOfFileToken; if (token() === SyntaxKind.EndOfFileToken) { - sourceFile.statements = createNodeArray([], pos, pos); - sourceFile.endOfFileToken = parseTokenNode(); + statements = createNodeArray([], pos, pos); + endOfFileToken = parseTokenNode(); } else { - const statement = createNode(SyntaxKind.ExpressionStatement) as JsonObjectExpressionStatement; + let expression; switch (token()) { case SyntaxKind.OpenBracketToken: - statement.expression = parseArrayLiteralExpression(); + expression = parseArrayLiteralExpression(); break; case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: case SyntaxKind.NullKeyword: - statement.expression = parseTokenNode(); + expression = parseTokenNode(); break; case SyntaxKind.MinusToken: if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) { - statement.expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; + expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; } else { - statement.expression = parseObjectLiteralExpression(); + expression = parseObjectLiteralExpression(); } break; case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) { - statement.expression = parseLiteralNode() as StringLiteral | NumericLiteral; + expression = parseLiteralNode() as StringLiteral | NumericLiteral; break; } // falls through default: - statement.expression = parseObjectLiteralExpression(); + expression = parseObjectLiteralExpression(); break; } - finishNode(statement); - sourceFile.statements = createNodeArray([statement], pos); - sourceFile.endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); + + // TODO(rbuckton): this does not create the tree correctly and transform flags won't be properly set + const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement; + finishNode(statement, pos); + statements = createNodeArray([statement], pos); + endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); } + // Set source file so that errors will be reported with this file name + const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken); + sourceFile.flags |= sourceFlags; + if (setParentNodes) { fixupParentReferences(sourceFile); } @@ -778,32 +836,36 @@ namespace ts { sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = parseDiagnostics; + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } const result = sourceFile as JsonSourceFile; clearState(); return result; } - function getLanguageVariant(scriptKind: ScriptKind) { - // .tsx and .jsx files are treated as jsx language variant. - return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; - } - - function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, scriptKind: ScriptKind) { + function initializeState(_sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind, setParentNodes: boolean) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); SourceFileConstructor = objectAllocator.getSourceFileConstructor(); + factory = setParentNodes ? factoryWithParentPointers : factoryWithoutParentPointers; + sourceText = _sourceText; + languageVersion = _languageVersion; syntaxCursor = _syntaxCursor; + scriptKind = _scriptKind; + languageVariant = getLanguageVariant(_scriptKind); parseDiagnostics = []; parsingContext = 0; identifiers = createMap(); identifierCount = 0; nodeCount = 0; + sourceFlags = 0; switch (scriptKind) { case ScriptKind.JS: @@ -823,7 +885,7 @@ namespace ts { scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + scanner.setLanguageVariant(languageVariant); } function clearState() { @@ -832,54 +894,72 @@ namespace ts { scanner.setOnError(undefined); // Clear any data. We don't want to accidentally hold onto it for too long. + factory = factoryWithoutParentPointers; + sourceText = undefined!; + languageVersion = undefined!; + syntaxCursor = undefined; + scriptKind = undefined!; + languageVariant = undefined!; + sourceFlags = 0; parseDiagnostics = undefined!; - sourceFile = undefined!; + jsDocDiagnostics = undefined!; + parsingContext = 0; identifiers = undefined!; - syntaxCursor = undefined; - sourceText = undefined!; notParenthesizedArrow = undefined!; + factory.setSkipTransformationFlags(/*inDeclarationFile*/ false); } function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile { const isDeclarationFile = isDeclarationFileName(fileName); + factory.setSkipTransformationFlags(isDeclarationFile); if (isDeclarationFile) { contextFlags |= NodeFlags.Ambient; } - sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); - sourceFile.flags = contextFlags; + sourceFlags = contextFlags; // Prime the scanner. nextToken(); - // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future - processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); - processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic); - sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement); + const statements = parseList(ParsingContext.SourceElements, parseStatement); Debug.assert(token() === SyntaxKind.EndOfFileToken); - sourceFile.endOfFileToken = addJSDocComment(parseTokenNode()); + const endOfFileToken = addJSDocComment(parseTokenNode()); - setExternalModuleIndicator(sourceFile); + const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken); + sourceFile.flags |= sourceFlags; + + // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future + processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); + processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic); sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = parseDiagnostics; + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } + setExternalModuleIndicator(sourceFile); if (setParentNodes) { fixupParentReferences(sourceFile); } + factory.setSkipTransformationFlags(/*inDeclarationFile*/ false); return sourceFile; function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) { - parseDiagnostics.push(createFileDiagnostic(sourceFile, pos, end, diagnostic)); + parseDiagnostics.push(createDetachedDiagnostic(pos, end, diagnostic)); } } + function withJSDoc(node: T, hasJSDoc: boolean): T { + return hasJSDoc ? addJSDocComment(node) : node; + } + function addJSDocComment(node: T): T { Debug.assert(!node.jsDoc); // Should only be called once per node - const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceFile.text), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); + const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); if (jsDoc.length) node.jsDoc = jsDoc; return node; } @@ -916,12 +996,12 @@ namespace ts { } } - function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile { + function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean, statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible - const sourceFile = new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length); - nodeCount++; - + const sourceFile = factory.createSourceFile(statements, endOfFileToken); + sourceFile.pos = 0; + sourceFile.end = sourceText.length; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.bindSuggestionDiagnostics = undefined; @@ -1061,7 +1141,7 @@ namespace ts { // Don't report another error if it would just be at the same position as the last error. const lastError = lastOrUndefined(parseDiagnostics); if (!lastError || start !== lastError.start) { - parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0)); + parseDiagnostics.push(createDetachedDiagnostic(start, length, message, arg0)); } // Mark that we've encountered an error. We'll set an appropriate bit on the next @@ -1085,6 +1165,10 @@ namespace ts { return scanner.getStartPos(); } + function hasPrecedingJSDocComment() { + return scanner.hasPrecedingJSDocComment(); + } + // Use this function to access the current token instead of reading the currentToken // variable. Since function results aren't narrowed in control flow analysis, this ensures // that the type checker doesn't make wrong assumptions about the type of the current @@ -1099,6 +1183,11 @@ namespace ts { return currentToken = scanner.scan(); } + function nextTokenAnd(func: () => T): T { + nextToken(); + return func(); + } + function nextToken(): SyntaxKind { // if the keyword had an escape if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) { @@ -1275,15 +1364,17 @@ namespace ts { } function parseTokenNode(): T { - const node = createNode(token()); + const pos = getNodePos(); + const kind = token(); nextToken(); - return finishNode(node); + return finishNode(factory.createToken(kind), pos); } function parseTokenNodeJSDoc(): T { - const node = createNode(token()); + const pos = getNodePos(); + const kind = token(); nextTokenJSDoc(); - return finishNode(node); + return finishNode(factory.createToken(kind), pos); } function canParseSemicolon() { @@ -1310,34 +1401,15 @@ namespace ts { } } - function createNode(kind: SyntaxKind, pos?: number): Node { - nodeCount++; - const p = pos! >= 0 ? pos! : scanner.getStartPos(); - return isNodeKind(kind) || kind === SyntaxKind.Unknown ? new NodeConstructor(kind, p, p) : - kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, p, p) : - new TokenConstructor(kind, p, p); - } - - function createNodeWithJSDoc(kind: SyntaxKind, pos?: number): Node { - const node = createNode(kind, pos); - if (scanner.getTokenFlags() & TokenFlags.PrecedingJSDocComment) { - addJSDocComment(node); - } - return node; - } - function createNodeArray(elements: T[], pos: number, end?: number): NodeArray { - // Since the element list of a node array is typically created by starting with an empty array and - // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for - // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. - const length = elements.length; - const array = >(length >= 1 && length <= 4 ? elements.slice() : elements); + const array = factory.createNodeArray(elements, /*hasTrailingComma*/ undefined); array.pos = pos; array.end = end === undefined ? scanner.getStartPos() : end; return array; } - function finishNode(node: T, end?: number): T { + function finishNode(node: T, pos: number, end?: number): T { + node.pos = pos; node.end = end === undefined ? scanner.getStartPos() : end; if (contextFlags) { @@ -1365,16 +1437,15 @@ namespace ts { parseErrorAtCurrentToken(diagnosticMessage, arg0); } - const result = createNode(kind); - - if (kind === SyntaxKind.Identifier) { - (result as Identifier).escapedText = "" as __String; - } - else if (isLiteralKind(kind) || isTemplateLiteralKind(kind)) { - (result as LiteralLikeNode).text = ""; - } - - return finishNode(result) as T; + const pos = getNodePos(); + const result = + kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) : + isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "") : + kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) : + kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) : + kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : + factory.createToken(kind); + return finishNode(result, pos) as T; } function internIdentifier(text: string): string { @@ -1391,15 +1462,12 @@ namespace ts { function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage): Identifier { identifierCount++; if (isIdentifier) { - const node = createNode(SyntaxKind.Identifier); - + const pos = getNodePos(); // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker - if (token() !== SyntaxKind.Identifier) { - node.originalKeywordKind = token(); - } - node.escapedText = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); + const originalKeywordKind = token(); + const text = internIdentifier(scanner.getTokenValue()); nextTokenWithoutCheck(); - return finishNode(node); + return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos); } // Only for end of file because the error gets reported incorrectly on embedded script tags. @@ -1449,16 +1517,14 @@ namespace ts { // PropertyName [Yield]: // LiteralPropertyName // ComputedPropertyName[?Yield] - const node = createNode(SyntaxKind.ComputedPropertyName); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBracketToken); - // We parse any expression (including a comma expression). But the grammar // says that only an assignment expression is allowed, so the grammar checker // will error if it sees a comma expression. - node.expression = allowInAnd(parseExpression); - + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseBracketToken); - return finishNode(node); + return finishNode(factory.createComputedPropertyName(expression), pos); } function parseContextualModifier(t: SyntaxKind): boolean { @@ -2213,25 +2279,29 @@ namespace ts { } function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { + const pos = getNodePos(); let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); - let dotPos = scanner.getStartPos(); + let dotPos = getNodePos(); while (parseOptional(SyntaxKind.DotToken)) { if (token() === SyntaxKind.LessThanToken) { // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting entity.jsdocDotPos = dotPos; break; } - dotPos = scanner.getStartPos(); - entity = createQualifiedName(entity, parseRightSideOfDot(allowReservedWords)); + dotPos = getNodePos(); + entity = finishNode( + factory.createQualifiedName( + entity, + parseRightSideOfDot(allowReservedWords) + ), + pos + ); } return entity; } function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName { - const node = createNode(SyntaxKind.QualifiedName, entity.pos) as QualifiedName; - node.left = entity; - node.right = name; - return finishNode(node); + return finishNode(factory.createQualifiedName(entity, name), entity.pos); } function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier { @@ -2268,40 +2338,49 @@ namespace ts { return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } - function parseTemplateExpression(): TemplateExpression { - const template = createNode(SyntaxKind.TemplateExpression); - - template.head = parseTemplateHead(); - Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); - + function parseTemplateSpans() { + const pos = getNodePos(); const list = []; - const listPos = getNodePos(); - + let node: TemplateSpan; do { - list.push(parseTemplateSpan()); + node = parseTemplateSpan(); + list.push(node); } - while (last(list).literal.kind === SyntaxKind.TemplateMiddle); - - template.templateSpans = createNodeArray(list, listPos); - - return finishNode(template); + while (node.literal.kind === SyntaxKind.TemplateMiddle); + return createNodeArray(list, pos); } - function parseTemplateSpan(): TemplateSpan { - const span = createNode(SyntaxKind.TemplateSpan); - span.expression = allowInAnd(parseExpression); + function parseTemplateExpression(): TemplateExpression { + const pos = getNodePos(); + return finishNode( + factory.createTemplateExpression( + parseTemplateHead(), + parseTemplateSpans() + ), + pos + ); + } - let literal: TemplateMiddle | TemplateTail; + function parseLiteralOfTemplateSpan() { if (token() === SyntaxKind.CloseBraceToken) { reScanTemplateToken(); - literal = parseTemplateMiddleOrTemplateTail(); + return parseTemplateMiddleOrTemplateTail(); } else { - literal = parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)); + // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly? + return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)); } + } - span.literal = literal; - return finishNode(span); + function parseTemplateSpan(): TemplateSpan { + const pos = getNodePos(); + return finishNode( + factory.createTemplateSpan( + allowInAnd(parseExpression), + parseLiteralOfTemplateSpan() + ), + pos + ); } function parseLiteralNode(): LiteralExpression { @@ -2320,19 +2399,26 @@ namespace ts { return fragment; } + function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) { + const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail; + const tokenText = scanner.getTokenText(); + return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); + } + function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { - const node = createNode(kind); - node.text = scanner.getTokenValue(); - switch (kind) { - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail; - const tokenText = scanner.getTokenText(); - (node).rawText = tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); - break; - } + const pos = getNodePos(); + const node = + isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind)) : + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal. But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : + kind === SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : + isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) : + Debug.fail(); if (scanner.hasExtendedUnicodeEscape()) { node.hasExtendedUnicodeEscape = true; @@ -2342,31 +2428,31 @@ namespace ts { node.isUnterminated = true; } - // Octal literals are not allowed in strict mode or ES5 - // Note that theoretically the following condition would hold true literals like 009, - // which is not octal.But because of how the scanner separates the tokens, we would - // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. - // We also do not need to check for negatives because any prefix operator would be part of a - // parent unary expression. - if (node.kind === SyntaxKind.NumericLiteral) { - (node).numericLiteralFlags = scanner.getTokenFlags() & TokenFlags.NumericLiteralFlags; - } - nextToken(); - finishNode(node); - - return node; + return finishNode(node, pos); } // TYPES - function parseTypeReference(): TypeReferenceNode { - const node = createNode(SyntaxKind.TypeReference); - node.typeName = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected); + function parseEntityNameOfTypeReference() { + return parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected); + } + + function parseTypeArgumentsOfTypeReference() { if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) { - node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + return parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); } - return finishNode(node); + } + + function parseTypeReference(): TypeReferenceNode { + const pos = getNodePos(); + return finishNode( + factory.createTypeReferenceNode( + parseEntityNameOfTypeReference(), + parseTypeArgumentsOfTypeReference() + ), + pos + ); } // If true, we should abort parsing an error function. @@ -2388,38 +2474,38 @@ namespace ts { function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode { nextToken(); - const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode; - node.parameterName = lhs; - node.type = parseType(); - return finishNode(node); + return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, lhs, parseType()), lhs.pos); } function parseThisTypeNode(): ThisTypeNode { - const node = createNode(SyntaxKind.ThisType) as ThisTypeNode; + const pos = getNodePos(); nextToken(); - return finishNode(node); + return finishNode(factory.createThisTypeNode(), pos); } function parseJSDocAllType(postFixEquals: boolean): JSDocAllType | JSDocOptionalType { - const result = createNode(SyntaxKind.JSDocAllType) as JSDocAllType; + const pos = getNodePos(); + nextToken(); + + const node = factory.createJSDocAllType(); if (postFixEquals) { - return createPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType; + // Trim the trailing `=` from the `*=` token + const end = Math.max(getNodePos() - 1, pos); + return finishNode(factory.createJSDocOptionalType(finishNode(node, pos, end)), pos); } else { - nextToken(); + return finishNode(node, pos); } - return finishNode(result); } function parseJSDocNonNullableType(): TypeNode { - const result = createNode(SyntaxKind.JSDocNonNullableType) as JSDocNonNullableType; + const pos = getNodePos(); nextToken(); - result.type = parseNonArrayType(); - return finishNode(result); + return finishNode(factory.createJSDocNonNullableType(parseNonArrayType()), pos); } function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { - const pos = scanner.getStartPos(); + const pos = getNodePos(); // skip the ? nextToken(); @@ -2439,44 +2525,52 @@ namespace ts { token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.BarToken) { - - const result = createNode(SyntaxKind.JSDocUnknownType, pos); - return finishNode(result); + return finishNode(factory.createJSDocUnknownType(), pos); } else { - const result = createNode(SyntaxKind.JSDocNullableType, pos); - result.type = parseType(); - return finishNode(result); + return finishNode(factory.createJSDocNullableType(parseType()), pos); } } function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode { + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); if (lookAhead(nextTokenIsOpenParen)) { - const result = createNodeWithJSDoc(SyntaxKind.JSDocFunctionType); nextToken(); - fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type | SignatureFlags.JSDoc, result); - return finishNode(result); + const { parameters, type } = parseSignature(SyntaxKind.ColonToken, SignatureFlags.Type | SignatureFlags.JSDoc); + return withJSDoc(finishNode(factory.createJSDocFunctionType(parameters, type), pos), hasJSDoc); } - const node = createNode(SyntaxKind.TypeReference); - node.typeName = parseIdentifierName(); - return finishNode(node); + return finishNode(factory.createTypeReferenceNode(parseIdentifierName(), /*typeArguments*/ undefined), pos); } function parseJSDocParameter(): ParameterDeclaration { - const parameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration; + const pos = getNodePos(); + let name: Identifier | undefined; if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) { - parameter.name = parseIdentifierName(); + name = parseIdentifierName(); parseExpected(SyntaxKind.ColonToken); } - parameter.type = parseJSDocType(); - return finishNode(parameter); + return finishNode( + factory.createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + // TODO(rbuckton): JSDoc parameters don't have names (except `this`/`new`), should we manufacture an empty identifier? + name!, + /*questionToken*/ undefined, + parseJSDocType(), + /*initializer*/ undefined + ), + pos + ); } function parseJSDocType(): TypeNode { scanner.setInJSDocType(true); - const moduleSpecifier = parseOptionalToken(SyntaxKind.ModuleKeyword); - if (moduleSpecifier) { - const moduleTag = createNode(SyntaxKind.JSDocNamepathType, moduleSpecifier.pos) as JSDocNamepathType; + const pos = getNodePos(); + if (parseOptional(SyntaxKind.ModuleKeyword)) { + // TODO(rbuckton): We never set the type for a JSDocNamepathType. What should we put here? + const moduleTag = factory.createJSDocNamepathType(/*type*/ undefined!); terminate: while (true) { switch (token()) { case SyntaxKind.CloseBraceToken: @@ -2490,40 +2584,40 @@ namespace ts { } scanner.setInJSDocType(false); - return finishNode(moduleTag); + return finishNode(moduleTag, pos); } - const dotdotdot = parseOptionalToken(SyntaxKind.DotDotDotToken); + const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken); let type = parseTypeOrTypePredicate(); scanner.setInJSDocType(false); - if (dotdotdot) { - const variadic = createNode(SyntaxKind.JSDocVariadicType, dotdotdot.pos) as JSDocVariadicType; - variadic.type = type; - type = finishNode(variadic); + if (hasDotDotDot) { + type = finishNode(factory.createJSDocVariadicType(type), pos); } if (token() === SyntaxKind.EqualsToken) { - return createPostfixType(SyntaxKind.JSDocOptionalType, type); + nextToken(); + return finishNode(factory.createJSDocOptionalType(type), pos); } return type; } function parseTypeQuery(): TypeQueryNode { - const node = createNode(SyntaxKind.TypeQuery); + const pos = getNodePos(); parseExpected(SyntaxKind.TypeOfKeyword); - node.exprName = parseEntityName(/*allowReservedWords*/ true); - return finishNode(node); + return finishNode(factory.createTypeQueryNode(parseEntityName(/*allowReservedWords*/ true)), pos); } function parseTypeParameter(): TypeParameterDeclaration { - const node = createNode(SyntaxKind.TypeParameter); - node.name = parseIdentifier(); + const pos = getNodePos(); + const name = parseIdentifier(); + let constraint: TypeNode | undefined; + let expression: Expression | undefined; if (parseOptional(SyntaxKind.ExtendsKeyword)) { // It's not uncommon for people to write improper constraints to a generic. If the // user writes a constraint that is an expression and not an actual type, then parse // it out as an expression (so we can recover well), but report that a type is needed // instead. if (isStartOfType() || !isStartOfExpression()) { - node.constraint = parseType(); + constraint = parseType(); } else { // It was not a type, and it looked like an expression. Parse out an expression @@ -2533,15 +2627,14 @@ namespace ts { // // // We do *not* want to consume the `>` as we're consuming the expression for "". - node.expression = parseUnaryExpressionOrHigher(); + expression = parseUnaryExpressionOrHigher(); } } - if (parseOptional(SyntaxKind.EqualsToken)) { - node.default = parseType(); - } - - return finishNode(node); + const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined; + const node = factory.createTypeParameterDeclaration(name, constraint, defaultType); + if (expression) factory.trackExtraneousChildNode(node, node.expression = expression); + return finishNode(node, pos); } function parseTypeParameters(): NodeArray | undefined { @@ -2550,14 +2643,6 @@ namespace ts { } } - function parseParameterType(): TypeNode | undefined { - if (parseOptional(SyntaxKind.ColonToken)) { - return parseType(); - } - - return undefined; - } - function isStartOfParameter(isJSDocParameter: boolean): boolean { return token() === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || @@ -2566,22 +2651,11 @@ namespace ts { isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); } - function parseParameter(): ParameterDeclaration { - const node = createNodeWithJSDoc(SyntaxKind.Parameter); - if (token() === SyntaxKind.ThisKeyword) { - node.name = createIdentifier(/*isIdentifier*/ true); - node.type = parseParameterType(); - return finishNode(node); - } - - node.decorators = parseDecorators(); - node.modifiers = parseModifiers(); - node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); - + function parseNameOfParameter(modifiers: ModifiersArray | undefined) { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && !hasModifiers(node) && isModifierKind(token())) { + const name = parseIdentifierOrPattern(); + if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) { // in cases like // 'use strict' // function foo(static) @@ -2592,12 +2666,64 @@ namespace ts { // to avoid this we'll advance cursor to the next token. nextToken(); } + return name; + } - node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); - node.type = parseParameterType(); - node.initializer = parseInitializer(); + function parseParameter(): ParameterDeclaration { + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + if (token() === SyntaxKind.ThisKeyword) { + const node = factory.createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + createIdentifier(/*isIdentifier*/ true), + /*questionToken*/ undefined, + parseTypeAnnotation(), + /*initializer*/ undefined + ); + return withJSDoc(finishNode(node, pos), hasJSDoc); + } - return finishNode(node); + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] + let modifiers; + return withJSDoc( + finishNode( + factory.createParameterDeclaration( + parseDecorators(), + modifiers = parseModifiers(), + parseOptionalToken(SyntaxKind.DotDotDotToken), + parseNameOfParameter(modifiers), + parseOptionalToken(SyntaxKind.QuestionToken), + parseTypeAnnotation(), + parseInitializer() + ), + pos + ), + hasJSDoc + ); + } + + interface SignatureInfo { + typeParameters?: NodeArray; + parameters: NodeArray; + parametersParsedSuccessfully?: boolean; + type?: TypeNode; + } + + function parseSignature( + returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, + flags: SignatureFlags + ) { + const signature: SignatureInfo = { + typeParameters: undefined, + parameters: undefined!, + parametersParsedSuccessfully: undefined, + type: undefined + }; + signature.parametersParsedSuccessfully = fillSignature(returnToken, flags, signature); + return signature; } /** @@ -2607,7 +2733,7 @@ namespace ts { function fillSignature( returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, flags: SignatureFlags, - signature: SignatureDeclaration): boolean { + signature: SignatureInfo): boolean { if (!(flags & SignatureFlags.JSDoc)) { signature.typeParameters = parseTypeParameters(); } @@ -2637,7 +2763,7 @@ namespace ts { } // Returns true on success. - function parseParameterList(signature: SignatureDeclaration, flags: SignatureFlags): boolean { + function parseParameterList(signature: SignatureInfo, flags: SignatureFlags): boolean { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -2684,13 +2810,17 @@ namespace ts { } function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { - const node = createNodeWithJSDoc(kind); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); if (kind === SyntaxKind.ConstructSignature) { parseExpected(SyntaxKind.NewKeyword); } - fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type, node); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, SignatureFlags.Type); parseTypeMemberSemicolon(); - return finishNode(node); + const node = kind === SyntaxKind.CallSignature + ? factory.createCallSignature(typeParameters, parameters, type) + : factory.createConstructSignature(typeParameters, parameters, type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function isIndexSignature(): boolean { @@ -2752,35 +2882,34 @@ namespace ts { return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken; } - function parseIndexSignatureDeclaration(node: IndexSignatureDeclaration): IndexSignatureDeclaration { - node.kind = SyntaxKind.IndexSignature; - node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); - node.type = parseTypeAnnotation(); + function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): IndexSignatureDeclaration { + const parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + const type = parseTypeAnnotation(); parseTypeMemberSemicolon(); - return finishNode(node); + const node = factory.createIndexSignature(decorators, modifiers, parameters, type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parsePropertyOrMethodSignature(node: PropertySignature | MethodSignature): PropertySignature | MethodSignature { - node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): PropertySignature | MethodSignature { + const name = parsePropertyName(); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + let node: PropertySignature | MethodSignature; if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - node.kind = SyntaxKind.MethodSignature; // Method signatures don't exist in expression contexts. So they have neither // [Yield] nor [Await] - fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type, node); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, SignatureFlags.Type); + node = factory.createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type); } else { - node.kind = SyntaxKind.PropertySignature; - node.type = parseTypeAnnotation(); - if (token() === SyntaxKind.EqualsToken) { - // Although type literal properties cannot not have initializers, we attempt - // to parse an initializer so we can report in the checker that an interface - // property or type literal property cannot have an initializer. - (node).initializer = parseInitializer(); - } + const type = parseTypeAnnotation(); + node = factory.createPropertySignature(modifiers, name, questionToken, type); + // Although type literal properties cannot not have initializers, we attempt + // to parse an initializer so we can report in the checker that an interface + // property or type literal property cannot have an initializer. + if (token() === SyntaxKind.EqualsToken) factory.trackExtraneousChildNode(node, node.initializer = parseInitializer()); } parseTypeMemberSemicolon(); - return finishNode(node); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function isTypeMemberStart(): boolean { @@ -2823,12 +2952,13 @@ namespace ts { if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } - const node = createNodeWithJSDoc(SyntaxKind.Unknown); - node.modifiers = parseModifiers(); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + const modifiers = parseModifiers(); if (isIndexSignature()) { - return parseIndexSignatureDeclaration(node); + return parseIndexSignatureDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers); } - return parsePropertyOrMethodSignature(node); + return parsePropertyOrMethodSignature(pos, hasJSDoc, modifiers); } function nextTokenIsOpenParenOrLessThan() { @@ -2851,9 +2981,8 @@ namespace ts { } function parseTypeLiteral(): TypeLiteralNode { - const node = createNode(SyntaxKind.TypeLiteral); - node.members = parseObjectTypeMembers(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos); } function parseObjectTypeMembers(): NodeArray { @@ -2881,71 +3010,82 @@ namespace ts { } function parseMappedTypeParameter() { - const node = createNode(SyntaxKind.TypeParameter); - node.name = parseIdentifier(); + const pos = getNodePos(); + const name = parseIdentifierName(); parseExpected(SyntaxKind.InKeyword); - node.constraint = parseType(); - return finishNode(node); + const type = parseType(); + return finishNode(factory.createTypeParameterDeclaration(name, type, /*defaultType*/ undefined), pos); } function parseMappedType() { - const node = createNode(SyntaxKind.MappedType); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); + let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - node.readonlyToken = parseTokenNode(); - if (node.readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { - parseExpectedToken(SyntaxKind.ReadonlyKeyword); + readonlyToken = parseTokenNode(); + if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { + parseExpected(SyntaxKind.ReadonlyKeyword); } } parseExpected(SyntaxKind.OpenBracketToken); - node.typeParameter = parseMappedTypeParameter(); + const typeParameter = parseMappedTypeParameter(); parseExpected(SyntaxKind.CloseBracketToken); + let questionToken: QuestionToken | PlusToken | MinusToken | undefined; if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - node.questionToken = parseTokenNode(); - if (node.questionToken.kind !== SyntaxKind.QuestionToken) { - parseExpectedToken(SyntaxKind.QuestionToken); + questionToken = parseTokenNode(); + if (questionToken.kind !== SyntaxKind.QuestionToken) { + parseExpected(SyntaxKind.QuestionToken); } } - node.type = parseTypeAnnotation(); + const type = parseTypeAnnotation(); parseSemicolon(); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(node); + return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), pos); } function parseTupleElementType() { const pos = getNodePos(); if (parseOptional(SyntaxKind.DotDotDotToken)) { - const node = createNode(SyntaxKind.RestType, pos); - node.type = parseType(); - return finishNode(node); + return finishNode(factory.createRestTypeNode(parseType()), pos); } const type = parseType(); - if (!(contextFlags & NodeFlags.JSDoc) && type.kind === SyntaxKind.JSDocNullableType && type.pos === (type).type.pos) { - type.kind = SyntaxKind.OptionalType; + if (!(contextFlags & NodeFlags.JSDoc) && isJSDocNullableType(type) && type.pos === type.type.pos) { + const node = factory.createOptionalTypeNode(type.type); + node.pos = type.pos; + node.end = type.end; + node.flags = type.flags; + return node; } return type; } function parseTupleType(): TupleTypeNode { - const node = createNode(SyntaxKind.TupleType); - node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); - return finishNode(node); + const pos = getNodePos(); + return finishNode( + factory.createTupleTypeNode( + parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken) + ), + pos + ); } function parseParenthesizedType(): TypeNode { - const node = createNode(SyntaxKind.ParenthesizedType); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenParenToken); - node.type = parseType(); + const type = parseType(); parseExpected(SyntaxKind.CloseParenToken); - return finishNode(node); + return finishNode(factory.createParenthesizedType(type), pos); } function parseFunctionOrConstructorType(): TypeNode { const pos = getNodePos(); - const kind = parseOptional(SyntaxKind.NewKeyword) ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType; - const node = createNodeWithJSDoc(kind, pos); - fillSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type, node); - return finishNode(node); + const hasJSDoc = hasPrecedingJSDocComment(); + const isConstructorType = parseOptional(SyntaxKind.NewKeyword); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type); + const node = isConstructorType + ? factory.createConstructorTypeNode(typeParameters, parameters, type) + : factory.createFunctionTypeNode(typeParameters, parameters, type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseKeywordAndNoDot(): TypeNode | undefined { @@ -2954,23 +3094,18 @@ namespace ts { } function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { - const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode; - let unaryMinusExpression!: PrefixUnaryExpression; + const pos = getNodePos(); if (negative) { - unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression; - unaryMinusExpression.operator = SyntaxKind.MinusToken; nextToken(); } - let expression: BooleanLiteral | LiteralExpression | PrefixUnaryExpression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword - ? parseTokenNode() - : parseLiteralLikeNode(token()) as LiteralExpression; + let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = + token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? + parseTokenNode() : + parseLiteralLikeNode(token()) as LiteralExpression; if (negative) { - unaryMinusExpression.operand = expression; - finishNode(unaryMinusExpression); - expression = unaryMinusExpression; + expression = finishNode(factory.createPrefix(SyntaxKind.MinusToken, expression), pos); } - node.literal = expression; - return finishNode(node); + return finishNode(factory.createLiteralTypeNode(expression), pos); } function isStartOfTypeOfImportType() { @@ -2979,22 +3114,16 @@ namespace ts { } function parseImportType(): ImportTypeNode { - sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; - const node = createNode(SyntaxKind.ImportType) as ImportTypeNode; - if (parseOptional(SyntaxKind.TypeOfKeyword)) { - node.isTypeOf = true; - } + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; + const pos = getNodePos(); + const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword); parseExpected(SyntaxKind.ImportKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.argument = parseType(); + const type = parseType(); parseExpected(SyntaxKind.CloseParenToken); - if (parseOptional(SyntaxKind.DotToken)) { - node.qualifier = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected); - } - if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) { - node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); - } - return finishNode(node); + const qualifier = parseOptional(SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : undefined; + const typeArguments = parseTypeArgumentsOfTypeReference(); + return finishNode(factory.createImportTypeNode(type, qualifier, typeArguments, isTypeOf), pos); } function nextTokenIsNumericOrBigIntLiteral() { @@ -3036,11 +3165,11 @@ namespace ts { case SyntaxKind.BigIntLiteral: case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: return parseLiteralTypeNode(); case SyntaxKind.MinusToken: return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); case SyntaxKind.VoidKeyword: - case SyntaxKind.NullKeyword: return parseTokenNode(); case SyntaxKind.ThisKeyword: { const thisKeyword = parseThisTypeNode(); @@ -3124,33 +3253,32 @@ namespace ts { } function parsePostfixTypeOrHigher(): TypeNode { + const pos = getNodePos(); let type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak()) { switch (token()) { case SyntaxKind.ExclamationToken: - type = createPostfixType(SyntaxKind.JSDocNonNullableType, type); + nextToken(); + type = finishNode(factory.createJSDocNonNullableType(type), pos); break; case SyntaxKind.QuestionToken: // If not in JSDoc and next token is start of a type we have a conditional type if (!(contextFlags & NodeFlags.JSDoc) && lookAhead(nextTokenIsStartOfType)) { return type; } - type = createPostfixType(SyntaxKind.JSDocNullableType, type); + nextToken(); + type = finishNode(factory.createJSDocNullableType(type), pos); break; case SyntaxKind.OpenBracketToken: parseExpected(SyntaxKind.OpenBracketToken); if (isStartOfType()) { - const node = createNode(SyntaxKind.IndexedAccessType, type.pos) as IndexedAccessTypeNode; - node.objectType = type; - node.indexType = parseType(); + const indexType = parseType(); parseExpected(SyntaxKind.CloseBracketToken); - type = finishNode(node); + type = finishNode(factory.createIndexedAccessTypeNode(type, indexType), pos); } else { - const node = createNode(SyntaxKind.ArrayType, type.pos) as ArrayTypeNode; - node.elementType = type; parseExpected(SyntaxKind.CloseBracketToken); - type = finishNode(node); + type = finishNode(factory.createArrayTypeNode(type), pos); } break; default: @@ -3160,28 +3288,28 @@ namespace ts { return type; } - function createPostfixType(kind: SyntaxKind, type: TypeNode) { - nextToken(); - const postfix = createNode(kind, type.pos) as OptionalTypeNode | JSDocOptionalType | JSDocNonNullableType | JSDocNullableType; - postfix.type = type; - return finishNode(postfix); - } - function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) { - const node = createNode(SyntaxKind.TypeOperator); + const pos = getNodePos(); parseExpected(operator); - node.operator = operator; - node.type = parseTypeOperatorOrHigher(); - return finishNode(node); + return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos); + } + + function parseTypeParameterOfInferType() { + const pos = getNodePos(); + return finishNode( + factory.createTypeParameterDeclaration( + parseIdentifier(), + /*constraint*/ undefined, + /*defaultType*/ undefined + ), + pos + ); } function parseInferType(): InferTypeNode { - const node = createNode(SyntaxKind.InferType); + const pos = getNodePos(); parseExpected(SyntaxKind.InferKeyword); - const typeParameter = createNode(SyntaxKind.TypeParameter); - typeParameter.name = parseIdentifier(); - node.typeParameter = finishNode(typeParameter); - return finishNode(node); + return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos); } function parseTypeOperatorOrHigher(): TypeNode { @@ -3197,8 +3325,12 @@ namespace ts { return parsePostfixTypeOrHigher(); } - function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { - const start = scanner.getStartPos(); + function parseUnionOrIntersectionType( + operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken, + parseConstituentType: () => TypeNode, + createTypeNode: (types: NodeArray) => UnionOrIntersectionTypeNode + ): TypeNode { + const pos = getNodePos(); const hasLeadingOperator = parseOptional(operator); let type = parseConstituentType(); if (token() === operator || hasLeadingOperator) { @@ -3206,19 +3338,17 @@ namespace ts { while (parseOptional(operator)) { types.push(parseConstituentType()); } - const node = createNode(kind, start); - node.types = createNodeArray(types, start); - type = finishNode(node); + type = finishNode(createTypeNode(createNodeArray(types, pos)), pos); } return type; } function parseIntersectionTypeOrHigher(): TypeNode { - return parseUnionOrIntersectionType(SyntaxKind.IntersectionType, parseTypeOperatorOrHigher, SyntaxKind.AmpersandToken); + return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode); } function parseUnionTypeOrHigher(): TypeNode { - return parseUnionOrIntersectionType(SyntaxKind.UnionType, parseIntersectionTypeOrHigher, SyntaxKind.BarToken); + return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode); } function isStartOfFunctionType(): boolean { @@ -3276,14 +3406,11 @@ namespace ts { } function parseTypeOrTypePredicate(): TypeNode { + const pos = getNodePos(); const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); const type = parseType(); if (typePredicateVariable) { - const node = createNode(SyntaxKind.TypePredicate, typePredicateVariable.pos); - node.assertsModifier = undefined; - node.parameterName = typePredicateVariable; - node.type = type; - return finishNode(node); + return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, typePredicateVariable, type), pos); } else { return type; @@ -3299,11 +3426,11 @@ namespace ts { } function parseAssertsTypePredicate(): TypeNode { - const node = createNode(SyntaxKind.TypePredicate); - node.assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword); - node.parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier(); - node.type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined; - return finishNode(node); + const pos = getNodePos(); + const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword); + const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier(); + const type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined; + return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos); } function parseType(): TypeNode { @@ -3316,17 +3443,16 @@ namespace ts { if (isStartOfFunctionType() || token() === SyntaxKind.NewKeyword) { return parseFunctionOrConstructorType(); } + const pos = getNodePos(); const type = parseUnionTypeOrHigher(); if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) { - const node = createNode(SyntaxKind.ConditionalType, type.pos); - node.checkType = type; // The type following 'extends' is not permitted to be another conditional type - node.extendsType = parseTypeWorker(/*noConditionalTypes*/ true); + const extendsType = parseTypeWorker(/*noConditionalTypes*/ true); parseExpected(SyntaxKind.QuestionToken); - node.trueType = parseTypeWorker(); + const trueType = parseTypeWorker(); parseExpected(SyntaxKind.ColonToken); - node.falseType = parseTypeWorker(); - return finishNode(node); + const falseType = parseTypeWorker(); + return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos); } return type; } @@ -3478,13 +3604,14 @@ namespace ts { // Otherwise, we try to parse out the conditional expression bit. We want to allow any // binary expression here, so we pass in the 'lowest' precedence here so that it matches // and consumes anything. - const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + const pos = getNodePos(); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { - return parseSimpleArrowFunctionExpression(expr); + return parseSimpleArrowFunctionExpression(pos, expr, /*asyncModifier*/ undefined); } // Now see if we might be in cases '2' or '3'. @@ -3535,7 +3662,7 @@ namespace ts { } function parseYieldExpression(): YieldExpression { - const node = createNode(SyntaxKind.YieldExpression); + const pos = getNodePos(); // YieldExpression[In] : // yield @@ -3545,39 +3672,41 @@ namespace ts { if (!scanner.hasPrecedingLineBreak() && (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) { - node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); - node.expression = parseAssignmentExpressionOrHigher(); - return finishNode(node); + return finishNode( + factory.createYield( + parseOptionalToken(SyntaxKind.AsteriskToken), + parseAssignmentExpressionOrHigher() + ), + pos + ); } else { // if the next token is not on the same line as yield. or we don't have an '*' or // the start of an expression, then this is just a simple "yield" expression. - return finishNode(node); + return finishNode(factory.createYield(/*asteriskToken*/ undefined, /*expression*/ undefined), pos); } } - function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray | undefined): ArrowFunction { + function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, asyncModifier?: NodeArray | undefined): ArrowFunction { Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); - let node: ArrowFunction; - if (asyncModifier) { - node = createNode(SyntaxKind.ArrowFunction, asyncModifier.pos); - node.modifiers = asyncModifier; - } - else { - node = createNode(SyntaxKind.ArrowFunction, identifier.pos); - } - - const parameter = createNode(SyntaxKind.Parameter, identifier.pos); - parameter.name = identifier; - finishNode(parameter); - - node.parameters = createNodeArray([parameter], parameter.pos, parameter.end); + const parameter = factory.createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + identifier, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ); + finishNode(parameter, identifier.pos); - node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); - node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); + const parameters = createNodeArray([parameter], parameter.pos, parameter.end); + const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); + const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); + const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body); - return addJSDocComment(finishNode(node)); + return addJSDocComment(finishNode(node, pos)); } function tryParseParenthesizedArrowFunctionExpression(): Expression | undefined { @@ -3591,6 +3720,8 @@ namespace ts { // following => or { token. Otherwise, we *might* have an arrow function. Try to parse // it out, but don't allow any ambiguity, and return 'undefined' if this could be an // expression instead. + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); const arrowFunction = triState === Tristate.True ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead); @@ -3600,17 +3731,19 @@ namespace ts { return undefined; } - const isAsync = hasModifier(arrowFunction, ModifierFlags.Async); + const { modifiers, typeParameters, parameters, type } = arrowFunction; + const isAsync = some(modifiers, isAsyncModifier); // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. const lastToken = token(); - arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); - arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) + const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); + const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) ? parseArrowFunctionExpressionBody(isAsync) : parseIdentifier(); - return finishNode(arrowFunction); + const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body); + return withJSDoc(finishNode(node, pos), hasJSDoc); } // True -> We definitely expect a parenthesized arrow function here. @@ -3725,7 +3858,7 @@ namespace ts { } // JSX overrides - if (sourceFile.languageVariant === LanguageVariant.JSX) { + if (languageVariant === LanguageVariant.JSX) { const isArrowFunctionInJsx = lookAhead(() => { const third = nextToken(); if (third === SyntaxKind.ExtendsKeyword) { @@ -3756,7 +3889,7 @@ namespace ts { } } - function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction | undefined { + function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunctionHead | undefined { const tokenPos = scanner.getTokenPos(); if (notParenthesizedArrow && notParenthesizedArrow.has(tokenPos.toString())) { return undefined; @@ -3774,9 +3907,10 @@ namespace ts { // We do a check here so that we won't be doing unnecessarily call to "lookAhead" if (token() === SyntaxKind.AsyncKeyword) { if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) { + const pos = getNodePos(); const asyncModifier = parseModifiersForArrowFunction(); - const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); - return parseSimpleArrowFunctionExpression(expr, asyncModifier); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); + return parseSimpleArrowFunctionExpression(pos, expr, asyncModifier); } } return undefined; @@ -3794,7 +3928,7 @@ namespace ts { return Tristate.False; } // Check for un-parenthesized AsyncArrowFunction - const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { return Tristate.True; } @@ -3803,10 +3937,16 @@ namespace ts { return Tristate.False; } - function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction | undefined { - const node = createNodeWithJSDoc(SyntaxKind.ArrowFunction); - node.modifiers = parseModifiersForArrowFunction(); - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; + interface ArrowFunctionHead extends SignatureInfo { + modifiers?: ModifiersArray; + typeParameters?: NodeArray; + parameters: NodeArray; + type?: TypeNode; + } + + function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunctionHead | undefined { + const modifiers = parseModifiersForArrowFunction(); + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -3814,10 +3954,13 @@ namespace ts { // a => (b => c) // And think that "(b =>" was actually a parenthesized arrow function with a missing // close paren. - if (!fillSignature(SyntaxKind.ColonToken, isAsync, node) && !allowAmbiguity) { + const signature = parseSignature(SyntaxKind.ColonToken, isAsync); + if (!signature.parametersParsedSuccessfully && !allowAmbiguity) { return undefined; } + const { typeParameters, parameters, type } = signature; + // Parsing a signature isn't enough. // Parenthesized arrow signatures often look like other valid expressions. // For instance: @@ -3827,13 +3970,13 @@ namespace ts { // - "a ? (b): function() {}" will too, since function() is a valid JSDoc function type. // // So we need just a bit of lookahead to ensure that it can only be a signature. - const hasJSDocFunctionType = node.type && isJSDocFunctionType(node.type); + const hasJSDocFunctionType = type && isJSDocFunctionType(type); if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) { // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } - return node; + return { modifiers, typeParameters, parameters, type }; } function parseArrowFunctionExpressionBody(isAsync: boolean): Block | Expression { @@ -3877,18 +4020,22 @@ namespace ts { // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and // we do not that for the 'whenFalse' part. - const node = createNode(SyntaxKind.ConditionalExpression, leftOperand.pos); - node.condition = leftOperand; - node.questionToken = questionToken; - node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher); - node.colonToken = parseExpectedToken(SyntaxKind.ColonToken); - node.whenFalse = nodeIsPresent(node.colonToken) - ? parseAssignmentExpressionOrHigher() - : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)); - return finishNode(node); - } - - function parseBinaryExpressionOrHigher(precedence: number): Expression { + let colonToken; + return finishNode( + factory.createConditional( + leftOperand, + questionToken, + doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher), + colonToken = parseExpectedToken(SyntaxKind.ColonToken), + nodeIsPresent(colonToken) + ? parseAssignmentExpressionOrHigher() + : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)) + ), + leftOperand.pos + ); + } + + function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): Expression { const leftOperand = parseUnaryExpressionOrHigher(); return parseBinaryExpressionRest(precedence, leftOperand); } @@ -3897,7 +4044,7 @@ namespace ts { return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword; } - function parseBinaryExpressionRest(precedence: number, leftOperand: Expression): Expression { + function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression): Expression { while (true) { // We either have a binary operator here, or we're finished. We call // reScanGreaterToken so that we merge token sequences like > and = into >= @@ -3969,48 +4116,31 @@ namespace ts { } function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression): BinaryExpression { - const node = createNode(SyntaxKind.BinaryExpression, left.pos); - node.left = left; - node.operatorToken = operatorToken; - node.right = right; - return finishNode(node); + return finishNode(factory.createBinary(left, operatorToken, right), left.pos); } function makeAsExpression(left: Expression, right: TypeNode): AsExpression { - const node = createNode(SyntaxKind.AsExpression, left.pos); - node.expression = left; - node.type = right; - return finishNode(node); + return finishNode(factory.createAsExpression(left, right), left.pos); } function parsePrefixUnaryExpression() { - const node = createNode(SyntaxKind.PrefixUnaryExpression); - node.operator = token(); - nextToken(); - node.operand = parseSimpleUnaryExpression(); - - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createPrefix(token(), nextTokenAnd(parseSimpleUnaryExpression)), pos); } function parseDeleteExpression() { - const node = createNode(SyntaxKind.DeleteExpression); - nextToken(); - node.expression = parseSimpleUnaryExpression(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createDelete(nextTokenAnd(parseSimpleUnaryExpression)), pos); } function parseTypeOfExpression() { - const node = createNode(SyntaxKind.TypeOfExpression); - nextToken(); - node.expression = parseSimpleUnaryExpression(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createTypeOf(nextTokenAnd(parseSimpleUnaryExpression)), pos); } function parseVoidExpression() { - const node = createNode(SyntaxKind.VoidExpression); - nextToken(); - node.expression = parseSimpleUnaryExpression(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createVoid(nextTokenAnd(parseSimpleUnaryExpression)), pos); } function isAwaitExpression(): boolean { @@ -4027,10 +4157,8 @@ namespace ts { } function parseAwaitExpression() { - const node = createNode(SyntaxKind.AwaitExpression); - nextToken(); - node.expression = parseSimpleUnaryExpression(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createAwait(nextTokenAnd(parseSimpleUnaryExpression)), pos); } /** @@ -4150,7 +4278,7 @@ namespace ts { return false; case SyntaxKind.LessThanToken: // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression - if (sourceFile.languageVariant !== LanguageVariant.JSX) { + if (languageVariant !== LanguageVariant.JSX) { return false; } // We are in JSX context and the token is part of JSXElement. @@ -4173,13 +4301,10 @@ namespace ts { */ function parseUpdateExpression(): UpdateExpression { if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) { - const node = createNode(SyntaxKind.PrefixUnaryExpression); - node.operator = token(); - nextToken(); - node.operand = parseLeftHandSideExpressionOrHigher(); - return finishNode(node); + const pos = getNodePos(); + return finishNode(factory.createPrefix(token(), nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); } - else if (sourceFile.languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { // JSXElement is part of primaryExpression return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } @@ -4188,11 +4313,9 @@ namespace ts { Debug.assert(isLeftHandSideExpression(expression)); if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { - const node = createNode(SyntaxKind.PostfixUnaryExpression, expression.pos); - node.operand = expression; - node.operator = token(); + const operator = token(); nextToken(); - return finishNode(node); + return finishNode(factory.createPostfix(expression, operator), expression.pos); } return expression; @@ -4230,6 +4353,7 @@ namespace ts { // the last two CallExpression productions. 2) We see 'import' which must start import call. // 3)we have a MemberExpression which either completes the LeftHandSideExpression, // or starts the beginning of the first four CallExpression productions. + const pos = getNodePos(); let expression: MemberExpression; if (token() === SyntaxKind.ImportKeyword) { if (lookAhead(nextTokenIsOpenParenOrLessThan)) { @@ -4238,20 +4362,15 @@ namespace ts { // var foo3 = require("subfolder // import * as foo1 from "module-from-node // We want this import to be a statement rather than import call expression - sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { // This is an 'import.*' metaproperty (i.e. 'import.meta') - const fullStart = scanner.getStartPos(); nextToken(); // advance past the 'import' nextToken(); // advance past the dot - const node = createNode(SyntaxKind.MetaProperty, fullStart) as MetaProperty; - node.keywordToken = SyntaxKind.ImportKeyword; - node.name = parseIdentifierName(); - expression = finishNode(node); - - sourceFile.flags |= NodeFlags.PossiblyContainsImportMeta; + expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos); + sourceFlags |= NodeFlags.PossiblyContainsImportMeta; } else { expression = parseMemberExpressionOrHigher(); @@ -4264,7 +4383,7 @@ namespace ts { // Now, we *may* be complete. However, we might have consumed the start of a // CallExpression or OptionalExpression. As such, we need to consume the rest // of it here to be complete. - return parseCallExpressionRest(expression); + return parseCallExpressionRest(pos, expression); } function parseMemberExpressionOrHigher(): MemberExpression { @@ -4315,11 +4434,13 @@ namespace ts { // // Because CallExpression and MemberExpression are left recursive, we need to bottom out // of the recursion immediately. So we parse out a primary expression to start with. + const pos = getNodePos(); const expression = parsePrimaryExpression(); - return parseMemberExpressionRest(expression, /*allowOptionalChain*/ true); + return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); } function parseSuperExpression(): MemberExpression { + const pos = getNodePos(); const expression = parseTokenNode(); if (token() === SyntaxKind.LessThanToken) { const startPos = getNodePos(); @@ -4335,36 +4456,26 @@ namespace ts { // If we have seen "super" it must be followed by '(' or '.'. // If it wasn't then just try to parse out a '.' and report an error. - const node = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); - node.expression = expression; parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); - return finishNode(node); + return finishNode(factory.createPropertyAccess(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true)), pos); } function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement | JsxFragment { + const pos = getNodePos(); const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); let result: JsxElement | JsxSelfClosingElement | JsxFragment; if (opening.kind === SyntaxKind.JsxOpeningElement) { - const node = createNode(SyntaxKind.JsxElement, opening.pos); - node.openingElement = opening; + const children = parseJsxChildren(opening); + const closingElement = parseJsxClosingElement(inExpressionContext); - node.children = parseJsxChildren(node.openingElement); - node.closingElement = parseJsxClosingElement(inExpressionContext); - - if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) { - parseErrorAtRange(node.closingElement, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, node.openingElement.tagName)); + if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) { + parseErrorAtRange(closingElement, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName)); } - result = finishNode(node); + result = finishNode(factory.createJsxElement(opening, children, closingElement), pos); } else if (opening.kind === SyntaxKind.JsxOpeningFragment) { - const node = createNode(SyntaxKind.JsxFragment, opening.pos); - node.openingFragment = opening; - node.children = parseJsxChildren(node.openingFragment); - node.closingFragment = parseJsxClosingFragment(inExpressionContext); - - result = finishNode(node); + result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos); } else { Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement); @@ -4383,13 +4494,9 @@ namespace ts { const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true)); if (invalidElement) { parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); - const badNode = createNode(SyntaxKind.BinaryExpression, result.pos); - badNode.end = invalidElement.end; - badNode.left = result; - badNode.right = invalidElement; - badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); - badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos; - return badNode; + const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); + operatorToken.pos = operatorToken.end = invalidElement.pos; + return finishNode(factory.createBinary(result, operatorToken as Token, invalidElement), pos); } } @@ -4397,11 +4504,10 @@ namespace ts { } function parseJsxText(): JsxText { - const node = createNode(SyntaxKind.JsxText); - node.text = scanner.getTokenValue(); - node.containsOnlyTriviaWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces; + const pos = getNodePos(); + const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces); currentToken = scanner.scanJsxToken(); - return finishNode(node); + return finishNode(node, pos); } function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { @@ -4448,21 +4554,19 @@ namespace ts { } function parseJsxAttributes(): JsxAttributes { - const jsxAttributes = createNode(SyntaxKind.JsxAttributes); - jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute); - return finishNode(jsxAttributes); + const pos = getNodePos(); + return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos); } function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { - const fullStart = scanner.getStartPos(); + const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); if (token() === SyntaxKind.GreaterThanToken) { // See below for explanation of scanJsxText - const node: JsxOpeningFragment = createNode(SyntaxKind.JsxOpeningFragment, fullStart); scanJsxText(); - return finishNode(node); + return finishNode(factory.createJsxOpeningFragment(), pos); } const tagName = parseJsxElementName(); @@ -4475,8 +4579,8 @@ namespace ts { // Closing tag, so scan the immediately-following text with the JSX scanning instead // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate // scanning errors - node = createNode(SyntaxKind.JsxOpeningElement, fullStart); scanJsxText(); + node = factory.createJsxOpeningElement(tagName, typeArguments, attributes); } else { parseExpected(SyntaxKind.SlashToken); @@ -4487,17 +4591,14 @@ namespace ts { parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } - node = createNode(SyntaxKind.JsxSelfClosingElement, fullStart); + node = factory.createJsxSelfClosingElement(tagName, typeArguments, attributes); } - node.tagName = tagName; - node.typeArguments = typeArguments; - node.attributes = attributes; - - return finishNode(node); + return finishNode(node, pos); } function parseJsxElementName(): JsxTagNameExpression { + const pos = getNodePos(); scanJsxIdentifier(); // JsxElement can have name in the form of // propertyAccessExpression @@ -4507,27 +4608,25 @@ namespace ts { let expression: JsxTagNameExpression = token() === SyntaxKind.ThisKeyword ? parseTokenNode() : parseIdentifierName(); while (parseOptional(SyntaxKind.DotToken)) { - const propertyAccess: JsxTagNamePropertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); - propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); - expression = finishNode(propertyAccess); + expression = finishNode(factory.createPropertyAccess(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true)), pos) as JsxTagNamePropertyAccess; } return expression; } function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined { - const node = createNode(SyntaxKind.JsxExpression); - + const pos = getNodePos(); if (!parseExpected(SyntaxKind.OpenBraceToken)) { return undefined; } + let dotDotDotToken: DotDotDotToken | undefined; + let expression: Expression | undefined; if (token() !== SyntaxKind.CloseBraceToken) { - node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); + dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // Only an AssignmentExpression is valid here per the JSX spec, // but we can unambiguously parse a comma sequence and provide // a better error message in grammar checking. - node.expression = parseExpression(); + expression = parseExpression(); } if (inExpressionContext) { parseExpected(SyntaxKind.CloseBraceToken); @@ -4538,7 +4637,7 @@ namespace ts { } } - return finishNode(node); + return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos); } function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute { @@ -4547,34 +4646,31 @@ namespace ts { } scanJsxIdentifier(); - const node = createNode(SyntaxKind.JsxAttribute); - node.name = parseIdentifierName(); - if (token() === SyntaxKind.EqualsToken) { - switch (scanJsxAttributeValue()) { - case SyntaxKind.StringLiteral: - node.initializer = parseLiteralNode(); - break; - default: - node.initializer = parseJsxExpression(/*inExpressionContext*/ true); - break; - } - } - return finishNode(node); + const pos = getNodePos(); + return finishNode( + factory.createJsxAttribute( + parseIdentifierName(), + token() !== SyntaxKind.EqualsToken ? undefined : + scanJsxAttributeValue() === SyntaxKind.StringLiteral ? parseLiteralNode() as StringLiteral : + parseJsxExpression(/*inExpressionContext*/ true) + ), + pos + ); } function parseJsxSpreadAttribute(): JsxSpreadAttribute { - const node = createNode(SyntaxKind.JsxSpreadAttribute); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); parseExpected(SyntaxKind.DotDotDotToken); - node.expression = parseExpression(); + const expression = parseExpression(); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(node); + return finishNode(factory.createJsxSpreadAttribute(expression), pos); } function parseJsxClosingElement(inExpressionContext: boolean): JsxClosingElement { - const node = createNode(SyntaxKind.JsxClosingElement); + const pos = getNodePos(); parseExpected(SyntaxKind.LessThanSlashToken); - node.tagName = parseJsxElementName(); + const tagName = parseJsxElementName(); if (inExpressionContext) { parseExpected(SyntaxKind.GreaterThanToken); } @@ -4582,11 +4678,11 @@ namespace ts { parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } - return finishNode(node); + return finishNode(factory.createJsxClosingElement(tagName), pos); } function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { - const node = createNode(SyntaxKind.JsxClosingFragment); + const pos = getNodePos(); parseExpected(SyntaxKind.LessThanSlashToken); if (tokenIsIdentifierOrKeyword(token())) { parseErrorAtRange(parseJsxElementName(), Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment); @@ -4598,16 +4694,16 @@ namespace ts { parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } - return finishNode(node); + return finishNode(factory.createJsxJsxClosingFragment(), pos); } function parseTypeAssertion(): TypeAssertion { - const node = createNode(SyntaxKind.TypeAssertionExpression); + const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); - node.type = parseType(); + const type = parseType(); parseExpected(SyntaxKind.GreaterThanToken); - node.expression = parseSimpleUnaryExpression(); - return finishNode(node); + const expression = parseSimpleUnaryExpression(); + return finishNode(factory.createTypeAssertion(type, expression), pos); } function nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate() { @@ -4622,41 +4718,36 @@ namespace ts { && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate); } - function parsePropertyAccessExpressionRest(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { - const propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos); - propertyAccess.expression = expression; - propertyAccess.questionDotToken = questionDotToken; - propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); - if (questionDotToken || expression.flags & NodeFlags.OptionalChain) { - propertyAccess.flags |= NodeFlags.OptionalChain; - } - return finishNode(propertyAccess); + function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { + const name = parseRightSideOfDot(/*allowIdentifierNames*/ true); + const propertyAccess = questionDotToken || expression.flags & NodeFlags.OptionalChain ? + factory.createPropertyAccessChain(expression, questionDotToken, name) : + factory.createPropertyAccess(expression, name); + return finishNode(propertyAccess, pos); } - function parseElementAccessExpressionRest(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { - const indexedAccess = createNode(SyntaxKind.ElementAccessExpression, expression.pos); - indexedAccess.expression = expression; - indexedAccess.questionDotToken = questionDotToken; - + function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { + let argumentExpression: Expression; if (token() === SyntaxKind.CloseBracketToken) { - indexedAccess.argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument); + argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument); } else { const argument = allowInAnd(parseExpression); if (isStringOrNumericLiteralLike(argument)) { argument.text = internIdentifier(argument.text); } - indexedAccess.argumentExpression = argument; + argumentExpression = argument; } parseExpected(SyntaxKind.CloseBracketToken); - if (questionDotToken || expression.flags & NodeFlags.OptionalChain) { - indexedAccess.flags |= NodeFlags.OptionalChain; - } - return finishNode(indexedAccess); + + const indexedAccess = questionDotToken || expression.flags & NodeFlags.OptionalChain ? + factory.createElementAccessChain(expression, questionDotToken, argumentExpression) : + factory.createElementAccess(expression, argumentExpression); + return finishNode(indexedAccess, pos); } - function parseMemberExpressionRest(expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { + function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { while (true) { let questionDotToken: QuestionDotToken | undefined; let isPropertyAccess = false; @@ -4669,26 +4760,24 @@ namespace ts { } if (isPropertyAccess) { - expression = parsePropertyAccessExpressionRest(expression, questionDotToken); + expression = parsePropertyAccessExpressionRest(pos, expression, questionDotToken); continue; } if (!questionDotToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { nextToken(); - const nonNullExpression = createNode(SyntaxKind.NonNullExpression, expression.pos); - nonNullExpression.expression = expression; - expression = finishNode(nonNullExpression); + expression = finishNode(factory.createNonNullExpression(expression), pos); continue; } // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName if ((questionDotToken || !inDecoratorContext()) && parseOptional(SyntaxKind.OpenBracketToken)) { - expression = parseElementAccessExpressionRest(expression, questionDotToken); + expression = parseElementAccessExpressionRest(pos, expression, questionDotToken); continue; } if (isTemplateStartOfTaggedTemplate()) { - expression = parseTaggedTemplateRest(expression, questionDotToken, /*typeArguments*/ undefined); + expression = parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); continue; } @@ -4700,25 +4789,24 @@ namespace ts { return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; } - function parseTaggedTemplateRest(tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined) { - const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, tag.pos); - tagExpression.tag = tag; - tagExpression.questionDotToken = questionDotToken; - tagExpression.typeArguments = typeArguments; - tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral - ? parseLiteralNode() - : parseTemplateExpression(); + function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined) { + const tagExpression = factory.createTaggedTemplate( + tag, + typeArguments, + token() === SyntaxKind.NoSubstitutionTemplateLiteral ? parseLiteralNode() as NoSubstitutionTemplateLiteral : + parseTemplateExpression() + ); if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { tagExpression.flags |= NodeFlags.OptionalChain; } - return finishNode(tagExpression); + factory.trackExtraneousChildNode(tagExpression, tagExpression.questionDotToken = questionDotToken); + return finishNode(tagExpression, pos); } - function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { + function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { - expression = parseMemberExpressionRest(expression, /*allowOptionalChain*/ true); + expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken); - // handle 'foo<()' if (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken) { // See if this is the start of a generic invocation. If so, consume it and @@ -4728,41 +4816,30 @@ namespace ts { const typeArguments = tryParse(parseTypeArgumentsInExpression); if (typeArguments) { if (isTemplateStartOfTaggedTemplate()) { - expression = parseTaggedTemplateRest(expression, questionDotToken, typeArguments); + expression = parseTaggedTemplateRest(pos, expression, questionDotToken, typeArguments); continue; } - const callExpr = createNode(SyntaxKind.CallExpression, expression.pos); - callExpr.expression = expression; - callExpr.questionDotToken = questionDotToken; - callExpr.typeArguments = typeArguments; - callExpr.arguments = parseArgumentList(); - if (questionDotToken || expression.flags & NodeFlags.OptionalChain) { - callExpr.flags |= NodeFlags.OptionalChain; - } - expression = finishNode(callExpr); + const argumentList = parseArgumentList(); + const callExpr = questionDotToken || expression.flags & NodeFlags.OptionalChain ? + factory.createCallChain(expression, questionDotToken, typeArguments, argumentList) : + factory.createCall(expression, typeArguments, argumentList); + expression = finishNode(callExpr, pos); continue; } } else if (token() === SyntaxKind.OpenParenToken) { - const callExpr = createNode(SyntaxKind.CallExpression, expression.pos); - callExpr.expression = expression; - callExpr.questionDotToken = questionDotToken; - callExpr.arguments = parseArgumentList(); - if (questionDotToken || expression.flags & NodeFlags.OptionalChain) { - callExpr.flags |= NodeFlags.OptionalChain; - } - expression = finishNode(callExpr); + const argumentList = parseArgumentList(); + const callExpr = questionDotToken || expression.flags & NodeFlags.OptionalChain ? + factory.createCallChain(expression, questionDotToken, /*typeArguments*/ undefined, argumentList) : + factory.createCall(expression, /*typeArguments*/ undefined, argumentList); + expression = finishNode(callExpr, pos); continue; } if (questionDotToken) { // We failed to parse anything, so report a missing identifier here. - const propertyAccess = createNode(SyntaxKind.PropertyAccessExpression, expression.pos) as PropertyAccessExpression; - propertyAccess.expression = expression; - propertyAccess.questionDotToken = questionDotToken; - propertyAccess.name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); - propertyAccess.flags |= NodeFlags.OptionalChain; - expression = finishNode(propertyAccess); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); + expression = finishNode(factory.createPropertyAccessChain(expression, questionDotToken, name), pos); } break; } @@ -4886,23 +4963,24 @@ namespace ts { } function parseParenthesizedExpression(): ParenthesizedExpression { - const node = createNodeWithJSDoc(SyntaxKind.ParenthesizedExpression); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - return finishNode(node); + return withJSDoc(finishNode(factory.createParen(expression), pos), hasJSDoc); } function parseSpreadElement(): Expression { - const node = createNode(SyntaxKind.SpreadElement); + const pos = getNodePos(); parseExpected(SyntaxKind.DotDotDotToken); - node.expression = parseAssignmentExpressionOrHigher(); - return finishNode(node); + const expression = parseAssignmentExpressionOrHigher(); + return finishNode(factory.createSpread(expression), pos); } function parseArgumentOrArrayLiteralElement(): Expression { return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() : - token() === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : + token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : parseAssignmentExpressionOrHigher(); } @@ -4911,44 +4989,43 @@ namespace ts { } function parseArrayLiteralExpression(): ArrayLiteralExpression { - const node = createNode(SyntaxKind.ArrayLiteralExpression); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBracketToken); - if (scanner.hasPrecedingLineBreak()) { - node.multiLine = true; - } - node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement); + const multiLine = scanner.hasPrecedingLineBreak(); + const elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement); parseExpected(SyntaxKind.CloseBracketToken); - return finishNode(node); + return finishNode(factory.createArrayLiteral(elements, multiLine), pos); } function parseObjectLiteralElement(): ObjectLiteralElementLike { - const node = createNodeWithJSDoc(SyntaxKind.Unknown); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); if (parseOptionalToken(SyntaxKind.DotDotDotToken)) { - node.kind = SyntaxKind.SpreadAssignment; - (node).expression = parseAssignmentExpressionOrHigher(); - return finishNode(node); + const expression = parseAssignmentExpressionOrHigher(); + return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc); } - node.decorators = parseDecorators(); - node.modifiers = parseModifiers(); + const decorators = parseDecorators(); + const modifiers = parseModifiers(); if (parseContextualModifier(SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(node, SyntaxKind.GetAccessor); + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor); } if (parseContextualModifier(SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(node, SyntaxKind.SetAccessor); + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor); } const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const tokenIsIdentifier = isIdentifier(); - node.name = parsePropertyName(); + const name = parsePropertyName(); + // Disallowing of optional property assignments and definite assignment assertion happens in the grammar checker. - (node).questionToken = parseOptionalToken(SyntaxKind.QuestionToken); - (node).exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken); if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - return parseMethodDeclaration(node, asteriskToken); + return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, exclamationToken); } // check if it is short-hand property assignment or normal property assignment @@ -4956,33 +5033,38 @@ namespace ts { // CoverInitializedName[Yield] : // IdentifierReference[?Yield] Initializer[In, ?Yield] // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern + let node: ShorthandPropertyAssignment | PropertyAssignment; const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken); if (isShorthandPropertyAssignment) { - node.kind = SyntaxKind.ShorthandPropertyAssignment; const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken); - if (equalsToken) { - (node).equalsToken = equalsToken; - (node).objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher); - } + const objectAssignmentInitializer = equalsToken ? allowInAnd(parseAssignmentExpressionOrHigher) : undefined; + node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer); + // Save equals token for error reporting. + // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful. + if (equalsToken) factory.trackExtraneousChildNode(node, node.equalsToken = equalsToken); } else { - node.kind = SyntaxKind.PropertyAssignment; parseExpected(SyntaxKind.ColonToken); - (node).initializer = allowInAnd(parseAssignmentExpressionOrHigher); + const initializer = allowInAnd(parseAssignmentExpressionOrHigher); + node = factory.createPropertyAssignment(name, initializer); } - return finishNode(node); + // Decorators, Modifiers, questionToken, and exclamationToken are not supported by property assignments and are reported in the grammar checker + if (decorators) factory.trackExtraneousChildNodes(node, node.decorators = decorators); + // TODO(rbuckton): Use this instead... + // if (modifiers) factory.trackExtraneousChildNodes(node, node.modifiers = modifiers); + if (modifiers) node.modifiers = modifiers; + if (questionToken) factory.trackExtraneousChildNode(node, node.questionToken = questionToken); + if (exclamationToken) factory.trackExtraneousChildNode(node, node.exclamationToken = exclamationToken); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseObjectLiteralExpression(): ObjectLiteralExpression { - const node = createNode(SyntaxKind.ObjectLiteralExpression); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); - if (scanner.hasPrecedingLineBreak()) { - node.multiLine = true; - } - - node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); + const multiLine = scanner.hasPrecedingLineBreak(); + const properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(node); + return finishNode(factory.createObjectLiteral(properties, multiLine), pos); } function parseFunctionExpression(): FunctionExpression { @@ -4996,27 +5078,28 @@ namespace ts { setDecoratorContext(/*val*/ false); } - const node = createNodeWithJSDoc(SyntaxKind.FunctionExpression); - node.modifiers = parseModifiers(); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + const modifiers = parseModifiers(); parseExpected(SyntaxKind.FunctionKeyword); - node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); - - const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; - node.name = + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); + const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : isAsync ? doInAwaitContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); - node.body = parseFunctionBlock(isGenerator | isAsync); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, isGenerator | isAsync); + const body = parseFunctionBlock(isGenerator | isAsync); if (saveDecoratorContext) { setDecoratorContext(/*val*/ true); } - return finishNode(node); + const node = factory.createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseOptionalIdentifier(): Identifier | undefined { @@ -5024,53 +5107,45 @@ namespace ts { } function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty { - const fullStart = scanner.getStartPos(); + const pos = getNodePos(); parseExpected(SyntaxKind.NewKeyword); if (parseOptional(SyntaxKind.DotToken)) { - const node = createNode(SyntaxKind.MetaProperty, fullStart); - node.keywordToken = SyntaxKind.NewKeyword; - node.name = parseIdentifierName(); - return finishNode(node); + const name = parseIdentifierName(); + return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos); } + const expressionPos = getNodePos(); let expression: MemberExpression = parsePrimaryExpression(); let typeArguments; while (true) { - expression = parseMemberExpressionRest(expression, /*allowOptionalChain*/ false); + expression = parseMemberExpressionRest(expressionPos, expression, /*allowOptionalChain*/ false); typeArguments = tryParse(parseTypeArgumentsInExpression); if (isTemplateStartOfTaggedTemplate()) { Debug.assert(!!typeArguments, "Expected a type argument list; all plain tagged template starts should be consumed in 'parseMemberExpressionRest'"); - expression = parseTaggedTemplateRest(expression, /*optionalChain*/ undefined, typeArguments); + expression = parseTaggedTemplateRest(expressionPos, expression, /*optionalChain*/ undefined, typeArguments); typeArguments = undefined; } break; } - const node = createNode(SyntaxKind.NewExpression, fullStart); - node.expression = expression; - node.typeArguments = typeArguments; - if (node.typeArguments || token() === SyntaxKind.OpenParenToken) { - node.arguments = parseArgumentList(); - } - return finishNode(node); + const argumentsArray = typeArguments || token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; + return finishNode(factory.createNew(expression, typeArguments, argumentsArray), pos); } // STATEMENTS function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block { - const node = createNode(SyntaxKind.Block); + const pos = getNodePos(); if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) { - if (scanner.hasPrecedingLineBreak()) { - node.multiLine = true; - } - - node.statements = parseList(ParsingContext.BlockStatements, parseStatement); + const multiLine = scanner.hasPrecedingLineBreak(); + const statements = parseList(ParsingContext.BlockStatements, parseStatement); parseExpected(SyntaxKind.CloseBraceToken); + return finishNode(factory.createBlock(statements, multiLine), pos); } else { - node.statements = createMissingList(); + const statements = createMissingList(); + return finishNode(factory.createBlock(statements, /*multiLine*/ undefined), pos); } - return finishNode(node); } function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block { @@ -5100,29 +5175,29 @@ namespace ts { } function parseEmptyStatement(): Statement { - const node = createNode(SyntaxKind.EmptyStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.SemicolonToken); - return finishNode(node); + return finishNode(factory.createEmptyStatement(), pos); } function parseIfStatement(): IfStatement { - const node = createNode(SyntaxKind.IfStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.IfKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - node.thenStatement = parseStatement(); - node.elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined; - return finishNode(node); + const thenStatement = parseStatement(); + const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined; + return finishNode(factory.createIf(expression, thenStatement, elseStatement), pos); } function parseDoStatement(): DoStatement { - const node = createNode(SyntaxKind.DoStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.DoKeyword); - node.statement = parseStatement(); + const statement = parseStatement(); parseExpected(SyntaxKind.WhileKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html @@ -5130,17 +5205,17 @@ namespace ts { // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby // do;while(0)x will have a semicolon inserted before x. parseOptional(SyntaxKind.SemicolonToken); - return finishNode(node); + return finishNode(factory.createDo(statement, expression), pos); } function parseWhileStatement(): WhileStatement { - const node = createNode(SyntaxKind.WhileStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.WhileKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - node.statement = parseStatement(); - return finishNode(node); + const statement = parseStatement(); + return finishNode(factory.createWhile(expression, statement), pos); } function parseForOrForInOrForOfStatement(): Statement { @@ -5158,109 +5233,102 @@ namespace ts { initializer = disallowInAnd(parseExpression); } } - let forOrForInOrForOfStatement: IterationStatement; + + let node: IterationStatement; if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { - const forOfStatement = createNode(SyntaxKind.ForOfStatement, pos); - forOfStatement.awaitModifier = awaitToken; - forOfStatement.initializer = initializer; - forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher); + const expression = allowInAnd(parseAssignmentExpressionOrHigher); parseExpected(SyntaxKind.CloseParenToken); - forOrForInOrForOfStatement = forOfStatement; + node = factory.createForOf(awaitToken, initializer, expression, parseStatement()); } else if (parseOptional(SyntaxKind.InKeyword)) { - const forInStatement = createNode(SyntaxKind.ForInStatement, pos); - forInStatement.initializer = initializer; - forInStatement.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - forOrForInOrForOfStatement = forInStatement; + node = factory.createForIn(initializer, expression, parseStatement()); } else { - const forStatement = createNode(SyntaxKind.ForStatement, pos); - forStatement.initializer = initializer; parseExpected(SyntaxKind.SemicolonToken); - if (token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken) { - forStatement.condition = allowInAnd(parseExpression); - } + const condition = token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken + ? allowInAnd(parseExpression) + : undefined; parseExpected(SyntaxKind.SemicolonToken); - if (token() !== SyntaxKind.CloseParenToken) { - forStatement.incrementor = allowInAnd(parseExpression); - } + const incrementor = token() !== SyntaxKind.CloseParenToken + ? allowInAnd(parseExpression) + : undefined; parseExpected(SyntaxKind.CloseParenToken); - forOrForInOrForOfStatement = forStatement; + node = factory.createFor(initializer, condition, incrementor, parseStatement()); } - forOrForInOrForOfStatement.statement = parseStatement(); - - return finishNode(forOrForInOrForOfStatement); + return finishNode(node, pos); } function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement { - const node = createNode(kind); + const pos = getNodePos(); parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword); - if (!canParseSemicolon()) { - node.label = parseIdentifier(); - } + const label = canParseSemicolon() ? undefined : parseIdentifier(); parseSemicolon(); - return finishNode(node); + const node = kind === SyntaxKind.BreakStatement + ? factory.createBreak(label) + : factory.createContinue(label); + return finishNode(node, pos); } function parseReturnStatement(): ReturnStatement { - const node = createNode(SyntaxKind.ReturnStatement); - + const pos = getNodePos(); parseExpected(SyntaxKind.ReturnKeyword); - if (!canParseSemicolon()) { - node.expression = allowInAnd(parseExpression); - } - + const expression = canParseSemicolon() ? undefined : allowInAnd(parseExpression); parseSemicolon(); - return finishNode(node); + return finishNode(factory.createReturn(expression), pos); } function parseWithStatement(): WithStatement { - const node = createNode(SyntaxKind.WithStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.WithKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - node.statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement); - return finishNode(node); + const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement); + return finishNode(factory.createWith(expression, statement), pos); } function parseCaseClause(): CaseClause { - const node = createNode(SyntaxKind.CaseClause); + const pos = getNodePos(); parseExpected(SyntaxKind.CaseKeyword); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.ColonToken); - node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); - return finishNode(node); + const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); + return finishNode(factory.createCaseClause(expression, statements), pos); } function parseDefaultClause(): DefaultClause { - const node = createNode(SyntaxKind.DefaultClause); + const pos = getNodePos(); parseExpected(SyntaxKind.DefaultKeyword); parseExpected(SyntaxKind.ColonToken); - node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); - return finishNode(node); + const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); + return finishNode(factory.createDefaultClause(statements), pos); } function parseCaseOrDefaultClause(): CaseOrDefaultClause { return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause(); } + function parseCaseBlock(): CaseBlock { + const pos = getNodePos(); + parseExpected(SyntaxKind.OpenBraceToken); + const clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause); + parseExpected(SyntaxKind.CloseBraceToken); + return finishNode(factory.createCaseBlock(clauses), pos); + } + function parseSwitchStatement(): SwitchStatement { - const node = createNode(SyntaxKind.SwitchStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.SwitchKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = allowInAnd(parseExpression); + const expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); - const caseBlock = createNode(SyntaxKind.CaseBlock); - parseExpected(SyntaxKind.OpenBraceToken); - caseBlock.clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause); - parseExpected(SyntaxKind.CloseBraceToken); - node.caseBlock = finishNode(caseBlock); - return finishNode(node); + const caseBlock = parseCaseBlock(); + return finishNode(factory.createSwitch(expression, caseBlock), pos); } function parseThrowStatement(): ThrowStatement { @@ -5272,72 +5340,73 @@ namespace ts { // directly as that might consume an expression on the following line. // We just return 'undefined' in that case. The actual error will be reported in the // grammar walker. - const node = createNode(SyntaxKind.ThrowStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.ThrowKeyword); - node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); + const expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); parseSemicolon(); - return finishNode(node); + return finishNode(factory.createThrow(expression!), pos); } // TODO: Review for error recovery function parseTryStatement(): TryStatement { - const node = createNode(SyntaxKind.TryStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.TryKeyword); - node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); - node.catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; + const tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); + const catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. - if (!node.catchClause || token() === SyntaxKind.FinallyKeyword) { + let finallyBlock: Block | undefined; + if (!catchClause || token() === SyntaxKind.FinallyKeyword) { parseExpected(SyntaxKind.FinallyKeyword); - node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); + finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); } - return finishNode(node); + return finishNode(factory.createTry(tryBlock, catchClause, finallyBlock), pos); } function parseCatchClause(): CatchClause { - const result = createNode(SyntaxKind.CatchClause); + const pos = getNodePos(); parseExpected(SyntaxKind.CatchKeyword); + let variableDeclaration; if (parseOptional(SyntaxKind.OpenParenToken)) { - result.variableDeclaration = parseVariableDeclaration(); + variableDeclaration = parseVariableDeclaration(); parseExpected(SyntaxKind.CloseParenToken); } else { // Keep shape of node to avoid degrading performance. - result.variableDeclaration = undefined; + variableDeclaration = undefined; } - result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); - return finishNode(result); + const block = parseBlock(/*ignoreMissingOpenBrace*/ false); + return finishNode(factory.createCatchClause(variableDeclaration, block), pos); } function parseDebuggerStatement(): Statement { - const node = createNode(SyntaxKind.DebuggerStatement); + const pos = getNodePos(); parseExpected(SyntaxKind.DebuggerKeyword); parseSemicolon(); - return finishNode(node); + return finishNode(factory.createDebuggerStatement(), pos); } function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement { // Avoiding having to do the lookahead for a labeled statement by just trying to parse // out an expression, seeing if it is identifier and then seeing if it is followed by // a colon. - const node = createNodeWithJSDoc(SyntaxKind.Unknown); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + let node: ExpressionStatement | LabeledStatement; const expression = allowInAnd(parseExpression); if (expression.kind === SyntaxKind.Identifier && parseOptional(SyntaxKind.ColonToken)) { - node.kind = SyntaxKind.LabeledStatement; - (node).label = expression; - (node).statement = parseStatement(); + node = factory.createLabel(expression as Identifier, parseStatement()); } else { - node.kind = SyntaxKind.ExpressionStatement; - (node).expression = expression; parseSemicolon(); + node = factory.createExpressionStatement(expression); } - return finishNode(node); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function nextTokenIsIdentifierOrKeywordOnSameLine() { @@ -5520,16 +5589,16 @@ namespace ts { case SyntaxKind.OpenBraceToken: return parseBlock(/*ignoreMissingOpenBrace*/ false); case SyntaxKind.VarKeyword: - return parseVariableStatement(createNodeWithJSDoc(SyntaxKind.VariableDeclaration)); + return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); case SyntaxKind.LetKeyword: if (isLetDeclaration()) { - return parseVariableStatement(createNodeWithJSDoc(SyntaxKind.VariableDeclaration)); + return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); } break; case SyntaxKind.FunctionKeyword: - return parseFunctionDeclaration(createNodeWithJSDoc(SyntaxKind.FunctionDeclaration)); + return parseFunctionDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); case SyntaxKind.ClassKeyword: - return parseClassDeclaration(createNodeWithJSDoc(SyntaxKind.ClassDeclaration)); + return parseClassDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); case SyntaxKind.IfKeyword: return parseIfStatement(); case SyntaxKind.DoKeyword: @@ -5590,11 +5659,13 @@ namespace ts { } function parseDeclaration(): Statement { - const modifiers = lookAhead(() => (parseDecorators(), parseModifiers())); + // TODO: Can we hold onto the parsed decorators/modifiers and advance the scanner + // if we can't reuse the declaration, so that we don't do this work twice? + // // `parseListElement` attempted to get the reused node at this position, // but the ambient context flag was not yet set, so the node appeared // not reusable in that context. - const isAmbient = some(modifiers, isDeclareModifier); + const isAmbient = some(lookAhead(() => (parseDecorators(), parseModifiers())), isDeclareModifier); if (isAmbient) { const node = tryReuseAmbientDeclaration(); if (node) { @@ -5602,17 +5673,18 @@ namespace ts { } } - const node = createNodeWithJSDoc(SyntaxKind.Unknown); - node.decorators = parseDecorators(); - node.modifiers = parseModifiers(); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + const decorators = parseDecorators(); + const modifiers = parseModifiers(); if (isAmbient) { - for (const m of node.modifiers!) { + for (const m of modifiers!) { m.flags |= NodeFlags.Ambient; } - return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(node)); + return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers)); } else { - return parseDeclarationWorker(node); + return parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers); } } @@ -5625,48 +5697,48 @@ namespace ts { }); } - function parseDeclarationWorker(node: Statement): Statement { + function parseDeclarationWorker(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): Statement { switch (token()) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: case SyntaxKind.ConstKeyword: - return parseVariableStatement(node); + return parseVariableStatement(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.FunctionKeyword: - return parseFunctionDeclaration(node); + return parseFunctionDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.ClassKeyword: - return parseClassDeclaration(node); + return parseClassDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.InterfaceKeyword: - return parseInterfaceDeclaration(node); + return parseInterfaceDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.TypeKeyword: - return parseTypeAliasDeclaration(node); + return parseTypeAliasDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.EnumKeyword: - return parseEnumDeclaration(node); + return parseEnumDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.GlobalKeyword: case SyntaxKind.ModuleKeyword: case SyntaxKind.NamespaceKeyword: - return parseModuleDeclaration(node); + return parseModuleDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.ImportKeyword: - return parseImportDeclarationOrImportEqualsDeclaration(node); + return parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.ExportKeyword: nextToken(); switch (token()) { case SyntaxKind.DefaultKeyword: case SyntaxKind.EqualsToken: - return parseExportAssignment(node); + return parseExportAssignment(pos, hasJSDoc, decorators, modifiers); case SyntaxKind.AsKeyword: - return parseNamespaceExportDeclaration(node); + return parseNamespaceExportDeclaration(pos, hasJSDoc, decorators, modifiers); default: - return parseExportDeclaration(node); + return parseExportDeclaration(pos, hasJSDoc, decorators, modifiers); } default: - if (node.decorators || node.modifiers) { + if (decorators || modifiers) { // We reached this point because we encountered decorators and/or modifiers and assumed a declaration // would follow. For recovery and error reporting purposes, return an incomplete declaration. const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); - missing.pos = node.pos; - missing.decorators = node.decorators; - missing.modifiers = node.modifiers; - return finishNode(missing); + missing.pos = pos; + missing.decorators = decorators; + missing.modifiers = modifiers; + return missing; } return undefined!; // TODO: GH#18217 } @@ -5689,47 +5761,48 @@ namespace ts { // DECLARATIONS function parseArrayBindingElement(): ArrayBindingElement { + const pos = getNodePos(); if (token() === SyntaxKind.CommaToken) { - return createNode(SyntaxKind.OmittedExpression); + return finishNode(factory.createOmittedExpression(), pos); } - const node = createNode(SyntaxKind.BindingElement); - node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); - node.name = parseIdentifierOrPattern(); - node.initializer = parseInitializer(); - return finishNode(node); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); + const name = parseIdentifierOrPattern(); + const initializer = parseInitializer(); + return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos); } function parseObjectBindingElement(): BindingElement { - const node = createNode(SyntaxKind.BindingElement); - node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); + const pos = getNodePos(); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const tokenIsIdentifier = isIdentifier(); - const propertyName = parsePropertyName(); + let propertyName: PropertyName | undefined = parsePropertyName(); + let name: BindingName; if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) { - node.name = propertyName; + name = propertyName; + propertyName = undefined; } else { parseExpected(SyntaxKind.ColonToken); - node.propertyName = propertyName; - node.name = parseIdentifierOrPattern(); + name = parseIdentifierOrPattern(); } - node.initializer = parseInitializer(); - return finishNode(node); + const initializer = parseInitializer(); + return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos); } function parseObjectBindingPattern(): ObjectBindingPattern { - const node = createNode(SyntaxKind.ObjectBindingPattern); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); - node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement); + const elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(node); + return finishNode(factory.createObjectBindingPattern(elements), pos); } function parseArrayBindingPattern(): ArrayBindingPattern { - const node = createNode(SyntaxKind.ArrayBindingPattern); + const pos = getNodePos(); parseExpected(SyntaxKind.OpenBracketToken); - node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement); + const elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement); parseExpected(SyntaxKind.CloseBracketToken); - return finishNode(node); + return finishNode(factory.createArrayBindingPattern(elements), pos); } function isIdentifierOrPattern() { @@ -5751,30 +5824,31 @@ namespace ts { } function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration { - const node = createNode(SyntaxKind.VariableDeclaration); - node.name = parseIdentifierOrPattern(); - if (allowExclamation && node.name.kind === SyntaxKind.Identifier && + const pos = getNodePos(); + const name = parseIdentifierOrPattern(); + let exclamationToken: ExclamationToken | undefined; + if (allowExclamation && name.kind === SyntaxKind.Identifier && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { - node.exclamationToken = parseTokenNode>(); + exclamationToken = parseTokenNode>(); } - node.type = parseTypeAnnotation(); - if (!isInOrOfKeyword(token())) { - node.initializer = parseInitializer(); - } - return finishNode(node); + const type = parseTypeAnnotation(); + const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer(); + const node = factory.createVariableDeclaration(name, exclamationToken, type, initializer); + return finishNode(node, pos); } function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList { - const node = createNode(SyntaxKind.VariableDeclarationList); + const pos = getNodePos(); + let flags: NodeFlags = 0; switch (token()) { case SyntaxKind.VarKeyword: break; case SyntaxKind.LetKeyword: - node.flags |= NodeFlags.Let; + flags |= NodeFlags.Let; break; case SyntaxKind.ConstKeyword: - node.flags |= NodeFlags.Const; + flags |= NodeFlags.Const; break; default: Debug.fail(); @@ -5791,43 +5865,47 @@ namespace ts { // So we need to look ahead to determine if 'of' should be treated as a keyword in // this context. // The checker will then give an error that there is an empty declaration list. + let declarations; if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) { - node.declarations = createMissingList(); + declarations = createMissingList(); } else { const savedDisallowIn = inDisallowInContext(); setDisallowInContext(inForStatementInitializer); - node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations, + declarations = parseDelimitedList(ParsingContext.VariableDeclarations, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); setDisallowInContext(savedDisallowIn); } - return finishNode(node); + return finishNode(factory.createVariableDeclarationList(declarations, flags), pos); } function canFollowContextualOfKeyword(): boolean { return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken; } - function parseVariableStatement(node: VariableStatement): VariableStatement { - node.kind = SyntaxKind.VariableStatement; - node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); + function parseVariableStatement(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): VariableStatement { + const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); - return finishNode(node); + const node = factory.createVariableStatement(modifiers, declarationList); + // Decorators are not allowed on a variable statement, so we keep track of them to report them in the grammar checker. + if (decorators) factory.trackExtraneousChildNodes(node, node.decorators = decorators); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseFunctionDeclaration(node: FunctionDeclaration): FunctionDeclaration { - node.kind = SyntaxKind.FunctionDeclaration; + function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): FunctionDeclaration { + const modifierFlags = modifiersToFlags(modifiers); parseExpected(SyntaxKind.FunctionKeyword); - node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); - node.name = hasModifier(node, ModifierFlags.Default) ? parseOptionalIdentifier() : parseIdentifier(); - const isGenerator = node.asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; - fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); - node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected); - return finishNode(node); + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); + const name = modifierFlags & ModifierFlags.Default ? parseOptionalIdentifier() : parseIdentifier(); + const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; + const isAsync = modifierFlags & ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None; + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, isGenerator | isAsync); + const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected); + const node = factory.createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseConstructorName() { @@ -5842,57 +5920,96 @@ namespace ts { } } - function tryParseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration | undefined { + function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ConstructorDeclaration | undefined { return tryParse(() => { if (parseConstructorName()) { - node.kind = SyntaxKind.Constructor; - fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node); - node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected); - return finishNode(node); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, SignatureFlags.None); + const body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected); + const node = factory.createConstructorDeclaration(decorators, modifiers, parameters, body); + // Attach `typeParameters` and `type` if they exist so that we can report them in the grammar checker. + if (typeParameters) factory.trackExtraneousChildNodes(node, node.typeParameters = typeParameters); + if (type) factory.trackExtraneousChildNode(node, node.type = type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } }); } - function parseMethodDeclaration(node: MethodDeclaration, asteriskToken: AsteriskToken, diagnosticMessage?: DiagnosticMessage): MethodDeclaration { - node.kind = SyntaxKind.MethodDeclaration; - node.asteriskToken = asteriskToken; + function parseMethodDeclaration( + pos: number, + hasJSDoc: boolean, + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + exclamationToken: ExclamationToken | undefined, + diagnosticMessage?: DiagnosticMessage + ): MethodDeclaration { const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; - fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); - node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); - return finishNode(node); - } - - function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration { - node.kind = SyntaxKind.PropertyDeclaration; - if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { - node.exclamationToken = parseTokenNode>(); - } - node.type = parseTypeAnnotation(); - node.initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer); - + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, isGenerator | isAsync); + const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); + const node = factory.createMethodDeclaration( + decorators, + modifiers, + asteriskToken, + name, + questionToken, + typeParameters, + parameters, + type, + body + ); + // An exclamation token on a method is invalid syntax and will be handled by the grammar checker + if (exclamationToken) factory.trackExtraneousChildNode(node, node.exclamationToken = exclamationToken); + + return withJSDoc(finishNode(node, pos), hasJSDoc); + } + + function parsePropertyDeclaration( + pos: number, + hasJSDoc: boolean, + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined + ): PropertyDeclaration { + const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined; + const type = parseTypeAnnotation(); + const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer); parseSemicolon(); - return finishNode(node); + const node = factory.createPropertyDeclaration(decorators, modifiers, name, questionToken || exclamationToken, type, initializer); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parsePropertyOrMethodDeclaration(node: PropertyDeclaration | MethodDeclaration): PropertyDeclaration | MethodDeclaration { + function parsePropertyOrMethodDeclaration( + pos: number, + hasJSDoc: boolean, + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined + ): PropertyDeclaration | MethodDeclaration { const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); - node.name = parsePropertyName(); + const name = parsePropertyName(); // Note: this is not legal as per the grammar. But we allow it in the parser and // report an error in the grammar checker. - node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - return parseMethodDeclaration(node, asteriskToken, Diagnostics.or_expected); + return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, Diagnostics.or_expected); } - return parsePropertyDeclaration(node); + return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, questionToken); } - function parseAccessorDeclaration(node: AccessorDeclaration, kind: AccessorDeclaration["kind"]): AccessorDeclaration { - node.kind = kind; - node.name = parsePropertyName(); - fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node); - node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None); - return finishNode(node); + function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"]): AccessorDeclaration { + const name = parsePropertyName(); + const { typeParameters, parameters, type } = parseSignature(SyntaxKind.ColonToken, SignatureFlags.None); + const body = parseFunctionBlockOrSemicolon(SignatureFlags.None); + const node = kind === SyntaxKind.GetAccessor + ? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body) + : factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body); + // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors + if (typeParameters) factory.trackExtraneousChildNodes(node, node.typeParameters = typeParameters); + if (type && kind === SyntaxKind.SetAccessor) factory.trackExtraneousChildNode(node, node.type = type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function isClassMemberStart(): boolean { @@ -5964,20 +6081,42 @@ namespace ts { return false; } + function tryParseDecorator(): Decorator | undefined { + const pos = getNodePos(); + if (!parseOptional(SyntaxKind.AtToken)) { + return undefined; + } + const expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); + return finishNode(factory.createDecorator(expression), pos); + } + function parseDecorators(): NodeArray | undefined { - let list: Decorator[] | undefined; - const listPos = getNodePos(); - while (true) { - const decoratorStart = getNodePos(); - if (!parseOptional(SyntaxKind.AtToken)) { - break; + const pos = getNodePos(); + let list, decorator; + while (decorator = tryParseDecorator()) { + list = append(list, decorator); + } + return list && createNodeArray(list, pos); + } + + function tryParseModifier(permitInvalidConstAsModifier?: boolean): Modifier | undefined { + const pos = getNodePos(); + const kind = token(); + + if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) { + // We need to ensure that any subsequent modifiers appear on the same line + // so that when 'const' is a standalone declaration, we don't issue an error. + if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { + return undefined; + } + } + else { + if (!parseAnyContextualModifier()) { + return undefined; } - const decorator = createNode(SyntaxKind.Decorator, decoratorStart); - decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); - finishNode(decorator); - (list || (list = [])).push(decorator); } - return list && createNodeArray(list, listPos); + + return finishNode(factory.createToken(kind as Modifier["kind"]), pos); } /* @@ -5988,71 +6127,53 @@ namespace ts { * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray | undefined { - let list: Modifier[] | undefined; - const listPos = getNodePos(); - while (true) { - const modifierStart = scanner.getStartPos(); - const modifierKind = token(); - - if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) { - // We need to ensure that any subsequent modifiers appear on the same line - // so that when 'const' is a standalone declaration, we don't issue an error. - if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { - break; - } - } - else { - if (!parseAnyContextualModifier()) { - break; - } - } - - const modifier = finishNode(createNode(modifierKind, modifierStart)); - (list || (list = [])).push(modifier); + const pos = getNodePos(); + let list, modifier; + while (modifier = tryParseModifier(permitInvalidConstAsModifier)) { + list = append(list, modifier); } - return list && createNodeArray(list, listPos); + return list && createNodeArray(list, pos); } function parseModifiersForArrowFunction(): NodeArray | undefined { let modifiers: NodeArray | undefined; if (token() === SyntaxKind.AsyncKeyword) { - const modifierStart = scanner.getStartPos(); - const modifierKind = token(); + const pos = getNodePos(); nextToken(); - const modifier = finishNode(createNode(modifierKind, modifierStart)); - modifiers = createNodeArray([modifier], modifierStart); + const modifier = finishNode(factory.createToken(SyntaxKind.AsyncKeyword), pos); + modifiers = createNodeArray([modifier], pos); } return modifiers; } function parseClassElement(): ClassElement { + const pos = getNodePos(); if (token() === SyntaxKind.SemicolonToken) { - const result = createNode(SyntaxKind.SemicolonClassElement); nextToken(); - return finishNode(result); + return finishNode(factory.createSemicolonClassElement(), pos); } - const node = createNodeWithJSDoc(SyntaxKind.Unknown); - node.decorators = parseDecorators(); - node.modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true); + const hasJSDoc = hasPrecedingJSDocComment(); + const decorators = parseDecorators(); + const modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true); if (parseContextualModifier(SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(node, SyntaxKind.GetAccessor); + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor); } if (parseContextualModifier(SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(node, SyntaxKind.SetAccessor); + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor); } if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) { - const constructorDeclaration = tryParseConstructorDeclaration(node); + const constructorDeclaration = tryParseConstructorDeclaration(pos, hasJSDoc, decorators, modifiers); if (constructorDeclaration) { return constructorDeclaration; } } if (isIndexSignature()) { - return parseIndexSignatureDeclaration(node); + return parseIndexSignatureDeclaration(pos, hasJSDoc, decorators, modifiers); } // It is very important that we check this *after* checking indexers because @@ -6062,22 +6183,22 @@ namespace ts { token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBracketToken) { - const isAmbient = node.modifiers && some(node.modifiers, isDeclareModifier); + const isAmbient = some(modifiers, isDeclareModifier); if (isAmbient) { - for (const m of node.modifiers!) { + for (const m of modifiers!) { m.flags |= NodeFlags.Ambient; } - return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(node as PropertyDeclaration | MethodDeclaration)); + return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers)); } else { - return parsePropertyOrMethodDeclaration(node as PropertyDeclaration | MethodDeclaration); + return parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers); } } - if (node.decorators || node.modifiers) { + if (decorators || modifiers) { // treat this as a property declaration with a missing name. - node.name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); - return parsePropertyDeclaration(node); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, /*questionToken*/ undefined); } // 'isClassMemberStart' should have hinted not to attempt parsing. @@ -6085,31 +6206,34 @@ namespace ts { } function parseClassExpression(): ClassExpression { - return parseClassDeclarationOrExpression(createNodeWithJSDoc(SyntaxKind.Unknown), SyntaxKind.ClassExpression); + return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression); } - function parseClassDeclaration(node: ClassLikeDeclaration): ClassDeclaration { - return parseClassDeclarationOrExpression(node, SyntaxKind.ClassDeclaration); + function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ClassDeclaration { + return parseClassDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers, SyntaxKind.ClassDeclaration); } - function parseClassDeclarationOrExpression(node: ClassLikeDeclaration, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration { - node.kind = kind; + function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration { parseExpected(SyntaxKind.ClassKeyword); - node.name = parseNameOfClassDeclarationOrExpression(); - node.typeParameters = parseTypeParameters(); - node.heritageClauses = parseHeritageClauses(); + const name = parseNameOfClassDeclarationOrExpression(); + const typeParameters = parseTypeParameters(); + const heritageClauses = parseHeritageClauses(); + let members; if (parseExpected(SyntaxKind.OpenBraceToken)) { // ClassTail[Yield,Await] : (Modified) See 14.5 // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } - node.members = parseClassMembers(); + members = parseClassMembers(); parseExpected(SyntaxKind.CloseBraceToken); } else { - node.members = createMissingList(); + members = createMissingList(); } - return finishNode(node); + const node = kind === SyntaxKind.ClassDeclaration + ? factory.createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members) + : factory.createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseNameOfClassDeclarationOrExpression(): Identifier | undefined { @@ -6139,20 +6263,19 @@ namespace ts { } function parseHeritageClause(): HeritageClause { + const pos = getNodePos(); const tok = token(); Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this. - const node = createNode(SyntaxKind.HeritageClause); - node.token = tok as SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; nextToken(); - node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments); - return finishNode(node); + const types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments); + return finishNode(factory.createHeritageClause(tok as HeritageClause["token"], types), pos); } function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments { - const node = createNode(SyntaxKind.ExpressionWithTypeArguments); - node.expression = parseLeftHandSideExpressionOrHigher(); - node.typeArguments = tryParseTypeArguments(); - return finishNode(node); + const pos = getNodePos(); + const expression = parseLeftHandSideExpressionOrHigher(); + const typeArguments = tryParseTypeArguments(); + return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos); } function tryParseTypeArguments(): NodeArray | undefined { @@ -6168,25 +6291,25 @@ namespace ts { return parseList(ParsingContext.ClassMembers, parseClassElement); } - function parseInterfaceDeclaration(node: InterfaceDeclaration): InterfaceDeclaration { - node.kind = SyntaxKind.InterfaceDeclaration; + function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): InterfaceDeclaration { parseExpected(SyntaxKind.InterfaceKeyword); - node.name = parseIdentifier(); - node.typeParameters = parseTypeParameters(); - node.heritageClauses = parseHeritageClauses(); - node.members = parseObjectTypeMembers(); - return finishNode(node); + const name = parseIdentifier(); + const typeParameters = parseTypeParameters(); + const heritageClauses = parseHeritageClauses(); + const members = parseObjectTypeMembers(); + const node = factory.createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseTypeAliasDeclaration(node: TypeAliasDeclaration): TypeAliasDeclaration { - node.kind = SyntaxKind.TypeAliasDeclaration; + function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): TypeAliasDeclaration { parseExpected(SyntaxKind.TypeKeyword); - node.name = parseIdentifier(); - node.typeParameters = parseTypeParameters(); + const name = parseIdentifier(); + const typeParameters = parseTypeParameters(); parseExpected(SyntaxKind.EqualsToken); - node.type = parseType(); + const type = parseType(); parseSemicolon(); - return finishNode(node); + const node = factory.createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type); + return withJSDoc(finishNode(node, pos), hasJSDoc); } // In an ambient declaration, the grammar only allows integer literals as initializers. @@ -6194,76 +6317,81 @@ namespace ts { // ConstantEnumMemberSection, which starts at the beginning of an enum declaration // or any time an integer literal initializer is encountered. function parseEnumMember(): EnumMember { - const node = createNodeWithJSDoc(SyntaxKind.EnumMember); - node.name = parsePropertyName(); - node.initializer = allowInAnd(parseInitializer); - return finishNode(node); + const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); + const name = parsePropertyName(); + const initializer = allowInAnd(parseInitializer); + return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc); } - function parseEnumDeclaration(node: EnumDeclaration): EnumDeclaration { - node.kind = SyntaxKind.EnumDeclaration; + function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): EnumDeclaration { parseExpected(SyntaxKind.EnumKeyword); - node.name = parseIdentifier(); + const name = parseIdentifier(); + let members; if (parseExpected(SyntaxKind.OpenBraceToken)) { - node.members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember)); + members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember)); parseExpected(SyntaxKind.CloseBraceToken); } else { - node.members = createMissingList(); + members = createMissingList(); } - return finishNode(node); + const node = factory.createEnumDeclaration(decorators, modifiers, name, members); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseModuleBlock(): ModuleBlock { - const node = createNode(SyntaxKind.ModuleBlock); + const pos = getNodePos(); + let statements; if (parseExpected(SyntaxKind.OpenBraceToken)) { - node.statements = parseList(ParsingContext.BlockStatements, parseStatement); + statements = parseList(ParsingContext.BlockStatements, parseStatement); parseExpected(SyntaxKind.CloseBraceToken); } else { - node.statements = createMissingList(); + statements = createMissingList(); } - return finishNode(node); + return finishNode(factory.createModuleBlock(statements), pos); } - function parseModuleOrNamespaceDeclaration(node: ModuleDeclaration, flags: NodeFlags): ModuleDeclaration { - node.kind = SyntaxKind.ModuleDeclaration; + function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, flags: NodeFlags): ModuleDeclaration { // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. const namespaceFlag = flags & NodeFlags.Namespace; - node.flags |= flags; - node.name = parseIdentifier(); - node.body = parseOptional(SyntaxKind.DotToken) - ? parseModuleOrNamespaceDeclaration(createNode(SyntaxKind.Unknown), NodeFlags.NestedNamespace | namespaceFlag) + const name = parseIdentifier(); + const body = parseOptional(SyntaxKind.DotToken) + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) : parseModuleBlock(); - return finishNode(node); + const node = factory.createModuleDeclaration(decorators, modifiers, name, body, flags); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseAmbientExternalModuleDeclaration(node: ModuleDeclaration): ModuleDeclaration { - node.kind = SyntaxKind.ModuleDeclaration; + function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { + let flags: NodeFlags = 0; + let name; if (token() === SyntaxKind.GlobalKeyword) { // parse 'global' as name of global scope augmentation - node.name = parseIdentifier(); - node.flags |= NodeFlags.GlobalAugmentation; + name = parseIdentifier(); + flags |= NodeFlags.GlobalAugmentation; } else { - node.name = parseLiteralNode(); - node.name.text = internIdentifier(node.name.text); + name = parseLiteralNode(); + name.text = internIdentifier(name.text); } + let body: ModuleBlock | undefined; if (token() === SyntaxKind.OpenBraceToken) { - node.body = parseModuleBlock(); + body = parseModuleBlock(); } else { parseSemicolon(); } - return finishNode(node); + const node = factory.createModuleDeclaration(decorators, modifiers, name, body, flags); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleDeclaration(node: ModuleDeclaration): ModuleDeclaration { + function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { let flags: NodeFlags = 0; if (token() === SyntaxKind.GlobalKeyword) { // global augmentation - return parseAmbientExternalModuleDeclaration(node); + return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers); } else if (parseOptional(SyntaxKind.NamespaceKeyword)) { flags |= NodeFlags.Namespace; @@ -6271,10 +6399,10 @@ namespace ts { else { parseExpected(SyntaxKind.ModuleKeyword); if (token() === SyntaxKind.StringLiteral) { - return parseAmbientExternalModuleDeclaration(node); + return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers); } } - return parseModuleOrNamespaceDeclaration(node, flags); + return parseModuleOrNamespaceDeclaration(pos, hasJSDoc, decorators, modifiers, flags); } function isExternalModuleReference() { @@ -6290,16 +6418,19 @@ namespace ts { return nextToken() === SyntaxKind.SlashToken; } - function parseNamespaceExportDeclaration(node: NamespaceExportDeclaration): NamespaceExportDeclaration { - node.kind = SyntaxKind.NamespaceExportDeclaration; + function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): NamespaceExportDeclaration { parseExpected(SyntaxKind.AsKeyword); parseExpected(SyntaxKind.NamespaceKeyword); - node.name = parseIdentifier(); + const name = parseIdentifier(); parseSemicolon(); - return finishNode(node); + const node = factory.createNamespaceExportDeclaration(name); + // NamespaceExportDeclaration nodes cannot have decorators or modifiers, so we attach them here so we can report them in the grammar checker + if (decorators) factory.trackExtraneousChildNodes(node, node.decorators = decorators); + if (modifiers) factory.trackExtraneousChildNodes(node, node.modifiers = modifiers); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportDeclarationOrImportEqualsDeclaration(node: ImportEqualsDeclaration | ImportDeclaration): ImportEqualsDeclaration | ImportDeclaration { + function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ImportEqualsDeclaration | ImportDeclaration { parseExpected(SyntaxKind.ImportKeyword); const afterImportPos = scanner.getStartPos(); @@ -6307,37 +6438,36 @@ namespace ts { if (isIdentifier()) { identifier = parseIdentifier(); if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) { - return parseImportEqualsDeclaration(node, identifier); + return parseImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers, identifier); } } - // Import statement - node.kind = SyntaxKind.ImportDeclaration; // ImportDeclaration: // import ImportClause from ModuleSpecifier ; // import ModuleSpecifier; + let importClause: ImportClause | undefined; if (identifier || // import id token() === SyntaxKind.AsteriskToken || // import * token() === SyntaxKind.OpenBraceToken) { // import { - (node).importClause = parseImportClause(identifier, afterImportPos); + importClause = parseImportClause(identifier, afterImportPos); parseExpected(SyntaxKind.FromKeyword); } - (node).moduleSpecifier = parseModuleSpecifier(); + const moduleSpecifier = parseModuleSpecifier(); parseSemicolon(); - return finishNode(node); + const node = factory.createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportEqualsDeclaration(node: ImportEqualsDeclaration, identifier: Identifier): ImportEqualsDeclaration { - node.kind = SyntaxKind.ImportEqualsDeclaration; - node.name = identifier; + function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, identifier: Identifier): ImportEqualsDeclaration { parseExpected(SyntaxKind.EqualsToken); - node.moduleReference = parseModuleReference(); + const moduleReference = parseModuleReference(); parseSemicolon(); - return finishNode(node); + const node = factory.createImportEqualsDeclaration(decorators, modifiers, identifier, moduleReference); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportClause(identifier: Identifier | undefined, fullStart: number) { + function parseImportClause(identifier: Identifier | undefined, pos: number) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -6345,21 +6475,15 @@ namespace ts { // ImportedDefaultBinding, NameSpaceImport // ImportedDefaultBinding, NamedImports - const importClause = createNode(SyntaxKind.ImportClause, fullStart); - if (identifier) { - // ImportedDefaultBinding: - // ImportedBinding - importClause.name = identifier; - } - // If there was no default import or if there is comma token after default import // parse namespace or named imports - if (!importClause.name || + let namedBindings: NamespaceImport | NamedImports | undefined; + if (!identifier || parseOptional(SyntaxKind.CommaToken)) { - importClause.namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports); + namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports); } - return finishNode(importClause); + return finishNode(factory.createImportClause(identifier, namedBindings), pos); } function parseModuleReference() { @@ -6369,12 +6493,12 @@ namespace ts { } function parseExternalModuleReference() { - const node = createNode(SyntaxKind.ExternalModuleReference); + const pos = getNodePos(); parseExpected(SyntaxKind.RequireKeyword); parseExpected(SyntaxKind.OpenParenToken); - node.expression = parseModuleSpecifier(); + const expression = parseModuleSpecifier(); parseExpected(SyntaxKind.CloseParenToken); - return finishNode(node); + return finishNode(factory.createExternalModuleReference(expression), pos); } function parseModuleSpecifier(): Expression { @@ -6394,17 +6518,17 @@ namespace ts { function parseNamespaceImport(): NamespaceImport { // NameSpaceImport: // * as ImportedBinding - const namespaceImport = createNode(SyntaxKind.NamespaceImport); + const pos = getNodePos(); parseExpected(SyntaxKind.AsteriskToken); parseExpected(SyntaxKind.AsKeyword); - namespaceImport.name = parseIdentifier(); - return finishNode(namespaceImport); + const name = parseIdentifier(); + return finishNode(factory.createNamespaceImport(name), pos); } function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports; function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports; function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports { - const node = createNode(kind); + const pos = getNodePos(); // NamedImports: // { } @@ -6414,22 +6538,22 @@ namespace ts { // ImportsList: // ImportSpecifier // ImportsList, ImportSpecifier - node.elements = | NodeArray>parseBracketedList(ParsingContext.ImportOrExportSpecifiers, - kind === SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier, - SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); - return finishNode(node); + const node = kind === SyntaxKind.NamedImports + ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) + : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)); + return finishNode(node, pos); } function parseExportSpecifier() { - return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier); + return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as ExportSpecifier; } function parseImportSpecifier() { - return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier); + return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as ImportSpecifier; } function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier { - const node = createNode(kind); + const pos = getNodePos(); // ImportSpecifier: // BindingIdentifier // IdentifierName as BindingIdentifier @@ -6440,54 +6564,62 @@ namespace ts { let checkIdentifierStart = scanner.getTokenPos(); let checkIdentifierEnd = scanner.getTextPos(); const identifierName = parseIdentifierName(); + let propertyName: Identifier | undefined; + let name: Identifier; if (token() === SyntaxKind.AsKeyword) { - node.propertyName = identifierName; + propertyName = identifierName; parseExpected(SyntaxKind.AsKeyword); checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); checkIdentifierStart = scanner.getTokenPos(); checkIdentifierEnd = scanner.getTextPos(); - node.name = parseIdentifierName(); + name = parseIdentifierName(); } else { - node.name = identifierName; + name = identifierName; } if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) { parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected); } - return finishNode(node); + const node = kind === SyntaxKind.ImportSpecifier + ? factory.createImportSpecifier(propertyName, name) + : factory.createExportSpecifier(propertyName, name); + return finishNode(node, pos); } - function parseExportDeclaration(node: ExportDeclaration): ExportDeclaration { - node.kind = SyntaxKind.ExportDeclaration; + function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportDeclaration { + let exportClause: NamedExports | undefined; + let moduleSpecifier: Expression | undefined; if (parseOptional(SyntaxKind.AsteriskToken)) { parseExpected(SyntaxKind.FromKeyword); - node.moduleSpecifier = parseModuleSpecifier(); + moduleSpecifier = parseModuleSpecifier(); } else { - node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports); + exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports); // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) { parseExpected(SyntaxKind.FromKeyword); - node.moduleSpecifier = parseModuleSpecifier(); + moduleSpecifier = parseModuleSpecifier(); } } parseSemicolon(); - return finishNode(node); + const node = factory.createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier); + return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseExportAssignment(node: ExportAssignment): ExportAssignment { - node.kind = SyntaxKind.ExportAssignment; + function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportAssignment { + let isExportEquals: boolean | undefined; if (parseOptional(SyntaxKind.EqualsToken)) { - node.isExportEquals = true; + isExportEquals = true; } else { parseExpected(SyntaxKind.DefaultKeyword); } - node.expression = parseAssignmentExpressionOrHigher(); + const expression = parseAssignmentExpressionOrHigher(); parseSemicolon(); - return finishNode(node); + const node = factory.createExportAssignment(decorators, modifiers, isExportEquals, expression); + return withJSDoc(finishNode(node, pos), hasJSDoc); } function setExternalModuleIndicator(sourceFile: SourceFile) { @@ -6556,12 +6688,18 @@ namespace ts { export namespace JSDocParser { export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); - sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false); + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*setParentNodes*/ false); + factory.setSkipTransformationFlags(/*value*/ true); // reset in 'clearState' scanner.setText(content, start, length); currentToken = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); - const diagnostics = parseDiagnostics; + + const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(SyntaxKind.EndOfFileToken)); + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } + clearState(); return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined; @@ -6569,29 +6707,34 @@ namespace ts { // Parses out a JSDoc type expression. export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression { - const result = createNode(SyntaxKind.JSDocTypeExpression); - + const pos = getNodePos(); + const saveSkipTransformationFlags = factory.setSkipTransformationFlags(/*value*/ true); const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken); - result.type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); + const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); if (!mayOmitBraces || hasBrace) { parseExpectedJSDoc(SyntaxKind.CloseBraceToken); } + const result = factory.createJSDocTypeExpression(type); fixupParentReferences(result); - return finishNode(result); + factory.setSkipTransformationFlags(saveSkipTransformationFlags); + return finishNode(result, pos); } export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { - initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); - sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; + initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS, /*setParentNodes*/ false); + factory.setSkipTransformationFlags(/*value*/ true); // reset in 'clearState' const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); - const diagnostics = parseDiagnostics; + + const sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); clearState(); return jsDoc ? { jsDoc, diagnostics } : undefined; } export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined { + const saveSkipTransformationFlags = factory.setSkipTransformationFlags(true); const saveToken = currentToken; const saveParseDiagnosticsLength = parseDiagnostics.length; const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; @@ -6602,15 +6745,15 @@ namespace ts { } if (contextFlags & NodeFlags.JavaScriptFile) { - if (!sourceFile.jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = []; + if (!jsDocDiagnostics) { + jsDocDiagnostics = []; } - sourceFile.jsDocDiagnostics.push(...parseDiagnostics); + jsDocDiagnostics.push(...parseDiagnostics); } currentToken = saveToken; parseDiagnostics.length = saveParseDiagnosticsLength; parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; - + factory.setSkipTransformationFlags(saveSkipTransformationFlags); return comment; } @@ -6743,10 +6886,9 @@ namespace ts { } function createJSDocComment(): JSDoc { - const result = createNode(SyntaxKind.JSDocComment, start); - result.tags = tags && createNodeArray(tags, tagsPos, tagsEnd); - result.comment = comments.length ? comments.join("") : undefined; - return finishNode(result, end); + const comment = comments.length ? comments.join("") : undefined; + const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd); + return finishNode(factory.createJSDocComment(comment, tagsArray), start, end); } function isNextNonwhitespaceTokenEndOfFile(): boolean { @@ -6954,9 +7096,7 @@ namespace ts { } function parseUnknownTag(start: number, tagName: Identifier) { - const result = createNode(SyntaxKind.JSDocTag, start); - result.tagName = tagName; - return finishNode(result); + return finishNode(factory.createJSDocUnknownTag(tagName), start); } function addTag(tag: JSDocTag | undefined): void { @@ -7026,30 +7166,22 @@ namespace ts { typeExpression = tryParseTypeExpression(); } - const result = target === PropertyLikeParse.Property ? - createNode(SyntaxKind.JSDocPropertyTag, start) : - createNode(SyntaxKind.JSDocParameterTag, start); const comment = parseTagComments(indent + scanner.getStartPos() - start); const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target, indent); if (nestedTypeLiteral) { typeExpression = nestedTypeLiteral; isNameFirst = true; } - result.tagName = tagName; - result.typeExpression = typeExpression; - result.name = name; - result.isNameFirst = isNameFirst; - result.isBracketed = isBracketed; - result.comment = comment; - return finishNode(result); + const result = target === PropertyLikeParse.Property + ? factory.createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment) + : factory.createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment); + return finishNode(result, start); } function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { - const typeLiteralExpression = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); + const pos = getNodePos(); let child: JSDocPropertyLikeTag | JSDocTypeTag | false; - let jsdocTypeLiteral: JSDocTypeLiteral; - const start = scanner.getStartPos(); let children: JSDocPropertyLikeTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { @@ -7057,13 +7189,8 @@ namespace ts { } } if (children) { - jsdocTypeLiteral = createNode(SyntaxKind.JSDocTypeLiteral, start); - jsdocTypeLiteral.jsDocPropertyTags = children; - if (typeExpression.type.kind === SyntaxKind.ArrayType) { - jsdocTypeLiteral.isArrayType = true; - } - typeLiteralExpression.type = finishNode(jsdocTypeLiteral); - return finishNode(typeLiteralExpression); + const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos); + return finishNode(factory.createJSDocTypeExpression(literal), pos); } } } @@ -7073,10 +7200,8 @@ namespace ts { parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText); } - const result = createNode(SyntaxKind.JSDocReturnTag, start); - result.tagName = tagName; - result.typeExpression = tryParseTypeExpression(); - return finishNode(result); + const typeExpression = tryParseTypeExpression(); + return finishNode(factory.createJSDocReturnTag(tagName, typeExpression), start); } function parseTypeTag(start: number, tagName: Identifier): JSDocTypeTag { @@ -7084,31 +7209,25 @@ namespace ts { parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText); } - const result = createNode(SyntaxKind.JSDocTypeTag, start); - result.tagName = tagName; - result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); - return finishNode(result); + const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); + return finishNode(factory.createJSDocTypeTag(tagName, typeExpression), start); } function parseAuthorTag(start: number, tagName: Identifier, indent: number): JSDocAuthorTag { - const result = createNode(SyntaxKind.JSDocAuthorTag, start); - result.tagName = tagName; - const authorInfoWithEmail = tryParse(() => tryParseAuthorNameAndEmail()); if (!authorInfoWithEmail) { - return finishNode(result); + return finishNode(factory.createJSDocAuthorTag(tagName), start); } - result.comment = authorInfoWithEmail; - + let comments = authorInfoWithEmail; if (lookAhead(() => nextToken() !== SyntaxKind.NewLineTrivia)) { const comment = parseTagComments(indent); if (comment) { - result.comment += comment; + comments += comment; } } - return finishNode(result); + return finishNode(factory.createJSDocAuthorTag(tagName, comments), start); } function tryParseAuthorNameAndEmail(): string | undefined { @@ -7154,18 +7273,17 @@ namespace ts { } function parseAugmentsTag(start: number, tagName: Identifier): JSDocAugmentsTag { - const result = createNode(SyntaxKind.JSDocAugmentsTag, start); - result.tagName = tagName; - result.class = parseExpressionWithTypeArgumentsForAugments(); - return finishNode(result); + const className = parseExpressionWithTypeArgumentsForAugments(); + return finishNode(factory.createJSDocAugmentsTag(tagName, className), start); } function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } { const usedBrace = parseOptional(SyntaxKind.OpenBraceToken); - const node = createNode(SyntaxKind.ExpressionWithTypeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression }; - node.expression = parsePropertyAccessEntityNameExpression(); - node.typeArguments = tryParseTypeArguments(); - const res = finishNode(node); + const pos = getNodePos(); + const expression = parsePropertyAccessEntityNameExpression(); + const typeArguments = tryParseTypeArguments(); + const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression }; + const res = finishNode(node, pos); if (usedBrace) { parseExpected(SyntaxKind.CloseBraceToken); } @@ -7173,59 +7291,47 @@ namespace ts { } function parsePropertyAccessEntityNameExpression() { + const pos = getNodePos(); let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); while (parseOptional(SyntaxKind.DotToken)) { - const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression; - prop.expression = node; - prop.name = parseJSDocIdentifierName(); - node = finishNode(prop); + const name = parseJSDocIdentifierName(); + node = finishNode(factory.createPropertyAccess(node, name), pos) as PropertyAccessEntityNameExpression; } return node; } function parseClassTag(start: number, tagName: Identifier): JSDocClassTag { - const tag = createNode(SyntaxKind.JSDocClassTag, start); - tag.tagName = tagName; - return finishNode(tag); + return finishNode(factory.createJSDocClassTag(tagName), start); } function parseThisTag(start: number, tagName: Identifier): JSDocThisTag { - const tag = createNode(SyntaxKind.JSDocThisTag, start); - tag.tagName = tagName; - tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); + const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(tag); + return finishNode(factory.createJSDocThisTag(tagName, typeExpression), start); } function parseEnumTag(start: number, tagName: Identifier): JSDocEnumTag { - const tag = createNode(SyntaxKind.JSDocEnumTag, start); - tag.tagName = tagName; - tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); + const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(tag); + return finishNode(factory.createJSDocEnumTag(tagName, typeExpression), start); } function parseTypedefTag(start: number, tagName: Identifier, indent: number): JSDocTypedefTag { - const typeExpression = tryParseTypeExpression(); + let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); skipWhitespaceOrAsterisk(); - const typedefTag = createNode(SyntaxKind.JSDocTypedefTag, start); - typedefTag.tagName = tagName; - typedefTag.fullName = parseJSDocTypeNameWithNamespace(); - typedefTag.name = getJSDocTypeAliasName(typedefTag.fullName); + const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); - typedefTag.comment = parseTagComments(indent); + const comment = parseTagComments(indent); - typedefTag.typeExpression = typeExpression; let end: number | undefined; if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { let child: JSDocTypeTag | JSDocPropertyTag | false; - let jsdocTypeLiteral: JSDocTypeLiteral | undefined; let childTypeTag: JSDocTypeTag | undefined; + let jsDocPropertyTags: JSDocPropertyTag[] | undefined; + let hasChildren = false; while (child = tryParse(() => parseChildPropertyTag(indent))) { - if (!jsdocTypeLiteral) { - jsdocTypeLiteral = createNode(SyntaxKind.JSDocTypeLiteral, start); - } + hasChildren = true; if (child.kind === SyntaxKind.JSDocTypeTag) { if (childTypeTag) { break; @@ -7235,22 +7341,23 @@ namespace ts { } } else { - jsdocTypeLiteral.jsDocPropertyTags = append(jsdocTypeLiteral.jsDocPropertyTags as MutableNodeArray, child); + jsDocPropertyTags = append(jsDocPropertyTags, child); } } - if (jsdocTypeLiteral) { - if (typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType) { - jsdocTypeLiteral.isArrayType = true; - } - typedefTag.typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? + if (hasChildren) { + const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType; + const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType); + typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? childTypeTag.typeExpression : - finishNode(jsdocTypeLiteral); - end = typedefTag.typeExpression.end; + finishNode(jsdocTypeLiteral, start); + end = typeExpression.end; } } + const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment); + // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace - return finishNode(typedefTag, end || typedefTag.comment !== undefined ? scanner.getStartPos() : (typedefTag.fullName || typedefTag.typeExpression || typedefTag.tagName).end); + return finishNode(typedefTag, start, end || typedefTag.comment !== undefined ? scanner.getStartPos() : (typedefTag.fullName || typedefTag.typeExpression || typedefTag.tagName).end); } function parseJSDocTypeNameWithNamespace(nested?: boolean) { @@ -7260,13 +7367,15 @@ namespace ts { } const typeNameOrNamespaceName = parseJSDocIdentifierName(); if (parseOptional(SyntaxKind.DotToken)) { - const jsDocNamespaceNode = createNode(SyntaxKind.ModuleDeclaration, pos); - if (nested) { - jsDocNamespaceNode.flags |= NodeFlags.NestedNamespace; - } - jsDocNamespaceNode.name = typeNameOrNamespaceName; - jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(/*nested*/ true); - return finishNode(jsDocNamespaceNode); + const body = parseJSDocTypeNameWithNamespace(/*nested*/ true); + const jsDocNamespaceNode = factory.createModuleDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + typeNameOrNamespaceName, + body, + nested ? NodeFlags.NestedNamespace : undefined + ) as JSDocNamespaceDeclaration; + return finishNode(jsDocNamespaceNode, pos); } if (nested) { @@ -7275,20 +7384,22 @@ namespace ts { return typeNameOrNamespaceName; } - function parseCallbackTag(start: number, tagName: Identifier, indent: number): JSDocCallbackTag { - const callbackTag = createNode(SyntaxKind.JSDocCallbackTag, start) as JSDocCallbackTag; - callbackTag.tagName = tagName; - callbackTag.fullName = parseJSDocTypeNameWithNamespace(); - callbackTag.name = getJSDocTypeAliasName(callbackTag.fullName); - skipWhitespace(); - callbackTag.comment = parseTagComments(indent); + function parseCallbackTagParameters(indent: number) { + const pos = getNodePos(); let child: JSDocParameterTag | false; - const jsdocSignature = createNode(SyntaxKind.JSDocSignature, start) as JSDocSignature; - jsdocSignature.parameters = []; + let parameters; while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) { - jsdocSignature.parameters = append(jsdocSignature.parameters as MutableNodeArray, child); + parameters = append(parameters, child); } + return createNodeArray(parameters || [], pos); + } + + function parseCallbackTag(start: number, tagName: Identifier, indent: number): JSDocCallbackTag { + const fullName = parseJSDocTypeNameWithNamespace(); + skipWhitespace(); + const comment = parseTagComments(indent); + const parameters = parseCallbackTagParameters(indent); const returnTag = tryParse(() => { if (parseOptionalJsdoc(SyntaxKind.AtToken)) { const tag = parseTag(indent); @@ -7297,23 +7408,8 @@ namespace ts { } } }); - if (returnTag) { - jsdocSignature.type = returnTag; - } - callbackTag.typeExpression = finishNode(jsdocSignature); - return finishNode(callbackTag); - } - - function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) { - if (fullName) { - let rightNode = fullName; - while (true) { - if (ts.isIdentifier(rightNode) || !rightNode.body) { - return ts.isIdentifier(rightNode) ? rightNode : rightNode.name; - } - rightNode = rightNode.body; - } - } + const typeExpression = finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); + return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start); } function escapedTextsEqual(a: EntityName, b: EntityName): boolean { @@ -7398,30 +7494,38 @@ namespace ts { return parseParameterOrPropertyTag(start, tagName, target, indent); } - function parseTemplateTag(start: number, tagName: Identifier): JSDocTemplateTag { - // the template tag looks like '@template {Constraint} T,U,V' - let constraint: JSDocTypeExpression | undefined; - if (token() === SyntaxKind.OpenBraceToken) { - constraint = parseJSDocTypeExpression(); - } + function parseTemplateTagTypeParameter() { + const typeParameterPos = getNodePos(); + const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); + return finishNode(factory.createTypeParameterDeclaration(name, /*constraint*/ undefined, /*defaultType*/ undefined), typeParameterPos); + } + function parseTemplateTagTypeParameters() { + const pos = getNodePos(); const typeParameters = []; - const typeParametersPos = getNodePos(); do { skipWhitespace(); - const typeParameter = createNode(SyntaxKind.TypeParameter); - typeParameter.name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); - finishNode(typeParameter); + typeParameters.push(parseTemplateTagTypeParameter()); skipWhitespace(); - typeParameters.push(typeParameter); } while (parseOptionalJsdoc(SyntaxKind.CommaToken)); + return createNodeArray(typeParameters, pos); + } - const result = createNode(SyntaxKind.JSDocTemplateTag, start); - result.tagName = tagName; - result.constraint = constraint; - result.typeParameters = createNodeArray(typeParameters, typeParametersPos); - finishNode(result); - return result; + function parseTemplateTag(start: number, tagName: Identifier): JSDocTemplateTag { + // The template tag looks like one of the following: + // @template T,U,V + // @template {Constraint} T + // + // According to the [closure docs](https://github.com/google/closure-compiler/wiki/Generic-Types#multiple-bounded-template-types): + // > Multiple bounded generics cannot be declared on the same line. For the sake of clarity, if multiple templates share the same + // > type bound they must be declared on separate lines. + // + // TODO: Determine whether we should enforce this in the checker. + // TODO: Consider moving the `constraint` to the first type parameter as we could then remove `getEffectiveConstraintOfTypeParameter`. + // TODO: Consider only parsing a single type parameter if there is a constraint. + const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; + const typeParameters = parseTemplateTagTypeParameters(); + return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters), start); } function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean { @@ -7458,13 +7562,9 @@ namespace ts { identifierCount++; const pos = scanner.getTokenPos(); const end = scanner.getTextPos(); - const result = createNode(SyntaxKind.Identifier, pos); - if (token() !== SyntaxKind.Identifier) { - result.originalKeywordKind = token(); - } - result.escapedText = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); - finishNode(result, end); - + const originalKeywordKind = token(); + const text = internIdentifier(scanner.getTokenValue()); + const result = finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos, end); nextTokenJSDoc(); return result; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 429b7389f5b92..dff9d4aa1d7bb 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2070,8 +2070,8 @@ namespace ts { && (options.isolatedModules || isExternalModuleFile) && !file.isDeclarationFile) { // synthesize 'import "tslib"' declaration - const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText); - const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference); + const externalHelpersModuleReference = factory.createStringLiteral(externalHelpersModuleNameText); + const importDecl = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference); addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper); externalHelpersModuleReference.parent = importDecl; importDecl.parent = file; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index fbad8240bd353..8d5a86b8b5075 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -21,10 +21,14 @@ namespace ts { hasUnicodeEscape(): boolean; hasExtendedUnicodeEscape(): boolean; hasPrecedingLineBreak(): boolean; + /* @internal */ + hasPrecedingJSDocComment(): boolean; isIdentifier(): boolean; isReservedWord(): boolean; isUnterminated(): boolean; /* @internal */ + getNumericLiteralFlags(): TokenFlags; + /* @internal */ getTokenFlags(): TokenFlags; reScanGreaterToken(): SyntaxKind; reScanSlashToken(): SyntaxKind; @@ -893,9 +897,11 @@ namespace ts { hasUnicodeEscape: () => (tokenFlags & TokenFlags.UnicodeEscape) !== 0, hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0, hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0, + hasPrecedingJSDocComment: () => (tokenFlags & TokenFlags.PrecedingJSDocComment) !== 0, isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord, isUnterminated: () => (tokenFlags & TokenFlags.Unterminated) !== 0, + getNumericLiteralFlags: () => tokenFlags & TokenFlags.NumericLiteralFlags, getTokenFlags: () => tokenFlags, reScanGreaterToken, reScanSlashToken, diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index bd8f34ee128c6..c457de786e68b 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -104,11 +104,11 @@ namespace ts { /** * Wrap a transformer factory that may return a custom script or declaration transformer object. */ - function wrapCustomTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory, handleDefault: (node: Transformer) => Transformer): TransformerFactory { + function wrapCustomTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory, handleDefault: (context: TransformationContext, tx: Transformer) => Transformer): TransformerFactory { return context => { const customTransformer = transformer(context); return typeof customTransformer === "function" - ? handleDefault(customTransformer) + ? handleDefault(context, customTransformer) : wrapCustomTransformer(customTransformer); }; } @@ -118,7 +118,7 @@ namespace ts { } function wrapDeclarationTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory): TransformerFactory { - return wrapCustomTransformerFactory(transformer, identity); + return wrapCustomTransformerFactory(transformer, (_, node) => node); } export function noEmitSubstitution(_hint: EmitHint, node: Node) { @@ -139,7 +139,7 @@ namespace ts { * @param transforms An array of `TransformerFactory` callbacks. * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. */ - export function transformNodes(resolver: EmitResolver | undefined, host: EmitHost | undefined, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory[], allowDtsFiles: boolean): TransformationResult { + export function transformNodes(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory[], allowDtsFiles: boolean): TransformationResult { const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; @@ -156,9 +156,11 @@ namespace ts { // The transformation context is provided to each transformer as part of transformer // initialization. const context: TransformationContext = { + factory, getCompilerOptions: () => options, getEmitResolver: () => resolver!, // TODO: GH#18217 getEmitHost: () => host!, // TODO: GH#18217 + getEmitHelperFactory: memoize(() => createEmitHelperFactory(context)), startLexicalEnvironment, suspendLexicalEnvironment, resumeLexicalEnvironment, @@ -298,7 +300,7 @@ namespace ts { function hoistVariableDeclaration(name: Identifier): void { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - const decl = setEmitFlags(createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); + const decl = setEmitFlags(factory.createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; } @@ -373,9 +375,9 @@ namespace ts { } if (lexicalEnvironmentVariableDeclarations) { - const statement = createVariableStatement( + const statement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList(lexicalEnvironmentVariableDeclarations) + factory.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations) ); setEmitFlags(statement, EmitFlags.CustomPrologue); @@ -436,4 +438,27 @@ namespace ts { } } } + + export const nullTransformationContext: TransformationContext = { + get factory() { return factory; }, + enableEmitNotification: noop, + enableSubstitution: noop, + endLexicalEnvironment: returnUndefined, + getCompilerOptions: notImplemented, + getEmitHost: notImplemented, + getEmitResolver: notImplemented, + getEmitHelperFactory: notImplemented, + hoistFunctionDeclaration: noop, + hoistVariableDeclaration: noop, + isEmitNotificationEnabled: notImplemented, + isSubstitutionEnabled: notImplemented, + onEmitNode: noop, + onSubstituteNode: notImplemented, + readEmitHelpers: notImplemented, + requestEmitHelper: noop, + resumeLexicalEnvironment: noop, + startLexicalEnvironment: noop, + suspendLexicalEnvironment: noop, + addDiagnostic: noop, + }; } diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index b3e598608884a..b45c4010d480d 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -16,6 +16,7 @@ namespace ts { */ export function transformClassFields(context: TransformationContext) { const { + factory, hoistVariableDeclaration, endLexicalEnvironment, resumeLexicalEnvironment @@ -41,7 +42,7 @@ namespace ts { */ let pendingStatements: Statement[] | undefined; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { const options = context.getCompilerOptions(); @@ -119,9 +120,9 @@ namespace ts { const expressions = pendingExpressions; expressions.push(name.expression); pendingExpressions = []; - node = updateComputedPropertyName( + node = factory.updateComputedPropertyName( node, - inlineExpressions(expressions) + factory.inlineExpressions(expressions) ); } return node; @@ -151,7 +152,7 @@ namespace ts { const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); const statements: Statement[] = [ - updateClassDeclaration( + factory.updateClassDeclaration( node, /*decorators*/ undefined, node.modifiers, @@ -164,7 +165,7 @@ namespace ts { // Write any pending expressions from elided or moved computed property names if (some(pendingExpressions)) { - statements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + statements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); } pendingExpressions = savedPendingExpressions; @@ -176,7 +177,7 @@ namespace ts { // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. const staticProperties = getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true); if (some(staticProperties)) { - addPropertyStatements(statements, staticProperties, getInternalName(node)); + addPropertyStatements(statements, staticProperties, factory.getInternalName(node)); } return statements; @@ -202,8 +203,9 @@ namespace ts { const extendsClauseElement = getEffectiveBaseTypeNode(node); const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); - const classExpression = updateClassExpression( + const classExpression = factory.updateClassExpression( node, + visitNodes(node.decorators, visitor, isDecorator), node.modifiers, node.name, /*typeParameters*/ undefined, @@ -217,23 +219,23 @@ namespace ts { // Write any pending expressions from elided or moved computed property names if (pendingStatements && pendingExpressions && some(pendingExpressions)) { - pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + pendingStatements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); } pendingExpressions = savedPendingExpressions; if (pendingStatements && some(staticProperties)) { - addPropertyStatements(pendingStatements, staticProperties, getInternalName(node)); + addPropertyStatements(pendingStatements, staticProperties, factory.getInternalName(node)); } return classExpression; } else { const expressions: Expression[] = []; const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; - const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); + const temp = factory.createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); if (isClassWithConstructorReference) { // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); - const alias = getSynthesizedClone(temp); + const alias = getSynthesizedClone(temp) as GeneratedIdentifier; alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; classAliases[getOriginalNodeId(node)] = alias; } @@ -241,14 +243,14 @@ namespace ts { // To preserve the behavior of the old emitter, we explicitly indent // the body of a class with static initializers. setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); - expressions.push(startOnNewLine(createAssignment(temp, classExpression))); + expressions.push(startOnNewLine(factory.createAssignment(temp, classExpression))); // Add any pending expressions leftover from elided or relocated computed property names addRange(expressions, map(pendingExpressions, startOnNewLine)); addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); expressions.push(startOnNewLine(temp)); pendingExpressions = savedPendingExpressions; - return inlineExpressions(expressions); + return factory.inlineExpressions(expressions); } } @@ -263,7 +265,7 @@ namespace ts { members.push(constructor); } addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return setTextRange(createNodeArray(members), /*location*/ node.members); + return setTextRange(factory.createNodeArray(members), /*location*/ node.members); } function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { @@ -280,7 +282,7 @@ namespace ts { return startOnNewLine( setOriginalNode( setTextRange( - createConstructor( + factory.createConstructorDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, parameters, @@ -312,18 +314,18 @@ namespace ts { // super(...arguments); // statements.push( - createExpressionStatement( - createCall( - createSuper(), + factory.createExpressionStatement( + factory.createCall( + factory.createSuper(), /*typeArguments*/ undefined, - [createSpread(createIdentifier("arguments"))] + [factory.createSpread(factory.createIdentifier("arguments"))] ) ) ); } if (constructor) { - indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(factory, constructor, statements, visitor); } // Add the property initializers. Transforms this: @@ -351,7 +353,7 @@ namespace ts { indexOfFirstStatement += parameterPropertyDeclarationCount; } } - addPropertyStatements(statements, properties, createThis()); + addPropertyStatements(statements, properties, factory.createThis()); // Add existing statements, skipping the initial super call. if (constructor) { @@ -361,9 +363,9 @@ namespace ts { statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); return setTextRange( - createBlock( + factory.createBlock( setTextRange( - createNodeArray(statements), + factory.createNodeArray(statements), /*location*/ constructor ? constructor.body!.statements : node.members ), /*multiLine*/ true @@ -380,7 +382,7 @@ namespace ts { */ function addPropertyStatements(statements: Statement[], properties: readonly PropertyDeclaration[], receiver: LeftHandSideExpression) { for (const property of properties) { - const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); + const statement = factory.createExpressionStatement(transformInitializedProperty(property, receiver)); setSourceMapRange(statement, moveRangePastModifiers(property)); setCommentRange(statement, property); setOriginalNode(statement, property); @@ -418,20 +420,20 @@ namespace ts { // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) const emitAssignment = !context.getCompilerOptions().useDefineForClassFields; const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) - ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) + ? factory.updateComputedPropertyName(property.name, factory.getGeneratedNameForNode(property.name)) : property.name; - const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) : createVoidZero(); + const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) : factory.createVoidZero(); if (emitAssignment) { - const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); - return createAssignment(memberAccess, initializer); + const memberAccess = createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ propertyName); + return factory.createAssignment(memberAccess, initializer); } else { const name = isComputedPropertyName(propertyName) ? propertyName.expression - : isIdentifier(propertyName) ? createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) + : isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) : propertyName; - const descriptor = createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true }); - return createObjectDefinePropertyCall(receiver, name, descriptor); + const descriptor = factory.createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true }); + return factory.createObjectDefinePropertyCall(receiver, name, descriptor); } } @@ -511,9 +513,9 @@ namespace ts { const inlinable = isSimpleInlineableExpression(innerExpression); const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); if (!alreadyTransformed && !inlinable && shouldHoist) { - const generatedName = getGeneratedNameForNode(name); + const generatedName = factory.getGeneratedNameForNode(name); hoistVariableDeclaration(generatedName); - return createAssignment(generatedName, expression); + return factory.createAssignment(generatedName, expression); } return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 7746ad00b430e..4036161258f27 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -2,7 +2,7 @@ namespace ts { export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined { const compilerOptions = host.getCompilerOptions(); - const result = transformNodes(resolver, host, compilerOptions, file ? [file] : host.getSourceFiles(), [transformDeclarations], /*allowDtsFiles*/ false); + const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : host.getSourceFiles(), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } @@ -64,6 +64,7 @@ namespace ts { let suppressNewDiagnosticContexts: boolean; let exportedModulesFromDeclarationEmit: Symbol[] | undefined; + const { factory } = context; const host = context.getEmitHost(); const symbolTracker: SymbolTracker = { trackSymbol, @@ -213,7 +214,7 @@ namespace ts { refs = createMap(); libs = createMap(); let hasNoDefaultLib = false; - const bundle = createBundle(map(node.sourceFiles, + const bundle = factory.createBundle(map(node.sourceFiles, sourceFile => { if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib; @@ -230,18 +231,18 @@ namespace ts { if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) { resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules) needsDeclare = false; - const statements = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements); - const newFile = updateSourceFileNode(sourceFile, [createModuleDeclaration( + const statements = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements); + const newFile = factory.updateSourceFile(sourceFile, [factory.createModuleDeclaration( [], - [createModifier(SyntaxKind.DeclareKeyword)], - createLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), - createModuleBlock(setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)) + [factory.createModifier(SyntaxKind.DeclareKeyword)], + factory.createStringLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), + factory.createModuleBlock(setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)) )], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); return newFile; } needsDeclare = true; - const updated = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements); - return updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); + const updated = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements); + return factory.updateSourceFile(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); } ), mapDefined(node.prepends, prepend => { if (prepend.kind === SyntaxKind.InputFiles) { @@ -284,20 +285,20 @@ namespace ts { const referenceVisitor = mapReferencesIntoArray(references, outputFilePath); let combinedStatements: NodeArray; if (isSourceFileJS(currentSourceFile)) { - combinedStatements = createNodeArray(transformDeclarationsForJS(node)); + combinedStatements = factory.createNodeArray(transformDeclarationsForJS(node)); refs.forEach(referenceVisitor); emittedImports = filter(combinedStatements, isAnyImportSyntax); } else { const statements = visitNodes(node.statements, visitDeclarationStatements); - combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); + combinedStatements = setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); refs.forEach(referenceVisitor); emittedImports = filter(combinedStatements, isAnyImportSyntax); if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { - combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements); + combinedStatements = setTextRange(factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), combinedStatements); } } - const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences()); + const updated = factory.updateSourceFile(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences()); updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit; return updated; @@ -410,10 +411,10 @@ namespace ts { } else { if (name.kind === SyntaxKind.ArrayBindingPattern) { - return updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement)); + return factory.updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement)); } else { - return updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement)); + return factory.updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement)); } } @@ -422,7 +423,7 @@ namespace ts { if (elem.kind === SyntaxKind.OmittedExpression) { return elem; } - return updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined); + return factory.updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined); } } @@ -432,13 +433,13 @@ namespace ts { oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p); } - const newParam = updateParameter( + const newParam = factory.updateParameterDeclaration( p, /*decorators*/ undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(p.name), - resolver.isOptionalParameter(p) ? (p.questionToken || createToken(SyntaxKind.QuestionToken)) : undefined, + resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) : undefined, ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param ensureNoInitializer(p) ); @@ -489,12 +490,12 @@ namespace ts { return visitNode(type, visitDeclarationSubtree); } if (!getParseTreeNode(node)) { - return type ? visitNode(type, visitDeclarationSubtree) : createKeywordTypeNode(SyntaxKind.AnyKeyword); + return type ? visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } if (node.kind === SyntaxKind.SetAccessor) { // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that) - return createKeywordTypeNode(SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } errorNameNode = node.name; let oldDiag: typeof getSymbolAccessibilityDiagnostic; @@ -518,7 +519,7 @@ namespace ts { if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } - return returnValue || createKeywordTypeNode(SyntaxKind.AnyKeyword); + return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } } @@ -565,7 +566,7 @@ namespace ts { if (!newParams) { return undefined!; // TODO: GH#18217 } - return createNodeArray(newParams, params.hasTrailingComma); + return factory.createNodeArray(newParams, params.hasTrailingComma); } function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) { @@ -586,7 +587,7 @@ namespace ts { } } if (!newValueParameter) { - newValueParameter = createParameter( + newValueParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -595,7 +596,7 @@ namespace ts { } newParams = append(newParams, newValueParameter); } - return createNodeArray(newParams || emptyArray) as NodeArray; + return factory.createNodeArray(newParams || emptyArray) as NodeArray; } function ensureTypeParams(node: Node, params: NodeArray | undefined) { @@ -633,7 +634,7 @@ namespace ts { if (isBundledEmit) { const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); if (newName) { - return createLiteral(newName); + return factory.createStringLiteral(newName); } } else { @@ -651,12 +652,12 @@ namespace ts { if (decl.moduleReference.kind === SyntaxKind.ExternalModuleReference) { // Rewrite external module names if necessary const specifier = getExternalModuleImportEqualsDeclarationExpression(decl); - return updateImportEqualsDeclaration( + return factory.updateImportEqualsDeclaration( decl, /*decorators*/ undefined, decl.modifiers, decl.name, - updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier)) + factory.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier)) ); } else { @@ -671,7 +672,7 @@ namespace ts { function transformImportDeclaration(decl: ImportDeclaration) { if (!decl.importClause) { // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc) - return updateImportDeclaration( + return factory.updateImportDeclaration( decl, /*decorators*/ undefined, decl.modifiers, @@ -683,7 +684,7 @@ namespace ts { const visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined; if (!decl.importClause.namedBindings) { // No named bindings (either namespace or list), meaning the import is just default or should be elided - return visibleDefaultBinding && updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause( + return visibleDefaultBinding && factory.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, factory.updateImportClause( decl.importClause, visibleDefaultBinding, /*namedBindings*/ undefined @@ -692,7 +693,7 @@ namespace ts { if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { // Namespace import (optionally with visible default) const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined; - return visibleDefaultBinding || namedBindings ? updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause( + return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, factory.updateImportClause( decl.importClause, visibleDefaultBinding, namedBindings @@ -701,14 +702,14 @@ namespace ts { // Named imports (optionally with visible default) const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined); if ((bindingList && bindingList.length) || visibleDefaultBinding) { - return updateImportDeclaration( + return factory.updateImportDeclaration( decl, /*decorators*/ undefined, decl.modifiers, - updateImportClause( + factory.updateImportClause( decl.importClause, visibleDefaultBinding, - bindingList && bindingList.length ? updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined + bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined ), rewriteModuleSpecifier(decl, decl.moduleSpecifier) ); @@ -801,7 +802,7 @@ namespace ts { if (isMethodDeclaration(input) || isMethodSignature(input)) { if (hasModifier(input, ModifierFlags.Private)) { if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload - return cleanup(createProperty(/*decorators*/undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); + return cleanup(factory.createPropertyDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); } } @@ -825,15 +826,15 @@ namespace ts { checkEntityNameVisibility(input.expression, enclosingDeclaration); } const node = visitEachChild(input, visitDeclarationSubtree, context); - return cleanup(updateExpressionWithTypeArguments(node, parenthesizeTypeParameters(node.typeArguments), node.expression)); + return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments)); } case SyntaxKind.TypeReference: { checkEntityNameVisibility(input.typeName, enclosingDeclaration); const node = visitEachChild(input, visitDeclarationSubtree, context); - return cleanup(updateTypeReferenceNode(node, node.typeName, parenthesizeTypeParameters(node.typeArguments))); + return cleanup(factory.updateTypeReferenceNode(node, node.typeName, node.typeArguments)); } case SyntaxKind.ConstructSignature: - return cleanup(updateConstructSignature( + return cleanup(factory.updateConstructSignature( input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), @@ -842,32 +843,32 @@ namespace ts { case SyntaxKind.Constructor: { const isPrivate = hasModifier(input, ModifierFlags.Private); // A constructor declaration may not have a type annotation - const ctor = createSignatureDeclaration( - SyntaxKind.Constructor, - isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), - // TODO: GH#18217 - isPrivate ? undefined! : updateParamsList(input, input.parameters, ModifierFlags.None), - /*type*/ undefined + const ctor = factory.createConstructorDeclaration( + /*decorators*/ undefined, + /*modifiers*/ ensureModifiers(input), + isPrivate ? [] : updateParamsList(input, input.parameters, ModifierFlags.None), + /*body*/ undefined ); - ctor.modifiers = createNodeArray(ensureModifiers(input)); return cleanup(ctor); } case SyntaxKind.MethodDeclaration: { - const sig = createSignatureDeclaration( - SyntaxKind.MethodSignature, + const sig = factory.createMethodDeclaration( + /*decorators*/ undefined, + ensureModifiers(input), + /*asteriskToken*/ undefined, + input.name, + input.questionToken, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), - ensureType(input, input.type) - ) as MethodSignature; - sig.name = input.name; - sig.modifiers = createNodeArray(ensureModifiers(input)); - sig.questionToken = input.questionToken; + ensureType(input, input.type), + /*body*/ undefined + ); return cleanup(sig); } case SyntaxKind.GetAccessor: { const isPrivate = hasModifier(input, ModifierFlags.Private); const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); - return cleanup(updateGetAccessor( + return cleanup(factory.updateGetAccessorDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -877,7 +878,7 @@ namespace ts { /*body*/ undefined)); } case SyntaxKind.SetAccessor: { - return cleanup(updateSetAccessor( + return cleanup(factory.updateSetAccessorDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -886,7 +887,7 @@ namespace ts { /*body*/ undefined)); } case SyntaxKind.PropertyDeclaration: - return cleanup(updateProperty( + return cleanup(factory.updatePropertyDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -896,26 +897,26 @@ namespace ts { ensureNoInitializer(input) )); case SyntaxKind.PropertySignature: - return cleanup(updatePropertySignature( + return cleanup(factory.updatePropertySignature( input, ensureModifiers(input), input.name, input.questionToken, - !hasModifier(input, ModifierFlags.Private) ? ensureType(input, input.type) : undefined, - ensureNoInitializer(input) + !hasModifier(input, ModifierFlags.Private) ? ensureType(input, input.type) : undefined )); case SyntaxKind.MethodSignature: { - return cleanup(updateMethodSignature( + return cleanup(factory.updateMethodSignature( input, + ensureModifiers(input), + input.name, + input.questionToken, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), - ensureType(input, input.type), - input.name, - input.questionToken + ensureType(input, input.type) )); } case SyntaxKind.CallSignature: { - return cleanup(updateCallSignature( + return cleanup(factory.updateCallSignature( input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), @@ -923,12 +924,12 @@ namespace ts { )); } case SyntaxKind.IndexSignature: { - return cleanup(updateIndexSignature( + return cleanup(factory.updateIndexSignature( input, /*decorators*/ undefined, ensureModifiers(input), updateParamsList(input, input.parameters), - visitNode(input.type, visitDeclarationSubtree) || createKeywordTypeNode(SyntaxKind.AnyKeyword) + visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) )); } case SyntaxKind.VariableDeclaration: { @@ -937,11 +938,11 @@ namespace ts { } shouldEnterSuppressNewDiagnosticsContextContext = true; suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types - return cleanup(updateVariableDeclaration(input, input.name, ensureType(input, input.type), ensureNoInitializer(input))); + return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input))); } case SyntaxKind.TypeParameter: { if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) { - return cleanup(updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); + return cleanup(factory.updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); } return cleanup(visitEachChild(input, visitDeclarationSubtree, context)); } @@ -955,19 +956,19 @@ namespace ts { const trueType = visitNode(input.trueType, visitDeclarationSubtree); enclosingDeclaration = oldEnclosingDecl; const falseType = visitNode(input.falseType, visitDeclarationSubtree); - return cleanup(updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); + return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); } case SyntaxKind.FunctionType: { - return cleanup(updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); + return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); } case SyntaxKind.ConstructorType: { - return cleanup(updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); + return cleanup(factory.updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); } case SyntaxKind.ImportType: { if (!isLiteralImportTypeNode(input)) return cleanup(input); - return cleanup(updateImportTypeNode( + return cleanup(factory.updateImportTypeNode( input, - updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), + factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), input.qualifier, visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode), input.isTypeOf @@ -1018,7 +1019,7 @@ namespace ts { resultHasScopeMarker = true; // Always visible if the parent node isn't dropped for being not visible // Rewrite external module names if necessary - return updateExportDeclaration(input, /*decorators*/ undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); + return factory.updateExportDeclaration(input, /*decorators*/ undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); } case SyntaxKind.ExportAssignment: { // Always visible if the parent node isn't dropped for being not visible @@ -1030,14 +1031,14 @@ namespace ts { return input; } else { - const newId = createOptimisticUniqueName("_default"); + const newId = factory.createOptimisticUniqueName("_default"); getSymbolAccessibilityDiagnostic = () => ({ diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input }); - const varDecl = createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); - const statement = createVariableStatement(needsDeclare ? [createModifier(SyntaxKind.DeclareKeyword)] : [], createVariableDeclarationList([varDecl], NodeFlags.Const)); - return [statement, updateExportAssignment(input, input.decorators, input.modifiers, newId)]; + const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + return [statement, factory.updateExportAssignment(input, input.decorators, input.modifiers, newId)]; } } } @@ -1055,8 +1056,8 @@ namespace ts { return statement; } const clone = getMutableClone(statement); - const modifiers = createModifiersFromModifierFlags(getModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export)); - clone.modifiers = modifiers.length ? createNodeArray(modifiers) : undefined; + const modifiers = factory.createModifiersFromModifierFlags(getModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export)); + clone.modifiers = modifiers.length ? factory.createNodeArray(modifiers) : undefined; return clone; } @@ -1090,7 +1091,7 @@ namespace ts { const previousNeedsDeclare = needsDeclare; switch (input.kind) { case SyntaxKind.TypeAliasDeclaration: // Type aliases get `declare`d if need be (for legacy support), but that's all - return cleanup(updateTypeAliasDeclaration( + return cleanup(factory.updateTypeAliasDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -1099,7 +1100,7 @@ namespace ts { visitNode(input.type, visitDeclarationSubtree, isTypeNode) )); case SyntaxKind.InterfaceDeclaration: { - return cleanup(updateInterfaceDeclaration( + return cleanup(factory.updateInterfaceDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -1111,7 +1112,7 @@ namespace ts { } case SyntaxKind.FunctionDeclaration: { // Generators lose their generator-ness, excepting their return type - const clean = cleanup(updateFunctionDeclaration( + const clean = cleanup(factory.updateFunctionDeclaration( input, /*decorators*/ undefined, ensureModifiers(input), @@ -1124,7 +1125,7 @@ namespace ts { )); if (clean && resolver.isExpandoFunctionDeclaration(input)) { const props = resolver.getPropertiesOfContainerFunction(input); - const fakespace = createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || createIdentifier("_default"), createModuleBlock([]), NodeFlags.Namespace); + const fakespace = factory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace); fakespace.flags ^= NodeFlags.Synthesized; // unset synthesized so it is usable as an enclosing declaration fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration; fakespace.locals = createSymbolTable(props); @@ -1136,17 +1137,17 @@ namespace ts { getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker); getSymbolAccessibilityDiagnostic = oldDiag; - const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined); - return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl])); + const varDecl = factory.createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), /*exclamationToken*/ undefined, type, /*initializer*/ undefined); + return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([varDecl])); }); - const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, createModuleBlock(declarations), NodeFlags.Namespace); + const namespaceDecl = factory.createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace); if (!hasModifier(clean, ModifierFlags.Default)) { return [clean, namespaceDecl]; } - const modifiers = createModifiersFromModifierFlags((getModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient); - const cleanDeclaration = updateFunctionDeclaration( + const modifiers = factory.createModifiersFromModifierFlags((getModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient); + const cleanDeclaration = factory.updateFunctionDeclaration( clean, /*decorators*/ undefined, modifiers, @@ -1158,7 +1159,7 @@ namespace ts { /*body*/ undefined ); - const namespaceDeclaration = updateModuleDeclaration( + const namespaceDeclaration = factory.updateModuleDeclaration( namespaceDecl, /*decorators*/ undefined, modifiers, @@ -1166,7 +1167,7 @@ namespace ts { namespaceDecl.body ); - const exportDefaultDeclaration = createExportAssignment( + const exportDefaultDeclaration = factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, @@ -1203,18 +1204,18 @@ namespace ts { // 3. Some things are exported, some are not, and there's no marker - add an empty marker if (!isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) { if (needsScopeFixMarker) { - lateStatements = createNodeArray([...lateStatements, createEmptyExports()]); + lateStatements = factory.createNodeArray([...lateStatements, createEmptyExports(factory)]); } else { lateStatements = visitNodes(lateStatements, stripExportModifiers); } } - const body = updateModuleBlock(inner, lateStatements); + const body = factory.updateModuleBlock(inner, lateStatements); needsDeclare = previousNeedsDeclare; needsScopeFixMarker = oldNeedsScopeFix; resultHasScopeMarker = oldHasScopeFix; const mods = ensureModifiers(input); - return cleanup(updateModuleDeclaration( + return cleanup(factory.updateModuleDeclaration( input, /*decorators*/ undefined, mods, @@ -1231,7 +1232,7 @@ namespace ts { const id = "" + getOriginalNodeId(inner!); // TODO: GH#18217 const body = lateStatementReplacementMap.get(id); lateStatementReplacementMap.delete(id); - return cleanup(updateModuleDeclaration( + return cleanup(factory.updateModuleDeclaration( input, /*decorators*/ undefined, mods, @@ -1241,7 +1242,7 @@ namespace ts { } } case SyntaxKind.ClassDeclaration: { - const modifiers = createNodeArray(ensureModifiers(input)); + const modifiers = factory.createNodeArray(ensureModifiers(input)); const typeParameters = ensureTypeParams(input, input.typeParameters); const ctor = getFirstConstructorWithBody(input); let parameterProperties: readonly PropertyDeclaration[] | undefined; @@ -1251,7 +1252,7 @@ namespace ts { if (!hasModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param); if (param.name.kind === SyntaxKind.Identifier) { - return preserveJsDoc(createProperty( + return preserveJsDoc(factory.createPropertyDeclaration( /*decorators*/ undefined, ensureModifiers(param), param.name, @@ -1272,7 +1273,7 @@ namespace ts { elems = concatenate(elems, walkBindingPattern(elem.name)); } elems = elems || []; - elems.push(createProperty( + elems.push(factory.createPropertyDeclaration( /*decorators*/ undefined, ensureModifiers(param), elem.name as Identifier, @@ -1286,32 +1287,32 @@ namespace ts { })); getSymbolAccessibilityDiagnostic = oldDiag; } - const members = createNodeArray(concatenate(parameterProperties, visitNodes(input.members, visitDeclarationSubtree))); + const members = factory.createNodeArray(concatenate(parameterProperties, visitNodes(input.members, visitDeclarationSubtree))); const extendsClause = getEffectiveBaseTypeNode(input); if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) { // We must add a temporary declaration for the extends clause expression const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default"; - const newId = createOptimisticUniqueName(`${oldId}_base`); + const newId = factory.createOptimisticUniqueName(`${oldId}_base`); getSymbolAccessibilityDiagnostic = () => ({ diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, typeName: input.name }); - const varDecl = createVariableDeclaration(newId, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); - const statement = createVariableStatement(needsDeclare ? [createModifier(SyntaxKind.DeclareKeyword)] : [], createVariableDeclarationList([varDecl], NodeFlags.Const)); - const heritageClauses = createNodeArray(map(input.heritageClauses, clause => { + const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => { if (clause.token === SyntaxKind.ExtendsKeyword) { const oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); - const newClause = updateHeritageClause(clause, map(clause.types, t => updateExpressionWithTypeArguments(t, visitNodes(t.typeArguments, visitDeclarationSubtree), newId))); + const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree)))); getSymbolAccessibilityDiagnostic = oldDiag; return newClause; } - return updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree)); + return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree)); })); - return [statement, cleanup(updateClassDeclaration( + return [statement, cleanup(factory.updateClassDeclaration( input, /*decorators*/ undefined, modifiers, @@ -1323,7 +1324,7 @@ namespace ts { } else { const heritageClauses = transformHeritageClauses(input.heritageClauses); - return cleanup(updateClassDeclaration( + return cleanup(factory.updateClassDeclaration( input, /*decorators*/ undefined, modifiers, @@ -1338,11 +1339,11 @@ namespace ts { return cleanup(transformVariableStatement(input)); } case SyntaxKind.EnumDeclaration: { - return cleanup(updateEnumDeclaration(input, /*decorators*/ undefined, createNodeArray(ensureModifiers(input)), input.name, createNodeArray(mapDefined(input.members, m => { + return cleanup(factory.updateEnumDeclaration(input, /*decorators*/ undefined, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(mapDefined(input.members, m => { if (shouldStripInternal(m)) return; // Rewrite enum values to their constants, if available const constValue = resolver.getConstantValue(m); - return preserveJsDoc(updateEnumMember(m, m.name, constValue !== undefined ? createLiteral(constValue) : undefined), m); + return preserveJsDoc(factory.updateEnumMember(m, m.name, constValue !== undefined ? typeof constValue === "string" ? factory.createStringLiteral(constValue) : factory.createNumericLiteral(constValue) : undefined), m); })))); } } @@ -1370,7 +1371,7 @@ namespace ts { if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return; const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree); if (!length(nodes)) return; - return updateVariableStatement(input, createNodeArray(ensureModifiers(input)), updateVariableDeclarationList(input.declarationList, nodes)); + return factory.updateVariableStatement(input, factory.createNodeArray(ensureModifiers(input)), factory.updateVariableDeclarationList(input.declarationList, nodes)); } function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] { @@ -1387,7 +1388,7 @@ namespace ts { return recreateBindingPattern(e.name); } else { - return createVariableDeclaration(e.name, ensureType(e, /*type*/ undefined), /*initializer*/ undefined); + return factory.createVariableDeclaration(e.name, /*exclamationToken*/ undefined, ensureType(e, /*type*/ undefined), /*initializer*/ undefined); } } } @@ -1427,7 +1428,7 @@ namespace ts { if (currentFlags === newFlags) { return node.modifiers; } - return createModifiersFromModifierFlags(newFlags); + return factory.createModifiersFromModifierFlags(newFlags); } function ensureModifierFlags(node: Node): ModifierFlags { @@ -1457,7 +1458,7 @@ namespace ts { } function transformHeritageClauses(nodes: NodeArray | undefined) { - return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => { + return factory.createNodeArray(filter(map(nodes, clause => factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => { return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword); })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length)); } @@ -1472,7 +1473,7 @@ namespace ts { // Elide "public" modifier, as it is the default function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] { - return createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); + return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); } function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags { diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 23f19ef9da81f..5c18aafa4aaf1 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -59,8 +59,8 @@ namespace ts { hoistTempVariables: true, emitExpression, emitBindingOrAssignment, - createArrayBindingOrAssignmentPattern: makeArrayAssignmentPattern, - createObjectBindingOrAssignmentPattern: makeObjectAssignmentPattern, + createArrayBindingOrAssignmentPattern: elements => makeArrayAssignmentPattern(context.factory, elements), + createObjectBindingOrAssignmentPattern: elements => makeObjectAssignmentPattern(context.factory, elements), createArrayBindingOrAssignmentElement: makeAssignmentElement, visitor }; @@ -104,13 +104,12 @@ namespace ts { expressions.push(value); } - return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression(); + return context.factory.inlineExpressions(expressions!) || context.factory.createOmittedExpression(); function emitExpression(expression: Expression) { // NOTE: this completely disables source maps, but aligns with the behavior of // `emitAssignment` in the old emitter. setEmitFlags(expression, EmitFlags.NoNestedSourceMaps); - aggregateTransformFlags(expression); expressions = append(expressions, expression); } @@ -119,7 +118,7 @@ namespace ts { const expression = createAssignmentCallback ? createAssignmentCallback(target, value, location) : setTextRange( - createAssignment(visitNode(target, visitor, isExpression), value), + context.factory.createAssignment(visitNode(target, visitor, isExpression), value), location ); expression.original = original; @@ -190,9 +189,9 @@ namespace ts { hoistTempVariables, emitExpression, emitBindingOrAssignment, - createArrayBindingOrAssignmentPattern: makeArrayBindingPattern, - createObjectBindingOrAssignmentPattern: makeObjectBindingPattern, - createArrayBindingOrAssignmentElement: makeBindingElement, + createArrayBindingOrAssignmentPattern: elements => makeArrayBindingPattern(context.factory, elements), + createObjectBindingOrAssignmentPattern: elements => makeObjectBindingPattern(context.factory, elements), + createArrayBindingOrAssignmentElement: name => makeBindingElement(context.factory, name), visitor }; @@ -203,15 +202,15 @@ namespace ts { // If the right-hand value of the assignment is also an assignment target then // we need to cache the right-hand value. initializer = ensureIdentifier(flattenContext, initializer, /*reuseIdentifierExpressions*/ false, initializer); - node = updateVariableDeclaration(node, node.name, node.type, initializer); + node = context.factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, initializer); } } flattenBindingOrAssignmentElement(flattenContext, node, rval, node, skipInitializer); if (pendingExpressions) { - const temp = createTempVariable(/*recordTempVariable*/ undefined); + const temp = context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (hoistTempVariables) { - const value = inlineExpressions(pendingExpressions); + const value = context.factory.inlineExpressions(pendingExpressions); pendingExpressions = undefined; emitBindingOrAssignment(temp, value, /*location*/ undefined, /*original*/ undefined); } @@ -220,24 +219,24 @@ namespace ts { const pendingDeclaration = last(pendingDeclarations); pendingDeclaration.pendingExpressions = append( pendingDeclaration.pendingExpressions, - createAssignment(temp, pendingDeclaration.value) + context.factory.createAssignment(temp, pendingDeclaration.value) ); addRange(pendingDeclaration.pendingExpressions, pendingExpressions); pendingDeclaration.value = temp; } } for (const { pendingExpressions, name, value, location, original } of pendingDeclarations) { - const variable = createVariableDeclaration( + const variable = context.factory.createVariableDeclaration( name, + /*exclamationToken*/ undefined, /*type*/ undefined, - pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value + pendingExpressions ? context.factory.inlineExpressions(append(pendingExpressions, value)) : value ); variable.original = original; setTextRange(variable, location); if (isIdentifier(name)) { setEmitFlags(variable, EmitFlags.NoNestedSourceMaps); } - aggregateTransformFlags(variable); declarations.push(variable); } return declarations; @@ -249,7 +248,7 @@ namespace ts { function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) { Debug.assertNode(target, isBindingName); if (pendingExpressions) { - value = inlineExpressions(append(pendingExpressions, value)); + value = context.factory.inlineExpressions(append(pendingExpressions, value)); pendingExpressions = undefined; } pendingDeclarations.push({ pendingExpressions, name: target, value, location, original }); @@ -280,7 +279,7 @@ namespace ts { } else if (!value) { // Use 'void 0' in absence of value and initializer - value = createVoidZero(); + value = flattenContext.context.factory.createVoidZero(); } } const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 @@ -344,7 +343,10 @@ namespace ts { flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); bindingElements = undefined; } - const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables!, pattern); // TODO: GH#18217 + const rhsValue = setTextRange( + flattenContext.context.getEmitHelperFactory().createRestHelper(value, elements, computedTempVariables!), + pattern + ); // TODO: GH#18217 flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); } } @@ -369,12 +371,13 @@ namespace ts { // Read the elements of the iterable into an array value = ensureIdentifier( flattenContext, - createReadHelper( - flattenContext.context, - value, - numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) - ? undefined - : numElements, + setTextRange( + flattenContext.context.getEmitHelperFactory().createReadHelper( + value, + numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) + ? undefined + : numElements + ), location ), /*reuseIdentifierExpressions*/ false, @@ -400,7 +403,7 @@ namespace ts { // If an array pattern contains an ObjectRest, we must cache the result so that we // can perform the ObjectRest destructuring in a different declaration if (element.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { - const temp = createTempVariable(/*recordTempVariable*/ undefined); + const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); } @@ -416,11 +419,11 @@ namespace ts { continue; } else if (!getRestIndicatorOfBindingOrAssignmentElement(element)) { - const rhsValue = createElementAccess(value, i); + const rhsValue = flattenContext.context.factory.createElementAccess(value, i); flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } else if (i === numElements - 1) { - const rhsValue = createArraySlice(value, i); + const rhsValue = flattenContext.context.factory.createArraySliceCall(value, i); flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } @@ -444,7 +447,7 @@ namespace ts { */ function createDefaultValueCheck(flattenContext: FlattenContext, value: Expression, defaultValue: Expression, location: TextRange): Expression { value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); - return createConditional(createTypeCheck(value, "undefined"), defaultValue, value); + return flattenContext.context.factory.createConditional(flattenContext.context.factory.createTypeCheck(value, "undefined"), /*questionToken*/ undefined, defaultValue, /*colonToken*/ undefined, value); } /** @@ -460,16 +463,16 @@ namespace ts { function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: Expression, propertyName: PropertyName): LeftHandSideExpression { if (isComputedPropertyName(propertyName)) { const argumentExpression = ensureIdentifier(flattenContext, visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); - return createElementAccess(value, argumentExpression); + return flattenContext.context.factory.createElementAccess(value, argumentExpression); } else if (isStringOrNumericLiteralLike(propertyName)) { const argumentExpression = getSynthesizedClone(propertyName); argumentExpression.text = argumentExpression.text; - return createElementAccess(value, argumentExpression); + return flattenContext.context.factory.createElementAccess(value, argumentExpression); } else { - const name = createIdentifier(idText(propertyName)); - return createPropertyAccess(value, name); + const name = flattenContext.context.factory.createIdentifier(idText(propertyName)); + return flattenContext.context.factory.createPropertyAccess(value, name); } } @@ -489,10 +492,10 @@ namespace ts { return value; } else { - const temp = createTempVariable(/*recordTempVariable*/ undefined); + const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); - flattenContext.emitExpression(setTextRange(createAssignment(temp, value), location)); + flattenContext.emitExpression(setTextRange(flattenContext.context.factory.createAssignment(temp, value), location)); } else { flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); @@ -501,86 +504,29 @@ namespace ts { } } - function makeArrayBindingPattern(elements: BindingOrAssignmentElement[]) { + function makeArrayBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { Debug.assertEachNode(elements, isArrayBindingElement); - return createArrayBindingPattern(elements); + return factory.createArrayBindingPattern(elements); } - function makeArrayAssignmentPattern(elements: BindingOrAssignmentElement[]) { - return createArrayLiteral(map(elements, convertToArrayAssignmentElement)); + function makeArrayAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + return factory.createArrayLiteral(map(elements, factory.converters.convertToArrayAssignmentElement)); } - function makeObjectBindingPattern(elements: BindingOrAssignmentElement[]) { + function makeObjectBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { Debug.assertEachNode(elements, isBindingElement); - return createObjectBindingPattern(elements); + return factory.createObjectBindingPattern(elements); } - function makeObjectAssignmentPattern(elements: BindingOrAssignmentElement[]) { - return createObjectLiteral(map(elements, convertToObjectAssignmentElement)); + function makeObjectAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + return factory.createObjectLiteral(map(elements, factory.converters.convertToObjectAssignmentElement)); } - function makeBindingElement(name: Identifier) { - return createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); + function makeBindingElement(factory: NodeFactory, name: Identifier) { + return factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); } function makeAssignmentElement(name: Identifier) { return name; } - - export const restHelper: UnscopedEmitHelper = { - name: "typescript:rest", - importName: "__rest", - scoped: false, - text: ` - var __rest = (this && this.__rest) || function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; - };` - }; - - /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement - * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` - */ - function createRestCall(context: TransformationContext, value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[], location: TextRange): Expression { - context.requestEmitHelper(restHelper); - const propertyNames: Expression[] = []; - let computedTempVariableOffset = 0; - for (let i = 0; i < elements.length - 1; i++) { - const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); - if (propertyName) { - if (isComputedPropertyName(propertyName)) { - const temp = computedTempVariables[computedTempVariableOffset]; - computedTempVariableOffset++; - // typeof _tmp === "symbol" ? _tmp : _tmp + "" - propertyNames.push( - createConditional( - createTypeCheck(temp, "symbol"), - temp, - createAdd(temp, createLiteral("")) - ) - ); - } - else { - propertyNames.push(createLiteral(propertyName)); - } - } - } - return createCall( - getUnscopedHelperName("__rest"), - /*typeArguments*/ undefined, - [ - value, - setTextRange( - createArrayLiteral(propertyNames), - location - ) - ]); - } } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 2684b1acdd554..19497ba336f5f 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -244,6 +244,8 @@ namespace ts { export function transformES2015(context: TransformationContext) { const { + factory, + getEmitHelperFactory: emitHelpers, startLexicalEnvironment, resumeLexicalEnvironment, endLexicalEnvironment, @@ -265,7 +267,7 @@ namespace ts { function recordTaggedTemplateString(temp: Identifier) { taggedTemplateStringDeclarations = append( taggedTemplateStringDeclarations, - createVariableDeclaration(temp)); + factory.createVariableDeclaration(temp)); } /** @@ -280,7 +282,7 @@ namespace ts { */ let enabledSubstitutions: ES2015SubstitutionFlags; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -328,10 +330,26 @@ namespace ts { && !(node).expression; } + function isOrMayContainReturnCompletion(node: Node) { + return node.transformFlags & TransformFlags.ContainsHoistedDeclarationOrCompletion + && (isReturnStatement(node) + || isIfStatement(node) + || isWithStatement(node) + || isSwitchStatement(node) + || isCaseBlock(node) + || isCaseClause(node) + || isDefaultClause(node) + || isTryStatement(node) + || isCatchClause(node) + || isLabeledStatement(node) + || isIterationStatement(node, /*lookInLabeledStatements*/ false) + || isBlock(node)); + } + function shouldVisitNode(node: Node): boolean { return (node.transformFlags & TransformFlags.ContainsES2015) !== 0 || convertedLoopState !== undefined - || (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block))) + || (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && isOrMayContainReturnCompletion(node)) || (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatement(node)) || (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0; } @@ -499,20 +517,19 @@ namespace ts { const prologue: Statement[] = []; const statements: Statement[] = []; startLexicalEnvironment(); - let statementOffset = addStandardPrologue(prologue, node.statements, /*ensureUseStrict*/ false); - statementOffset = addCustomPrologue(prologue, node.statements, statementOffset, visitor); + const statementOffset = factory.copyPrologue(node.statements, prologue, /*ensureUseStrict*/ false, visitor); addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset)); if (taggedTemplateStringDeclarations) { statements.push( - createVariableStatement(/*modifiers*/ undefined, - createVariableDeclarationList(taggedTemplateStringDeclarations))); + factory.createVariableStatement(/*modifiers*/ undefined, + factory.createVariableDeclarationList(taggedTemplateStringDeclarations))); } mergeLexicalEnvironment(prologue, endLexicalEnvironment()); insertCaptureThisForNodeIfNeeded(prologue, node); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); - return updateSourceFileNode( + return factory.updateSourceFile( node, - setTextRange(createNodeArray(concatenate(prologue, statements)), node.statements) + setTextRange(factory.createNodeArray(concatenate(prologue, statements)), node.statements) ); } @@ -536,7 +553,7 @@ namespace ts { } function returnCapturedThis(node: Node): ReturnStatement { - return setOriginalNode(createReturn(createFileLevelUniqueName("_this")), node); + return setOriginalNode(factory.createReturn(factory.createFileLevelUniqueName("_this")), node); } function visitReturnStatement(node: ReturnStatement): Statement { @@ -545,14 +562,14 @@ namespace ts { if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) { node = returnCapturedThis(node); } - return createReturn( - createObjectLiteral( + return factory.createReturn( + factory.createObjectLiteral( [ - createPropertyAssignment( - createIdentifier("value"), + factory.createPropertyAssignment( + factory.createIdentifier("value"), node.expression ? visitNode(node.expression, visitor, isExpression) - : createVoidZero() + : factory.createVoidZero() ) ] ) @@ -574,7 +591,7 @@ namespace ts { convertedLoopState.containsLexicalThis = true; return node; } - return convertedLoopState.thisName || (convertedLoopState.thisName = createUniqueName("this")); + return convertedLoopState.thisName || (convertedLoopState.thisName = factory.createUniqueName("this")); } return node; } @@ -589,7 +606,7 @@ namespace ts { if (node.escapedText !== "arguments" || !resolver.isArgumentsLocalBinding(node)) { return node; } - return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments")); + return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = factory.createUniqueName("arguments")); } function visitBreakOrContinueStatement(node: BreakOrContinueStatement): Statement { @@ -627,7 +644,7 @@ namespace ts { setLabeledJump(convertedLoopState, /*isBreak*/ false, idText(label), labelMarker); } } - let returnExpression: Expression = createLiteral(labelMarker); + let returnExpression: Expression = factory.createStringLiteral(labelMarker); if (convertedLoopState.loopOutParameters.length) { const outParams = convertedLoopState.loopOutParameters; let expr: Expression | undefined; @@ -637,12 +654,12 @@ namespace ts { expr = copyExpr; } else { - expr = createBinary(expr!, SyntaxKind.CommaToken, copyExpr); + expr = factory.createBinary(expr!, SyntaxKind.CommaToken, copyExpr); } } - returnExpression = createBinary(expr!, SyntaxKind.CommaToken, returnExpression); + returnExpression = factory.createBinary(expr!, SyntaxKind.CommaToken, returnExpression); } - return createReturn(returnExpression); + return factory.createReturn(returnExpression); } } return visitEachChild(node, visitor, context); @@ -664,8 +681,9 @@ namespace ts { // return C; // }()); - const variable = createVariableDeclaration( - getLocalName(node, /*allowComments*/ true), + const variable = factory.createVariableDeclaration( + factory.getLocalName(node, /*allowComments*/ true), + /*exclamationToken*/ undefined, /*type*/ undefined, transformClassLikeDeclarationToExpression(node) ); @@ -673,7 +691,7 @@ namespace ts { setOriginalNode(variable, node); const statements: Statement[] = []; - const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable])); + const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([variable])); setOriginalNode(statement, node); setTextRange(statement, node); @@ -683,8 +701,8 @@ namespace ts { // Add an `export default` statement for default exports (for `--target es5 --module es6`) if (hasModifier(node, ModifierFlags.Export)) { const exportStatement = hasModifier(node, ModifierFlags.Default) - ? createExportDefault(getLocalName(node)) - : createExternalModuleExport(getLocalName(node)); + ? factory.createExportDefault(factory.getLocalName(node)) + : factory.createExternalModuleExport(factory.getLocalName(node)); setOriginalNode(exportStatement, statement); statements.push(exportStatement); @@ -693,7 +711,7 @@ namespace ts { const emitFlags = getEmitFlags(node); if ((emitFlags & EmitFlags.HasEndOfDeclarationMarker) === 0) { // Add a DeclarationMarker as a marker for the end of the declaration - statements.push(createEndOfDeclarationMarker(node)); + statements.push(factory.createEndOfDeclarationMarker(node)); setEmitFlags(statement, emitFlags | EmitFlags.HasEndOfDeclarationMarker); } @@ -753,12 +771,12 @@ namespace ts { } const extendsClauseElement = getClassExtendsHeritageElement(node); - const classFunction = createFunctionExpression( + const classFunction = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - extendsClauseElement ? [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, createFileLevelUniqueName("_super"))] : [], + extendsClauseElement ? [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, factory.createFileLevelUniqueName("_super"))] : [], /*type*/ undefined, transformClassBody(node, extendsClauseElement) ); @@ -770,16 +788,16 @@ namespace ts { // "inner" and "outer" below are added purely to preserve source map locations from // the old emitter - const inner = createPartiallyEmittedExpression(classFunction); + const inner = factory.createPartiallyEmittedExpression(classFunction); inner.end = node.end; setEmitFlags(inner, EmitFlags.NoComments); - const outer = createPartiallyEmittedExpression(inner); + const outer = factory.createPartiallyEmittedExpression(inner); outer.end = skipTrivia(currentText, node.pos); setEmitFlags(outer, EmitFlags.NoComments); - const result = createParen( - createCall( + const result = factory.createParen( + factory.createCall( outer, /*typeArguments*/ undefined, extendsClauseElement @@ -806,22 +824,22 @@ namespace ts { // Create a synthetic text range for the return statement. const closingBraceLocation = createTokenRange(skipTrivia(currentText, node.members.end), SyntaxKind.CloseBraceToken); - const localName = getInternalName(node); + const localName = factory.getInternalName(node); // The following partially-emitted expression exists purely to align our sourcemap // emit with the original emitter. - const outer = createPartiallyEmittedExpression(localName); + const outer = factory.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; setEmitFlags(outer, EmitFlags.NoComments); - const statement = createReturn(outer); + const statement = factory.createReturn(outer); statement.pos = closingBraceLocation.pos; setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps); statements.push(statement); insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const block = createBlock(setTextRange(createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); + const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); setEmitFlags(block, EmitFlags.NoComments); return block; } @@ -837,8 +855,8 @@ namespace ts { if (extendsClauseElement) { statements.push( setTextRange( - createExpressionStatement( - createExtendsHelper(context, getInternalName(node)) + factory.createExpressionStatement( + emitHelpers().createExtendsHelper(factory.getInternalName(node)) ), /*location*/ extendsClauseElement ) @@ -859,11 +877,11 @@ namespace ts { const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes); const constructor = getFirstConstructorWithBody(node); const hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); - const constructorFunction = createFunctionDeclaration( + const constructorFunction = factory.createFunctionDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, - getInternalName(node), + factory.getInternalName(node), /*typeParameters*/ undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), /*type*/ undefined, @@ -907,13 +925,13 @@ namespace ts { if (isDerivedClass) { // return _super !== null && _super.apply(this, arguments) || this; - statements.push(createReturn(createDefaultSuperCallOrThis())); + statements.push(factory.createReturn(createDefaultSuperCallOrThis())); } - const statementsArray = createNodeArray(statements); + const statementsArray = factory.createNodeArray(statements); setTextRange(statementsArray, node.members); - const block = createBlock(statementsArray, /*multiLine*/ true); + const block = factory.createBlock(statementsArray, /*multiLine*/ true); setTextRange(block, node); setEmitFlags(block, EmitFlags.NoComments); return block; @@ -959,10 +977,10 @@ namespace ts { // we're going to assume that we should just transform everything after that. // The assumption is that no prior step in the pipeline has added any prologue directives. let statementOffset = 0; - if (!hasSynthesizedSuper) statementOffset = addStandardPrologue(prologue, constructor.body.statements, /*ensureUseStrict*/ false); + if (!hasSynthesizedSuper) statementOffset = factory.copyStandardPrologue(constructor.body.statements, prologue, /*ensureUseStrict*/ false); addDefaultValueAssignmentsIfNeeded(statements, constructor); addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); - if (!hasSynthesizedSuper) statementOffset = addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor); + if (!hasSynthesizedSuper) statementOffset = factory.copyCustomPrologue(constructor.body.statements, statements, statementOffset, visitor); // If the first statement is a call to `super()`, visit the statement directly let superCallExpression: Expression | undefined; @@ -1009,7 +1027,7 @@ namespace ts { // })(Base); // ``` const superCall = cast(cast(superCallExpression, isBinaryExpression).left, isCallExpression); - const returnStatement = createReturn(superCallExpression); + const returnStatement = factory.createReturn(superCallExpression); setCommentRange(returnStatement, getCommentRange(superCall)); setEmitFlags(superCall, EmitFlags.NoComments); statements.push(returnStatement); @@ -1042,7 +1060,7 @@ namespace ts { insertCaptureThisForNode(statements, constructor, superCallExpression || createActualThis()); if (!isSufficientlyCoveredByReturnStatements(constructor.body)) { - statements.push(createReturn(createFileLevelUniqueName("_this"))); + statements.push(factory.createReturn(factory.createFileLevelUniqueName("_this"))); } } } @@ -1064,9 +1082,9 @@ namespace ts { insertCaptureThisForNodeIfNeeded(prologue, constructor); } - const block = createBlock( + const block = factory.createBlock( setTextRange( - createNodeArray( + factory.createNodeArray( concatenate(prologue, statements) ), /*location*/ constructor.body.statements @@ -1109,20 +1127,20 @@ namespace ts { } function createActualThis() { - return setEmitFlags(createThis(), EmitFlags.NoSubstitution); + return setEmitFlags(factory.createThis(), EmitFlags.NoSubstitution); } function createDefaultSuperCallOrThis() { - return createLogicalOr( - createLogicalAnd( - createStrictInequality( - createFileLevelUniqueName("_super"), - createNull() + return factory.createLogicalOr( + factory.createLogicalAnd( + factory.createStrictInequality( + factory.createFileLevelUniqueName("_super"), + factory.createNull() ), - createFunctionApply( - createFileLevelUniqueName("_super"), + factory.createFunctionApplyCall( + factory.createFileLevelUniqueName("_super"), createActualThis(), - createIdentifier("arguments"), + factory.createIdentifier("arguments"), ) ), createActualThis() @@ -1144,11 +1162,11 @@ namespace ts { // evaluated inside the function body. return setOriginalNode( setTextRange( - createParameter( + factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - getGeneratedNameForNode(node), + factory.getGeneratedNameForNode(node), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined @@ -1162,7 +1180,7 @@ namespace ts { // Initializers are elided return setOriginalNode( setTextRange( - createParameter( + factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -1235,15 +1253,15 @@ namespace ts { insertStatementAfterCustomPrologue( statements, setEmitFlags( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( flattenDestructuringBinding( parameter, visitor, context, FlattenLevel.All, - getGeneratedNameForNode(parameter) + factory.getGeneratedNameForNode(parameter) ) ) ), @@ -1256,9 +1274,9 @@ namespace ts { insertStatementAfterCustomPrologue( statements, setEmitFlags( - createExpressionStatement( - createAssignment( - getGeneratedNameForNode(parameter), + factory.createExpressionStatement( + factory.createAssignment( + factory.getGeneratedNameForNode(parameter), visitNode(initializer, visitor, isExpression) ) ), @@ -1280,15 +1298,15 @@ namespace ts { */ function insertDefaultValueAssignmentForInitializer(statements: Statement[], parameter: ParameterDeclaration, name: Identifier, initializer: Expression): void { initializer = visitNode(initializer, visitor, isExpression); - const statement = createIf( - createTypeCheck(getSynthesizedClone(name), "undefined"), + const statement = factory.createIf( + factory.createTypeCheck(getSynthesizedClone(name), "undefined"), setEmitFlags( setTextRange( - createBlock([ - createExpressionStatement( + factory.createBlock([ + factory.createExpressionStatement( setEmitFlags( setTextRange( - createAssignment( + factory.createAssignment( setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap), setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments) ), @@ -1339,25 +1357,26 @@ namespace ts { } // `declarationName` is the name of the local declaration for the parameter. - const declarationName = parameter.name.kind === SyntaxKind.Identifier ? getMutableClone(parameter.name) : createTempVariable(/*recordTempVariable*/ undefined); + const declarationName = parameter.name.kind === SyntaxKind.Identifier ? getMutableClone(parameter.name) : factory.createTempVariable(/*recordTempVariable*/ undefined); setEmitFlags(declarationName, EmitFlags.NoSourceMap); // `expressionName` is the name of the parameter used in expressions. const expressionName = parameter.name.kind === SyntaxKind.Identifier ? getSynthesizedClone(parameter.name) : declarationName; const restIndex = node.parameters.length - 1; - const temp = createLoopVariable(); + const temp = factory.createLoopVariable(); // var param = []; prologueStatements.push( setEmitFlags( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( declarationName, + /*exclamationToken*/ undefined, /*type*/ undefined, - createArrayLiteral([]) + factory.createArrayLiteral([]) ) ]) ), @@ -1370,33 +1389,33 @@ namespace ts { // for (var _i = restIndex; _i < arguments.length; _i++) { // param[_i - restIndex] = arguments[_i]; // } - const forStatement = createFor( + const forStatement = factory.createFor( setTextRange( - createVariableDeclarationList([ - createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex)) + factory.createVariableDeclarationList([ + factory.createVariableDeclaration(temp, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(restIndex)) ]), parameter ), setTextRange( - createLessThan( + factory.createLessThan( temp, - createPropertyAccess(createIdentifier("arguments"), "length") + factory.createPropertyAccess(factory.createIdentifier("arguments"), "length") ), parameter ), - setTextRange(createPostfixIncrement(temp), parameter), - createBlock([ + setTextRange(factory.createPostfixIncrement(temp), parameter), + factory.createBlock([ startOnNewLine( setTextRange( - createExpressionStatement( - createAssignment( - createElementAccess( + factory.createExpressionStatement( + factory.createAssignment( + factory.createElementAccess( expressionName, restIndex === 0 ? temp - : createSubtract(temp, createLiteral(restIndex)) + : factory.createSubtract(temp, factory.createNumericLiteral(restIndex)) ), - createElementAccess(createIdentifier("arguments"), temp) + factory.createElementAccess(factory.createIdentifier("arguments"), temp) ) ), /*location*/ parameter @@ -1414,9 +1433,9 @@ namespace ts { prologueStatements.push( setEmitFlags( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( flattenDestructuringBinding(parameter, visitor, context, FlattenLevel.All, expressionName), ) ), @@ -1440,7 +1459,7 @@ namespace ts { */ function insertCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): boolean { if (hierarchyFacts & HierarchyFacts.CapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) { - insertCaptureThisForNode(statements, node, createThis()); + insertCaptureThisForNode(statements, node, factory.createThis()); return true; } return false; @@ -1448,11 +1467,12 @@ namespace ts { function insertCaptureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined): void { enableSubstitutionsForCapturedThis(); - const captureThisStatement = createVariableStatement( + const captureThisStatement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( - createFileLevelUniqueName("_this"), + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.createFileLevelUniqueName("_this"), + /*exclamationToken*/ undefined, /*type*/ undefined, initializer ) @@ -1475,14 +1495,14 @@ namespace ts { case SyntaxKind.SetAccessor: // Methods and accessors cannot be constructors, so 'new.target' will // always return 'undefined'. - newTarget = createVoidZero(); + newTarget = factory.createVoidZero(); break; case SyntaxKind.Constructor: // Class constructors can only be called with `new`, so `this.constructor` // should be relatively safe to use. - newTarget = createPropertyAccess( - setEmitFlags(createThis(), EmitFlags.NoSubstitution), + newTarget = factory.createPropertyAccess( + setEmitFlags(factory.createThis(), EmitFlags.NoSubstitution), "constructor" ); break; @@ -1491,20 +1511,22 @@ namespace ts { case SyntaxKind.FunctionExpression: // Functions can be called or constructed, and may have a `this` due to // being a member or when calling an imported function via `other_1.f()`. - newTarget = createConditional( - createLogicalAnd( - setEmitFlags(createThis(), EmitFlags.NoSubstitution), - createBinary( - setEmitFlags(createThis(), EmitFlags.NoSubstitution), + newTarget = factory.createConditional( + factory.createLogicalAnd( + setEmitFlags(factory.createThis(), EmitFlags.NoSubstitution), + factory.createBinary( + setEmitFlags(factory.createThis(), EmitFlags.NoSubstitution), SyntaxKind.InstanceOfKeyword, - getLocalName(node) + factory.getLocalName(node) ) ), - createPropertyAccess( - setEmitFlags(createThis(), EmitFlags.NoSubstitution), + /*questionToken*/ undefined, + factory.createPropertyAccess( + setEmitFlags(factory.createThis(), EmitFlags.NoSubstitution), "constructor" ), - createVoidZero() + /*colonToken*/ undefined, + factory.createVoidZero() ); break; @@ -1512,11 +1534,12 @@ namespace ts { return Debug.failBadSyntaxKind(node); } - const captureNewTargetStatement = createVariableStatement( + const captureNewTargetStatement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( - createFileLevelUniqueName("_newTarget"), + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.createFileLevelUniqueName("_newTarget"), + /*exclamationToken*/ undefined, /*type*/ undefined, newTarget ) @@ -1579,7 +1602,7 @@ namespace ts { * @param member The SemicolonClassElement node. */ function transformSemicolonClassElementToStatement(member: SemicolonClassElement) { - return setTextRange(createEmptyStatement(), member); + return setTextRange(factory.createEmptyStatement(), member); } /** @@ -1596,17 +1619,17 @@ namespace ts { if (context.getCompilerOptions().useDefineForClassFields) { const propertyName = visitNode(member.name, visitor, isPropertyName); const name = isComputedPropertyName(propertyName) ? propertyName.expression - : isIdentifier(propertyName) ? createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) + : isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) : propertyName; - e = createObjectDefinePropertyCall(receiver, name, createPropertyDescriptor({ value: memberFunction, enumerable: false, writable: true, configurable: true })); + e = factory.createObjectDefinePropertyCall(receiver, name, factory.createPropertyDescriptor({ value: memberFunction, enumerable: false, writable: true, configurable: true })); } else { - const memberName = createMemberAccessForPropertyName(receiver, visitNode(member.name, visitor, isPropertyName), /*location*/ member.name); - e = createAssignment(memberName, memberFunction); + const memberName = createMemberAccessForPropertyName(factory, receiver, visitNode(member.name, visitor, isPropertyName), /*location*/ member.name); + e = factory.createAssignment(memberName, memberFunction); } setEmitFlags(memberFunction, EmitFlags.NoComments); setSourceMapRange(memberFunction, sourceMapRange); - const statement = setTextRange(createExpressionStatement(e), /*location*/ member); + const statement = setTextRange(factory.createExpressionStatement(e), /*location*/ member); setOriginalNode(statement, member); setCommentRange(statement, commentRange); @@ -1625,7 +1648,7 @@ namespace ts { * @param accessors The set of related get/set accessors. */ function transformAccessorsToStatement(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations, container: Node): Statement { - const statement = createExpressionStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); + const statement = factory.createExpressionStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); // The location for the statement is used to emit source maps only. // No comments should be emitted for this statement to align with the // old emitter. @@ -1647,7 +1670,7 @@ namespace ts { setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap); setSourceMapRange(target, firstAccessor.name); - const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); + const propertyName = createExpressionForPropertyName(factory, visitNode(firstAccessor.name, visitor, isPropertyName)); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); setSourceMapRange(propertyName, firstAccessor.name); @@ -1656,7 +1679,7 @@ namespace ts { const getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined, container); setSourceMapRange(getterFunction, getSourceMapRange(getAccessor)); setEmitFlags(getterFunction, EmitFlags.NoLeadingComments); - const getter = createPropertyAssignment("get", getterFunction); + const getter = factory.createPropertyAssignment("get", getterFunction); setCommentRange(getter, getCommentRange(getAccessor)); properties.push(getter); } @@ -1665,23 +1688,23 @@ namespace ts { const setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined, container); setSourceMapRange(setterFunction, getSourceMapRange(setAccessor)); setEmitFlags(setterFunction, EmitFlags.NoLeadingComments); - const setter = createPropertyAssignment("set", setterFunction); + const setter = factory.createPropertyAssignment("set", setterFunction); setCommentRange(setter, getCommentRange(setAccessor)); properties.push(setter); } properties.push( - createPropertyAssignment("enumerable", createTrue()), - createPropertyAssignment("configurable", createTrue()) + factory.createPropertyAssignment("enumerable", factory.createTrue()), + factory.createPropertyAssignment("configurable", factory.createTrue()) ); - const call = createCall( - createPropertyAccess(createIdentifier("Object"), "defineProperty"), + const call = factory.createCall( + factory.createPropertyAccess(factory.createIdentifier("Object"), "defineProperty"), /*typeArguments*/ undefined, [ target, propertyName, - createObjectLiteral(properties, /*multiLine*/ true) + factory.createObjectLiteral(properties, /*multiLine*/ true) ] ); if (startsOnNewLine) { @@ -1704,7 +1727,7 @@ namespace ts { const savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.ArrowFunctionExcludes, HierarchyFacts.ArrowFunctionIncludes); - const func = createFunctionExpression( + const func = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, @@ -1743,12 +1766,12 @@ namespace ts { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); const name = hierarchyFacts & HierarchyFacts.NewTarget - ? getLocalName(node) + ? factory.getLocalName(node) : node.name; exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; - return updateFunctionExpression( + return factory.updateFunctionExpression( node, /*modifiers*/ undefined, node.asteriskToken, @@ -1772,12 +1795,12 @@ namespace ts { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); const name = hierarchyFacts & HierarchyFacts.NewTarget - ? getLocalName(node) + ? factory.getLocalName(node) : node.name; exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; - return updateFunctionDeclaration( + return factory.updateFunctionDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, visitor, isModifier), @@ -1806,14 +1829,14 @@ namespace ts { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); if (hierarchyFacts & HierarchyFacts.NewTarget && !name && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) { - name = getGeneratedNameForNode(node); + name = factory.getGeneratedNameForNode(node); } exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; return setOriginalNode( setTextRange( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, node.asteriskToken, name, @@ -1848,7 +1871,7 @@ namespace ts { if (isBlock(body)) { // ensureUseStrict is false because no new prologue-directive should be added. // addStandardPrologue will put already-existing directives at the beginning of the target statement-array - statementOffset = addStandardPrologue(prologue, body.statements, /*ensureUseStrict*/ false); + statementOffset = factory.copyStandardPrologue(body.statements, prologue, /*ensureUseStrict*/ false); } multiLine = addDefaultValueAssignmentsIfNeeded(statements, node) || multiLine; @@ -1856,7 +1879,7 @@ namespace ts { if (isBlock(body)) { // addCustomPrologue puts already-existing directives at the beginning of the target statement-array - statementOffset = addCustomPrologue(statements, body.statements, statementOffset, visitor); + statementOffset = factory.copyCustomPrologue(body.statements, statements, statementOffset, visitor); statementsLocation = body.statements; addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset)); @@ -1886,7 +1909,7 @@ namespace ts { } const expression = visitNode(body, visitor, isExpression); - const returnStatement = createReturn(expression); + const returnStatement = factory.createReturn(expression); setTextRange(returnStatement, body); moveSyntheticComments(returnStatement, body); setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments); @@ -1912,7 +1935,7 @@ namespace ts { return body; } - const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine); + const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), statementsLocation), multiLine); setTextRange(block, node.body); if (!multiLine && singleLine) { setEmitFlags(block, EmitFlags.SingleLine); @@ -1948,9 +1971,9 @@ namespace ts { // If we are here it is most likely because our expression is a destructuring assignment. switch (node.expression.kind) { case SyntaxKind.ParenthesizedExpression: - return updateExpressionStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + return factory.updateExpressionStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); case SyntaxKind.BinaryExpression: - return updateExpressionStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); + return factory.updateExpressionStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } return visitEachChild(node, visitor, context); } @@ -1970,9 +1993,9 @@ namespace ts { // we pass that information along to the children that care about it. switch (node.expression.kind) { case SyntaxKind.ParenthesizedExpression: - return updateParen(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + return factory.updateParen(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); case SyntaxKind.BinaryExpression: - return updateParen(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); + return factory.updateParen(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } } return visitEachChild(node, visitor, context); @@ -2017,7 +2040,7 @@ namespace ts { ); } else { - assignment = createBinary(decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression)); + assignment = factory.createBinary(decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression)); setTextRange(assignment, decl); } @@ -2025,7 +2048,7 @@ namespace ts { } } if (assignments) { - updated = setTextRange(createExpressionStatement(inlineExpressions(assignments)), node); + updated = setTextRange(factory.createExpressionStatement(factory.inlineExpressions(assignments)), node); } else { // none of declarations has initializer - the entire variable statement can be deleted @@ -2055,7 +2078,7 @@ namespace ts { ? visitVariableDeclarationInLetDeclarationList : visitVariableDeclaration); - const declarationList = createVariableDeclarationList(declarations); + const declarationList = factory.createVariableDeclarationList(declarations); setOriginalNode(declarationList, node); setTextRange(declarationList, node); setCommentRange(declarationList, node); @@ -2165,9 +2188,7 @@ namespace ts { } if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) { - const clone = getMutableClone(node); - clone.initializer = createVoidZero(); - return clone; + return factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createVoidZero()); } return visitEachChild(node, visitor, context); @@ -2214,7 +2235,7 @@ namespace ts { const statement = unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel); return isIterationStatement(statement, /*lookInLabeledStatements*/ false) ? visitIterationStatement(statement, /*outermostLabeledStatement*/ node) - : restoreEnclosingLabel(visitNode(statement, visitor, isStatement, liftToBlock), node, convertedLoopState && resetLabel); + : factory.restoreEnclosingLabel(visitNode(statement, visitor, isStatement, factory.liftToBlock), node, convertedLoopState && resetLabel); } function visitIterationStatement(node: IterationStatement, outermostLabeledStatement: LabeledStatement) { @@ -2291,7 +2312,7 @@ namespace ts { boundValue ); - const declarationList = setTextRange(createVariableDeclarationList(declarations), node.initializer); + const declarationList = setTextRange(factory.createVariableDeclarationList(declarations), node.initializer); setOriginalNode(declarationList, node.initializer); // Adjust the source map range for the first declaration to align with the old @@ -2299,7 +2320,7 @@ namespace ts { setSourceMapRange(declarationList, createRange(declarations[0].pos, last(declarations).end)); statements.push( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, declarationList ) @@ -2310,13 +2331,14 @@ namespace ts { // to emit it separately. statements.push( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, setOriginalNode( setTextRange( - createVariableDeclarationList([ - createVariableDeclaration( - firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined), + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + firstOriginalDeclaration ? firstOriginalDeclaration.name : factory.createTempVariable(/*recordTempVariable*/ undefined), + /*exclamationToken*/ undefined, /*type*/ undefined, boundValue ) @@ -2334,14 +2356,13 @@ namespace ts { else { // Initializer is an expression. Emit the expression in the body, so that it's // evaluated on every iteration. - const assignment = createAssignment(initializer, boundValue); + const assignment = factory.createAssignment(initializer, boundValue); if (isDestructuringAssignment(assignment)) { - aggregateTransformFlags(assignment); - statements.push(createExpressionStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); + statements.push(factory.createExpressionStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); } else { assignment.end = initializer.end; - statements.push(setTextRange(createExpressionStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(initializer, -1))); + statements.push(setTextRange(factory.createExpressionStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(initializer, -1))); } } @@ -2349,9 +2370,9 @@ namespace ts { return createSyntheticBlockForConvertedStatements(addRange(statements, convertedLoopBodyStatements)); } else { - const statement = visitNode(node.statement, visitor, isStatement, liftToBlock); + const statement = visitNode(node.statement, visitor, isStatement, factory.liftToBlock); if (isBlock(statement)) { - return updateBlock(statement, setTextRange(createNodeArray(concatenate(statements, statement.statements)), statement.statements)); + return factory.updateBlock(statement, setTextRange(factory.createNodeArray(concatenate(statements, statement.statements)), statement.statements)); } else { statements.push(statement); @@ -2362,8 +2383,8 @@ namespace ts { function createSyntheticBlockForConvertedStatements(statements: Statement[]) { return setEmitFlags( - createBlock( - createNodeArray(statements), + factory.createBlock( + factory.createNodeArray(statements), /*multiLine*/ true ), EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps @@ -2399,35 +2420,35 @@ namespace ts { // for (let v of arr) { } // // we don't want to emit a temporary variable for the RHS, just use it directly. - const counter = createLoopVariable(); - const rhsReference = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined); + const counter = factory.createLoopVariable(); + const rhsReference = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); // The old emitter does not emit source maps for the expression setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression)); const forStatement = setTextRange( - createFor( + factory.createFor( /*initializer*/ setEmitFlags( setTextRange( - createVariableDeclarationList([ - setTextRange(createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0)), moveRangePos(node.expression, -1)), - setTextRange(createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression) + factory.createVariableDeclarationList([ + setTextRange(factory.createVariableDeclaration(counter, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(0)), moveRangePos(node.expression, -1)), + setTextRange(factory.createVariableDeclaration(rhsReference, /*exclamationToken*/ undefined, /*type*/ undefined, expression), node.expression) ]), node.expression ), EmitFlags.NoHoisting ), /*condition*/ setTextRange( - createLessThan( + factory.createLessThan( counter, - createPropertyAccess(rhsReference, "length") + factory.createPropertyAccess(rhsReference, "length") ), node.expression ), - /*incrementor*/ setTextRange(createPostfixIncrement(counter), node.expression), + /*incrementor*/ setTextRange(factory.createPostfixIncrement(counter), node.expression), /*statement*/ convertForOfStatementHead( node, - createElementAccess(rhsReference, counter), + factory.createElementAccess(rhsReference, counter), convertedLoopBodyStatements ) ), @@ -2437,45 +2458,45 @@ namespace ts { // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps); setTextRange(forStatement, node); - return restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); + return factory.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } function convertForOfStatementForIterable(node: ForOfStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[], ancestorFacts: HierarchyFacts): Statement { const expression = visitNode(node.expression, visitor, isExpression); - const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined); - const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined); - const errorRecord = createUniqueName("e"); - const catchVariable = getGeneratedNameForNode(errorRecord); - const returnMethod = createTempVariable(/*recordTempVariable*/ undefined); - const values = createValuesHelper(context, expression, node.expression); - const next = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); + const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const errorRecord = factory.createUniqueName("e"); + const catchVariable = factory.getGeneratedNameForNode(errorRecord); + const returnMethod = factory.createTempVariable(/*recordTempVariable*/ undefined); + const values = setTextRange(emitHelpers().createValuesHelper(expression), node.expression); + const next = factory.createCall(factory.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); // if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration const initializer = ancestorFacts & HierarchyFacts.IterationContainer - ? inlineExpressions([createAssignment(errorRecord, createVoidZero()), values]) + ? factory.inlineExpressions([factory.createAssignment(errorRecord, factory.createVoidZero()), values]) : values; const forStatement = setEmitFlags( setTextRange( - createFor( + factory.createFor( /*initializer*/ setEmitFlags( setTextRange( - createVariableDeclarationList([ - setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, initializer), node.expression), - createVariableDeclaration(result, /*type*/ undefined, next) + factory.createVariableDeclarationList([ + setTextRange(factory.createVariableDeclaration(iterator, /*exclamationToken*/ undefined, /*type*/ undefined, initializer), node.expression), + factory.createVariableDeclaration(result, /*exclamationToken*/ undefined, /*type*/ undefined, next) ]), node.expression ), EmitFlags.NoHoisting ), - /*condition*/ createLogicalNot(createPropertyAccess(result, "done")), - /*incrementor*/ createAssignment(result, next), + /*condition*/ factory.createLogicalNot(factory.createPropertyAccess(result, "done")), + /*incrementor*/ factory.createAssignment(result, next), /*statement*/ convertForOfStatementHead( node, - createPropertyAccess(result, "value"), + factory.createPropertyAccess(result, "value"), convertedLoopBodyStatements ) ), @@ -2484,22 +2505,22 @@ namespace ts { EmitFlags.NoTokenTrailingSourceMaps ); - return createTry( - createBlock([ - restoreEnclosingLabel( + return factory.createTry( + factory.createBlock([ + factory.restoreEnclosingLabel( forStatement, outermostLabeledStatement, convertedLoopState && resetLabel ) ]), - createCatchClause(createVariableDeclaration(catchVariable), + factory.createCatchClause(factory.createVariableDeclaration(catchVariable), setEmitFlags( - createBlock([ - createExpressionStatement( - createAssignment( + factory.createBlock([ + factory.createExpressionStatement( + factory.createAssignment( errorRecord, - createObjectLiteral([ - createPropertyAssignment("error", catchVariable) + factory.createObjectLiteral([ + factory.createPropertyAssignment("error", catchVariable) ]) ) ) @@ -2507,25 +2528,25 @@ namespace ts { EmitFlags.SingleLine ) ), - createBlock([ - createTry( - /*tryBlock*/ createBlock([ + factory.createBlock([ + factory.createTry( + /*tryBlock*/ factory.createBlock([ setEmitFlags( - createIf( - createLogicalAnd( - createLogicalAnd( + factory.createIf( + factory.createLogicalAnd( + factory.createLogicalAnd( result, - createLogicalNot( - createPropertyAccess(result, "done") + factory.createLogicalNot( + factory.createPropertyAccess(result, "done") ) ), - createAssignment( + factory.createAssignment( returnMethod, - createPropertyAccess(iterator, "return") + factory.createPropertyAccess(iterator, "return") ) ), - createExpressionStatement( - createFunctionCall(returnMethod, iterator, []) + factory.createExpressionStatement( + factory.createFunctionCallCall(returnMethod, iterator, []) ) ), EmitFlags.SingleLine @@ -2533,12 +2554,12 @@ namespace ts { ]), /*catchClause*/ undefined, /*finallyBlock*/ setEmitFlags( - createBlock([ + factory.createBlock([ setEmitFlags( - createIf( + factory.createIf( errorRecord, - createThrow( - createPropertyAccess(errorRecord, "error") + factory.createThrow( + factory.createPropertyAccess(errorRecord, "error") ) ), EmitFlags.SingleLine @@ -2584,14 +2605,14 @@ namespace ts { // For computed properties, we need to create a unique handle to the object // literal so we can modify it without risking internal assignments tainting the object. - const temp = createTempVariable(hoistVariableDeclaration); + const temp = factory.createTempVariable(hoistVariableDeclaration); // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. const expressions: Expression[] = []; - const assignment = createAssignment( + const assignment = factory.createAssignment( temp, setEmitFlags( - createObjectLiteral( + factory.createObjectLiteral( visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties), node.multiLine ), @@ -2610,7 +2631,7 @@ namespace ts { // We need to clone the temporary identifier so that we can write it on a // new line expressions.push(node.multiLine ? startOnNewLine(getMutableClone(temp)) : temp); - return inlineExpressions(expressions); + return factory.inlineExpressions(expressions); } return visitEachChild(node, visitor, context); } @@ -2688,7 +2709,7 @@ namespace ts { const result = convert ? convert(node, outermostLabeledStatement, /*convertedLoopBodyStatements*/ undefined, ancestorFacts) - : restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel); + : factory.restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel); if (convertedLoopState) { convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; @@ -2722,15 +2743,13 @@ namespace ts { loop = convert(node, outermostLabeledStatement, bodyFunction.part, ancestorFacts); } else { - const clone = convertIterationStatementCore(node, initializerFunction, createBlock(bodyFunction.part, /*multiLine*/ true)); - aggregateTransformFlags(clone); - loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); + const clone = convertIterationStatementCore(node, initializerFunction, factory.createBlock(bodyFunction.part, /*multiLine*/ true)); + loop = factory.restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); } } else { - const clone = convertIterationStatementCore(node, initializerFunction, visitNode(node.statement, visitor, isStatement, liftToBlock)); - aggregateTransformFlags(clone); - loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); + const clone = convertIterationStatementCore(node, initializerFunction, visitNode(node.statement, visitor, isStatement, factory.liftToBlock)); + loop = factory.restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); } statements.push(loop); @@ -2751,7 +2770,7 @@ namespace ts { function convertForStatement(node: ForStatement, initializerFunction: IterationStatementPartFunction | undefined, convertedLoopBody: Statement) { const shouldConvertCondition = node.condition && shouldConvertPartOfIterationStatement(node.condition); const shouldConvertIncrementor = shouldConvertCondition || node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor); - return updateFor( + return factory.updateFor( node, visitNode(initializerFunction ? initializerFunction.part : node.initializer, visitor, isForInitializer), visitNode(shouldConvertCondition ? undefined : node.condition, visitor, isExpression), @@ -2761,7 +2780,7 @@ namespace ts { } function convertForOfStatement(node: ForOfStatement, convertedLoopBody: Statement) { - return updateForOf( + return factory.updateForOf( node, /*awaitModifier*/ undefined, visitNode(node.initializer, visitor, isForInitializer), @@ -2770,7 +2789,7 @@ namespace ts { } function convertForInStatement(node: ForInStatement, convertedLoopBody: Statement) { - return updateForIn( + return factory.updateForIn( node, visitNode(node.initializer, visitor, isForInitializer), visitNode(node.expression, visitor, isExpression), @@ -2778,14 +2797,14 @@ namespace ts { } function convertDoStatement(node: DoStatement, convertedLoopBody: Statement) { - return updateDo( + return factory.updateDo( node, convertedLoopBody, visitNode(node.expression, visitor, isExpression)); } function convertWhileStatement(node: WhileStatement, convertedLoopBody: Statement) { - return updateWhile( + return factory.updateWhile( node, visitNode(node.expression, visitor, isExpression), convertedLoopBody); @@ -2850,10 +2869,11 @@ namespace ts { else { // this is top level converted loop and we need to create an alias for 'arguments' object (extraVariableDeclarations || (extraVariableDeclarations = [])).push( - createVariableDeclaration( + factory.createVariableDeclaration( state.argumentsName, + /*exclamationToken*/ undefined, /*type*/ undefined, - createIdentifier("arguments") + factory.createIdentifier("arguments") ) ); } @@ -2871,10 +2891,11 @@ namespace ts { // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. (extraVariableDeclarations || (extraVariableDeclarations = [])).push( - createVariableDeclaration( + factory.createVariableDeclaration( state.thisName, + /*exclamationToken*/ undefined, /*type*/ undefined, - createIdentifier("this") + factory.createIdentifier("this") ) ); } @@ -2892,7 +2913,7 @@ namespace ts { } // hoist collected variable declarations for (const identifier of state.hoistedLocalVariables) { - extraVariableDeclarations.push(createVariableDeclaration(identifier)); + extraVariableDeclarations.push(factory.createVariableDeclaration(identifier)); } } } @@ -2903,7 +2924,7 @@ namespace ts { extraVariableDeclarations = []; } for (const outParam of state.loopOutParameters) { - extraVariableDeclarations.push(createVariableDeclaration(outParam.outParamName)); + extraVariableDeclarations.push(factory.createVariableDeclaration(outParam.outParamName)); } } @@ -2911,14 +2932,14 @@ namespace ts { if (!extraVariableDeclarations) { extraVariableDeclarations = []; } - extraVariableDeclarations.push(createVariableDeclaration(state.conditionVariable, /*type*/ undefined, createFalse())); + extraVariableDeclarations.push(factory.createVariableDeclaration(state.conditionVariable, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createFalse())); } // create variable statement to hold all introduced variable declarations if (extraVariableDeclarations) { - statements.push(createVariableStatement( + statements.push(factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList(extraVariableDeclarations) + factory.createVariableDeclarationList(extraVariableDeclarations) )); } } @@ -2931,7 +2952,7 @@ namespace ts { } function createOutVariable(p: LoopOutParameter) { - return createVariableDeclaration(p.originalName, /*type*/ undefined, p.outParamName); + return factory.createVariableDeclaration(p.originalName, /*exclamationToken*/ undefined, /*type*/ undefined, p.outParamName); } /** @@ -2941,7 +2962,7 @@ namespace ts { * [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation). */ function createFunctionForInitializerOfForStatement(node: ForStatementWithConvertibleInitializer, currentState: ConvertedLoopState): IterationStatementPartFunction { - const functionName = createUniqueName("_loop_init"); + const functionName = factory.createUniqueName("_loop_init"); const containsYield = (node.initializer.transformFlags & TransformFlags.ContainsYield) !== 0; let emitFlags = EmitFlags.None; @@ -2949,7 +2970,7 @@ namespace ts { if (containsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) emitFlags |= EmitFlags.AsyncFunctionBody; const statements: Statement[] = []; - statements.push(createVariableStatement(/*modifiers*/ undefined, node.initializer)); + statements.push(factory.createVariableStatement(/*modifiers*/ undefined, node.initializer)); copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Initializer, CopyDirection.ToOutParameter, statements); // This transforms the following ES2015 syntax: @@ -2973,23 +2994,24 @@ namespace ts { // Which prevents mutations to `i` in the per-iteration environment of the body // from affecting the initial value for `i` outside of the per-iteration environment. - const functionDeclaration = createVariableStatement( + const functionDeclaration = factory.createVariableStatement( /*modifiers*/ undefined, setEmitFlags( - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( functionName, + /*exclamationToken*/ undefined, /*type*/ undefined, setEmitFlags( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, - containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined, + containsYield ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, visitNode( - createBlock(statements, /*multiLine*/ true), + factory.createBlock(statements, /*multiLine*/ true), visitor, isBlock ) @@ -3002,7 +3024,7 @@ namespace ts { ) ); - const part = createVariableDeclarationList(map(currentState.loopOutParameters, createOutVariable)); + const part = factory.createVariableDeclarationList(map(currentState.loopOutParameters, createOutVariable)); return { functionName, containsYield, functionDeclaration, part }; } @@ -3013,9 +3035,9 @@ namespace ts { * [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation). */ function createFunctionForBodyOfIterationStatement(node: IterationStatement, currentState: ConvertedLoopState, outerState: ConvertedLoopState | undefined): IterationStatementPartFunction { - const functionName = createUniqueName("_loop"); + const functionName = factory.createUniqueName("_loop"); startLexicalEnvironment(); - const statement = visitNode(node.statement, visitor, isStatement, liftToBlock); + const statement = visitNode(node.statement, visitor, isStatement, factory.liftToBlock); const lexicalEnvironment = endLexicalEnvironment(); const statements: Statement[] = []; @@ -3058,17 +3080,17 @@ namespace ts { // we must indicate whether this is the first evaluation of the loop body so that // we only evaluate the incrementor on subsequent evaluations. - currentState.conditionVariable = createUniqueName("inc"); - statements.push(createIf( + currentState.conditionVariable = factory.createUniqueName("inc"); + statements.push(factory.createIf( currentState.conditionVariable, - createStatement(visitNode(node.incrementor, visitor, isExpression)), - createStatement(createAssignment(currentState.conditionVariable, createTrue())) + factory.createExpressionStatement(visitNode(node.incrementor, visitor, isExpression)), + factory.createExpressionStatement(factory.createAssignment(currentState.conditionVariable, factory.createTrue())) )); if (shouldConvertConditionOfForStatement(node)) { - statements.push(createIf( - createPrefix(SyntaxKind.ExclamationToken, visitNode(node.condition, visitor, isExpression)), - visitNode(createBreak(), visitor, isStatement) + statements.push(factory.createIf( + factory.createPrefix(SyntaxKind.ExclamationToken, visitNode(node.condition, visitor, isExpression)), + visitNode(factory.createBreak(), visitor, isStatement) )); } } @@ -3083,7 +3105,7 @@ namespace ts { copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOutParameter, statements); insertStatementsAfterStandardPrologue(statements, lexicalEnvironment); - const loopBody = createBlock(statements, /*multiLine*/ true); + const loopBody = factory.createBlock(statements, /*multiLine*/ true); if (isBlock(statement)) setOriginalNode(loopBody, statement); const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; @@ -3108,18 +3130,19 @@ namespace ts { // } const functionDeclaration = - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, setEmitFlags( - createVariableDeclarationList( + factory.createVariableDeclarationList( [ - createVariableDeclaration( + factory.createVariableDeclaration( functionName, + /*exclamationToken*/ undefined, /*type*/ undefined, setEmitFlags( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, - containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined, + containsYield ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, /*name*/ undefined, /*typeParameters*/ undefined, currentState.loopParameters, @@ -3142,26 +3165,26 @@ namespace ts { function copyOutParameter(outParam: LoopOutParameter, copyDirection: CopyDirection): BinaryExpression { const source = copyDirection === CopyDirection.ToOriginal ? outParam.outParamName : outParam.originalName; const target = copyDirection === CopyDirection.ToOriginal ? outParam.originalName : outParam.outParamName; - return createBinary(target, SyntaxKind.EqualsToken, source); + return factory.createBinary(target, SyntaxKind.EqualsToken, source); } function copyOutParameters(outParams: LoopOutParameter[], partFlags: LoopOutParameterFlags, copyDirection: CopyDirection, statements: Statement[]): void { for (const outParam of outParams) { if (outParam.flags & partFlags) { - statements.push(createExpressionStatement(copyOutParameter(outParam, copyDirection))); + statements.push(factory.createExpressionStatement(copyOutParameter(outParam, copyDirection))); } } } function generateCallToConvertedLoopInitializer(initFunctionExpressionName: Identifier, containsYield: boolean): Statement { - const call = createCall(initFunctionExpressionName, /*typeArguments*/ undefined, []); + const call = factory.createCall(initFunctionExpressionName, /*typeArguments*/ undefined, []); const callResult = containsYield - ? createYield( - createToken(SyntaxKind.AsteriskToken), + ? factory.createYield( + factory.createToken(SyntaxKind.AsteriskToken), setEmitFlags(call, EmitFlags.Iterator) ) : call; - return createStatement(callResult); + return factory.createExpressionStatement(callResult); } function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, state: ConvertedLoopState, outerState: ConvertedLoopState | undefined, containsYield: boolean): Statement[] { @@ -3175,23 +3198,23 @@ namespace ts { !state.labeledNonLocalBreaks && !state.labeledNonLocalContinues; - const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(state.loopParameters, p => p.name)); + const call = factory.createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(state.loopParameters, p => p.name)); const callResult = containsYield - ? createYield( - createToken(SyntaxKind.AsteriskToken), + ? factory.createYield( + factory.createToken(SyntaxKind.AsteriskToken), setEmitFlags(call, EmitFlags.Iterator) ) : call; if (isSimpleLoop) { - statements.push(createExpressionStatement(callResult)); + statements.push(factory.createExpressionStatement(callResult)); copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements); } else { - const loopResultName = createUniqueName("state"); - const stateVariable = createVariableStatement( + const loopResultName = factory.createUniqueName("state"); + const stateVariable = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)] + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(loopResultName, /*exclamationToken*/ undefined, /*type*/ undefined, callResult)] ) ); statements.push(stateVariable); @@ -3201,18 +3224,14 @@ namespace ts { let returnStatement: ReturnStatement; if (outerState) { outerState.nonLocalJumps! |= Jump.Return; - returnStatement = createReturn(loopResultName); + returnStatement = factory.createReturn(loopResultName); } else { - returnStatement = createReturn(createPropertyAccess(loopResultName, "value")); + returnStatement = factory.createReturn(factory.createPropertyAccess(loopResultName, "value")); } statements.push( - createIf( - createBinary( - createTypeOf(loopResultName), - SyntaxKind.EqualsEqualsEqualsToken, - createLiteral("object") - ), + factory.createIf( + factory.createTypeCheck(loopResultName, "object"), returnStatement ) ); @@ -3220,13 +3239,12 @@ namespace ts { if (state.nonLocalJumps! & Jump.Break) { statements.push( - createIf( - createBinary( + factory.createIf( + factory.createStrictEquality( loopResultName, - SyntaxKind.EqualsEqualsEqualsToken, - createLiteral("break") + factory.createStringLiteral("break") ), - createBreak() + factory.createBreak() ) ); } @@ -3236,9 +3254,9 @@ namespace ts { processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerState, caseClauses); processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerState, caseClauses); statements.push( - createSwitch( + factory.createSwitch( loopResultName, - createCaseBlock(caseClauses) + factory.createCaseBlock(caseClauses) ) ); } @@ -3271,14 +3289,14 @@ namespace ts { // then emit labeled break\continue // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do if (!outerLoop || (outerLoop.labels && outerLoop.labels.get(labelText))) { - const label = createIdentifier(labelText); - statements.push(isBreak ? createBreak(label) : createContinue(label)); + const label = factory.createIdentifier(labelText); + statements.push(isBreak ? factory.createBreak(label) : factory.createContinue(label)); } else { setLabeledJump(outerLoop, isBreak, labelText, labelMarker); - statements.push(createReturn(loopResultName)); + statements.push(factory.createReturn(loopResultName)); } - caseClauses.push(createCaseClause(createLiteral(labelMarker), statements)); + caseClauses.push(factory.createCaseClause(factory.createStringLiteral(labelMarker), statements)); }); } @@ -3292,10 +3310,10 @@ namespace ts { } } else { - loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); + loopParameters.push(factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); const checkFlags = resolver.getNodeCheckFlags(decl); if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForInitializer) { - const outParamName = createUniqueName("out_" + idText(name)); + const outParamName = factory.createUniqueName("out_" + idText(name)); let flags: LoopOutParameterFlags = 0; if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter) { flags |= LoopOutParameterFlags.Body; @@ -3359,8 +3377,9 @@ namespace ts { * @param receiver The receiver for the assignment. */ function transformPropertyAssignmentToExpression(property: PropertyAssignment, receiver: Expression, startsOnNewLine: boolean) { - const expression = createAssignment( + const expression = factory.createAssignment( createMemberAccessForPropertyName( + factory, receiver, visitNode(property.name, visitor, isPropertyName) ), @@ -3381,8 +3400,9 @@ namespace ts { * @param receiver The receiver for the assignment. */ function transformShorthandPropertyAssignmentToExpression(property: ShorthandPropertyAssignment, receiver: Expression, startsOnNewLine: boolean) { - const expression = createAssignment( + const expression = factory.createAssignment( createMemberAccessForPropertyName( + factory, receiver, visitNode(property.name, visitor, isPropertyName) ), @@ -3403,8 +3423,9 @@ namespace ts { * @param receiver The receiver for the assignment. */ function transformObjectLiteralMethodDeclarationToExpression(method: MethodDeclaration, receiver: Expression, container: Node, startsOnNewLine: boolean) { - const expression = createAssignment( + const expression = factory.createAssignment( createMemberAccessForPropertyName( + factory, receiver, visitNode(method.name, visitor, isPropertyName) ), @@ -3422,8 +3443,8 @@ namespace ts { let updated: CatchClause; Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); if (isBindingPattern(node.variableDeclaration!.name)) { - const temp = createTempVariable(/*recordTempVariable*/ undefined); - const newVariableDeclaration = createVariableDeclaration(temp); + const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); + const newVariableDeclaration = factory.createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); const vars = flattenDestructuringBinding( node.variableDeclaration!, @@ -3432,10 +3453,10 @@ namespace ts { FlattenLevel.All, temp ); - const list = createVariableDeclarationList(vars); + const list = factory.createVariableDeclarationList(vars); setTextRange(list, node.variableDeclaration); - const destructure = createVariableStatement(/*modifiers*/ undefined, list); - updated = updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); + const destructure = factory.createVariableStatement(/*modifiers*/ undefined, list); + updated = factory.updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); } else { updated = visitEachChild(node, visitor, context); @@ -3447,7 +3468,7 @@ namespace ts { function addStatementToStartOfBlock(block: Block, statement: Statement): Block { const transformedStatements = visitNodes(block.statements, visitor, isStatement); - return updateBlock(block, [statement, ...transformedStatements]); + return factory.updateBlock(block, [statement, ...transformedStatements]); } /** @@ -3464,7 +3485,7 @@ namespace ts { const functionExpression = transformFunctionLikeToExpression(node, /*location*/ moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined); setEmitFlags(functionExpression, EmitFlags.NoLeadingComments | getEmitFlags(functionExpression)); return setTextRange( - createPropertyAssignment( + factory.createPropertyAssignment( node.name, functionExpression ), @@ -3486,10 +3507,10 @@ namespace ts { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); if (node.kind === SyntaxKind.GetAccessor) { - updated = updateGetAccessor(node, node.decorators, node.modifiers, node.name, parameters, node.type, body); + updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, body); } else { - updated = updateSetAccessor(node, node.decorators, node.modifiers, node.name, parameters, body); + updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, body); } exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; @@ -3503,7 +3524,7 @@ namespace ts { */ function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment): ObjectLiteralElementLike { return setTextRange( - createPropertyAssignment( + factory.createPropertyAssignment( node.name, getSynthesizedClone(node.name) ), @@ -3555,7 +3576,7 @@ namespace ts { return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } - return updateCall( + return factory.updateCall( node, visitNode(node.expression, callExpressionVisitor, isExpression), /*typeArguments*/ undefined, @@ -3653,8 +3674,8 @@ namespace ts { // Add the class alias following the declaration. statements.push( - createExpressionStatement( - createAssignment( + factory.createExpressionStatement( + factory.createAssignment( aliasAssignment.left, cast(variable.name, isIdentifier) ) @@ -3686,12 +3707,12 @@ namespace ts { // Recreate any outer parentheses or partially-emitted expressions to preserve source map // and comment locations. - return recreateOuterExpressions(node.expression, - recreateOuterExpressions(variable.initializer, - recreateOuterExpressions(aliasAssignment && aliasAssignment.right, - updateCall(call, - recreateOuterExpressions(call.expression, - updateFunctionExpression( + return factory.restoreOuterExpressions(node.expression, + factory.restoreOuterExpressions(variable.initializer, + factory.restoreOuterExpressions(aliasAssignment && aliasAssignment.right, + factory.updateCall(call, + factory.restoreOuterExpressions(call.expression, + factory.updateFunctionExpression( func, /*modifiers*/ undefined, /*asteriskToken*/ undefined, @@ -3699,7 +3720,7 @@ namespace ts { /*typeParameters*/ undefined, func.parameters, /*type*/ undefined, - updateBlock( + factory.updateBlock( func.body, statements ) @@ -3724,7 +3745,7 @@ namespace ts { node.expression.kind === SyntaxKind.SuperKeyword || isSuperProperty(skipOuterExpressions(node.expression))) { - const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration); + const { target, thisArg } = factory.createCallBinding(node.expression, hoistVariableDeclaration); if (node.expression.kind === SyntaxKind.SuperKeyword) { setEmitFlags(thisArg, EmitFlags.NoSubstitution); } @@ -3745,7 +3766,7 @@ namespace ts { // _super.m.apply(this, a.concat([b])) // _super.prototype.m.apply(this, a.concat([b])) - resultingCall = createFunctionApply( + resultingCall = factory.createFunctionApplyCall( visitNode(target, callExpressionVisitor, isExpression), node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : visitNode(thisArg, visitor, isExpression), transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) @@ -3761,22 +3782,24 @@ namespace ts { // _super.call(this, a) // _super.m.call(this, a) // _super.prototype.m.call(this, a) - resultingCall = createFunctionCall( - visitNode(target, callExpressionVisitor, isExpression), - node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : visitNode(thisArg, visitor, isExpression), - visitNodes(node.arguments, visitor, isExpression), - /*location*/ node + resultingCall = setTextRange( + factory.createFunctionCallCall( + visitNode(target, callExpressionVisitor, isExpression), + node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : visitNode(thisArg, visitor, isExpression), + visitNodes(node.arguments, visitor, isExpression) + ), + node ); } if (node.expression.kind === SyntaxKind.SuperKeyword) { const initializer = - createLogicalOr( + factory.createLogicalOr( resultingCall, createActualThis() ); resultingCall = assignToCapturedThis - ? createAssignment(createFileLevelUniqueName("_this"), initializer) + ? factory.createAssignment(factory.createFileLevelUniqueName("_this"), initializer) : initializer; } return setOriginalNode(resultingCall, node); @@ -3799,12 +3822,12 @@ namespace ts { // [output] // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() - const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); - return createNew( - createFunctionApply( + const { target, thisArg } = factory.createCallBinding(factory.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); + return factory.createNew( + factory.createFunctionApplyCall( visitNode(target, visitor, isExpression), thisArg, - transformAndSpreadElements(createNodeArray([createVoidZero(), ...node.arguments!]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) + transformAndSpreadElements(factory.createNodeArray([factory.createVoidZero(), ...node.arguments!]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) ), /*typeArguments*/ undefined, [] @@ -3847,7 +3870,7 @@ namespace ts { } } - return createSpreadHelper(context, segments); + return emitHelpers().createSpreadHelper(segments); } else { if (segments.length === 1) { @@ -3859,7 +3882,7 @@ namespace ts { } } - return createSpreadArraysHelper(context, segments); + return emitHelpers().createSpreadArraysHelper(segments); } } @@ -3889,8 +3912,8 @@ namespace ts { } function visitSpanOfNonSpreads(chunk: Expression[], multiLine: boolean, hasTrailingComma: boolean): VisitResult { - return createArrayLiteral( - visitNodes(createNodeArray(chunk, hasTrailingComma), visitor, isExpression), + return factory.createArrayLiteral( + visitNodes(factory.createNodeArray(chunk, hasTrailingComma), visitor, isExpression), multiLine ); } @@ -3914,7 +3937,7 @@ namespace ts { * @param node A template literal. */ function visitTemplateLiteral(node: LiteralExpression): LeftHandSideExpression { - return setTextRange(createLiteral(node.text), node); + return setTextRange(factory.createStringLiteral(node.text), node); } /** @@ -3924,7 +3947,7 @@ namespace ts { */ function visitStringLiteral(node: StringLiteral) { if (node.hasExtendedUnicodeEscape) { - return setTextRange(createLiteral(node.text), node); + return setTextRange(factory.createStringLiteral(node.text), node); } return node; } @@ -3936,7 +3959,7 @@ namespace ts { */ function visitNumericLiteral(node: NumericLiteral) { if (node.numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { - return setTextRange(createNumericLiteral(node.text), node); + return setTextRange(factory.createNumericLiteral(node.text), node); } return node; } @@ -3958,30 +3981,30 @@ namespace ts { const rawStrings: Expression[] = []; const template = node.template; if (isNoSubstitutionTemplateLiteral(template)) { - cookedStrings.push(createLiteral(template.text)); + cookedStrings.push(factory.createStringLiteral(template.text)); rawStrings.push(getRawLiteral(template)); } else { - cookedStrings.push(createLiteral(template.head.text)); + cookedStrings.push(factory.createStringLiteral(template.head.text)); rawStrings.push(getRawLiteral(template.head)); for (const templateSpan of template.templateSpans) { - cookedStrings.push(createLiteral(templateSpan.literal.text)); + cookedStrings.push(factory.createStringLiteral(templateSpan.literal.text)); rawStrings.push(getRawLiteral(templateSpan.literal)); templateArguments.push(visitNode(templateSpan.expression, visitor, isExpression)); } } - const helperCall = createTemplateObjectHelper(context, createArrayLiteral(cookedStrings), createArrayLiteral(rawStrings)); + const helperCall = emitHelpers().createTemplateObjectHelper(factory.createArrayLiteral(cookedStrings), factory.createArrayLiteral(rawStrings)); // Create a variable to cache the template object if we're in a module. // Do not do this in the global scope, as any variable we currently generate could conflict with // variables from outside of the current compilation. In the future, we can revisit this behavior. if (isExternalModule(currentSourceFile)) { - const tempVar = createUniqueName("templateObject"); + const tempVar = factory.createUniqueName("templateObject"); recordTaggedTemplateString(tempVar); - templateArguments[0] = createLogicalOr( + templateArguments[0] = factory.createLogicalOr( tempVar, - createAssignment( + factory.createAssignment( tempVar, helperCall) ); @@ -3990,7 +4013,7 @@ namespace ts { templateArguments[0] = helperCall; } - return createCall(tag, /*typeArguments*/ undefined, templateArguments); + return factory.createCall(tag, /*typeArguments*/ undefined, templateArguments); } /** @@ -4018,7 +4041,7 @@ namespace ts { // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's // and LineTerminatorSequences are normalized to for both TV and TRV. text = text.replace(/\r\n?/g, "\n"); - return setTextRange(createLiteral(text), node); + return setTextRange(factory.createStringLiteral(text), node); } /** @@ -4040,7 +4063,7 @@ namespace ts { // ("abc" + 1) << (2 + "") // rather than // "abc" + (1 << 2) + "" - const expression = reduceLeft(expressions, createAdd)!; + const expression = reduceLeft(expressions, factory.createAdd)!; if (nodeIsSynthesized(expression)) { expression.pos = node.pos; expression.end = node.end; @@ -4087,7 +4110,7 @@ namespace ts { return; } - expressions.push(createLiteral(node.head.text)); + expressions.push(factory.createStringLiteral(node.head.text)); } /** @@ -4105,7 +4128,7 @@ namespace ts { // with the head will force the result up to this point to be a string. // Emitting a '+ ""' has no semantic effect for middles and tails. if (span.literal.text.length !== 0) { - expressions.push(createLiteral(span.literal.text)); + expressions.push(factory.createStringLiteral(span.literal.text)); } } } @@ -4114,14 +4137,16 @@ namespace ts { * Visits the `super` keyword */ function visitSuperKeyword(isExpressionOfCall: boolean): LeftHandSideExpression { - return hierarchyFacts & HierarchyFacts.NonStaticClassElement && !isExpressionOfCall ? createPropertyAccess(createFileLevelUniqueName("_super"), "prototype") : - createFileLevelUniqueName("_super"); + return hierarchyFacts & HierarchyFacts.NonStaticClassElement + && !isExpressionOfCall + ? factory.createPropertyAccess(factory.createFileLevelUniqueName("_super"), "prototype") + : factory.createFileLevelUniqueName("_super"); } function visitMetaProperty(node: MetaProperty) { if (node.keywordToken === SyntaxKind.NewKeyword && node.name.escapedText === "target") { hierarchyFacts |= HierarchyFacts.NewTarget; - return createFileLevelUniqueName("_newTarget"); + return factory.createFileLevelUniqueName("_newTarget"); } return node; } @@ -4206,7 +4231,7 @@ namespace ts { if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) { const original = getParseTreeNode(node, isIdentifier); if (original && isNameOfDeclarationWithCollidingName(original)) { - return setTextRange(getGeneratedNameForNode(original), node); + return setTextRange(factory.getGeneratedNameForNode(original), node); } } @@ -4258,7 +4283,7 @@ namespace ts { if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) { const declaration = resolver.getReferencedDeclarationWithCollidingName(node); if (declaration && !(isClassLike(declaration) && isPartOfClassBody(declaration, node))) { - return setTextRange(getGeneratedNameForNode(getNameOfDeclaration(declaration)), node); + return setTextRange(factory.getGeneratedNameForNode(getNameOfDeclaration(declaration)), node); } } @@ -4297,15 +4322,15 @@ namespace ts { function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression { if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && hierarchyFacts & HierarchyFacts.CapturesThis) { - return setTextRange(createFileLevelUniqueName("_this"), node); + return setTextRange(factory.createFileLevelUniqueName("_this"), node); } return node; } function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) { return hasModifier(member, ModifierFlags.Static) - ? getInternalName(node) - : createPropertyAccess(getInternalName(node), "prototype"); + ? factory.getInternalName(node) + : factory.createPropertyAccess(factory.getInternalName(node), "prototype"); } function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration | undefined, hasExtendsClause: boolean) { @@ -4341,63 +4366,4 @@ namespace ts { return isIdentifier(expression) && expression.escapedText === "arguments"; } } - - function createExtendsHelper(context: TransformationContext, name: Identifier) { - context.requestEmitHelper(extendsHelper); - return createCall( - getUnscopedHelperName("__extends"), - /*typeArguments*/ undefined, - [ - name, - createFileLevelUniqueName("_super") - ] - ); - } - - function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) { - context.requestEmitHelper(templateObjectHelper); - return createCall( - getUnscopedHelperName("__makeTemplateObject"), - /*typeArguments*/ undefined, - [ - cooked, - raw - ] - ); - } - - export const extendsHelper: UnscopedEmitHelper = { - name: "typescript:extends", - importName: "__extends", - scoped: false, - priority: 0, - text: ` - var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - })();` - }; - - export const templateObjectHelper: UnscopedEmitHelper = { - name: "typescript:makeTemplateObject", - importName: "__makeTemplateObject", - scoped: false, - priority: 0, - text: ` - var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { - if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } - return cooked; - };` - }; - } diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 93b5d45714ff2..4a3996c87d5d3 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -1,9 +1,12 @@ /*@internal*/ namespace ts { export function transformES2016(context: TransformationContext) { - const { hoistVariableDeclaration } = context; + const { + factory, + hoistVariableDeclaration + } = context; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -43,17 +46,17 @@ namespace ts { const right = visitNode(node.right, visitor, isExpression); if (isElementAccessExpression(left)) { // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` - const expressionTemp = createTempVariable(hoistVariableDeclaration); - const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration); + const expressionTemp = factory.createTempVariable(hoistVariableDeclaration); + const argumentExpressionTemp = factory.createTempVariable(hoistVariableDeclaration); target = setTextRange( - createElementAccess( - setTextRange(createAssignment(expressionTemp, left.expression), left.expression), - setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) + factory.createElementAccess( + setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression), + setTextRange(factory.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) ), left ); value = setTextRange( - createElementAccess( + factory.createElementAccess( expressionTemp, argumentExpressionTemp ), @@ -62,16 +65,16 @@ namespace ts { } else if (isPropertyAccessExpression(left)) { // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` - const expressionTemp = createTempVariable(hoistVariableDeclaration); + const expressionTemp = factory.createTempVariable(hoistVariableDeclaration); target = setTextRange( - createPropertyAccess( - setTextRange(createAssignment(expressionTemp, left.expression), left.expression), + factory.createPropertyAccess( + setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression), left.name ), left ); value = setTextRange( - createPropertyAccess( + factory.createPropertyAccess( expressionTemp, left.name ), @@ -84,9 +87,9 @@ namespace ts { value = left; } return setTextRange( - createAssignment( + factory.createAssignment( target, - createMathPow(value, right, /*location*/ node) + setTextRange(factory.createGlobalMethodCall("Math", "pow", [value, right]), node) ), node ); @@ -96,7 +99,7 @@ namespace ts { // Transforms `a ** b` into `Math.pow(a, b)` const left = visitNode(node.left, visitor, isExpression); const right = visitNode(node.right, visitor, isExpression); - return createMathPow(left, right, /*location*/ node); + return setTextRange(factory.createGlobalMethodCall("Math", "pow", [left, right]), node); } } } diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 005d5a8fdd6ed..c46143f115292 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -9,6 +9,8 @@ namespace ts { export function transformES2017(context: TransformationContext) { const { + factory, + getEmitHelperFactory: emitHelpers, resumeLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration @@ -51,7 +53,7 @@ namespace ts { context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -188,44 +190,44 @@ namespace ts { function visitVariableStatementInAsyncBody(node: VariableStatement) { if (isVariableDeclarationListWithCollidingName(node.declarationList)) { const expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false); - return expression ? createExpressionStatement(expression) : undefined; + return expression ? factory.createExpressionStatement(expression) : undefined; } return visitEachChild(node, visitor, context); } function visitForInStatementInAsyncBody(node: ForInStatement) { - return updateForIn( + return factory.updateForIn( node, isVariableDeclarationListWithCollidingName(node.initializer) ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)! : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.expression, visitor, isExpression), - visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock) + visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock) ); } function visitForOfStatementInAsyncBody(node: ForOfStatement) { - return updateForOf( + return factory.updateForOf( node, visitNode(node.awaitModifier, visitor, isToken), isVariableDeclarationListWithCollidingName(node.initializer) ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)! : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.expression, visitor, isExpression), - visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock) + visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock) ); } function visitForStatementInAsyncBody(node: ForStatement) { const initializer = node.initializer!; // TODO: GH#18217 - return updateFor( + return factory.updateFor( node, isVariableDeclarationListWithCollidingName(initializer) ? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false) : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.condition, visitor, isExpression), visitNode(node.incrementor, visitor, isExpression), - visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock) + visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock) ); } @@ -239,7 +241,7 @@ namespace ts { function visitAwaitExpression(node: AwaitExpression): Expression { return setOriginalNode( setTextRange( - createYield( + factory.createYield( /*asteriskToken*/ undefined, visitNode(node.expression, visitor, isExpression) ), @@ -258,7 +260,7 @@ namespace ts { * @param node The node to visit. */ function visitMethodDeclaration(node: MethodDeclaration) { - return updateMethod( + return factory.updateMethodDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, visitor, isModifier), @@ -283,7 +285,7 @@ namespace ts { * @param node The node to visit. */ function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult { - return updateFunctionDeclaration( + return factory.updateFunctionDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, visitor, isModifier), @@ -307,7 +309,7 @@ namespace ts { * @param node The node to visit. */ function visitFunctionExpression(node: FunctionExpression): Expression { - return updateFunctionExpression( + return factory.updateFunctionExpression( node, visitNodes(node.modifiers, visitor, isModifier), node.asteriskToken, @@ -330,7 +332,7 @@ namespace ts { * @param node The node to visit. */ function visitArrowFunction(node: ArrowFunction) { - return updateArrowFunction( + return factory.updateArrowFunction( node, visitNodes(node.modifiers, visitor, isModifier), /*typeParameters*/ undefined, @@ -369,12 +371,12 @@ namespace ts { const variables = getInitializedVariables(node); if (variables.length === 0) { if (hasReceiver) { - return visitNode(convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression); + return visitNode(factory.converters.convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression); } return undefined; } - return inlineExpressions(map(variables, transformInitializedVariable)); + return factory.inlineExpressions(map(variables, transformInitializedVariable)); } function hoistVariableDeclarationList(node: VariableDeclarationList) { @@ -396,8 +398,8 @@ namespace ts { function transformInitializedVariable(node: VariableDeclaration) { const converted = setSourceMapRange( - createAssignment( - convertToAssignmentElementTarget(node.name), + factory.createAssignment( + factory.converters.convertToAssignmentElementTarget(node.name), node.initializer! ), node @@ -452,11 +454,10 @@ namespace ts { let result: ConciseBody; if (!isArrowFunction) { const statements: Statement[] = []; - const statementOffset = addPrologue(statements, (node.body).statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = factory.copyPrologue((node.body).statements, statements, /*ensureUseStrict*/ false, visitor); statements.push( - createReturn( - createAwaiterHelper( - context, + factory.createReturn( + emitHelpers().createAwaiterHelper( !topLevel, hasLexicalArguments, promiseConstructor, @@ -474,13 +475,13 @@ namespace ts { if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); if (hasEntries(capturedSuperProperties)) { - const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties); + const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties); substitutedSuperAccessors[getNodeId(variableStatement)] = true; insertStatementsAfterStandardPrologue(statements, [variableStatement]); } } - const block = createBlock(statements, /*multiLine*/ true); + const block = factory.createBlock(statements, /*multiLine*/ true); setTextRange(block, node.body); if (emitSuperHelpers && hasSuperElementAccess) { @@ -496,8 +497,7 @@ namespace ts { result = block; } else { - const expression = createAwaiterHelper( - context, + const expression = emitHelpers().createAwaiterHelper( !topLevel, hasLexicalArguments, promiseConstructor, @@ -506,8 +506,8 @@ namespace ts { const declarations = endLexicalEnvironment(); if (some(declarations)) { - const block = convertToFunctionBody(expression); - result = updateBlock(block, setTextRange(createNodeArray(concatenate(declarations, block.statements)), block.statements)); + const block = factory.converters.convertToFunctionBlock(expression); + result = factory.updateBlock(block, setTextRange(factory.createNodeArray(concatenate(declarations, block.statements)), block.statements)); } else { result = expression; @@ -524,10 +524,10 @@ namespace ts { function transformAsyncFunctionBodyWorker(body: ConciseBody, start?: number) { if (isBlock(body)) { - return updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start)); + return factory.updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start)); } else { - return convertToFunctionBody(visitNode(body, asyncBodyVisitor, isConciseBody)); + return factory.converters.convertToFunctionBlock(visitNode(body, asyncBodyVisitor, isConciseBody)); } } @@ -626,8 +626,8 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return setTextRange( - createPropertyAccess( - createFileLevelUniqueName("_super"), + factory.createPropertyAccess( + factory.createFileLevelUniqueName("_super"), node.name), node ); @@ -651,11 +651,11 @@ namespace ts { const argumentExpression = isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return createCall( - createPropertyAccess(argumentExpression, "call"), + return factory.createCall( + factory.createPropertyAccess(argumentExpression, "call"), /*typeArguments*/ undefined, [ - createThis(), + factory.createThis(), ...node.arguments ] ); @@ -675,9 +675,9 @@ namespace ts { function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression { if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) { return setTextRange( - createPropertyAccess( - createCall( - createFileLevelUniqueName("_superIndex"), + factory.createPropertyAccess( + factory.createCall( + factory.createFileLevelUniqueName("_superIndex"), /*typeArguments*/ undefined, [argumentExpression] ), @@ -688,8 +688,8 @@ namespace ts { } else { return setTextRange( - createCall( - createFileLevelUniqueName("_superIndex"), + factory.createCall( + factory.createFileLevelUniqueName("_superIndex"), /*typeArguments*/ undefined, [argumentExpression] ), @@ -700,7 +700,7 @@ namespace ts { } /** Creates a variable named `_super` with accessor properties for the given property names. */ - export function createSuperAccessVariableStatement(resolver: EmitResolver, node: FunctionLikeDeclaration, names: UnderscoreEscapedMap) { + export function createSuperAccessVariableStatement(factory: NodeFactory, resolver: EmitResolver, node: FunctionLikeDeclaration, names: UnderscoreEscapedMap) { // Create a variable declaration with a getter/setter (if binding) definition for each name: // const _super = Object.create(null, { x: { get: () => super.x, set: (v) => super.x = v }, ... }); const hasBinding = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) !== 0; @@ -708,18 +708,18 @@ namespace ts { names.forEach((_, key) => { const name = unescapeLeadingUnderscores(key); const getterAndSetter: PropertyAssignment[] = []; - getterAndSetter.push(createPropertyAssignment( + getterAndSetter.push(factory.createPropertyAssignment( "get", - createArrowFunction( + factory.createArrowFunction( /* modifiers */ undefined, /* typeParameters */ undefined, /* parameters */ [], /* type */ undefined, /* equalsGreaterThanToken */ undefined, setEmitFlags( - createPropertyAccess( + factory.createPropertyAccess( setEmitFlags( - createSuper(), + factory.createSuper(), EmitFlags.NoSubstitution ), name @@ -730,13 +730,13 @@ namespace ts { )); if (hasBinding) { getterAndSetter.push( - createPropertyAssignment( + factory.createPropertyAssignment( "set", - createArrowFunction( + factory.createArrowFunction( /* modifiers */ undefined, /* typeParameters */ undefined, /* parameters */ [ - createParameter( + factory.createParameterDeclaration( /* decorators */ undefined, /* modifiers */ undefined, /* dotDotDotToken */ undefined, @@ -748,112 +748,51 @@ namespace ts { ], /* type */ undefined, /* equalsGreaterThanToken */ undefined, - createAssignment( + factory.createAssignment( setEmitFlags( - createPropertyAccess( + factory.createPropertyAccess( setEmitFlags( - createSuper(), + factory.createSuper(), EmitFlags.NoSubstitution ), name ), EmitFlags.NoSubstitution ), - createIdentifier("v") + factory.createIdentifier("v") ) ) ) ); } accessors.push( - createPropertyAssignment( + factory.createPropertyAssignment( name, - createObjectLiteral(getterAndSetter), + factory.createObjectLiteral(getterAndSetter), ) ); }); - return createVariableStatement( + return factory.createVariableStatement( /* modifiers */ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( [ - createVariableDeclaration( - createFileLevelUniqueName("_super"), + factory.createVariableDeclaration( + factory.createFileLevelUniqueName("_super"), + /*exclamationToken*/ undefined, /* type */ undefined, - createCall( - createPropertyAccess( - createIdentifier("Object"), + factory.createCall( + factory.createPropertyAccess( + factory.createIdentifier("Object"), "create" ), /* typeArguments */ undefined, [ - createNull(), - createObjectLiteral(accessors, /* multiline */ true) + factory.createNull(), + factory.createObjectLiteral(accessors, /* multiline */ true) ] ) ) ], NodeFlags.Const)); } - - export const awaiterHelper: UnscopedEmitHelper = { - name: "typescript:awaiter", - importName: "__awaiter", - scoped: false, - priority: 5, - text: ` - var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - };` - }; - - function createAwaiterHelper(context: TransformationContext, hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) { - context.requestEmitHelper(awaiterHelper); - - const generatorFunc = createFunctionExpression( - /*modifiers*/ undefined, - createToken(SyntaxKind.AsteriskToken), - /*name*/ undefined, - /*typeParameters*/ undefined, - /*parameters*/ [], - /*type*/ undefined, - body - ); - - // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; - - return createCall( - getUnscopedHelperName("__awaiter"), - /*typeArguments*/ undefined, - [ - hasLexicalThis ? createThis() : createVoidZero(), - hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(), - promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(), - generatorFunc - ] - ); - } - - export const asyncSuperHelper: EmitHelper = { - name: "typescript:async-super", - scoped: true, - text: helperString` - const ${"_superIndex"} = name => super[name];` - }; - - export const advancedAsyncSuperHelper: EmitHelper = { - name: "typescript:advanced-async-super", - scoped: true, - text: helperString` - const ${"_superIndex"} = (function (geti, seti) { - const cache = Object.create(null); - return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); - })(name => super[name], (name, value) => super[name] = value);` - }; } diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index 01cabe76e517b..6702fbe719447 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -7,6 +7,8 @@ namespace ts { export function transformES2018(context: TransformationContext) { const { + factory, + getEmitHelperFactory: emitHelpers, resumeLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration @@ -35,7 +37,7 @@ namespace ts { /** A set of node IDs for generated super accessors. */ const substitutedSuperAccessors: boolean[] = []; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -149,7 +151,7 @@ namespace ts { if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { return setOriginalNode( setTextRange( - createYield(createAwaitHelper(context, visitNode(node.expression, visitor, isExpression))), + factory.createYield(/*asteriskToken*/ undefined, emitHelpers().createAwaitHelper(visitNode(node.expression, visitor, isExpression))), /*location*/ node ), node @@ -165,14 +167,19 @@ namespace ts { return setOriginalNode( setTextRange( - createYield( - createAwaitHelper(context, - updateYield( + factory.createYield( + /*asteriskToken*/ undefined, + emitHelpers().createAwaitHelper( + factory.updateYield( node, node.asteriskToken, - createAsyncDelegatorHelper( - context, - createAsyncValuesHelper(context, expression, expression), + setTextRange( + emitHelpers().createAsyncDelegatorHelper( + setTextRange( + emitHelpers().createAsyncValuesHelper(expression), + expression + ) + ), expression ) ) @@ -186,11 +193,12 @@ namespace ts { return setOriginalNode( setTextRange( - createYield( + factory.createYield( + /*asteriskToken*/ undefined, createDownlevelAwait( node.expression ? visitNode(node.expression, visitor, isExpression) - : createVoidZero() + : factory.createVoidZero() ) ), node @@ -204,8 +212,8 @@ namespace ts { function visitReturnStatement(node: ReturnStatement) { if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { - return updateReturn(node, createDownlevelAwait( - node.expression ? visitNode(node.expression, visitor, isExpression) : createVoidZero() + return factory.updateReturn(node, createDownlevelAwait( + node.expression ? visitNode(node.expression, visitor, isExpression) : factory.createVoidZero() )); } @@ -218,7 +226,7 @@ namespace ts { if (statement.kind === SyntaxKind.ForOfStatement && (statement).awaitModifier) { return visitForOfStatement(statement, node); } - return restoreEnclosingLabel(visitEachChild(statement, visitor, context), node); + return factory.restoreEnclosingLabel(visitEachChild(statement, visitor, context), node); } return visitEachChild(node, visitor, context); } @@ -229,7 +237,7 @@ namespace ts { for (const e of elements) { if (e.kind === SyntaxKind.SpreadAssignment) { if (chunkObject) { - objects.push(createObjectLiteral(chunkObject)); + objects.push(factory.createObjectLiteral(chunkObject)); chunkObject = undefined; } const target = e.expression; @@ -237,12 +245,12 @@ namespace ts { } else { chunkObject = append(chunkObject, e.kind === SyntaxKind.PropertyAssignment - ? createPropertyAssignment(e.name, visitNode(e.initializer, visitor, isExpression)) + ? factory.createPropertyAssignment(e.name, visitNode(e.initializer, visitor, isExpression)) : visitNode(e, visitor, isObjectLiteralElementLike)); } } if (chunkObject) { - objects.push(createObjectLiteral(chunkObject)); + objects.push(factory.createObjectLiteral(chunkObject)); } return objects; @@ -273,17 +281,17 @@ namespace ts { // end up with `{ a: 1, b: 2, c: 3 }` const objects = chunkObjectLiteralElements(node.properties); if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) { - objects.unshift(createObjectLiteral()); + objects.unshift(factory.createObjectLiteral()); } let expression: Expression = objects[0]; if (objects.length > 1) { for (let i = 1; i < objects.length; i++) { - expression = createAssignHelper(context, [expression, objects[i]]); + expression = emitHelpers().createAssignHelper([expression, objects[i]]); } return expression; } else { - return createAssignHelper(context, objects); + return emitHelpers().createAssignHelper(objects); } } return visitEachChild(node, visitor, context); @@ -313,7 +321,7 @@ namespace ts { ); } else if (node.operatorToken.kind === SyntaxKind.CommaToken) { - return updateBinary( + return factory.updateBinary( node, visitNode(node.left, visitorNoDestructuringValue, isExpression), visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression) @@ -326,19 +334,19 @@ namespace ts { if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name) && node.variableDeclaration.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { - const name = getGeneratedNameForNode(node.variableDeclaration.name); - const updatedDecl = updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*type*/ undefined, name); + const name = factory.getGeneratedNameForNode(node.variableDeclaration.name); + const updatedDecl = factory.updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*exclamationToken*/ undefined, /*type*/ undefined, name); const visitedBindings = flattenDestructuringBinding(updatedDecl, visitor, context, FlattenLevel.ObjectRest); let block = visitNode(node.block, visitor, isBlock); if (some(visitedBindings)) { - block = updateBlock(block, [ - createVariableStatement(/*modifiers*/ undefined, visitedBindings), + block = factory.updateBlock(block, [ + factory.createVariableStatement(/*modifiers*/ undefined, visitedBindings), ...block.statements, ]); } - return updateCatchClause( + return factory.updateCatchClause( node, - updateVariableDeclaration(node.variableDeclaration, name, /*type*/ undefined, /*initializer*/ undefined), + factory.updateVariableDeclaration(node.variableDeclaration, name, /*exclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined), block); } return visitEachChild(node, visitor, context); @@ -387,7 +395,7 @@ namespace ts { } function visitForStatement(node: ForStatement): VisitResult { - return updateFor( + return factory.updateFor( node, visitNode(node.initializer, visitorNoDestructuringValue, isForInitializer), visitNode(node.condition, visitor, isExpression), @@ -413,7 +421,7 @@ namespace ts { return transformForAwaitOfStatement(node, outermostLabeledStatement); } else { - return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); + return factory.restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); } } @@ -422,8 +430,8 @@ namespace ts { if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) { let bodyLocation: TextRange | undefined; let statementsLocation: TextRange | undefined; - const temp = createTempVariable(/*recordTempVariable*/ undefined); - const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)]; + const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); + const statements: Statement[] = [createForOfBindingStatement(factory, initializerWithoutParens, temp)]; if (isBlock(node.statement)) { addRange(statements, node.statement.statements); bodyLocation = node.statement; @@ -434,13 +442,13 @@ namespace ts { bodyLocation = node.statement; statementsLocation = node.statement; } - return updateForOf( + return factory.updateForOf( node, node.awaitModifier, setTextRange( - createVariableDeclarationList( + factory.createVariableDeclarationList( [ - setTextRange(createVariableDeclaration(temp), node.initializer) + setTextRange(factory.createVariableDeclaration(temp), node.initializer) ], NodeFlags.Let ), @@ -448,8 +456,8 @@ namespace ts { ), node.expression, setTextRange( - createBlock( - setTextRange(createNodeArray(statements), statementsLocation), + factory.createBlock( + setTextRange(factory.createNodeArray(statements), statementsLocation), /*multiLine*/ true ), bodyLocation @@ -460,7 +468,7 @@ namespace ts { } function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) { - const binding = createForOfBindingStatement(node.initializer, boundValue); + const binding = createForOfBindingStatement(factory, node.initializer, boundValue); let bodyLocation: TextRange | undefined; let statementsLocation: TextRange | undefined; @@ -477,8 +485,8 @@ namespace ts { return setEmitFlags( setTextRange( - createBlock( - setTextRange(createNodeArray(statements), statementsLocation), + factory.createBlock( + setTextRange(factory.createNodeArray(statements), statementsLocation), /*multiLine*/ true ), bodyLocation @@ -489,42 +497,42 @@ namespace ts { function createDownlevelAwait(expression: Expression) { return enclosingFunctionFlags & FunctionFlags.Generator - ? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression)) - : createAwait(expression); + ? factory.createYield(/*asteriskToken*/ undefined, emitHelpers().createAwaitHelper(expression)) + : factory.createAwait(expression); } function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined) { const expression = visitNode(node.expression, visitor, isExpression); - const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined); - const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined); - const errorRecord = createUniqueName("e"); - const catchVariable = getGeneratedNameForNode(errorRecord); - const returnMethod = createTempVariable(/*recordTempVariable*/ undefined); - const callValues = createAsyncValuesHelper(context, expression, /*location*/ node.expression); - const callNext = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); - const getDone = createPropertyAccess(result, "done"); - const getValue = createPropertyAccess(result, "value"); - const callReturn = createFunctionCall(returnMethod, iterator, []); + const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const errorRecord = factory.createUniqueName("e"); + const catchVariable = factory.getGeneratedNameForNode(errorRecord); + const returnMethod = factory.createTempVariable(/*recordTempVariable*/ undefined); + const callValues = setTextRange(emitHelpers().createAsyncValuesHelper(expression), node.expression); + const callNext = factory.createCall(factory.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); + const getDone = factory.createPropertyAccess(result, "done"); + const getValue = factory.createPropertyAccess(result, "value"); + const callReturn = factory.createFunctionCallCall(returnMethod, iterator, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); const forStatement = setEmitFlags( setTextRange( - createFor( + factory.createFor( /*initializer*/ setEmitFlags( setTextRange( - createVariableDeclarationList([ - setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, callValues), node.expression), - createVariableDeclaration(result) + factory.createVariableDeclarationList([ + setTextRange(factory.createVariableDeclaration(iterator, /*exclamationToken*/ undefined, /*type*/ undefined, callValues), node.expression), + factory.createVariableDeclaration(result) ]), node.expression ), EmitFlags.NoHoisting ), - /*condition*/ createComma( - createAssignment(result, createDownlevelAwait(callNext)), - createLogicalNot(getDone) + /*condition*/ factory.createComma( + factory.createAssignment(result, createDownlevelAwait(callNext)), + factory.createLogicalNot(getDone) ), /*incrementor*/ undefined, /*statement*/ convertForOfStatementHead(node, getValue) @@ -534,22 +542,22 @@ namespace ts { EmitFlags.NoTokenTrailingSourceMaps ); - return createTry( - createBlock([ - restoreEnclosingLabel( + return factory.createTry( + factory.createBlock([ + factory.restoreEnclosingLabel( forStatement, outermostLabeledStatement ) ]), - createCatchClause( - createVariableDeclaration(catchVariable), + factory.createCatchClause( + factory.createVariableDeclaration(catchVariable), setEmitFlags( - createBlock([ - createExpressionStatement( - createAssignment( + factory.createBlock([ + factory.createExpressionStatement( + factory.createAssignment( errorRecord, - createObjectLiteral([ - createPropertyAssignment("error", catchVariable) + factory.createObjectLiteral([ + factory.createPropertyAssignment("error", catchVariable) ]) ) ) @@ -557,34 +565,34 @@ namespace ts { EmitFlags.SingleLine ) ), - createBlock([ - createTry( - /*tryBlock*/ createBlock([ + factory.createBlock([ + factory.createTry( + /*tryBlock*/ factory.createBlock([ setEmitFlags( - createIf( - createLogicalAnd( - createLogicalAnd( + factory.createIf( + factory.createLogicalAnd( + factory.createLogicalAnd( result, - createLogicalNot(getDone) + factory.createLogicalNot(getDone) ), - createAssignment( + factory.createAssignment( returnMethod, - createPropertyAccess(iterator, "return") + factory.createPropertyAccess(iterator, "return") ) ), - createExpressionStatement(createDownlevelAwait(callReturn)) + factory.createExpressionStatement(createDownlevelAwait(callReturn)) ), EmitFlags.SingleLine ) ]), /*catchClause*/ undefined, /*finallyBlock*/ setEmitFlags( - createBlock([ + factory.createBlock([ setEmitFlags( - createIf( + factory.createIf( errorRecord, - createThrow( - createPropertyAccess(errorRecord, "error") + factory.createThrow( + factory.createPropertyAccess(errorRecord, "error") ) ), EmitFlags.SingleLine @@ -601,12 +609,12 @@ namespace ts { if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { // Binding patterns are converted into a generated name and are // evaluated inside the function body. - return updateParameter( + return factory.updateParameterDeclaration( node, /*decorators*/ undefined, /*modifiers*/ undefined, node.dotDotDotToken, - getGeneratedNameForNode(node), + factory.getGeneratedNameForNode(node), /*questionToken*/ undefined, /*type*/ undefined, visitNode(node.initializer, visitor, isExpression) @@ -618,7 +626,7 @@ namespace ts { function visitConstructorDeclaration(node: ConstructorDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = FunctionFlags.Normal; - const updated = updateConstructor( + const updated = factory.updateConstructorDeclaration( node, /*decorators*/ undefined, node.modifiers, @@ -632,7 +640,7 @@ namespace ts { function visitGetAccessorDeclaration(node: GetAccessorDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = FunctionFlags.Normal; - const updated = updateGetAccessor( + const updated = factory.updateGetAccessorDeclaration( node, /*decorators*/ undefined, node.modifiers, @@ -648,7 +656,7 @@ namespace ts { function visitSetAccessorDeclaration(node: SetAccessorDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = FunctionFlags.Normal; - const updated = updateSetAccessor( + const updated = factory.updateSetAccessorDeclaration( node, /*decorators*/ undefined, node.modifiers, @@ -663,7 +671,7 @@ namespace ts { function visitMethodDeclaration(node: MethodDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = getFunctionFlags(node); - const updated = updateMethod( + const updated = factory.updateMethodDeclaration( node, /*decorators*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator @@ -688,7 +696,7 @@ namespace ts { function visitFunctionDeclaration(node: FunctionDeclaration) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = getFunctionFlags(node); - const updated = updateFunctionDeclaration( + const updated = factory.updateFunctionDeclaration( node, /*decorators*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator @@ -712,7 +720,7 @@ namespace ts { function visitArrowFunction(node: ArrowFunction) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = getFunctionFlags(node); - const updated = updateArrowFunction( + const updated = factory.updateArrowFunction( node, node.modifiers, /*typeParameters*/ undefined, @@ -728,7 +736,7 @@ namespace ts { function visitFunctionExpression(node: FunctionExpression) { const savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = getFunctionFlags(node); - const updated = updateFunctionExpression( + const updated = factory.updateFunctionExpression( node, enclosingFunctionFlags & FunctionFlags.Generator ? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier) @@ -751,7 +759,7 @@ namespace ts { function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody { resumeLexicalEnvironment(); const statements: Statement[] = []; - const statementOffset = addPrologue(statements, node.body!.statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = factory.copyPrologue(node.body!.statements, statements, /*ensureUseStrict*/ false, visitor); appendObjectRestAssignmentsIfNeeded(statements, node); const savedCapturedSuperProperties = capturedSuperProperties; @@ -759,17 +767,16 @@ namespace ts { capturedSuperProperties = createUnderscoreEscapedMap(); hasSuperElementAccess = false; - const returnStatement = createReturn( - createAsyncGeneratorHelper( - context, - createFunctionExpression( + const returnStatement = factory.createReturn( + emitHelpers().createAsyncGeneratorHelper( + factory.createFunctionExpression( /*modifiers*/ undefined, - createToken(SyntaxKind.AsteriskToken), - node.name && getGeneratedNameForNode(node.name), + factory.createToken(SyntaxKind.AsteriskToken), + node.name && factory.getGeneratedNameForNode(node.name), /*typeParameters*/ undefined, /*parameters*/ [], /*type*/ undefined, - updateBlock( + factory.updateBlock( node.body!, visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset) ) @@ -784,7 +791,7 @@ namespace ts { if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); - const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties); + const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties); substitutedSuperAccessors[getNodeId(variableStatement)] = true; insertStatementsAfterStandardPrologue(statements, [variableStatement]); } @@ -792,7 +799,7 @@ namespace ts { statements.push(returnStatement); insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const block = updateBlock(node.body!, statements); + const block = factory.updateBlock(node.body!, statements); if (emitSuperHelpers && hasSuperElementAccess) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) { @@ -817,15 +824,15 @@ namespace ts { const statements: Statement[] = []; const body = visitNode(node.body, visitor, isConciseBody); if (isBlock(body)) { - statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); + statementOffset = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor); } addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node)); const leadingStatements = endLexicalEnvironment(); if (statementOffset > 0 || some(statements) || some(leadingStatements)) { - const block = convertToFunctionBody(body, /*multiLine*/ true); + const block = factory.converters.convertToFunctionBlock(body, /*multiLine*/ true); insertStatementsAfterStandardPrologue(statements, leadingStatements); addRange(statements, block.statements.slice(statementOffset)); - return updateBlock(block, setTextRange(createNodeArray(statements), block.statements)); + return factory.updateBlock(block, setTextRange(factory.createNodeArray(statements), block.statements)); } return body; } @@ -833,7 +840,7 @@ namespace ts { function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined { for (const parameter of node.parameters) { if (parameter.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { - const temp = getGeneratedNameForNode(parameter); + const temp = factory.getGeneratedNameForNode(parameter); const declarations = flattenDestructuringBinding( parameter, visitor, @@ -844,9 +851,9 @@ namespace ts { /*skipInitializer*/ true, ); if (some(declarations)) { - const statement = createVariableStatement( + const statement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( declarations ) ); @@ -940,8 +947,8 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return setTextRange( - createPropertyAccess( - createFileLevelUniqueName("_super"), + factory.createPropertyAccess( + factory.createFileLevelUniqueName("_super"), node.name), node ); @@ -965,11 +972,11 @@ namespace ts { const argumentExpression = isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return createCall( - createPropertyAccess(argumentExpression, "call"), + return factory.createCall( + factory.createPropertyAccess(argumentExpression, "call"), /*typeArguments*/ undefined, [ - createThis(), + factory.createThis(), ...node.arguments ] ); @@ -989,9 +996,9 @@ namespace ts { function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression { if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) { return setTextRange( - createPropertyAccess( - createCall( - createIdentifier("_superIndex"), + factory.createPropertyAccess( + factory.createCall( + factory.createIdentifier("_superIndex"), /*typeArguments*/ undefined, [argumentExpression] ), @@ -1002,8 +1009,8 @@ namespace ts { } else { return setTextRange( - createCall( - createIdentifier("_superIndex"), + factory.createCall( + factory.createIdentifier("_superIndex"), /*typeArguments*/ undefined, [argumentExpression] ), @@ -1012,135 +1019,4 @@ namespace ts { } } } - - export const assignHelper: UnscopedEmitHelper = { - name: "typescript:assign", - importName: "__assign", - scoped: false, - priority: 1, - text: ` - var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - };` - }; - - export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) { - if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) { - return createCall(createPropertyAccess(createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, attributesSegments); - } - context.requestEmitHelper(assignHelper); - return createCall( - getUnscopedHelperName("__assign"), - /*typeArguments*/ undefined, - attributesSegments - ); - } - - export const awaitHelper: UnscopedEmitHelper = { - name: "typescript:await", - importName: "__await", - scoped: false, - text: ` - var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }` - }; - - function createAwaitHelper(context: TransformationContext, expression: Expression) { - context.requestEmitHelper(awaitHelper); - return createCall(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]); - } - - export const asyncGeneratorHelper: UnscopedEmitHelper = { - name: "typescript:asyncGenerator", - importName: "__asyncGenerator", - scoped: false, - text: ` - var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; - function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } - function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } - };` - }; - - function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression, hasLexicalThis: boolean) { - context.requestEmitHelper(awaitHelper); - context.requestEmitHelper(asyncGeneratorHelper); - - // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody; - - return createCall( - getUnscopedHelperName("__asyncGenerator"), - /*typeArguments*/ undefined, - [ - hasLexicalThis ? createThis() : createVoidZero(), - createIdentifier("arguments"), - generatorFunc - ] - ); - } - - export const asyncDelegator: UnscopedEmitHelper = { - name: "typescript:asyncDelegator", - importName: "__asyncDelegator", - scoped: false, - text: ` - var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { - var i, p; - return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } - };` - }; - - function createAsyncDelegatorHelper(context: TransformationContext, expression: Expression, location?: TextRange) { - context.requestEmitHelper(awaitHelper); - context.requestEmitHelper(asyncDelegator); - return setTextRange( - createCall( - getUnscopedHelperName("__asyncDelegator"), - /*typeArguments*/ undefined, - [expression] - ), - location - ); - } - - export const asyncValues: UnscopedEmitHelper = { - name: "typescript:asyncValues", - importName: "__asyncValues", - scoped: false, - text: ` - var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } - };` - }; - - function createAsyncValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) { - context.requestEmitHelper(asyncValues); - return setTextRange( - createCall( - getUnscopedHelperName("__asyncValues"), - /*typeArguments*/ undefined, - [expression] - ), - location - ); - } } diff --git a/src/compiler/transformers/es2019.ts b/src/compiler/transformers/es2019.ts index 7dfd17481ebe7..0d696b4f5ca01 100644 --- a/src/compiler/transformers/es2019.ts +++ b/src/compiler/transformers/es2019.ts @@ -1,7 +1,8 @@ /*@internal*/ namespace ts { export function transformES2019(context: TransformationContext) { - return chainBundle(transformSourceFile); + const factory = context.factory; + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -25,9 +26,9 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { if (!node.variableDeclaration) { - return updateCatchClause( + return factory.updateCatchClause( node, - createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), + factory.createVariableDeclaration(factory.createTempVariable(/*recordTempVariable*/ undefined)), visitNode(node.block, visitor, isBlock) ); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 1c85e684e8cba..3dc4472066075 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -6,6 +6,7 @@ namespace ts { * @param context Context and state information for the transformation. */ export function transformES5(context: TransformationContext) { + const { factory } = context; const compilerOptions = context.getCompilerOptions(); // enable emit notification only if using --jsx preserve or react-native @@ -24,7 +25,7 @@ namespace ts { context.onSubstituteNode = onSubstituteNode; context.enableSubstitution(SyntaxKind.PropertyAccessExpression); context.enableSubstitution(SyntaxKind.PropertyAssignment); - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); /** * Transforms an ES5 source file to ES3. @@ -84,7 +85,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression { const literalName = trySubstituteReservedName(node.name); if (literalName) { - return setTextRange(createElementAccess(node.expression, literalName), node); + return setTextRange(factory.createElementAccess(node.expression, literalName), node); } return node; } @@ -97,7 +98,7 @@ namespace ts { function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment { const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name); if (literalName) { - return updatePropertyAssignment(node, literalName, node.initializer); + return factory.updatePropertyAssignment(node, literalName, node.initializer); } return node; } @@ -110,7 +111,7 @@ namespace ts { function trySubstituteReservedName(name: Identifier) { const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(idText(name)) : undefined); if (token !== undefined && token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { - return setTextRange(createLiteral(name), name); + return setTextRange(factory.createStringLiteralFromNode(name), name); } return undefined; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 2300feeb0e20d..df9c22e617de4 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -2,10 +2,11 @@ namespace ts { export function transformESNext(context: TransformationContext) { const { + factory, hoistVariableDeclaration, } = context; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -55,9 +56,9 @@ namespace ts { if (isSyntheticReference(expression)) { // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } - return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg); + return factory.createSyntheticReferenceExpression(factory.updateParen(node, expression.expression), expression.thisArg); } - return updateParen(node, expression); + return factory.updateParen(node, expression); } function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { @@ -72,8 +73,8 @@ namespace ts { let thisArg: Expression | undefined; if (captureThisArg) { if (shouldCaptureInTempVariable(expression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - expression = createAssignment(thisArg, expression); + thisArg = factory.createTempVariable(hoistVariableDeclaration); + expression = factory.createAssignment(thisArg, expression); } else { thisArg = expression; @@ -81,9 +82,9 @@ namespace ts { } expression = node.kind === SyntaxKind.PropertyAccessExpression - ? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) - : updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); - return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression; + ? factory.updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) + : factory.updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); + return thisArg ? factory.createSyntheticReferenceExpression(expression, thisArg) : expression; } function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { @@ -111,8 +112,8 @@ namespace ts { let leftExpression = isSyntheticReference(left) ? left.expression : left; let capturedLeft: Expression = leftExpression; if (shouldCaptureInTempVariable(leftExpression)) { - capturedLeft = createTempVariable(hoistVariableDeclaration); - leftExpression = createAssignment(capturedLeft, leftExpression); + capturedLeft = factory.createTempVariable(hoistVariableDeclaration); + leftExpression = factory.createAssignment(capturedLeft, leftExpression); } let rightExpression = capturedLeft; let thisArg: Expression | undefined; @@ -123,27 +124,27 @@ namespace ts { case SyntaxKind.ElementAccessExpression: if (i === chain.length - 1 && captureThisArg) { if (shouldCaptureInTempVariable(rightExpression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - rightExpression = createAssignment(thisArg, rightExpression); + thisArg = factory.createTempVariable(hoistVariableDeclaration); + rightExpression = factory.createAssignment(thisArg, rightExpression); } else { thisArg = rightExpression; } } rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression - ? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) - : createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); + ? factory.createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) + : factory.createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); break; case SyntaxKind.CallExpression: if (i === 0 && leftThisArg) { - rightExpression = createFunctionCall( + rightExpression = factory.createFunctionCallCall( rightExpression, - leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg, + leftThisArg.kind === SyntaxKind.SuperKeyword ? factory.createThis() : leftThisArg, visitNodes(segment.arguments, visitor, isExpression) ); } else { - rightExpression = createCall( + rightExpression = factory.createCall( rightExpression, /*typeArguments*/ undefined, visitNodes(segment.arguments, visitor, isExpression) @@ -155,23 +156,23 @@ namespace ts { } const target = isDelete - ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) - : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); - return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; + ? factory.createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createTrue(), /*colonToken*/ undefined, factory.createDelete(rightExpression)) + : factory.createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createVoidZero(), /*colonToken*/ undefined, rightExpression); + return thisArg ? factory.createSyntheticReferenceExpression(target, thisArg) : target; } function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) { - return createBinary( - createBinary( + return factory.createBinary( + factory.createBinary( left, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createNull() + factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + factory.createNull() ), - createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), - createBinary( + factory.createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), + factory.createBinary( right, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createVoidZero() + factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + factory.createVoidZero() ) ); } @@ -180,12 +181,14 @@ namespace ts { let left = visitNode(node.left, visitor, isExpression); let right = left; if (shouldCaptureInTempVariable(left)) { - right = createTempVariable(hoistVariableDeclaration); - left = createAssignment(right, left); + right = factory.createTempVariable(hoistVariableDeclaration); + left = factory.createAssignment(right, left); } - return createConditional( + return factory.createConditional( createNotNullCondition(left, right), + /*questionToken*/ undefined, right, + /*colonToken*/ undefined, visitNode(node.right, visitor, isExpression), ); } @@ -201,7 +204,7 @@ namespace ts { function visitDeleteExpression(node: DeleteExpression) { return isOptionalChain(skipParentheses(node.expression)) ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) - : updateDelete(node, visitNode(node.expression, visitor, isExpression)); + : factory.updateDelete(node, visitNode(node.expression, visitor, isExpression)); } } } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index cc16aef60093f..d831acf256bf5 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -230,6 +230,8 @@ namespace ts { export function transformGenerators(context: TransformationContext) { const { + factory, + getEmitHelperFactory: emitHelpers, resumeLexicalEnvironment, endLexicalEnvironment, hoistFunctionDeclaration, @@ -290,7 +292,7 @@ namespace ts { let currentExceptionBlock: ExceptionBlock | undefined; // The current exception block. let withBlockStack: WithBlock[] | undefined; // A stack containing `with` blocks. - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { @@ -446,7 +448,7 @@ namespace ts { if (node.asteriskToken) { node = setOriginalNode( setTextRange( - createFunctionDeclaration( + factory.createFunctionDeclaration( /*decorators*/ undefined, node.modifiers, /*asteriskToken*/ undefined, @@ -496,7 +498,7 @@ namespace ts { if (node.asteriskToken) { node = setOriginalNode( setTextRange( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, node.name, @@ -577,18 +579,18 @@ namespace ts { operations = undefined; operationArguments = undefined; operationLocations = undefined; - state = createTempVariable(/*recordTempVariable*/ undefined); + state = factory.createTempVariable(/*recordTempVariable*/ undefined); // Build the generator resumeLexicalEnvironment(); - const statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor); transformAndEmitStatements(body.statements, statementOffset); const buildResult = build(); insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - statements.push(createReturn(buildResult)); + statements.push(factory.createReturn(buildResult)); // Restore previous generator state inGeneratorFunctionBody = savedInGeneratorFunctionBody; @@ -605,7 +607,7 @@ namespace ts { operationLocations = savedOperationLocations; state = savedState; - return setTextRange(createBlock(statements, body.multiLine), body); + return setTextRange(factory.createBlock(statements, body.multiLine), body); } /** @@ -637,8 +639,8 @@ namespace ts { } return setSourceMapRange( - createExpressionStatement( - inlineExpressions( + factory.createExpressionStatement( + factory.inlineExpressions( map(variables, transformInitializedVariable) ) ), @@ -710,7 +712,7 @@ namespace ts { // .mark resumeLabel // _a.b = %sent%; - target = updatePropertyAccess( + target = factory.updatePropertyAccess( left, cacheExpression(visitNode((left).expression, visitor, isLeftHandSideExpression)), (left).name @@ -729,7 +731,7 @@ namespace ts { // .mark resumeLabel // _a[_b] = %sent%; - target = updateElementAccess(left, + target = factory.updateElementAccess(left, cacheExpression(visitNode((left).expression, visitor, isLeftHandSideExpression)), cacheExpression(visitNode((left).argumentExpression, visitor, isExpression)) ); @@ -743,10 +745,10 @@ namespace ts { const operator = node.operatorToken.kind; if (isCompoundAssignment(operator)) { return setTextRange( - createAssignment( + factory.createAssignment( target, setTextRange( - createBinary( + factory.createBinary( cacheExpression(target), getOperatorForCompoundAssignment(operator), visitNode(right, visitor, isExpression) @@ -758,7 +760,7 @@ namespace ts { ); } else { - return updateBinary(node, target, visitNode(right, visitor, isExpression)); + return factory.updateBinary(node, target, visitNode(right, visitor, isExpression)); } } @@ -783,10 +785,9 @@ namespace ts { // .yield resumeLabel // _a + %sent% + c() - const clone = getMutableClone(node); - clone.left = cacheExpression(visitNode(node.left, visitor, isExpression)); - clone.right = visitNode(node.right, visitor, isExpression); - return clone; + return factory.updateBinary(node, + cacheExpression(visitNode(node.left, visitor, isExpression)), + visitNode(node.right, visitor, isExpression)); } return visitEachChild(node, visitor, context); @@ -863,7 +864,7 @@ namespace ts { let pendingExpressions: Expression[] = []; visit(node.left); visit(node.right); - return inlineExpressions(pendingExpressions); + return factory.inlineExpressions(pendingExpressions); function visit(node: Expression) { if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { @@ -872,7 +873,7 @@ namespace ts { } else { if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(OpCode.Statement, [createExpressionStatement(inlineExpressions(pendingExpressions))]); + emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); pendingExpressions = []; } @@ -939,7 +940,7 @@ namespace ts { const expression = visitNode(node.expression, visitor, isExpression); if (node.asteriskToken) { const iterator = (getEmitFlags(node.expression!) & EmitFlags.Iterator) === 0 - ? createValuesHelper(context, expression, /*location*/ node) + ? setTextRange(emitHelpers().createValuesHelper(expression), node) : expression; emitYieldStar(iterator, /*location*/ node); } @@ -985,7 +986,7 @@ namespace ts { temp = declareLocal(); const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements); emitAssignment(temp, - createArrayLiteral( + factory.createArrayLiteral( leadingElement ? [leadingElement, ...initialElements] : initialElements @@ -996,9 +997,9 @@ namespace ts { const expressions = reduceLeft(elements, reduceElement, [], numInitialElements); return temp - ? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)]) + ? factory.createArrayConcatCall(temp, [factory.createArrayLiteral(expressions, multiLine)]) : setTextRange( - createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine), + factory.createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine), location ); @@ -1012,11 +1013,11 @@ namespace ts { emitAssignment( temp, hasAssignedTemp - ? createArrayConcat( + ? factory.createArrayConcatCall( temp, - [createArrayLiteral(expressions, multiLine)] + [factory.createArrayLiteral(expressions, multiLine)] ) - : createArrayLiteral( + : factory.createArrayLiteral( leadingElement ? [leadingElement, ...expressions] : expressions, multiLine ) @@ -1055,7 +1056,7 @@ namespace ts { const temp = declareLocal(); emitAssignment(temp, - createObjectLiteral( + factory.createObjectLiteral( visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties), multiLine ) @@ -1063,15 +1064,15 @@ namespace ts { const expressions = reduceLeft(properties, reduceProperty, [], numInitialProperties); expressions.push(multiLine ? startOnNewLine(getMutableClone(temp)) : temp); - return inlineExpressions(expressions); + return factory.inlineExpressions(expressions); function reduceProperty(expressions: Expression[], property: ObjectLiteralElementLike) { if (containsYield(property) && expressions.length > 0) { - emitStatement(createExpressionStatement(inlineExpressions(expressions))); + emitStatement(factory.createExpressionStatement(factory.inlineExpressions(expressions))); expressions = []; } - const expression = createExpressionForObjectLiteralElementLike(node, property, temp); + const expression = createExpressionForObjectLiteralElementLike(factory, node, property, temp); const visited = visitNode(expression, visitor, isExpression); if (visited) { if (multiLine) { @@ -1100,10 +1101,9 @@ namespace ts { // .mark resumeLabel // a = _a[%sent%] - const clone = getMutableClone(node); - clone.expression = cacheExpression(visitNode(node.expression, visitor, isLeftHandSideExpression)); - clone.argumentExpression = visitNode(node.argumentExpression, visitor, isExpression); - return clone; + return factory.updateElementAccess(node, + cacheExpression(visitNode(node.expression, visitor, isLeftHandSideExpression)), + visitNode(node.argumentExpression, visitor, isExpression)); } return visitEachChild(node, visitor, context); @@ -1121,13 +1121,15 @@ namespace ts { // .yield resumeLabel // .mark resumeLabel // _b.apply(_a, _c.concat([%sent%, 2])); - const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); + const { target, thisArg } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); return setOriginalNode( - createFunctionApply( - cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)), - thisArg, - visitElements(node.arguments), - /*location*/ node + setTextRange( + factory.createFunctionApplyCall( + cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)), + thisArg, + visitElements(node.arguments) + ), + node ), node ); @@ -1149,16 +1151,16 @@ namespace ts { // .mark resumeLabel // new (_b.apply(_a, _c.concat([%sent%, 2]))); - const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); + const { target, thisArg } = factory.createCallBinding(factory.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); return setOriginalNode( setTextRange( - createNew( - createFunctionApply( + factory.createNew( + factory.createFunctionApplyCall( cacheExpression(visitNode(target, visitor, isExpression)), thisArg, visitElements( node.arguments!, - /*leadingElement*/ createVoidZero() + /*leadingElement*/ factory.createVoidZero() ) ), /*typeArguments*/ undefined, @@ -1270,7 +1272,7 @@ namespace ts { } if (pendingExpressions.length) { - emitStatement(createExpressionStatement(inlineExpressions(pendingExpressions))); + emitStatement(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); variablesWritten += pendingExpressions.length; pendingExpressions = []; } @@ -1281,7 +1283,7 @@ namespace ts { function transformInitializedVariable(node: VariableDeclaration) { return setSourceMapRange( - createAssignment( + factory.createAssignment( setSourceMapRange(getSynthesizedClone(node.name), node.name), visitNode(node.initializer, visitor, isExpression) ), @@ -1441,7 +1443,7 @@ namespace ts { else { emitStatement( setTextRange( - createExpressionStatement( + factory.createExpressionStatement( visitNode(initializer, visitor, isExpression) ), initializer @@ -1461,7 +1463,7 @@ namespace ts { if (node.incrementor) { emitStatement( setTextRange( - createExpressionStatement( + factory.createExpressionStatement( visitNode(node.incrementor, visitor, isExpression) ), node.incrementor @@ -1488,13 +1490,13 @@ namespace ts { } const variables = getInitializedVariables(initializer); - node = updateFor(node, + node = factory.updateFor(node, variables.length > 0 - ? inlineExpressions(map(variables, transformInitializedVariable)) + ? factory.inlineExpressions(map(variables, transformInitializedVariable)) : undefined, visitNode(node.condition, visitor, isExpression), visitNode(node.incrementor, visitor, isExpression), - visitNode(node.statement, visitor, isStatement, liftToBlock) + visitNode(node.statement, visitor, isStatement, factory.liftToBlock) ); } else { @@ -1534,18 +1536,18 @@ namespace ts { const keysArray = declareLocal(); // _a const key = declareLocal(); // _b - const keysIndex = createLoopVariable(); // _i + const keysIndex = factory.createLoopVariable(); // _i const initializer = node.initializer; hoistVariableDeclaration(keysIndex); - emitAssignment(keysArray, createArrayLiteral()); + emitAssignment(keysArray, factory.createArrayLiteral()); emitStatement( - createForIn( + factory.createForIn( key, visitNode(node.expression, visitor, isExpression), - createExpressionStatement( - createCall( - createPropertyAccess(keysArray, "push"), + factory.createExpressionStatement( + factory.createCall( + factory.createPropertyAccess(keysArray, "push"), /*typeArguments*/ undefined, [key] ) @@ -1553,14 +1555,14 @@ namespace ts { ) ); - emitAssignment(keysIndex, createLiteral(0)); + emitAssignment(keysIndex, factory.createNumericLiteral(0)); const conditionLabel = defineLabel(); const incrementLabel = defineLabel(); const endLabel = beginLoopBlock(incrementLabel); markLabel(conditionLabel); - emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length"))); + emitBreakWhenFalse(endLabel, factory.createLessThan(keysIndex, factory.createPropertyAccess(keysArray, "length"))); let variable: Expression; if (isVariableDeclarationList(initializer)) { @@ -1575,11 +1577,11 @@ namespace ts { Debug.assert(isLeftHandSideExpression(variable)); } - emitAssignment(variable, createElementAccess(keysArray, keysIndex)); + emitAssignment(variable, factory.createElementAccess(keysArray, keysIndex)); transformAndEmitEmbeddedStatement(node.statement); markLabel(incrementLabel); - emitStatement(createExpressionStatement(createPostfixIncrement(keysIndex))); + emitStatement(factory.createExpressionStatement(factory.createPostfixIncrement(keysIndex))); emitBreak(conditionLabel); endLoopBlock(); @@ -1613,10 +1615,10 @@ namespace ts { hoistVariableDeclaration(variable.name); } - node = updateForIn(node, + node = factory.updateForIn(node, initializer.declarations[0].name, visitNode(node.expression, visitor, isExpression), - visitNode(node.statement, visitor, isStatement, liftToBlock) + visitNode(node.statement, visitor, isStatement, factory.liftToBlock) ); } else { @@ -1774,7 +1776,7 @@ namespace ts { } pendingClauses.push( - createCaseClause( + factory.createCaseClause( visitNode(clause.expression, visitor, isExpression), [ createInlineBreak(clauseLabels[i], /*location*/ clause.expression) @@ -1788,7 +1790,7 @@ namespace ts { } if (pendingClauses.length) { - emitStatement(createSwitch(expression, createCaseBlock(pendingClauses))); + emitStatement(factory.createSwitch(expression, factory.createCaseBlock(pendingClauses))); clausesWritten += pendingClauses.length; pendingClauses = []; } @@ -1979,15 +1981,15 @@ namespace ts { return node; } - const temp = createTempVariable(hoistVariableDeclaration); + const temp = factory.createTempVariable(hoistVariableDeclaration); emitAssignment(temp, node, /*location*/ node); return temp; } function declareLocal(name?: string): Identifier { const temp = name - ? createUniqueName(name) - : createTempVariable(/*recordTempVariable*/ undefined); + ? factory.createUniqueName(name) + : factory.createTempVariable(/*recordTempVariable*/ undefined); hoistVariableDeclaration(temp); return temp; } @@ -2147,7 +2149,7 @@ namespace ts { exception.catchVariable = name; exception.catchLabel = catchLabel; - emitAssignment(name, createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); + emitAssignment(name, factory.createCall(factory.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); emitNop(); } @@ -2414,7 +2416,7 @@ namespace ts { labelExpressions = []; } - const expression = createLiteral(-1); + const expression = factory.createNumericLiteral(-1); if (labelExpressions[label] === undefined) { labelExpressions[label] = [expression]; } @@ -2425,14 +2427,14 @@ namespace ts { return expression; } - return createOmittedExpression(); + return factory.createOmittedExpression(); } /** * Creates a numeric literal for the provided instruction. */ function createInstruction(instruction: Instruction): NumericLiteral { - const literal = createLiteral(instruction); + const literal = factory.createNumericLiteral(instruction); addSyntheticTrailingComment(literal, SyntaxKind.MultiLineCommentTrivia, getInstructionName(instruction)); return literal; } @@ -2446,8 +2448,8 @@ namespace ts { function createInlineBreak(label: Label, location?: TextRange): ReturnStatement { Debug.assertLessThan(0, label, "Invalid label"); return setTextRange( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.Break), createLabel(label) ]) @@ -2464,8 +2466,8 @@ namespace ts { */ function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement { return setTextRange( - createReturn( - createArrayLiteral(expression + factory.createReturn( + factory.createArrayLiteral(expression ? [createInstruction(Instruction.Return), expression] : [createInstruction(Instruction.Return)] ) @@ -2479,8 +2481,8 @@ namespace ts { */ function createGeneratorResume(location?: TextRange): LeftHandSideExpression { return setTextRange( - createCall( - createPropertyAccess(state, "sent"), + factory.createCall( + factory.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [] ), @@ -2641,17 +2643,16 @@ namespace ts { withBlockStack = undefined; const buildResult = buildStatements(); - return createGeneratorHelper( - context, + return emitHelpers().createGeneratorHelper( setEmitFlags( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)], /*type*/ undefined, - createBlock( + factory.createBlock( buildResult, /*multiLine*/ buildResult.length > 0 ) @@ -2677,8 +2678,8 @@ namespace ts { } if (clauses) { - const labelExpression = createPropertyAccess(state, "label"); - const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses)); + const labelExpression = factory.createPropertyAccess(state, "label"); + const switchStatement = factory.createSwitch(labelExpression, factory.createCaseBlock(clauses)); return [startOnNewLine(switchStatement)]; } @@ -2767,7 +2768,7 @@ namespace ts { // surround the statements in generated `with` blocks to create the same environment. for (let i = withBlockStack.length - 1; i >= 0; i--) { const withBlock = withBlockStack[i]; - statements = [createWith(withBlock.expression, createBlock(statements))]; + statements = [factory.createWith(withBlock.expression, factory.createBlock(statements))]; } } @@ -2777,12 +2778,12 @@ namespace ts { // for each block in the protected region. const { startLabel, catchLabel, finallyLabel, endLabel } = currentExceptionBlock; statements.unshift( - createExpressionStatement( - createCall( - createPropertyAccess(createPropertyAccess(state, "trys"), "push"), + factory.createExpressionStatement( + factory.createCall( + factory.createPropertyAccess(factory.createPropertyAccess(state, "trys"), "push"), /*typeArguments*/ undefined, [ - createArrayLiteral([ + factory.createArrayLiteral([ createLabel(startLabel), createLabel(catchLabel), createLabel(finallyLabel), @@ -2800,10 +2801,10 @@ namespace ts { // The case clause for the last label falls through to this label, so we // add an assignment statement to reflect the change in labels. statements.push( - createExpressionStatement( - createAssignment( - createPropertyAccess(state, "label"), - createLiteral(labelNumber + 1) + factory.createExpressionStatement( + factory.createAssignment( + factory.createPropertyAccess(state, "label"), + factory.createNumericLiteral(labelNumber + 1) ) ) ); @@ -2811,8 +2812,8 @@ namespace ts { } clauses.push( - createCaseClause( - createLiteral(labelNumber), + factory.createCaseClause( + factory.createNumericLiteral(labelNumber), statements || [] ) ); @@ -2984,7 +2985,7 @@ namespace ts { * @param operationLocation The source map location for the operation. */ function writeAssign(left: Expression, right: Expression, operationLocation: TextRange | undefined): void { - writeStatement(setTextRange(createExpressionStatement(createAssignment(left, right)), operationLocation)); + writeStatement(setTextRange(factory.createExpressionStatement(factory.createAssignment(left, right)), operationLocation)); } /** @@ -2996,7 +2997,7 @@ namespace ts { function writeThrow(expression: Expression, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; - writeStatement(setTextRange(createThrow(expression), operationLocation)); + writeStatement(setTextRange(factory.createThrow(expression), operationLocation)); } /** @@ -3011,8 +3012,8 @@ namespace ts { writeStatement( setEmitFlags( setTextRange( - createReturn( - createArrayLiteral(expression + factory.createReturn( + factory.createArrayLiteral(expression ? [createInstruction(Instruction.Return), expression] : [createInstruction(Instruction.Return)] ) @@ -3035,8 +3036,8 @@ namespace ts { writeStatement( setEmitFlags( setTextRange( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.Break), createLabel(label) ]) @@ -3058,12 +3059,12 @@ namespace ts { function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange | undefined): void { writeStatement( setEmitFlags( - createIf( + factory.createIf( condition, setEmitFlags( setTextRange( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.Break), createLabel(label) ]) @@ -3088,12 +3089,12 @@ namespace ts { function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange | undefined): void { writeStatement( setEmitFlags( - createIf( - createLogicalNot(condition), + factory.createIf( + factory.createLogicalNot(condition), setEmitFlags( setTextRange( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.Break), createLabel(label) ]) @@ -3119,8 +3120,8 @@ namespace ts { writeStatement( setEmitFlags( setTextRange( - createReturn( - createArrayLiteral( + factory.createReturn( + factory.createArrayLiteral( expression ? [createInstruction(Instruction.Yield), expression] : [createInstruction(Instruction.Yield)] @@ -3144,8 +3145,8 @@ namespace ts { writeStatement( setEmitFlags( setTextRange( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.YieldStar), expression ]) @@ -3163,114 +3164,12 @@ namespace ts { function writeEndfinally(): void { lastOperationWasAbrupt = true; writeStatement( - createReturn( - createArrayLiteral([ + factory.createReturn( + factory.createArrayLiteral([ createInstruction(Instruction.Endfinally) ]) ) ); } } - - function createGeneratorHelper(context: TransformationContext, body: FunctionExpression) { - context.requestEmitHelper(generatorHelper); - return createCall( - getUnscopedHelperName("__generator"), - /*typeArguments*/ undefined, - [createThis(), body]); - } - - // The __generator helper is used by down-level transformations to emulate the runtime - // semantics of an ES2015 generator function. When called, this helper returns an - // object that implements the Iterator protocol, in that it has `next`, `return`, and - // `throw` methods that step through the generator when invoked. - // - // parameters: - // @param thisArg The value to use as the `this` binding for the transformed generator body. - // @param body A function that acts as the transformed generator body. - // - // variables: - // _ Persistent state for the generator that is shared between the helper and the - // generator body. The state object has the following members: - // sent() - A method that returns or throws the current completion value. - // label - The next point at which to resume evaluation of the generator body. - // trys - A stack of protected regions (try/catch/finally blocks). - // ops - A stack of pending instructions when inside of a finally block. - // f A value indicating whether the generator is executing. - // y An iterator to delegate for a yield*. - // t A temporary variable that holds one of the following values (note that these - // cases do not overlap): - // - The completion value when resuming from a `yield` or `yield*`. - // - The error value for a catch block. - // - The current protected region (array of try/catch/finally/end labels). - // - The verb (`next`, `throw`, or `return` method) to delegate to the expression - // of a `yield*`. - // - The result of evaluating the verb delegated to the expression of a `yield*`. - // - // functions: - // verb(n) Creates a bound callback to the `step` function for opcode `n`. - // step(op) Evaluates opcodes in a generator body until execution is suspended or - // completed. - // - // The __generator helper understands a limited set of instructions: - // 0: next(value?) - Start or resume the generator with the specified value. - // 1: throw(error) - Resume the generator with an exception. If the generator is - // suspended inside of one or more protected regions, evaluates - // any intervening finally blocks between the current label and - // the nearest catch block or function boundary. If uncaught, the - // exception is thrown to the caller. - // 2: return(value?) - Resume the generator as if with a return. If the generator is - // suspended inside of one or more protected regions, evaluates any - // intervening finally blocks. - // 3: break(label) - Jump to the specified label. If the label is outside of the - // current protected region, evaluates any intervening finally - // blocks. - // 4: yield(value?) - Yield execution to the caller with an optional value. When - // resumed, the generator will continue at the next label. - // 5: yield*(value) - Delegates evaluation to the supplied iterator. When - // delegation completes, the generator will continue at the next - // label. - // 6: catch(error) - Handles an exception thrown from within the generator body. If - // the current label is inside of one or more protected regions, - // evaluates any intervening finally blocks between the current - // label and the nearest catch block or function boundary. If - // uncaught, the exception is thrown to the caller. - // 7: endfinally - Ends a finally block, resuming the last instruction prior to - // entering a finally block. - // - // For examples of how these are used, see the comments in ./transformers/generators.ts - export const generatorHelper: UnscopedEmitHelper = { - name: "typescript:generator", - importName: "__generator", - scoped: false, - priority: 6, - text: ` - var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } - };` - }; } diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 4b75deb95cb46..ff31b29bb369e 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -1,10 +1,14 @@ /*@internal*/ namespace ts { export function transformJsx(context: TransformationContext) { + const { + factory, + getEmitHelperFactory: emitHelpers, + } = context; const compilerOptions = context.getCompilerOptions(); let currentSourceFile: SourceFile; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); /** * Transform JSX-specific syntax in a SourceFile. @@ -89,8 +93,8 @@ namespace ts { let objectProperties: Expression | undefined; const attrs = node.attributes.properties; if (attrs.length === 0) { + objectProperties = factory.createNull(); // When there are no attributes, React wants "null" - objectProperties = createNull(); } else { // Map spans of JsxAttribute nodes into object literals and spans @@ -98,25 +102,26 @@ namespace ts { const segments = flatten( spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread ? map(attrs, transformJsxSpreadAttributeToExpression) - : createObjectLiteral(map(attrs, transformJsxAttributeToObjectLiteralElement)) + : factory.createObjectLiteral(map(attrs, transformJsxAttributeToObjectLiteralElement)) ) ); if (isJsxSpreadAttribute(attrs[0])) { // We must always emit at least one object literal before a spread - // argument. - segments.unshift(createObjectLiteral()); + // argument.factory.createObjectLiteral + segments.unshift(factory.createObjectLiteral()); } // Either emit one big object literal (no spread attribs), or // a call to the __assign helper. objectProperties = singleOrUndefined(segments); if (!objectProperties) { - objectProperties = createAssignHelper(context, segments); + objectProperties = emitHelpers().createAssignHelper(segments); } } const element = createExpressionForJsxElement( + factory, context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace!, // TODO: GH#18217 tagName, @@ -135,6 +140,7 @@ namespace ts { function visitJsxOpeningFragment(node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { const element = createExpressionForJsxFragment( + factory, context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace!, // TODO: GH#18217 mapDefined(children, transformJsxChildToExpression), @@ -156,23 +162,23 @@ namespace ts { function transformJsxAttributeToObjectLiteralElement(node: JsxAttribute) { const name = getAttributeName(node); const expression = transformJsxAttributeInitializer(node.initializer); - return createPropertyAssignment(name, expression); + return factory.createPropertyAssignment(name, expression); } function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression | undefined): Expression { if (node === undefined) { - return createTrue(); + return factory.createTrue(); } else if (node.kind === SyntaxKind.StringLiteral) { // Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which // Need to be escaped to be handled correctly in a normal string - const literal = createLiteral(tryDecodeEntities(node.text) || node.text); - literal.singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile); + const singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile); + const literal = factory.createStringLiteral(tryDecodeEntities(node.text) || node.text, singleQuote); return setTextRange(literal, node); } else if (node.kind === SyntaxKind.JsxExpression) { if (node.expression === undefined) { - return createTrue(); + return factory.createTrue(); } return visitJsxExpression(node); } @@ -183,7 +189,7 @@ namespace ts { function visitJsxText(node: JsxText): StringLiteral | undefined { const fixed = fixupWhitespaceAndDecodeEntities(node.text); - return fixed === undefined ? undefined : createLiteral(fixed); + return fixed === undefined ? undefined : factory.createStringLiteral(fixed); } /** @@ -279,10 +285,10 @@ namespace ts { else { const name = node.tagName; if (isIdentifier(name) && isIntrinsicJsxName(name.escapedText)) { - return createLiteral(idText(name)); + return factory.createStringLiteral(idText(name)); } else { - return createExpressionFromEntityName(name); + return createExpressionFromEntityName(factory, name); } } } @@ -299,7 +305,7 @@ namespace ts { return name; } else { - return createLiteral(text); + return factory.createStringLiteral(text); } } diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index e1123d1248d9f..26deb414d5aea 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -1,6 +1,10 @@ /*@internal*/ namespace ts { export function transformES2015Module(context: TransformationContext) { + const { + factory, + getEmitHelperFactory: emitHelpers, + } = context; const compilerOptions = context.getCompilerOptions(); const previousOnEmitNode = context.onEmitNode; const previousOnSubstituteNode = context.onSubstituteNode; @@ -10,7 +14,7 @@ namespace ts { context.enableSubstitution(SyntaxKind.Identifier); let helperNameSubstitutions: Map | undefined; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { @@ -18,16 +22,16 @@ namespace ts { } if (isExternalModule(node) || compilerOptions.isolatedModules) { - const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(node, compilerOptions); + const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(factory, emitHelpers(), node, compilerOptions); if (externalHelpersImportDeclaration) { const statements: Statement[] = []; - const statementOffset = addPrologue(statements, node.statements); + const statementOffset = factory.copyPrologue(node.statements, statements); append(statements, externalHelpersImportDeclaration); addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset)); - return updateSourceFileNode( + return factory.updateSourceFile( node, - setTextRange(createNodeArray(statements), node.statements)); + setTextRange(factory.createNodeArray(statements), node.statements)); } else { return visitEachChild(node, visitor, context); @@ -99,7 +103,7 @@ namespace ts { const name = idText(node); let substitution = helperNameSubstitutions!.get(name); if (!substitution) { - helperNameSubstitutions!.set(name, substitution = createFileLevelUniqueName(name)); + helperNameSubstitutions!.set(name, substitution = factory.createFileLevelUniqueName(name)); } return substitution; } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 9726c6402e168..cee5fe0693cf4 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -16,6 +16,8 @@ namespace ts { } const { + factory, + getEmitHelperFactory: emitHelpers, startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration @@ -45,7 +47,7 @@ namespace ts { let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored. let needUMDDynamicImportHelper: boolean; - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); /** * Transforms the module aspects of a SourceFile. @@ -61,7 +63,7 @@ namespace ts { } currentSourceFile = node; - currentModuleInfo = collectExternalModuleInfo(node, resolver, compilerOptions); + currentModuleInfo = collectExternalModuleInfo(context, node, resolver, compilerOptions); moduleInfoMap[getOriginalNodeId(node)] = currentModuleInfo; // Perform the transformation. @@ -70,7 +72,7 @@ namespace ts { currentSourceFile = undefined!; currentModuleInfo = undefined!; needUMDDynamicImportHelper = false; - return aggregateTransformFlags(updated); + return updated; } @@ -91,7 +93,7 @@ namespace ts { const statements: Statement[] = []; const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); - const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); + const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict, sourceElementVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); @@ -102,7 +104,7 @@ namespace ts { addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements)); + const updated = factory.updateSourceFile(node, setTextRange(factory.createNodeArray(statements), node.statements)); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. @@ -118,8 +120,8 @@ namespace ts { * @param node The SourceFile node. */ function transformAMDModule(node: SourceFile) { - const define = createIdentifier("define"); - const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions); + const define = factory.createIdentifier("define"); + const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions); const jsonSourceFile = isJsonSourceFile(node) && node; // An AMD define function has the following shape: @@ -147,12 +149,12 @@ namespace ts { // Create an updated SourceFile: // - // define(moduleName?, ["module1", "module2"], function ... - const updated = updateSourceFileNode(node, + // define(mofactory.updateSourceFile", "module2"], function ... + const updated = factory.updateSourceFile(node, setTextRange( - createNodeArray([ - createExpressionStatement( - createCall( + factory.createNodeArray([ + factory.createExpressionStatement( + factory.createCall( define, /*typeArguments*/ undefined, [ @@ -162,9 +164,9 @@ namespace ts { // Add the dependency array argument: // // ["require", "exports", module1", "module2", ...] - createArrayLiteral(jsonSourceFile ? emptyArray : [ - createLiteral("require"), - createLiteral("exports"), + factory.createArrayLiteral(jsonSourceFile ? emptyArray : [ + factory.createStringLiteral("require"), + factory.createStringLiteral("exports"), ...aliasedModuleNames, ...unaliasedModuleNames ]), @@ -173,15 +175,15 @@ namespace ts { // // function (require, exports, module1, module2) ... jsonSourceFile ? - jsonSourceFile.statements.length ? jsonSourceFile.statements[0].expression : createObjectLiteral() : - createFunctionExpression( + jsonSourceFile.statements.length ? jsonSourceFile.statements[0].expression : factory.createObjectLiteral() : + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, [ - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), ...importAliasNames ], /*type*/ undefined, @@ -206,76 +208,77 @@ namespace ts { */ function transformUMDModule(node: SourceFile) { const { aliasedModuleNames, unaliasedModuleNames, importAliasNames } = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ false); - const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions); - const umdHeader = createFunctionExpression( + const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions); + const umdHeader = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")], /*type*/ undefined, setTextRange( - createBlock( + factory.createBlock( [ - createIf( - createLogicalAnd( - createTypeCheck(createIdentifier("module"), "object"), - createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object") + factory.createIf( + factory.createLogicalAnd( + factory.createTypeCheck(factory.createIdentifier("module"), "object"), + factory.createTypeCheck(factory.createPropertyAccess(factory.createIdentifier("module"), "exports"), "object") ), - createBlock([ - createVariableStatement( + factory.createBlock([ + factory.createVariableStatement( /*modifiers*/ undefined, [ - createVariableDeclaration( + factory.createVariableDeclaration( "v", + /*exclamationToken*/ undefined, /*type*/ undefined, - createCall( - createIdentifier("factory"), + factory.createCall( + factory.createIdentifier("factory"), /*typeArguments*/ undefined, [ - createIdentifier("require"), - createIdentifier("exports") + factory.createIdentifier("require"), + factory.createIdentifier("exports") ] ) ) ] ), setEmitFlags( - createIf( - createStrictInequality( - createIdentifier("v"), - createIdentifier("undefined") + factory.createIf( + factory.createStrictInequality( + factory.createIdentifier("v"), + factory.createIdentifier("undefined") ), - createExpressionStatement( - createAssignment( - createPropertyAccess(createIdentifier("module"), "exports"), - createIdentifier("v") + factory.createExpressionStatement( + factory.createAssignment( + factory.createPropertyAccess(factory.createIdentifier("module"), "exports"), + factory.createIdentifier("v") ) ) ), EmitFlags.SingleLine ) ]), - createIf( - createLogicalAnd( - createTypeCheck(createIdentifier("define"), "function"), - createPropertyAccess(createIdentifier("define"), "amd") + factory.createIf( + factory.createLogicalAnd( + factory.createTypeCheck(factory.createIdentifier("define"), "function"), + factory.createPropertyAccess(factory.createIdentifier("define"), "amd") ), - createBlock([ - createExpressionStatement( - createCall( - createIdentifier("define"), + factory.createBlock([ + factory.createExpressionStatement( + factory.createCall( + factory.createIdentifier("define"), /*typeArguments*/ undefined, [ // Add the module name (if provided). ...(moduleName ? [moduleName] : []), - createArrayLiteral([ - createLiteral("require"), - createLiteral("exports"), + factory.createArrayLiteral([ + factory.createStringLiteral("require"), + factory.createStringLiteral("exports"), ...aliasedModuleNames, ...unaliasedModuleNames ]), - createIdentifier("factory") + factory.createIdentifier("factory") ] ) ) @@ -301,26 +304,26 @@ namespace ts { // } // })(function ...) - const updated = updateSourceFileNode( + const updated = factory.updateSourceFile( node, setTextRange( - createNodeArray([ - createExpressionStatement( - createCall( + factory.createNodeArray([ + factory.createExpressionStatement( + factory.createCall( umdHeader, /*typeArguments*/ undefined, [ // Add the module body function argument: // // function (require, exports) ... - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, [ - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), ...importAliasNames ], /*type*/ undefined, @@ -359,20 +362,20 @@ namespace ts { // Fill in amd-dependency tags for (const amdDependency of node.amdDependencies) { if (amdDependency.name) { - aliasedModuleNames.push(createLiteral(amdDependency.path)); - importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, amdDependency.name)); + aliasedModuleNames.push(factory.createStringLiteral(amdDependency.path)); + importAliasNames.push(factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, amdDependency.name)); } else { - unaliasedModuleNames.push(createLiteral(amdDependency.path)); + unaliasedModuleNames.push(factory.createStringLiteral(amdDependency.path)); } } for (const importNode of currentModuleInfo.externalImports) { // Find the name of the external module - const externalModuleName = getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral(factory, importNode, currentSourceFile, host, resolver, compilerOptions); // Find the name of the module alias, if there is one - const importAliasName = getLocalNameForExternalImport(importNode, currentSourceFile); + const importAliasName = getLocalNameForExternalImport(factory, importNode, currentSourceFile); // It is possible that externalModuleName is undefined if it is not string literal. // This can happen in the invalid import syntax. // E.g : "import * from alias from 'someLib';" @@ -382,7 +385,7 @@ namespace ts { // This is so that when printer will not substitute the identifier setEmitFlags(importAliasName, EmitFlags.NoSubstitution); aliasedModuleNames.push(externalModuleName); - importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName)); + importAliasNames.push(factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName)); } else { unaliasedModuleNames.push(externalModuleName); @@ -394,15 +397,15 @@ namespace ts { } function getAMDImportExpressionForImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) { - if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) { + if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions)) { return undefined; } - const name = getLocalNameForExternalImport(node, currentSourceFile)!; // TODO: GH#18217 + const name = getLocalNameForExternalImport(factory, node, currentSourceFile)!; // TODO: GH#18217 const expr = getHelperExpressionForImport(node, name); if (expr === name) { return undefined; } - return createExpressionStatement(createAssignment(name, expr)); + return factory.createExpressionStatement(factory.createAssignment(name, expr)); } /** @@ -414,7 +417,7 @@ namespace ts { startLexicalEnvironment(); const statements: Statement[] = []; - const statementOffset = addPrologue(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); + const statementOffset = factory.copyPrologue(node.statements, statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); @@ -434,7 +437,7 @@ namespace ts { // and merge any new lexical declarations. insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const body = createBlock(statements, /*multiLine*/ true); + const body = factory.createBlock(statements, /*multiLine*/ true); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. @@ -460,16 +463,16 @@ namespace ts { const expressionResult = visitNode(currentModuleInfo.exportEquals.expression, moduleExpressionElementVisitor); if (expressionResult) { if (emitAsReturn) { - const statement = createReturn(expressionResult); + const statement = factory.createReturn(expressionResult); setTextRange(statement, currentModuleInfo.exportEquals); setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments); statements.push(statement); } else { - const statement = createExpressionStatement( - createAssignment( - createPropertyAccess( - createIdentifier("module"), + const statement = factory.createExpressionStatement( + factory.createAssignment( + factory.createPropertyAccess( + factory.createIdentifier("module"), "exports" ), expressionResult @@ -627,18 +630,22 @@ namespace ts { // }); needUMDDynamicImportHelper = true; if (isSimpleCopiableExpression(arg)) { - const argClone = isGeneratedIdentifier(arg) ? arg : isStringLiteral(arg) ? createLiteral(arg) : setEmitFlags(setTextRange(getSynthesizedClone(arg), arg), EmitFlags.NoComments); - return createConditional( - /*condition*/ createIdentifier("__syncRequire"), + const argClone = isGeneratedIdentifier(arg) ? arg : isStringLiteral(arg) ? factory.createStringLiteralFromNode(arg) : setEmitFlags(setTextRange(getSynthesizedClone(arg), arg), EmitFlags.NoComments); + return factory.createConditional( + /*condition*/ factory.createIdentifier("__syncRequire"), + /*questionToken*/ undefined, /*whenTrue*/ createImportCallExpressionCommonJS(arg, containsLexicalThis), + /*colonToken*/ undefined, /*whenFalse*/ createImportCallExpressionAMD(argClone, containsLexicalThis) ); } else { - const temp = createTempVariable(hoistVariableDeclaration); - return createComma(createAssignment(temp, arg), createConditional( - /*condition*/ createIdentifier("__syncRequire"), + const temp = factory.createTempVariable(hoistVariableDeclaration); + return factory.createComma(factory.createAssignment(temp, arg), factory.createConditional( + /*condition*/ factory.createIdentifier("__syncRequire"), + /*questionToken*/ undefined, /*whenTrue*/ createImportCallExpressionCommonJS(temp, containsLexicalThis), + /*colonToken*/ undefined, /*whenFalse*/ createImportCallExpressionAMD(temp, containsLexicalThis) )); } @@ -651,25 +658,25 @@ namespace ts { // ... // new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ // }); - const resolve = createUniqueName("resolve"); - const reject = createUniqueName("reject"); + const resolve = factory.createUniqueName("resolve"); + const reject = factory.createUniqueName("reject"); const parameters = [ - createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), - createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject) + factory.createParameterDeclaration(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), + factory.createParameterDeclaration(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject) ]; - const body = createBlock([ - createExpressionStatement( - createCall( - createIdentifier("require"), + const body = factory.createBlock([ + factory.createExpressionStatement( + factory.createCall( + factory.createIdentifier("require"), /*typeArguments*/ undefined, - [createArrayLiteral([arg || createOmittedExpression()]), resolve, reject] + [factory.createArrayLiteral([arg || factory.createOmittedExpression()]), resolve, reject] ) ) ]); let func: FunctionExpression | ArrowFunction; if (languageVersion >= ScriptTarget.ES2015) { - func = createArrowFunction( + func = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, parameters, @@ -678,7 +685,7 @@ namespace ts { body); } else { - func = createFunctionExpression( + func = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, @@ -695,10 +702,10 @@ namespace ts { } } - const promise = createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); + const promise = factory.createNew(factory.createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - return createCall(createPropertyAccess(promise, createIdentifier("then")), /*typeArguments*/ undefined, [getUnscopedHelperName("__importStar")]); + return factory.createCall(factory.createPropertyAccess(promise, factory.createIdentifier("then")), /*typeArguments*/ undefined, [emitHelpers().createImportStarCallbackHelper()]); } return promise; } @@ -709,16 +716,16 @@ namespace ts { // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ // We have to wrap require in then callback so that require is done in asynchronously // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately - const promiseResolveCall = createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); - let requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []); + const promiseResolveCall = factory.createCall(factory.createPropertyAccess(factory.createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); + let requireCall: Expression = factory.createCall(factory.createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - requireCall = createCall(getUnscopedHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]); + requireCall = emitHelpers().createImportStarHelper(requireCall); } let func: FunctionExpression | ArrowFunction; if (languageVersion >= ScriptTarget.ES2015) { - func = createArrowFunction( + func = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, /*parameters*/ [], @@ -727,14 +734,14 @@ namespace ts { requireCall); } else { - func = createFunctionExpression( + func = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ [], /*type*/ undefined, - createBlock([createReturn(requireCall)])); + factory.createBlock([factory.createReturn(requireCall)])); // if there is a lexical 'this' in the import call arguments, ensure we indicate // that this new function expression indicates it captures 'this' so that the @@ -744,7 +751,7 @@ namespace ts { } } - return createCall(createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); + return factory.createCall(factory.createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); } function getHelperExpressionForImport(node: ImportDeclaration, innerExpr: Expression) { @@ -753,11 +760,11 @@ namespace ts { } if (getImportNeedsImportStarHelper(node)) { context.requestEmitHelper(importStarHelper); - return createCall(getUnscopedHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]); + return emitHelpers().createImportStarHelper(innerExpr); } if (getImportNeedsImportDefaultHelper(node)) { context.requestEmitHelper(importDefaultHelper); - return createCall(getUnscopedHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]); + return emitHelpers().createImportDefaultHelper(innerExpr); } return innerExpr; } @@ -773,15 +780,16 @@ namespace ts { if (moduleKind !== ModuleKind.AMD) { if (!node.importClause) { // import "mod"; - return setOriginalNode(setTextRange(createExpressionStatement(createRequireCall(node)), node), node); + return setOriginalNode(setTextRange(factory.createExpressionStatement(createRequireCall(node)), node), node); } else { const variables: VariableDeclaration[] = []; if (namespaceDeclaration && !isDefaultImport(node)) { // import * as n from "mod"; variables.push( - createVariableDeclaration( + factory.createVariableDeclaration( getSynthesizedClone(namespaceDeclaration.name), + /*exclamationToken*/ undefined, /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)) ) @@ -793,8 +801,9 @@ namespace ts { // import d, { x, y } from "mod"; // import d, * as n from "mod"; variables.push( - createVariableDeclaration( - getGeneratedNameForNode(node), + factory.createVariableDeclaration( + factory.getGeneratedNameForNode(node), + /*exclamationToken*/ undefined, /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)) ) @@ -802,10 +811,11 @@ namespace ts { if (namespaceDeclaration && isDefaultImport(node)) { variables.push( - createVariableDeclaration( + factory.createVariableDeclaration( getSynthesizedClone(namespaceDeclaration.name), + /*exclamationToken*/ undefined, /*type*/ undefined, - getGeneratedNameForNode(node) + factory.getGeneratedNameForNode(node) ) ); } @@ -814,9 +824,9 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( variables, languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None ) @@ -830,16 +840,17 @@ namespace ts { else if (namespaceDeclaration && isDefaultImport(node)) { // import d, * as n from "mod"; statements = append(statements, - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( [ setOriginalNode( setTextRange( - createVariableDeclaration( + factory.createVariableDeclaration( getSynthesizedClone(namespaceDeclaration.name), + /*exclamationToken*/ undefined, /*type*/ undefined, - getGeneratedNameForNode(node) + factory.getGeneratedNameForNode(node) ), /*location*/ node), /*original*/ node @@ -869,13 +880,13 @@ namespace ts { * @param importNode The declararation to import. */ function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { - const moduleName = getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + const moduleName = getExternalModuleNameLiteral(factory, importNode, currentSourceFile, host, resolver, compilerOptions); const args: Expression[] = []; if (moduleName) { args.push(moduleName); } - return createCall(createIdentifier("require"), /*typeArguments*/ undefined, args); + return factory.createCall(factory.createIdentifier("require"), /*typeArguments*/ undefined, args); } /** @@ -892,7 +903,7 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createExpressionStatement( + factory.createExpressionStatement( createExportExpression( node.name, createRequireCall(node) @@ -907,12 +918,13 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( + factory.createVariableDeclarationList( [ - createVariableDeclaration( + factory.createVariableDeclaration( getSynthesizedClone(node.name), + /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(node) ) @@ -931,8 +943,8 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createExpressionStatement( - createExportExpression(getExportName(node), getLocalName(node)) + factory.createExpressionStatement( + createExportExpression(factory.getExportName(node), factory.getLocalName(node)) ), node), node @@ -965,7 +977,7 @@ namespace ts { return undefined; } - const generatedName = getGeneratedNameForNode(node); + const generatedName = factory.getGeneratedNameForNode(node); if (node.exportClause) { const statements: Statement[] = []; @@ -974,11 +986,12 @@ namespace ts { statements.push( setOriginalNode( setTextRange( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( generatedName, + /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(node) ) @@ -990,15 +1003,15 @@ namespace ts { ); } for (const specifier of node.exportClause.elements) { - const exportedValue = createPropertyAccess( + const exportedValue = factory.createPropertyAccess( generatedName, specifier.propertyName || specifier.name ); statements.push( setOriginalNode( setTextRange( - createExpressionStatement( - createExportExpression(getExportName(specifier), exportedValue) + factory.createExpressionStatement( + createExportExpression(factory.getExportName(specifier), exportedValue) ), specifier), specifier @@ -1012,7 +1025,7 @@ namespace ts { // export * from "mod"; return setOriginalNode( setTextRange( - createExpressionStatement( + factory.createExpressionStatement( createExportStarHelper(context, moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName) ), node), @@ -1036,10 +1049,10 @@ namespace ts { if (original && hasAssociatedEndOfDeclarationMarker(original)) { // Defer exports until we encounter an EndOfDeclarationMarker node const id = getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], createIdentifier("default"), visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); + deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } else { - statements = appendExportStatement(statements, createIdentifier("default"), visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); + statements = appendExportStatement(statements, factory.createIdentifier("default"), visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } return singleOrMany(statements); @@ -1056,11 +1069,11 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createFunctionDeclaration( + factory.createFunctionDeclaration( /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), node.asteriskToken, - getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + factory.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, visitNodes(node.parameters, moduleExpressionElementVisitor), /*type*/ undefined, @@ -1099,10 +1112,10 @@ namespace ts { statements = append(statements, setOriginalNode( setTextRange( - createClassDeclaration( + factory.createClassDeclaration( /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), - getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + factory.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, visitNodes(node.heritageClauses, moduleExpressionElementVisitor), visitNodes(node.members, moduleExpressionElementVisitor) @@ -1158,11 +1171,11 @@ namespace ts { } if (variables) { - statements = append(statements, updateVariableStatement(node, modifiers, updateVariableDeclarationList(node.declarationList, variables))); + statements = append(statements, factory.updateVariableStatement(node, modifiers, factory.updateVariableDeclarationList(node.declarationList, variables))); } if (expressions) { - statements = append(statements, setOriginalNode(setTextRange(createExpressionStatement(inlineExpressions(expressions)), node), node)); + statements = append(statements, setOriginalNode(setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node), node)); } } else { @@ -1185,7 +1198,7 @@ namespace ts { const exportedNames = getExports(name); if (exportedNames) { // For each additional export of the declaration, apply an export assignment. - let expression: Expression = isExportName(name) ? value : createAssignment(name, value); + let expression: Expression = isExportName(name) ? value : factory.createAssignment(name, value); for (const exportName of exportedNames) { // Mark the node to prevent triggering substitution. setEmitFlags(expression, EmitFlags.NoSubstitution); @@ -1194,7 +1207,7 @@ namespace ts { return expression; } - return createAssignment(name, value); + return factory.createAssignment(name, value); } /** @@ -1214,10 +1227,10 @@ namespace ts { ); } else { - return createAssignment( + return factory.createAssignment( setTextRange( - createPropertyAccess( - createIdentifier("exports"), + factory.createPropertyAccess( + factory.createIdentifier("exports"), node.name ), /*location*/ node.name @@ -1401,8 +1414,8 @@ namespace ts { } if (hasModifier(decl, ModifierFlags.Export)) { - const exportName = hasModifier(decl, ModifierFlags.Default) ? createIdentifier("default") : getDeclarationName(decl); - statements = appendExportStatement(statements, exportName, getLocalName(decl), /*location*/ decl); + const exportName = hasModifier(decl, ModifierFlags.Default) ? factory.createIdentifier("default") : factory.getDeclarationName(decl); + statements = appendExportStatement(statements, exportName, factory.getLocalName(decl), /*location*/ decl); } if (decl.name) { @@ -1421,7 +1434,7 @@ namespace ts { * @param decl The declaration to export. */ function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration): Statement[] | undefined { - const name = getDeclarationName(decl); + const name = factory.getDeclarationName(decl); const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(idText(name)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { @@ -1451,23 +1464,23 @@ namespace ts { function createUnderscoreUnderscoreESModule() { let statement: Statement; if (languageVersion === ScriptTarget.ES3) { - statement = createExpressionStatement( + statement = factory.createExpressionStatement( createExportExpression( - createIdentifier("__esModule"), - createLiteral(/*value*/ true) + factory.createIdentifier("__esModule"), + factory.createTrue() ) ); } else { - statement = createExpressionStatement( - createCall( - createPropertyAccess(createIdentifier("Object"), "defineProperty"), + statement = factory.createExpressionStatement( + factory.createCall( + factory.createPropertyAccess(factory.createIdentifier("Object"), "defineProperty"), /*typeArguments*/ undefined, [ - createIdentifier("exports"), - createLiteral("__esModule"), - createObjectLiteral([ - createPropertyAssignment("value", createLiteral(/*value*/ true)) + factory.createIdentifier("exports"), + factory.createStringLiteral("__esModule"), + factory.createObjectLiteral([ + factory.createPropertyAssignment("value", factory.createTrue()) ]) ] ) @@ -1486,7 +1499,7 @@ namespace ts { * @param allowComments An optional value indicating whether to emit comments for the statement. */ function createExportStatement(name: Identifier, value: Expression, location?: TextRange, allowComments?: boolean) { - const statement = setTextRange(createExpressionStatement(createExportExpression(name, value)), location); + const statement = setTextRange(factory.createExpressionStatement(createExportExpression(name, value)), location); startOnNewLine(statement); if (!allowComments) { setEmitFlags(statement, EmitFlags.NoComments); @@ -1504,9 +1517,9 @@ namespace ts { */ function createExportExpression(name: Identifier, value: Expression, location?: TextRange) { return setTextRange( - createAssignment( - createPropertyAccess( - createIdentifier("exports"), + factory.createAssignment( + factory.createPropertyAccess( + factory.createIdentifier("exports"), getSynthesizedClone(name) ), value @@ -1602,10 +1615,10 @@ namespace ts { // A shorthand property with an assignment initializer is probably part of a // destructuring assignment if (node.objectAssignmentInitializer) { - const initializer = createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); - return setTextRange(createPropertyAssignment(name, initializer), node); + const initializer = factory.createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); + return setTextRange(factory.createPropertyAssignment(name, initializer), node); } - return setTextRange(createPropertyAssignment(name, exportedOrImportedName), node); + return setTextRange(factory.createPropertyAssignment(name, exportedOrImportedName), node); } return node; } @@ -1639,7 +1652,7 @@ namespace ts { if (getEmitFlags(node) & EmitFlags.HelperName) { const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { - return createPropertyAccess(externalHelpersModuleName, node); + return factory.createPropertyAccess(externalHelpersModuleName, node); } return node; @@ -1649,8 +1662,8 @@ namespace ts { const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node)); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { return setTextRange( - createPropertyAccess( - createIdentifier("exports"), + factory.createPropertyAccess( + factory.createIdentifier("exports"), getSynthesizedClone(node) ), /*location*/ node @@ -1661,9 +1674,9 @@ namespace ts { if (importDeclaration) { if (isImportClause(importDeclaration)) { return setTextRange( - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent), - createIdentifier("default") + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent), + factory.createIdentifier("default") ), /*location*/ node ); @@ -1671,8 +1684,8 @@ namespace ts { else if (isImportSpecifier(importDeclaration)) { const name = importDeclaration.propertyName || importDeclaration.name; return setTextRange( - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent.parent.parent), + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent), getSynthesizedClone(name) ), /*location*/ node @@ -1743,10 +1756,10 @@ namespace ts { if (exportedNames) { let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression ? setTextRange( - createBinary( + factory.createBinary( node.operand, - createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken), - createLiteral(1) + factory.createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken), + factory.createNumericLiteral(1) ), /*location*/ node) : node; @@ -1793,8 +1806,8 @@ namespace ts { function createExportStarHelper(context: TransformationContext, module: Expression) { const compilerOptions = context.getCompilerOptions(); return compilerOptions.importHelpers - ? createCall(getUnscopedHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")]) - : createCall(createIdentifier("__export"), /*typeArguments*/ undefined, [module]); + ? context.factory.createCall(context.getEmitHelperFactory().getUnscopedHelperName("__exportStar"), /*typeArguments*/ undefined, [module, context.factory.createIdentifier("exports")]) + : context.factory.createCall(context.factory.createIdentifier("__export"), /*typeArguments*/ undefined, [module]); } // emit helper for dynamic import @@ -1804,30 +1817,4 @@ namespace ts { text: ` var __syncRequire = typeof module === "object" && typeof module.exports === "object";` }; - - // emit helper for `import * as Name from "foo"` - export const importStarHelper: UnscopedEmitHelper = { - name: "typescript:commonjsimportstar", - importName: "__importStar", - scoped: false, - text: ` -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -};` - }; - - // emit helper for `import Name from "foo"` - export const importDefaultHelper: UnscopedEmitHelper = { - name: "typescript:commonjsimportdefault", - importName: "__importDefault", - scoped: false, - text: ` -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -};` - }; } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 731ed6ef4fefe..f2518dbfab152 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -7,6 +7,7 @@ namespace ts { } const { + factory, startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration @@ -41,7 +42,7 @@ namespace ts { let enclosingBlockScopedContainer: Node; let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored. - return chainBundle(transformSourceFile); + return chainBundle(context, transformSourceFile); /** * Transforms the module aspects of a SourceFile. @@ -71,25 +72,25 @@ namespace ts { // see comment to 'substitutePostfixUnaryExpression' for more details // Collect information about the external module and dependency groups. - moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(node, resolver, compilerOptions); + moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(context, node, resolver, compilerOptions); // Make sure that the name of the 'exports' function does not conflict with // existing identifiers. - exportFunction = createUniqueName("exports"); + exportFunction = factory.createUniqueName("exports"); exportFunctionsMap[id] = exportFunction; - contextObject = contextObjectMap[id] = createUniqueName("context"); + contextObject = contextObjectMap[id] = factory.createUniqueName("context"); // Add the body of the module. const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports); const moduleBodyBlock = createSystemModuleBody(node, dependencyGroups); - const moduleBodyFunction = createFunctionExpression( + const moduleBodyFunction = factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, [ - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction), - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject) + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction), + factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject) ], /*type*/ undefined, moduleBodyBlock @@ -98,16 +99,16 @@ namespace ts { // Write the call to `System.register` // Clear the emit-helpers flag for later passes since we'll have already used it in the module body // So the helper will be emit at the correct position instead of at the top of the source-file - const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions); - const dependencies = createArrayLiteral(map(dependencyGroups, dependencyGroup => dependencyGroup.name)); + const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions); + const dependencies = factory.createArrayLiteral(map(dependencyGroups, dependencyGroup => dependencyGroup.name)); const updated = setEmitFlags( - updateSourceFileNode( + factory.updateSourceFile( node, setTextRange( - createNodeArray([ - createExpressionStatement( - createCall( - createPropertyAccess(createIdentifier("System"), "register"), + factory.createNodeArray([ + factory.createExpressionStatement( + factory.createCall( + factory.createPropertyAccess(factory.createIdentifier("System"), "register"), /*typeArguments*/ undefined, moduleName ? [moduleName, dependencies, moduleBodyFunction] @@ -134,7 +135,7 @@ namespace ts { contextObject = undefined!; hoistedStatements = undefined!; enclosingBlockScopedContainer = undefined!; - return aggregateTransformFlags(updated); + return updated; } /** @@ -146,7 +147,7 @@ namespace ts { const groupIndices = createMap(); const dependencyGroups: DependencyGroup[] = []; for (const externalImport of externalImports) { - const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral(factory, externalImport, currentSourceFile, host, resolver, compilerOptions); if (externalModuleName) { const text = externalModuleName.text; const groupIndex = groupIndices.get(text); @@ -224,19 +225,20 @@ namespace ts { // Add any prologue directives. const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); - const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); + const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict, sourceElementVisitor); // var __moduleName = context_1 && context_1.id; statements.push( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( "__moduleName", + /*exclamationToken*/ undefined, /*type*/ undefined, - createLogicalAnd( + factory.createLogicalAnd( contextObject, - createPropertyAccess(contextObject, "id") + factory.createPropertyAccess(contextObject, "id") ) ) ]) @@ -262,26 +264,25 @@ namespace ts { insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217 - const moduleObject = createObjectLiteral([ - createPropertyAssignment("setters", + const moduleObject = factory.createObjectLiteral([ + factory.createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups) ), - createPropertyAssignment("execute", - createFunctionExpression( + factory.createPropertyAssignment("execute", + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ [], /*type*/ undefined, - createBlock(executeStatements, /*multiLine*/ true) + factory.createBlock(executeStatements, /*multiLine*/ true) ) ) - ]); + ], /*multiLine*/ true); - moduleObject.multiLine = true; - statements.push(createReturn(moduleObject)); - return createBlock(statements, /*multiLine*/ true); + statements.push(factory.createReturn(moduleObject)); + return factory.createBlock(statements, /*multiLine*/ true); } /** @@ -328,9 +329,9 @@ namespace ts { // write name of exported declaration, i.e 'export var x...' exportedNames.push( - createPropertyAssignment( - createLiteral(exportedLocalName), - createTrue() + factory.createPropertyAssignment( + factory.createStringLiteralFromNode(exportedLocalName), + factory.createTrue() ) ); } @@ -349,23 +350,24 @@ namespace ts { for (const element of externalImport.exportClause.elements) { // write name of indirectly exported entry, i.e. 'export {x} from ...' exportedNames.push( - createPropertyAssignment( - createLiteral(idText(element.name || element.propertyName)), - createTrue() + factory.createPropertyAssignment( + factory.createStringLiteral(idText(element.name || element.propertyName)), + factory.createTrue() ) ); } } - const exportedNamesStorageRef = createUniqueName("exportedNames"); + const exportedNamesStorageRef = factory.createUniqueName("exportedNames"); statements.push( - createVariableStatement( + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( exportedNamesStorageRef, + /*exclamationToken*/ undefined, /*type*/ undefined, - createObjectLiteral(exportedNames, /*multiline*/ true) + factory.createObjectLiteral(exportedNames, /*multiline*/ true) ) ]) ) @@ -384,17 +386,17 @@ namespace ts { * names. */ function createExportStarFunction(localNames: Identifier | undefined) { - const exportStarFunction = createUniqueName("exportStar"); - const m = createIdentifier("m"); - const n = createIdentifier("n"); - const exports = createIdentifier("exports"); - let condition: Expression = createStrictInequality(n, createLiteral("default")); + const exportStarFunction = factory.createUniqueName("exportStar"); + const m = factory.createIdentifier("m"); + const n = factory.createIdentifier("n"); + const exports = factory.createIdentifier("exports"); + let condition: Expression = factory.createStrictInequality(n, factory.createStringLiteral("default")); if (localNames) { - condition = createLogicalAnd( + condition = factory.createLogicalAnd( condition, - createLogicalNot( - createCall( - createPropertyAccess(localNames, "hasOwnProperty"), + factory.createLogicalNot( + factory.createCall( + factory.createPropertyAccess(localNames, "hasOwnProperty"), /*typeArguments*/ undefined, [n] ) @@ -402,38 +404,39 @@ namespace ts { ); } - return createFunctionDeclaration( + return factory.createFunctionDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, exportStarFunction, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)], /*type*/ undefined, - createBlock([ - createVariableStatement( + factory.createBlock([ + factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( exports, + /*exclamationToken*/ undefined, /*type*/ undefined, - createObjectLiteral([]) + factory.createObjectLiteral([]) ) ]) ), - createForIn( - createVariableDeclarationList([ - createVariableDeclaration(n, /*type*/ undefined) + factory.createForIn( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration(n) ]), m, - createBlock([ + factory.createBlock([ setEmitFlags( - createIf( + factory.createIf( condition, - createExpressionStatement( - createAssignment( - createElementAccess(exports, n), - createElementAccess(m, n) + factory.createExpressionStatement( + factory.createAssignment( + factory.createElementAccess(exports, n), + factory.createElementAccess(m, n) ) ) ), @@ -441,8 +444,8 @@ namespace ts { ) ]) ), - createExpressionStatement( - createCall( + factory.createExpressionStatement( + factory.createCall( exportFunction, /*typeArguments*/ undefined, [exports] @@ -462,11 +465,11 @@ namespace ts { const setters: Expression[] = []; for (const group of dependencyGroups) { // derive a unique name for parameter from the first named entry in the group - const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(i, currentSourceFile)); - const parameterName = localName ? getGeneratedNameForNode(localName) : createUniqueName(""); + const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(factory, i, currentSourceFile)); + const parameterName = localName ? factory.getGeneratedNameForNode(localName) : factory.createUniqueName(""); const statements: Statement[] = []; for (const entry of group.externalImports) { - const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile)!; // TODO: GH#18217 + const importVariableName = getLocalNameForExternalImport(factory, entry, currentSourceFile)!; // TODO: GH#18217 switch (entry.kind) { case SyntaxKind.ImportDeclaration: if (!entry.importClause) { @@ -480,8 +483,8 @@ namespace ts { Debug.assert(importVariableName !== undefined); // save import into the local statements.push( - createExpressionStatement( - createAssignment(importVariableName, parameterName) + factory.createExpressionStatement( + factory.createAssignment(importVariableName, parameterName) ) ); break; @@ -500,22 +503,22 @@ namespace ts { const properties: PropertyAssignment[] = []; for (const e of entry.exportClause.elements) { properties.push( - createPropertyAssignment( - createLiteral(idText(e.name)), - createElementAccess( + factory.createPropertyAssignment( + factory.createStringLiteral(idText(e.name)), + factory.createElementAccess( parameterName, - createLiteral(idText(e.propertyName || e.name)) + factory.createStringLiteral(idText(e.propertyName || e.name)) ) ) ); } statements.push( - createExpressionStatement( - createCall( + factory.createExpressionStatement( + factory.createCall( exportFunction, /*typeArguments*/ undefined, - [createObjectLiteral(properties, /*multiline*/ true)] + [factory.createObjectLiteral(properties, /*multiline*/ true)] ) ) ); @@ -527,8 +530,8 @@ namespace ts { // // exportStar(foo_1_1); statements.push( - createExpressionStatement( - createCall( + factory.createExpressionStatement( + factory.createCall( exportStarFunction, /*typeArguments*/ undefined, [parameterName] @@ -541,19 +544,19 @@ namespace ts { } setters.push( - createFunctionExpression( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], /*type*/ undefined, - createBlock(statements, /*multiLine*/ true) + factory.createBlock(statements, /*multiLine*/ true) ) ); } - return createArrayLiteral(setters, /*multiLine*/ true); + return factory.createArrayLiteral(setters, /*multiLine*/ true); } // @@ -594,7 +597,7 @@ namespace ts { function visitImportDeclaration(node: ImportDeclaration): VisitResult { let statements: Statement[] | undefined; if (node.importClause) { - hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217 + hoistVariableDeclaration(getLocalNameForExternalImport(factory, node, currentSourceFile)!); // TODO: GH#18217 } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -618,7 +621,7 @@ namespace ts { Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); let statements: Statement[] | undefined; - hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217 + hoistVariableDeclaration(getLocalNameForExternalImport(factory, node, currentSourceFile)!); // TODO: GH#18217 if (hasAssociatedEndOfDeclarationMarker(node)) { // Defer exports until we encounter an EndOfDeclarationMarker node @@ -648,10 +651,10 @@ namespace ts { if (original && hasAssociatedEndOfDeclarationMarker(original)) { // Defer exports until we encounter an EndOfDeclarationMarker node const id = getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], createIdentifier("default"), expression, /*allowComments*/ true); + deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), expression, /*allowComments*/ true); } else { - return createExportStatement(createIdentifier("default"), expression, /*allowComments*/ true); + return createExportStatement(factory.createIdentifier("default"), expression, /*allowComments*/ true); } } @@ -663,12 +666,12 @@ namespace ts { function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult { if (hasModifier(node, ModifierFlags.Export)) { hoistedStatements = append(hoistedStatements, - updateFunctionDeclaration( + factory.updateFunctionDeclaration( node, node.decorators, visitNodes(node.modifiers, modifierVisitor, isModifier), node.asteriskToken, - getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + factory.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), /*typeParameters*/ undefined, visitNodes(node.parameters, destructuringAndImportCallVisitor, isParameterDeclaration), /*type*/ undefined, @@ -699,17 +702,18 @@ namespace ts { let statements: Statement[] | undefined; // Hoist the name of the class declaration to the outer module body function. - const name = getLocalName(node); + const name = factory.getLocalName(node); hoistVariableDeclaration(name); // Rewrite the class declaration into an assignment of a class expression. statements = append(statements, setTextRange( - createExpressionStatement( - createAssignment( + factory.createExpressionStatement( + factory.createAssignment( name, setTextRange( - createClassExpression( + factory.createClassExpression( + visitNodes(node.decorators, destructuringAndImportCallVisitor, isDecorator), /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, @@ -761,7 +765,7 @@ namespace ts { let statements: Statement[] | undefined; if (expressions) { - statements = append(statements, setTextRange(createExpressionStatement(inlineExpressions(expressions)), node)); + statements = append(statements, setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node)); } if (isMarkedDeclaration) { @@ -859,8 +863,8 @@ namespace ts { function createVariableAssignment(name: Identifier, value: Expression, location: TextRange | undefined, isExportedDeclaration: boolean) { hoistVariableDeclaration(getSynthesizedClone(name)); return isExportedDeclaration - ? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location))) - : preventSubstitution(setTextRange(createAssignment(name, value), location)); + ? createExportExpression(name, preventSubstitution(setTextRange(factory.createAssignment(name, value), location))) + : preventSubstitution(setTextRange(factory.createAssignment(name, value), location)); } /** @@ -1030,7 +1034,7 @@ namespace ts { else if (!isGeneratedIdentifier(decl.name)) { let excludeName: string | undefined; if (exportSelf) { - statements = appendExportStatement(statements, decl.name, getLocalName(decl)); + statements = appendExportStatement(statements, decl.name, factory.getLocalName(decl)); excludeName = idText(decl.name); } @@ -1056,8 +1060,8 @@ namespace ts { let excludeName: string | undefined; if (hasModifier(decl, ModifierFlags.Export)) { - const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name!; - statements = appendExportStatement(statements, exportName, getLocalName(decl)); + const exportName = hasModifier(decl, ModifierFlags.Default) ? factory.createStringLiteral("default") : decl.name!; + statements = appendExportStatement(statements, exportName, factory.getLocalName(decl)); excludeName = getTextOfIdentifierOrLiteral(exportName); } @@ -1082,7 +1086,7 @@ namespace ts { return statements; } - const name = getDeclarationName(decl); + const name = factory.getDeclarationName(decl); const exportSpecifiers = moduleInfo.exportSpecifiers.get(idText(name)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { @@ -1118,7 +1122,7 @@ namespace ts { * @param allowComments An optional value indicating whether to emit comments for the statement. */ function createExportStatement(name: Identifier | StringLiteral, value: Expression, allowComments?: boolean) { - const statement = createExpressionStatement(createExportExpression(name, value)); + const statement = factory.createExpressionStatement(createExportExpression(name, value)); startOnNewLine(statement); if (!allowComments) { setEmitFlags(statement, EmitFlags.NoComments); @@ -1134,9 +1138,9 @@ namespace ts { * @param value The exported value. */ function createExportExpression(name: Identifier | StringLiteral, value: Expression) { - const exportName = isIdentifier(name) ? createLiteral(name) : name; + const exportName = isIdentifier(name) ? factory.createStringLiteralFromNode(name) : name; setEmitFlags(value, getEmitFlags(value) | EmitFlags.NoComments); - return setCommentRange(createCall(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value); + return setCommentRange(factory.createCall(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value); } // @@ -1221,7 +1225,7 @@ namespace ts { const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; - node = updateFor( + node = factory.updateFor( node, node.initializer && visitForInitializer(node.initializer), visitNode(node.condition, destructuringAndImportCallVisitor, isExpression), @@ -1242,11 +1246,11 @@ namespace ts { const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; - node = updateForIn( + node = factory.updateForIn( node, visitForInitializer(node.initializer), visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock) ); enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; @@ -1262,12 +1266,12 @@ namespace ts { const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; - node = updateForOf( + node = factory.updateForOf( node, node.awaitModifier, visitForInitializer(node.initializer), visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock) ); enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; @@ -1300,7 +1304,7 @@ namespace ts { } } - return expressions ? inlineExpressions(expressions) : createOmittedExpression(); + return expressions ? factory.inlineExpressions(expressions) : factory.createOmittedExpression(); } else { return visitEachChild(node, nestedElementVisitor, context); @@ -1313,9 +1317,9 @@ namespace ts { * @param node The node to visit. */ function visitDoStatement(node: DoStatement): VisitResult { - return updateDo( + return factory.updateDo( node, - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock), + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock), visitNode(node.expression, destructuringAndImportCallVisitor, isExpression) ); } @@ -1326,10 +1330,10 @@ namespace ts { * @param node The node to visit. */ function visitWhileStatement(node: WhileStatement): VisitResult { - return updateWhile( + return factory.updateWhile( node, visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock) ); } @@ -1339,10 +1343,10 @@ namespace ts { * @param node The node to visit. */ function visitLabeledStatement(node: LabeledStatement): VisitResult { - return updateLabel( + return factory.updateLabel( node, node.label, - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock) ); } @@ -1352,10 +1356,10 @@ namespace ts { * @param node The node to visit. */ function visitWithStatement(node: WithStatement): VisitResult { - return updateWith( + return factory.updateWith( node, visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), - visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock) + visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock) ); } @@ -1365,7 +1369,7 @@ namespace ts { * @param node The node to visit. */ function visitSwitchStatement(node: SwitchStatement): VisitResult { - return updateSwitch( + return factory.updateSwitch( node, visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNode(node.caseBlock, nestedElementVisitor, isCaseBlock) @@ -1381,7 +1385,7 @@ namespace ts { const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; - node = updateCaseBlock( + node = factory.updateCaseBlock( node, visitNodes(node.clauses, nestedElementVisitor, isCaseOrDefaultClause) ); @@ -1396,7 +1400,7 @@ namespace ts { * @param node The node to visit. */ function visitCaseClause(node: CaseClause): VisitResult { - return updateCaseClause( + return factory.updateCaseClause( node, visitNode(node.expression, destructuringAndImportCallVisitor, isExpression), visitNodes(node.statements, nestedElementVisitor, isStatement) @@ -1430,7 +1434,7 @@ namespace ts { const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; - node = updateCatchClause( + node = factory.updateCatchClause( node, node.variableDeclaration, visitNode(node.block, nestedElementVisitor, isBlock) @@ -1490,10 +1494,10 @@ namespace ts { // } // }; // }); - return createCall( - createPropertyAccess( + return factory.createCall( + factory.createPropertyAccess( contextObject, - createIdentifier("import") + factory.createIdentifier("import") ), /*typeArguments*/ undefined, some(node.arguments) ? [visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : [] @@ -1658,11 +1662,11 @@ namespace ts { if (importDeclaration) { if (isImportClause(importDeclaration)) { return setTextRange( - createPropertyAssignment( + factory.createPropertyAssignment( getSynthesizedClone(name), - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent), - createIdentifier("default") + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent), + factory.createIdentifier("default") ) ), /*location*/ node @@ -1670,10 +1674,10 @@ namespace ts { } else if (isImportSpecifier(importDeclaration)) { return setTextRange( - createPropertyAssignment( + factory.createPropertyAssignment( getSynthesizedClone(name), - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent.parent.parent), + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent), getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name) ), ), @@ -1715,7 +1719,7 @@ namespace ts { if (getEmitFlags(node) & EmitFlags.HelperName) { const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { - return createPropertyAccess(externalHelpersModuleName, node); + return factory.createPropertyAccess(externalHelpersModuleName, node); } return node; @@ -1732,17 +1736,17 @@ namespace ts { if (importDeclaration) { if (isImportClause(importDeclaration)) { return setTextRange( - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent), - createIdentifier("default") + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent), + factory.createIdentifier("default") ), /*location*/ node ); } else if (isImportSpecifier(importDeclaration)) { return setTextRange( - createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent.parent.parent), + factory.createPropertyAccess( + factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent), getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name) ), /*location*/ node @@ -1812,7 +1816,7 @@ namespace ts { if (exportedNames) { let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression ? setTextRange( - createPrefix( + factory.createPrefix( node.operator, node.operand ), @@ -1826,8 +1830,8 @@ namespace ts { if (node.kind === SyntaxKind.PostfixUnaryExpression) { expression = node.operator === SyntaxKind.PlusPlusToken - ? createSubtract(preventSubstitution(expression), createLiteral(1)) - : createAdd(preventSubstitution(expression), createLiteral(1)); + ? factory.createSubtract(preventSubstitution(expression), factory.createNumericLiteral(1)) + : factory.createAdd(preventSubstitution(expression), factory.createNumericLiteral(1)); } return expression; @@ -1839,7 +1843,7 @@ namespace ts { function substituteMetaProperty(node: MetaProperty) { if (isImportMeta(node)) { - return createPropertyAccess(contextObject, createIdentifier("meta")); + return factory.createPropertyAccess(contextObject, factory.createIdentifier("meta")); } return node; } @@ -1858,7 +1862,7 @@ namespace ts { if (valueDeclaration) { const exportContainer = resolver.getReferencedExportContainer(name, /*prefixLocals*/ false); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { - exportedNames = append(exportedNames, getDeclarationName(valueDeclaration)); + exportedNames = append(exportedNames, factory.getDeclarationName(valueDeclaration)); } exportedNames = addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings[getOriginalNodeId(valueDeclaration)]); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index d413a835d0d86..f81f27a233934 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -33,6 +33,8 @@ namespace ts { export function transformTypeScript(context: TransformationContext) { const { + factory, + getEmitHelperFactory: emitHelpers, startLexicalEnvironment, resumeLexicalEnvironment, endLexicalEnvironment, @@ -94,7 +96,7 @@ namespace ts { } function transformBundle(node: Bundle) { - return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => { + return factory.createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => { if (prepend.kind === SyntaxKind.InputFiles) { return createUnparsedSourceFile(prepend, "js"); } @@ -231,13 +233,13 @@ namespace ts { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ExportAssignment: case SyntaxKind.ExportDeclaration: - return visitEllidableStatement(node); + return visitElidableStatement(node); default: return visitorWorker(node); } } - function visitEllidableStatement(node: ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration): VisitResult { + function visitElidableStatement(node: ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration): VisitResult { const parsed = getParseTreeNode(node); if (parsed !== node) { // If the node has been transformed by a `before` transformer, perform no ellision on it @@ -353,7 +355,7 @@ namespace ts { if (isStatement(node) && hasModifier(node, ModifierFlags.Ambient)) { // TypeScript ambient declarations are elided, but some comments may be preserved. // See the implementation of `getLeadingComments` in comments.ts for more details. - return createNotEmittedStatement(node); + return factory.createNotEmittedStatement(node); } switch (node.kind) { @@ -428,7 +430,7 @@ namespace ts { case SyntaxKind.InterfaceDeclaration: // TypeScript interfaces are elided, but some comments may be preserved. // See the implementation of `getLeadingComments` in comments.ts for more details. - return createNotEmittedStatement(node); + return factory.createNotEmittedStatement(node); case SyntaxKind.ClassDeclaration: // This may be a class declaration with TypeScript syntax extensions. @@ -552,7 +554,7 @@ namespace ts { !(isExternalModule(node) && moduleKind >= ModuleKind.ES2015) && !isJsonSourceFile(node); - return updateSourceFileNode( + return factory.updateSourceFile( node, visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict)); } @@ -617,7 +619,7 @@ namespace ts { context.startLexicalEnvironment(); } - const name = node.name || (facts & ClassFacts.NeedsName ? getGeneratedNameForNode(node) : undefined); + const name = node.name || (facts & ClassFacts.NeedsName ? factory.getGeneratedNameForNode(node) : undefined); const classStatement = facts & ClassFacts.HasConstructorDecorators ? createClassDeclarationHeadWithDecorators(node, name) : createClassDeclarationHeadWithoutDecorators(node, name, facts); @@ -643,29 +645,30 @@ namespace ts { // }(); // const closingBraceLocation = createTokenRange(skipTrivia(currentSourceFile.text, node.members.end), SyntaxKind.CloseBraceToken); - const localName = getInternalName(node); + const localName = factory.getInternalName(node); // The following partially-emitted expression exists purely to align our sourcemap // emit with the original emitter. - const outer = createPartiallyEmittedExpression(localName); + const outer = factory.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; setEmitFlags(outer, EmitFlags.NoComments); - const statement = createReturn(outer); + const statement = factory.createReturn(outer); statement.pos = closingBraceLocation.pos; setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps); statements.push(statement); insertStatementsAfterStandardPrologue(statements, context.endLexicalEnvironment()); - const iife = createImmediatelyInvokedArrowFunction(statements); + const iife = factory.createImmediatelyInvokedArrowFunction(statements); setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper); - const varStatement = createVariableStatement( + const varStatement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( - getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false), + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false), + /*exclamationToken*/ undefined, /*type*/ undefined, iife ) @@ -687,16 +690,16 @@ namespace ts { } else if (facts & ClassFacts.UseImmediatelyInvokedFunctionExpression || facts & ClassFacts.HasConstructorDecorators) { if (facts & ClassFacts.IsDefaultExternalExport) { - statements.push(createExportDefault(getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); + statements.push(factory.createExportDefault(factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } else if (facts & ClassFacts.IsNamedExternalExport) { - statements.push(createExternalModuleExport(getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); + statements.push(factory.createExternalModuleExport(factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } } if (statements.length > 1) { // Add a DeclarationMarker as a marker for the end of the declaration - statements.push(createEndOfDeclarationMarker(node)); + statements.push(factory.createEndOfDeclarationMarker(node)); setEmitFlags(classStatement, getEmitFlags(classStatement) | EmitFlags.HasEndOfDeclarationMarker); } @@ -720,7 +723,7 @@ namespace ts { ? visitNodes(node.modifiers, modifierVisitor, isModifier) : undefined; - const classDeclaration = createClassDeclaration( + const classDeclaration = factory.createClassDeclaration( /*decorators*/ undefined, modifiers, name, @@ -736,7 +739,6 @@ namespace ts { emitFlags |= EmitFlags.NoTrailingSourceMap; } - aggregateTransformFlags(classDeclaration); setTextRange(classDeclaration, node); setOriginalNode(classDeclaration, node); setEmitFlags(classDeclaration, emitFlags); @@ -836,27 +838,27 @@ namespace ts { const location = moveRangePastDecorators(node); const classAlias = getClassAliasIfNeeded(node); - const declName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const declName = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // ... = class ${name} ${heritageClauses} { // ${members} // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); const members = transformClassMembers(node); - const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); - aggregateTransformFlags(classExpression); + const classExpression = factory.createClassExpression(/*decorators*/ undefined, /*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); setOriginalNode(classExpression, node); setTextRange(classExpression, location); // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference // or decoratedClassAlias if the class contain self-reference. - const statement = createVariableStatement( + const statement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( declName, + /*exclamationToken*/ undefined, /*type*/ undefined, - classAlias ? createAssignment(classAlias, classExpression) : classExpression + classAlias ? factory.createAssignment(classAlias, classExpression) : classExpression ) ], NodeFlags.Let) ); @@ -871,7 +873,8 @@ namespace ts { return visitEachChild(node, visitor, context); } - const classExpression = createClassExpression( + const classExpression = factory.createClassExpression( + /*decorators*/ undefined, /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, @@ -879,7 +882,6 @@ namespace ts { transformClassMembers(node) ); - aggregateTransformFlags(classExpression); setOriginalNode(classExpression, node); setTextRange(classExpression, node); @@ -900,19 +902,19 @@ namespace ts { if (parametersWithPropertyAssignments) { for (const parameter of parametersWithPropertyAssignments) { if (isIdentifier(parameter.name)) { - members.push(aggregateTransformFlags(createProperty( + members.push(factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, parameter.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, - /*initializer*/ undefined))); + /*initializer*/ undefined)); } } } addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return setTextRange(createNodeArray(members), /*location*/ node.members); + return setTextRange(factory.createNodeArray(members), /*location*/ node.members); } @@ -1202,22 +1204,21 @@ namespace ts { ? member.kind === SyntaxKind.PropertyDeclaration // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it // should not invoke `Object.getOwnPropertyDescriptor`. - ? createVoidZero() + ? factory.createVoidZero() // We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly. // We have this extra argument here so that we can inject an explicit property descriptor at a later date. - : createNull() + : factory.createNull() : undefined; - const helper = createDecorateHelper( - context, + const helper = emitHelpers().createDecorateHelper( decoratorExpressions, prefix, memberName, - descriptor, - moveRangePastDecorators(member) + descriptor ); + setTextRange(helper, moveRangePastDecorators(member)); setEmitFlags(helper, EmitFlags.NoComments); return helper; } @@ -1230,7 +1231,7 @@ namespace ts { function addConstructorDecorationStatement(statements: Statement[], node: ClassDeclaration) { const expression = generateConstructorDecorationExpression(node); if (expression) { - statements.push(setOriginalNode(createExpressionStatement(expression), node)); + statements.push(setOriginalNode(factory.createExpressionStatement(expression), node)); } } @@ -1247,9 +1248,9 @@ namespace ts { } const classAlias = classAliases && classAliases[getOriginalNodeId(node)]; - const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); - const decorate = createDecorateHelper(context, decoratorExpressions, localName); - const expression = createAssignment(localName, classAlias ? createAssignment(classAlias, decorate) : decorate); + const localName = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const decorate = emitHelpers().createDecorateHelper(decoratorExpressions, localName); + const expression = factory.createAssignment(localName, classAlias ? factory.createAssignment(classAlias, decorate) : decorate); setEmitFlags(expression, EmitFlags.NoComments); setSourceMapRange(expression, moveRangePastDecorators(node)); return expression; @@ -1275,11 +1276,10 @@ namespace ts { if (decorators) { expressions = []; for (const decorator of decorators) { - const helper = createParamHelper( - context, + const helper = emitHelpers().createParamHelper( transformDecorator(decorator), - parameterOffset, - /*location*/ decorator.expression); + parameterOffset); + setTextRange(helper, decorator.expression); setEmitFlags(helper, EmitFlags.NoComments); expressions.push(helper); } @@ -1306,13 +1306,13 @@ namespace ts { function addOldTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) { if (compilerOptions.emitDecoratorMetadata) { if (shouldAddTypeMetadata(node)) { - decoratorExpressions.push(createMetadataHelper(context, "design:type", serializeTypeOfNode(node))); + decoratorExpressions.push(emitHelpers().createMetadataHelper("design:type", serializeTypeOfNode(node))); } if (shouldAddParamTypesMetadata(node)) { - decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node, container))); + decoratorExpressions.push(emitHelpers().createMetadataHelper("design:paramtypes", serializeParameterTypesOfNode(node, container))); } if (shouldAddReturnTypeMetadata(node)) { - decoratorExpressions.push(createMetadataHelper(context, "design:returntype", serializeReturnTypeOfNode(node))); + decoratorExpressions.push(emitHelpers().createMetadataHelper("design:returntype", serializeReturnTypeOfNode(node))); } } } @@ -1321,16 +1321,16 @@ namespace ts { if (compilerOptions.emitDecoratorMetadata) { let properties: ObjectLiteralElementLike[] | undefined; if (shouldAddTypeMetadata(node)) { - (properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node)))); + (properties || (properties = [])).push(factory.createPropertyAssignment("type", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node)))); } if (shouldAddParamTypesMetadata(node)) { - (properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node, container)))); + (properties || (properties = [])).push(factory.createPropertyAssignment("paramTypes", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node, container)))); } if (shouldAddReturnTypeMetadata(node)) { - (properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node)))); + (properties || (properties = [])).push(factory.createPropertyAssignment("returnType", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node)))); } if (properties) { - decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*multiLine*/ true))); + decoratorExpressions.push(emitHelpers().createMetadataHelper("design:typeinfo", factory.createObjectLiteral(properties, /*multiLine*/ true))); } } } @@ -1406,9 +1406,9 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.MethodDeclaration: - return createIdentifier("Function"); + return factory.createIdentifier("Function"); default: - return createVoidZero(); + return factory.createVoidZero(); } } @@ -1443,7 +1443,7 @@ namespace ts { } } - return createArrayLiteral(expressions); + return factory.createArrayLiteral(expressions); } function getParametersOfDecoratedDeclaration(node: SignatureDeclaration, container: ClassLikeDeclaration) { @@ -1466,10 +1466,10 @@ namespace ts { return serializeTypeNode(node.type); } else if (isAsyncFunction(node)) { - return createIdentifier("Promise"); + return factory.createIdentifier("Promise"); } - return createVoidZero(); + return factory.createVoidZero(); } /** @@ -1492,59 +1492,61 @@ namespace ts { */ function serializeTypeNode(node: TypeNode | undefined): SerializedTypeNode { if (node === undefined) { - return createIdentifier("Object"); + return factory.createIdentifier("Object"); } switch (node.kind) { case SyntaxKind.VoidKeyword: case SyntaxKind.UndefinedKeyword: - case SyntaxKind.NullKeyword: case SyntaxKind.NeverKeyword: - return createVoidZero(); + return factory.createVoidZero(); case SyntaxKind.ParenthesizedType: return serializeTypeNode((node).type); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: - return createIdentifier("Function"); + return factory.createIdentifier("Function"); case SyntaxKind.ArrayType: case SyntaxKind.TupleType: - return createIdentifier("Array"); + return factory.createIdentifier("Array"); case SyntaxKind.TypePredicate: case SyntaxKind.BooleanKeyword: - return createIdentifier("Boolean"); + return factory.createIdentifier("Boolean"); case SyntaxKind.StringKeyword: - return createIdentifier("String"); + return factory.createIdentifier("String"); case SyntaxKind.ObjectKeyword: - return createIdentifier("Object"); + return factory.createIdentifier("Object"); case SyntaxKind.LiteralType: switch ((node).literal.kind) { case SyntaxKind.StringLiteral: - return createIdentifier("String"); + return factory.createIdentifier("String"); case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.NumericLiteral: - return createIdentifier("Number"); + return factory.createIdentifier("Number"); case SyntaxKind.BigIntLiteral: return getGlobalBigIntNameWithFallback(); case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: - return createIdentifier("Boolean"); + return factory.createIdentifier("Boolean"); + + case SyntaxKind.NullKeyword: + return factory.createVoidZero(); default: return Debug.failBadSyntaxKind((node).literal); } case SyntaxKind.NumberKeyword: - return createIdentifier("Number"); + return factory.createIdentifier("Number"); case SyntaxKind.BigIntKeyword: return getGlobalBigIntNameWithFallback(); @@ -1552,7 +1554,7 @@ namespace ts { case SyntaxKind.SymbolKeyword: return languageVersion < ScriptTarget.ES2015 ? getGlobalSymbolNameWithFallback() - : createIdentifier("Symbol"); + : factory.createIdentifier("Symbol"); case SyntaxKind.TypeReference: return serializeTypeReferenceNode(node); @@ -1580,12 +1582,11 @@ namespace ts { case SyntaxKind.ImportType: break; - default: return Debug.failBadSyntaxKind(node); } - return createIdentifier("Object"); + return factory.createIdentifier("Object"); } function serializeTypeList(types: readonly TypeNode[]): SerializedTypeNode { @@ -1599,7 +1600,7 @@ namespace ts { if (typeNode.kind === SyntaxKind.NeverKeyword) { continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } const serializedIndividual = serializeTypeNode(typeNode); @@ -1615,7 +1616,7 @@ namespace ts { if (!isIdentifier(serializedUnion) || !isIdentifier(serializedIndividual) || serializedUnion.escapedText !== serializedIndividual.escapedText) { - return createIdentifier("Object"); + return factory.createIdentifier("Object"); } } else { @@ -1625,7 +1626,7 @@ namespace ts { } // If we were able to find common type, use it - return serializedUnion || createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never + return serializedUnion || factory.createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never } /** @@ -1640,59 +1641,61 @@ namespace ts { case TypeReferenceSerializationKind.Unknown: // From conditional type type reference that cannot be resolved is Similar to any or unknown if (findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && (n.parent.trueType === n || n.parent.falseType === n))) { - return createIdentifier("Object"); + return factory.createIdentifier("Object"); } const serialized = serializeEntityNameAsExpressionFallback(node.typeName); - const temp = createTempVariable(hoistVariableDeclaration); - return createConditional( - createTypeCheck(createAssignment(temp, serialized), "function"), + const temp = factory.createTempVariable(hoistVariableDeclaration); + return factory.createConditional( + factory.createTypeCheck(factory.createAssignment(temp, serialized), "function"), + /*questionToken*/ undefined, temp, - createIdentifier("Object") + /*colonToken*/ undefined, + factory.createIdentifier("Object") ); case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: return serializeEntityNameAsExpression(node.typeName); case TypeReferenceSerializationKind.VoidNullableOrNeverType: - return createVoidZero(); + return factory.createVoidZero(); case TypeReferenceSerializationKind.BigIntLikeType: return getGlobalBigIntNameWithFallback(); case TypeReferenceSerializationKind.BooleanType: - return createIdentifier("Boolean"); + return factory.createIdentifier("Boolean"); case TypeReferenceSerializationKind.NumberLikeType: - return createIdentifier("Number"); + return factory.createIdentifier("Number"); case TypeReferenceSerializationKind.StringLikeType: - return createIdentifier("String"); + return factory.createIdentifier("String"); case TypeReferenceSerializationKind.ArrayLikeType: - return createIdentifier("Array"); + return factory.createIdentifier("Array"); case TypeReferenceSerializationKind.ESSymbolType: return languageVersion < ScriptTarget.ES2015 ? getGlobalSymbolNameWithFallback() - : createIdentifier("Symbol"); + : factory.createIdentifier("Symbol"); case TypeReferenceSerializationKind.TypeWithCallSignature: - return createIdentifier("Function"); + return factory.createIdentifier("Function"); case TypeReferenceSerializationKind.Promise: - return createIdentifier("Promise"); + return factory.createIdentifier("Promise"); case TypeReferenceSerializationKind.ObjectType: - return createIdentifier("Object"); + return factory.createIdentifier("Object"); default: return Debug.assertNever(kind); } } function createCheckedValue(left: Expression, right: Expression) { - return createLogicalAnd( - createStrictInequality(createTypeOf(left), createLiteral("undefined")), + return factory.createLogicalAnd( + factory.createStrictInequality(factory.createTypeOf(left), factory.createStringLiteral("undefined")), right ); } @@ -1714,13 +1717,13 @@ namespace ts { } // A.B.C -> typeof A !== undefined && (_a = A.B) !== void 0 && _a.C const left = serializeEntityNameAsExpressionFallback(node.left); - const temp = createTempVariable(hoistVariableDeclaration); - return createLogicalAnd( - createLogicalAnd( + const temp = factory.createTempVariable(hoistVariableDeclaration); + return factory.createLogicalAnd( + factory.createLogicalAnd( left.left, - createStrictInequality(createAssignment(temp, left.right), createVoidZero()) + factory.createStrictInequality(factory.createAssignment(temp, left.right), factory.createVoidZero()) ), - createPropertyAccess(temp, node.right) + factory.createPropertyAccess(temp, node.right) ); } @@ -1737,7 +1740,7 @@ namespace ts { const name = getMutableClone(node); name.flags &= ~NodeFlags.Synthesized; name.original = undefined; - name.parent = getParseTreeNode(currentLexicalScope); // ensure the parent is set to a parse tree node. + name.parent = getParseTreeNode(currentLexicalScope)!; // ensure the parent is set to a parse tree node. return name; @@ -1754,7 +1757,7 @@ namespace ts { * qualified name at runtime. */ function serializeQualifiedNameAsExpression(node: QualifiedName): SerializedEntityNameAsExpression { - return createPropertyAccess(serializeEntityNameAsExpression(node.left), node.right); + return factory.createPropertyAccess(serializeEntityNameAsExpression(node.left), node.right); } /** @@ -1762,10 +1765,12 @@ namespace ts { * available. */ function getGlobalSymbolNameWithFallback(): ConditionalExpression { - return createConditional( - createTypeCheck(createIdentifier("Symbol"), "function"), - createIdentifier("Symbol"), - createIdentifier("Object") + return factory.createConditional( + factory.createTypeCheck(factory.createIdentifier("Symbol"), "function"), + /*questionToken*/ undefined, + factory.createIdentifier("Symbol"), + /*colonToken*/ undefined, + factory.createIdentifier("Object") ); } @@ -1775,12 +1780,14 @@ namespace ts { */ function getGlobalBigIntNameWithFallback(): SerializedTypeNode { return languageVersion < ScriptTarget.ESNext - ? createConditional( - createTypeCheck(createIdentifier("BigInt"), "function"), - createIdentifier("BigInt"), - createIdentifier("Object") + ? factory.createConditional( + factory.createTypeCheck(factory.createIdentifier("BigInt"), "function"), + /*questionToken*/ undefined, + factory.createIdentifier("BigInt"), + /*colonToken*/ undefined, + factory.createIdentifier("Object") ) - : createIdentifier("BigInt"); + : factory.createIdentifier("BigInt"); } /** @@ -1793,11 +1800,11 @@ namespace ts { const name = member.name!; if (isComputedPropertyName(name)) { return generateNameForComputedPropertyName && !isSimpleInlineableExpression(name.expression) - ? getGeneratedNameForNode(name) + ? factory.getGeneratedNameForNode(name) : name.expression; } else if (isIdentifier(name)) { - return createLiteral(idText(name)); + return factory.createStringLiteral(idText(name)); } else { return getSynthesizedClone(name); @@ -1821,9 +1828,9 @@ namespace ts { const expression = visitNode(name.expression, visitor, isExpression); const innerExpression = skipPartiallyEmittedExpressions(expression); if (!isSimpleInlineableExpression(innerExpression)) { - const generatedName = getGeneratedNameForNode(name); + const generatedName = factory.getGeneratedNameForNode(name); hoistVariableDeclaration(generatedName); - return updateComputedPropertyName(name, createAssignment(generatedName, expression)); + return factory.updateComputedPropertyName(name, factory.createAssignment(generatedName, expression)); } } return visitNode(name, visitor, isPropertyName); @@ -1855,10 +1862,10 @@ namespace ts { * @param node The ExpressionWithTypeArguments to transform. */ function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments): ExpressionWithTypeArguments { - return updateExpressionWithTypeArguments( + return factory.updateExpressionWithTypeArguments( node, - /*typeArguments*/ undefined, - visitNode(node.expression, visitor, isLeftHandSideExpression) + visitNode(node.expression, visitor, isLeftHandSideExpression), + /*typeArguments*/ undefined ); } @@ -1873,7 +1880,7 @@ namespace ts { } function visitPropertyDeclaration(node: PropertyDeclaration) { - const updated = updateProperty( + const updated = factory.updatePropertyDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, visitor, isModifier), @@ -1896,7 +1903,7 @@ namespace ts { return undefined; } - return updateConstructor( + return factory.updateConstructorDeclaration( node, /*decorators*/ undefined, /*modifiers*/ undefined, @@ -1917,7 +1924,7 @@ namespace ts { resumeLexicalEnvironment(); - indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(factory, constructor, statements, visitor); // Add parameters with property assignments. Transforms this: // @@ -1938,7 +1945,7 @@ namespace ts { // End the lexical environment. statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); - const block = createBlock(setTextRange(createNodeArray(statements), body.statements), /*multiLine*/ true); + const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), body.statements), /*multiLine*/ true); setTextRange(block, /*location*/ body); setOriginalNode(block, body); return block; @@ -1965,11 +1972,11 @@ namespace ts { removeAllComments( setTextRange( setOriginalNode( - createExpressionStatement( - createAssignment( + factory.createExpressionStatement( + factory.createAssignment( setTextRange( - createPropertyAccess( - createThis(), + factory.createPropertyAccess( + factory.createThis(), propertyName ), node.name @@ -1989,7 +1996,7 @@ namespace ts { if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; } - const updated = updateMethod( + const updated = factory.updateMethodDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), @@ -2024,14 +2031,14 @@ namespace ts { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - const updated = updateGetAccessor( + const updated = factory.updateGetAccessorDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), visitPropertyNameOfClassElement(node), visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - visitFunctionBody(node.body, visitor, context) || createBlock([]) + visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); if (updated !== node) { // While we emit the source map for the node after skipping decorators and modifiers, @@ -2046,13 +2053,13 @@ namespace ts { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - const updated = updateSetAccessor( + const updated = factory.updateSetAccessorDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), visitPropertyNameOfClassElement(node), visitParameterList(node.parameters, visitor, context), - visitFunctionBody(node.body, visitor, context) || createBlock([]) + visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); if (updated !== node) { // While we emit the source map for the node after skipping decorators and modifiers, @@ -2065,9 +2072,9 @@ namespace ts { function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult { if (!shouldEmitFunctionLikeDeclaration(node)) { - return createNotEmittedStatement(node); + return factory.createNotEmittedStatement(node); } - const updated = updateFunctionDeclaration( + const updated = factory.updateFunctionDeclaration( node, /*decorators*/ undefined, visitNodes(node.modifiers, modifierVisitor, isModifier), @@ -2076,7 +2083,7 @@ namespace ts { /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - visitFunctionBody(node.body, visitor, context) || createBlock([]) + visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); if (isExportOfNamespace(node)) { const statements: Statement[] = [updated]; @@ -2088,9 +2095,9 @@ namespace ts { function visitFunctionExpression(node: FunctionExpression): Expression { if (!shouldEmitFunctionLikeDeclaration(node)) { - return createOmittedExpression(); + return factory.createOmittedExpression(); } - const updated = updateFunctionExpression( + const updated = factory.updateFunctionExpression( node, visitNodes(node.modifiers, modifierVisitor, isModifier), node.asteriskToken, @@ -2098,13 +2105,13 @@ namespace ts { /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - visitFunctionBody(node.body, visitor, context) || createBlock([]) + visitFunctionBody(node.body, visitor, context) || factory.createBlock([]) ); return updated; } function visitArrowFunction(node: ArrowFunction) { - const updated = updateArrowFunction( + const updated = factory.updateArrowFunction( node, visitNodes(node.modifiers, modifierVisitor, isModifier), /*typeParameters*/ undefined, @@ -2121,7 +2128,7 @@ namespace ts { return undefined; } - const updated = updateParameter( + const updated = factory.updateParameterDeclaration( node, /*decorators*/ undefined, /*modifiers*/ undefined, @@ -2151,8 +2158,8 @@ namespace ts { } return setTextRange( - createExpressionStatement( - inlineExpressions( + factory.createExpressionStatement( + factory.inlineExpressions( map(variables, transformInitializedVariable) ) ), @@ -2178,7 +2185,7 @@ namespace ts { } else { return setTextRange( - createAssignment( + factory.createAssignment( getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), visitNode(node.initializer, visitor, isExpression) ), @@ -2188,9 +2195,10 @@ namespace ts { } function visitVariableDeclaration(node: VariableDeclaration) { - return updateVariableDeclaration( + return factory.updateVariableDeclaration( node, visitNode(node.name, visitor, isBindingName), + /*exclamationToken*/ undefined, /*type*/ undefined, visitNode(node.initializer, visitor, isExpression)); } @@ -2218,9 +2226,9 @@ namespace ts { // HOWEVER - if there are leading comments on the expression itself, to handle ASI // correctly for return and throw, we must keep the parenthesis if (length(getLeadingCommentRangesOfNode(expression, currentSourceFile))) { - return updateParen(node, expression); + return factory.updateParen(node, expression); } - return createPartiallyEmittedExpression(expression, node); + return factory.createPartiallyEmittedExpression(expression, node); } return visitEachChild(node, visitor, context); @@ -2228,16 +2236,16 @@ namespace ts { function visitAssertionExpression(node: AssertionExpression): Expression { const expression = visitNode(node.expression, visitor, isExpression); - return createPartiallyEmittedExpression(expression, node); + return factory.createPartiallyEmittedExpression(expression, node); } function visitNonNullExpression(node: NonNullExpression): Expression { const expression = visitNode(node.expression, visitor, isLeftHandSideExpression); - return createPartiallyEmittedExpression(expression, node); + return factory.createPartiallyEmittedExpression(expression, node); } function visitCallExpression(node: CallExpression) { - return updateCall( + return factory.updateCall( node, visitNode(node.expression, visitor, isExpression), /*typeArguments*/ undefined, @@ -2245,7 +2253,7 @@ namespace ts { } function visitNewExpression(node: NewExpression) { - return updateNew( + return factory.updateNew( node, visitNode(node.expression, visitor, isExpression), /*typeArguments*/ undefined, @@ -2253,7 +2261,7 @@ namespace ts { } function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { - return updateTaggedTemplate( + return factory.updateTaggedTemplate( node, visitNode(node.tag, visitor, isExpression), /*typeArguments*/ undefined, @@ -2280,7 +2288,7 @@ namespace ts { */ function visitEnumDeclaration(node: EnumDeclaration): VisitResult { if (!shouldEmitEnumDeclaration(node)) { - return createNotEmittedStatement(node); + return factory.createNotEmittedStatement(node); } const statements: Statement[] = []; @@ -2308,40 +2316,40 @@ namespace ts { // `exportName` is the expression used within this node's container for any exported references. const exportName = hasModifier(node, ModifierFlags.Export) - ? getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) - : getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + ? factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x || (x = {}) // exports.x || (exports.x = {}) let moduleArg = - createLogicalOr( + factory.createLogicalOr( exportName, - createAssignment( + factory.createAssignment( exportName, - createObjectLiteral() + factory.createObjectLiteral() ) ); if (hasNamespaceQualifiedExportName(node)) { // `localName` is the expression used within this node's containing scope for any local references. - const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const localName = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x = (exports.x || (exports.x = {})) - moduleArg = createAssignment(localName, moduleArg); + moduleArg = factory.createAssignment(localName, moduleArg); } // (function (x) { // x[x["y"] = 0] = "y"; // ... // })(x || (x = {})); - const enumStatement = createExpressionStatement( - createCall( - createFunctionExpression( + const enumStatement = factory.createExpressionStatement( + factory.createCall( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], /*type*/ undefined, transformEnumBody(node, containerName) ), @@ -2362,7 +2370,7 @@ namespace ts { // Add a DeclarationMarker for the enum to preserve trailing comments and mark // the end of the declaration. - statements.push(createEndOfDeclarationMarker(node)); + statements.push(factory.createEndOfDeclarationMarker(node)); return statements; } @@ -2382,8 +2390,8 @@ namespace ts { addRange(statements, members); currentNamespaceContainerName = savedCurrentNamespaceLocalName; - return createBlock( - setTextRange(createNodeArray(statements), /*location*/ node.members), + return factory.createBlock( + setTextRange(factory.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true ); } @@ -2399,8 +2407,8 @@ namespace ts { // old emitter always generate 'expression' part of the name as-is. const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); const valueExpression = transformEnumMemberDeclarationValue(member); - const innerAssignment = createAssignment( - createElementAccess( + const innerAssignment = factory.createAssignment( + factory.createElementAccess( currentNamespaceContainerName, name ), @@ -2408,15 +2416,15 @@ namespace ts { ); const outerAssignment = valueExpression.kind === SyntaxKind.StringLiteral ? innerAssignment : - createAssignment( - createElementAccess( + factory.createAssignment( + factory.createElementAccess( currentNamespaceContainerName, innerAssignment ), name ); return setTextRange( - createExpressionStatement( + factory.createExpressionStatement( setTextRange( outerAssignment, member @@ -2434,7 +2442,7 @@ namespace ts { function transformEnumMemberDeclarationValue(member: EnumMember): Expression { const value = resolver.getConstantValue(member); if (value !== undefined) { - return createLiteral(value); + return typeof value === "string" ? factory.createStringLiteral(value) : factory.createNumericLiteral(value); } else { enableSubstitutionForNonQualifiedEnumMembers(); @@ -2442,7 +2450,7 @@ namespace ts { return visitNode(member.initializer, visitor, isExpression); } else { - return createVoidZero(); + return factory.createVoidZero(); } } } @@ -2512,11 +2520,11 @@ namespace ts { // Emit a variable statement for the module. We emit top-level enums as a `var` // declaration to avoid static errors in global scripts scripts due to redeclaration. // enums in any other scope are emitted as a `let` declaration. - const statement = createVariableStatement( + const statement = factory.createVariableStatement( visitNodes(node.modifiers, modifierVisitor, isModifier), - createVariableDeclarationList([ - createVariableDeclaration( - getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) ) ], currentLexicalScope.kind === SyntaxKind.SourceFile ? NodeFlags.None : NodeFlags.Let) ); @@ -2561,7 +2569,7 @@ namespace ts { // declaration we do not emit a leading variable declaration. To preserve the // begin/end semantics of the declararation and to properly handle exports // we wrap the leading variable declaration in a `MergeDeclarationMarker`. - const mergeMarker = createMergeDeclarationMarker(statement); + const mergeMarker = factory.createMergeDeclarationMarker(statement); setEmitFlags(mergeMarker, EmitFlags.NoComments | EmitFlags.HasEndOfDeclarationMarker); statements.push(mergeMarker); return false; @@ -2577,7 +2585,7 @@ namespace ts { */ function visitModuleDeclaration(node: ModuleDeclaration): VisitResult { if (!shouldEmitModuleDeclaration(node)) { - return createNotEmittedStatement(node); + return factory.createNotEmittedStatement(node); } Debug.assertNode(node.name, isIdentifier, "A TypeScript namespace should have an Identifier name."); @@ -2608,39 +2616,39 @@ namespace ts { // `exportName` is the expression used within this node's container for any exported references. const exportName = hasModifier(node, ModifierFlags.Export) - ? getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) - : getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + ? factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x || (x = {}) // exports.x || (exports.x = {}) let moduleArg = - createLogicalOr( + factory.createLogicalOr( exportName, - createAssignment( + factory.createAssignment( exportName, - createObjectLiteral() + factory.createObjectLiteral() ) ); if (hasNamespaceQualifiedExportName(node)) { // `localName` is the expression used within this node's containing scope for any local references. - const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const localName = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x = (exports.x || (exports.x = {})) - moduleArg = createAssignment(localName, moduleArg); + moduleArg = factory.createAssignment(localName, moduleArg); } // (function (x_1) { // x_1.y = ...; // })(x || (x = {})); - const moduleStatement = createExpressionStatement( - createCall( - createFunctionExpression( + const moduleStatement = factory.createExpressionStatement( + factory.createCall( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], /*type*/ undefined, transformModuleBody(node, containerName) ), @@ -2661,7 +2669,7 @@ namespace ts { // Add a DeclarationMarker for the namespace to preserve trailing comments and mark // the end of the declaration. - statements.push(createEndOfDeclarationMarker(node)); + statements.push(factory.createEndOfDeclarationMarker(node)); return statements; } @@ -2709,9 +2717,9 @@ namespace ts { currentNamespace = savedCurrentNamespace; currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; - const block = createBlock( + const block = factory.createBlock( setTextRange( - createNodeArray(statements), + factory.createNodeArray(statements), /*location*/ statementsLocation ), /*multiLine*/ true @@ -2766,7 +2774,7 @@ namespace ts { // Elide the declaration if the import clause was elided. const importClause = visitNode(node.importClause, visitImportClause, isImportClause); return importClause - ? updateImportDeclaration( + ? factory.updateImportDeclaration( node, /*decorators*/ undefined, /*modifiers*/ undefined, @@ -2784,7 +2792,7 @@ namespace ts { // Elide the import clause if we elide both its name and its named bindings. const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings); - return (name || namedBindings) ? updateImportClause(node, name, namedBindings) : undefined; + return (name || namedBindings) ? factory.updateImportClause(node, name, namedBindings) : undefined; } /** @@ -2800,7 +2808,7 @@ namespace ts { else { // Elide named imports if all of its import specifiers are elided. const elements = visitNodes(node.elements, visitImportSpecifier, isImportSpecifier); - return some(elements) ? updateNamedImports(node, elements) : undefined; + return some(elements) ? factory.updateNamedImports(node, elements) : undefined; } } @@ -2847,7 +2855,7 @@ namespace ts { // Elide the export declaration if all of its named exports are elided. const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports); return exportClause - ? updateExportDeclaration( + ? factory.updateExportDeclaration( node, /*decorators*/ undefined, /*modifiers*/ undefined, @@ -2865,7 +2873,7 @@ namespace ts { function visitNamedExports(node: NamedExports): VisitResult { // Elide the named exports if all of its export specifiers were elided. const elements = visitNodes(node.elements, visitExportSpecifier, isExportSpecifier); - return some(elements) ? updateNamedExports(node, elements) : undefined; + return some(elements) ? factory.updateNamedExports(node, elements) : undefined; } /** @@ -2909,7 +2917,7 @@ namespace ts { return undefined; } - const moduleReference = createExpressionFromEntityName(node.moduleReference); + const moduleReference = createExpressionFromEntityName(factory, node.moduleReference); setEmitFlags(moduleReference, EmitFlags.NoComments | EmitFlags.NoNestedComments); if (isNamedExternalModuleExport(node) || !isExportOfNamespace(node)) { @@ -2917,12 +2925,13 @@ namespace ts { // var ${name} = ${moduleReference}; return setOriginalNode( setTextRange( - createVariableStatement( + factory.createVariableStatement( visitNodes(node.modifiers, modifierVisitor, isModifier), - createVariableDeclarationList([ + factory.createVariableDeclarationList([ setOriginalNode( - createVariableDeclaration( + factory.createVariableDeclaration( node.name, + /*exclamationToken*/ undefined, /*type*/ undefined, moduleReference ), @@ -2990,26 +2999,26 @@ namespace ts { * Creates a statement for the provided expression. This is used in calls to `map`. */ function expressionToStatement(expression: Expression) { - return createExpressionStatement(expression); + return factory.createExpressionStatement(expression); } function addExportMemberAssignment(statements: Statement[], node: ClassDeclaration | FunctionDeclaration) { - const expression = createAssignment( - getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true), - getLocalName(node) + const expression = factory.createAssignment( + factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true), + factory.getLocalName(node) ); setSourceMapRange(expression, createRange(node.name ? node.name.pos : node.pos, node.end)); - const statement = createExpressionStatement(expression); + const statement = factory.createExpressionStatement(expression); setSourceMapRange(statement, createRange(-1, node.end)); statements.push(statement); } function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) { return setTextRange( - createExpressionStatement( - createAssignment( - getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), + factory.createExpressionStatement( + factory.createAssignment( + factory.getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), exportValue ) ), @@ -3018,18 +3027,18 @@ namespace ts { } function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) { - return setTextRange(createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); + return setTextRange(factory.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); } function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) { - return getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true); + return factory.getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true); } /** * Gets the declaration name used inside of a namespace or enum. */ function getNamespaceParameterName(node: ModuleDeclaration | EnumDeclaration) { - const name = getGeneratedNameForNode(node); + const name = factory.getGeneratedNameForNode(node); setSourceMapRange(name, node.name); return name; } @@ -3039,7 +3048,7 @@ namespace ts { * of its declaration. */ function getNamespaceContainerName(node: ModuleDeclaration | EnumDeclaration) { - return getGeneratedNameForNode(node); + return factory.getGeneratedNameForNode(node); } /** @@ -3050,7 +3059,7 @@ namespace ts { function getClassAliasIfNeeded(node: ClassDeclaration) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) { enableSubstitutionForClassAliases(); - const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default"); + const classAlias = factory.createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default"); classAliases[getOriginalNodeId(node)] = classAlias; hoistVariableDeclaration(classAlias); return classAlias; @@ -3058,12 +3067,12 @@ namespace ts { } function getClassPrototype(node: ClassExpression | ClassDeclaration) { - return createPropertyAccess(getDeclarationName(node), "prototype"); + return factory.createPropertyAccess(factory.getDeclarationName(node), "prototype"); } function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) { return hasModifier(member, ModifierFlags.Static) - ? getDeclarationName(node) + ? factory.getDeclarationName(node) : getClassPrototype(node); } @@ -3164,10 +3173,10 @@ namespace ts { // A shorthand property with an assignment initializer is probably part of a // destructuring assignment if (node.objectAssignmentInitializer) { - const initializer = createAssignment(exportedName, node.objectAssignmentInitializer); - return setTextRange(createPropertyAssignment(name, initializer), node); + const initializer = factory.createAssignment(exportedName, node.objectAssignmentInitializer); + return setTextRange(factory.createPropertyAssignment(name, initializer), node); } - return setTextRange(createPropertyAssignment(name, exportedName), node); + return setTextRange(factory.createPropertyAssignment(name, exportedName), node); } } return node; @@ -3228,7 +3237,7 @@ namespace ts { (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); if (substitute) { return setTextRange( - createPropertyAccess(getGeneratedNameForNode(container), node), + factory.createPropertyAccess(factory.getGeneratedNameForNode(container), node), /*location*/ node ); } @@ -3252,7 +3261,7 @@ namespace ts { // track the constant value on the node for the printer in needsDotDotForPropertyAccess setConstantValue(node, constantValue); - const substitute = createLiteral(constantValue); + const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) : factory.createNumericLiteral(constantValue); if (!compilerOptions.removeComments) { const originalNode = getOriginalNode(node, isAccessExpression); const propertyName = isPropertyAccessExpression(originalNode) @@ -3276,89 +3285,4 @@ namespace ts { return isPropertyAccessExpression(node) || isElementAccessExpression(node) ? resolver.getConstantValue(node) : undefined; } } - - function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) { - const argumentsArray: Expression[] = []; - argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true)); - argumentsArray.push(target); - if (memberName) { - argumentsArray.push(memberName); - if (descriptor) { - argumentsArray.push(descriptor); - } - } - - context.requestEmitHelper(decorateHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__decorate"), - /*typeArguments*/ undefined, - argumentsArray - ), - location - ); - } - - export const decorateHelper: UnscopedEmitHelper = { - name: "typescript:decorate", - importName: "__decorate", - scoped: false, - priority: 2, - text: ` - var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; - };` - }; - - function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) { - context.requestEmitHelper(metadataHelper); - return createCall( - getUnscopedHelperName("__metadata"), - /*typeArguments*/ undefined, - [ - createLiteral(metadataKey), - metadataValue - ] - ); - } - - export const metadataHelper: UnscopedEmitHelper = { - name: "typescript:metadata", - importName: "__metadata", - scoped: false, - priority: 3, - text: ` - var __metadata = (this && this.__metadata) || function (k, v) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); - };` - }; - - function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) { - context.requestEmitHelper(paramHelper); - return setTextRange( - createCall( - getUnscopedHelperName("__param"), - /*typeArguments*/ undefined, - [ - createLiteral(parameterOffset), - expression - ] - ), - location - ); - } - - export const paramHelper: UnscopedEmitHelper = { - name: "typescript:param", - importName: "__param", - scoped: false, - priority: 4, - text: ` - var __param = (this && this.__param) || function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } - };` - }; } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index e2029ff7b602e..70caf79c7f451 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -25,7 +25,7 @@ namespace ts { return e.propertyName !== undefined && e.propertyName.escapedText === InternalSymbolName.Default; } - export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle { + export function chainBundle(context: CoreTransformationContext, transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle { return transformSourceFileOrBundle; function transformSourceFileOrBundle(node: SourceFile | Bundle) { @@ -33,7 +33,7 @@ namespace ts { } function transformBundle(node: Bundle) { - return createBundle(map(node.sourceFiles, transformSourceFile), node.prepends); + return context.factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends); } } @@ -61,7 +61,7 @@ namespace ts { return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 } - export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo { + export function collectExternalModuleInfo(context: TransformationContext, sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo { const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = []; const exportSpecifiers = createMultiMap(); const exportedBindings: Identifier[][] = []; @@ -150,7 +150,7 @@ namespace ts { if (hasModifier(node, ModifierFlags.Default)) { // export default function() { } if (!hasExportDefault) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node)); + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node)); hasExportDefault = true; } } @@ -171,7 +171,7 @@ namespace ts { if (hasModifier(node, ModifierFlags.Default)) { // export default class { } if (!hasExportDefault) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(node)); + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node)); hasExportDefault = true; } } @@ -189,7 +189,7 @@ namespace ts { } } - const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault); + const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(context.factory, context.getEmitHelperFactory(), sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault); if (externalHelpersImportDeclaration) { externalImports.unshift(externalHelpersImportDeclaration); } @@ -257,11 +257,11 @@ namespace ts { * @param visitor The visitor to apply to each node added to the result array. * @returns index of the statement that follows super call */ - export function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number { + export function addPrologueDirectivesAndInitialSuperCall(factory: NodeFactory, ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number { if (ctor.body) { const statements = ctor.body.statements; // add prologue directives to the list (if any) - const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); + const index = factory.copyPrologue(statements, result, /*ensureUseStrict*/ false, visitor); if (index === statements.length) { // list contains nothing but prologue directives (or empty) - exit return index; @@ -279,23 +279,6 @@ namespace ts { return 0; } - - /** - * @param input Template string input strings - * @param args Names which need to be made file-level unique - */ - export function helperString(input: TemplateStringsArray, ...args: string[]) { - return (uniqueName: EmitHelperUniqueNameCallback) => { - let result = ""; - for (let i = 0; i < args.length; i++) { - result += input[i]; - result += uniqueName(args[i]); - } - result += input[input.length - 1]; - return result; - }; - } - /** * Gets all the static or all the instance property declarations of a class * @@ -321,5 +304,4 @@ namespace ts { export function isInitializedProperty(member: ClassElement, requireInitializer: boolean): member is PropertyDeclaration { return isPropertyDeclaration(member) && (!!member.initializer || !requireInitializer); } - } diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index cef7aba0484de..219ba427dd993 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -21,6 +21,14 @@ "diagnosticInformationMap.generated.ts", "scanner.ts", "utilities.ts", + "factory/baseNodeFactory.ts", + "factory/parenthesizerRules.ts", + "factory/nodeConverters.ts", + "factory/nodeFactory.ts", + "factory/emitNode.ts", + "factory/emitHelpers.ts", + "factory/nodeTests.ts", + "factory/utilities.ts", "parser.ts", "commandLineParser.ts", "moduleNameResolver.ts", @@ -28,7 +36,6 @@ "binder.ts", "symbolWalker.ts", "checker.ts", - "factory.ts", "visitor.ts", "sourcemap.ts", "transformers/utilities.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 78f62f3013e8a..763893a8c77eb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -8,113 +8,6 @@ namespace ts { end: number; } - export type JSDocSyntaxKind = - | SyntaxKind.EndOfFileToken - | SyntaxKind.WhitespaceTrivia - | SyntaxKind.AtToken - | SyntaxKind.NewLineTrivia - | SyntaxKind.AsteriskToken - | SyntaxKind.OpenBraceToken - | SyntaxKind.CloseBraceToken - | SyntaxKind.LessThanToken - | SyntaxKind.GreaterThanToken - | SyntaxKind.OpenBracketToken - | SyntaxKind.CloseBracketToken - | SyntaxKind.EqualsToken - | SyntaxKind.CommaToken - | SyntaxKind.DotToken - | SyntaxKind.Identifier - | SyntaxKind.BacktickToken - | SyntaxKind.Unknown - | KeywordSyntaxKind; - - export type KeywordSyntaxKind = - | SyntaxKind.AbstractKeyword - | SyntaxKind.AnyKeyword - | SyntaxKind.AsKeyword - | SyntaxKind.AssertsKeyword - | SyntaxKind.BigIntKeyword - | SyntaxKind.BooleanKeyword - | SyntaxKind.BreakKeyword - | SyntaxKind.CaseKeyword - | SyntaxKind.CatchKeyword - | SyntaxKind.ClassKeyword - | SyntaxKind.ContinueKeyword - | SyntaxKind.ConstKeyword - | SyntaxKind.ConstructorKeyword - | SyntaxKind.DebuggerKeyword - | SyntaxKind.DeclareKeyword - | SyntaxKind.DefaultKeyword - | SyntaxKind.DeleteKeyword - | SyntaxKind.DoKeyword - | SyntaxKind.ElseKeyword - | SyntaxKind.EnumKeyword - | SyntaxKind.ExportKeyword - | SyntaxKind.ExtendsKeyword - | SyntaxKind.FalseKeyword - | SyntaxKind.FinallyKeyword - | SyntaxKind.ForKeyword - | SyntaxKind.FromKeyword - | SyntaxKind.FunctionKeyword - | SyntaxKind.GetKeyword - | SyntaxKind.IfKeyword - | SyntaxKind.ImplementsKeyword - | SyntaxKind.ImportKeyword - | SyntaxKind.InKeyword - | SyntaxKind.InferKeyword - | SyntaxKind.InstanceOfKeyword - | SyntaxKind.InterfaceKeyword - | SyntaxKind.IsKeyword - | SyntaxKind.KeyOfKeyword - | SyntaxKind.LetKeyword - | SyntaxKind.ModuleKeyword - | SyntaxKind.NamespaceKeyword - | SyntaxKind.NeverKeyword - | SyntaxKind.NewKeyword - | SyntaxKind.NullKeyword - | SyntaxKind.NumberKeyword - | SyntaxKind.ObjectKeyword - | SyntaxKind.PackageKeyword - | SyntaxKind.PrivateKeyword - | SyntaxKind.ProtectedKeyword - | SyntaxKind.PublicKeyword - | SyntaxKind.ReadonlyKeyword - | SyntaxKind.RequireKeyword - | SyntaxKind.GlobalKeyword - | SyntaxKind.ReturnKeyword - | SyntaxKind.SetKeyword - | SyntaxKind.StaticKeyword - | SyntaxKind.StringKeyword - | SyntaxKind.SuperKeyword - | SyntaxKind.SwitchKeyword - | SyntaxKind.SymbolKeyword - | SyntaxKind.ThisKeyword - | SyntaxKind.ThrowKeyword - | SyntaxKind.TrueKeyword - | SyntaxKind.TryKeyword - | SyntaxKind.TypeKeyword - | SyntaxKind.TypeOfKeyword - | SyntaxKind.UndefinedKeyword - | SyntaxKind.UniqueKeyword - | SyntaxKind.UnknownKeyword - | SyntaxKind.VarKeyword - | SyntaxKind.VoidKeyword - | SyntaxKind.WhileKeyword - | SyntaxKind.WithKeyword - | SyntaxKind.YieldKeyword - | SyntaxKind.AsyncKeyword - | SyntaxKind.AwaitKeyword - | SyntaxKind.OfKeyword; - - export type JsxTokenSyntaxKind = - | SyntaxKind.LessThanSlashToken - | SyntaxKind.EndOfFileToken - | SyntaxKind.ConflictMarkerTrivia - | SyntaxKind.JsxText - | SyntaxKind.JsxTextAllWhiteSpaces - | SyntaxKind.OpenBraceToken - | SyntaxKind.LessThanToken; - // token > SyntaxKind.Identifier => token is a keyword // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync export const enum SyntaxKind { @@ -528,6 +421,278 @@ namespace ts { /* @internal */ LastContextualKeyword = OfKeyword, } + export type TriviaSyntaxKind = + | SyntaxKind.SingleLineCommentTrivia + | SyntaxKind.MultiLineCommentTrivia + | SyntaxKind.NewLineTrivia + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.ShebangTrivia + | SyntaxKind.ConflictMarkerTrivia + ; + + export type LiteralSyntaxKind = + | SyntaxKind.NumericLiteral + | SyntaxKind.BigIntLiteral + | SyntaxKind.StringLiteral + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.RegularExpressionLiteral + | SyntaxKind.NoSubstitutionTemplateLiteral + ; + + export type PseudoLiteralSyntaxKind = + | SyntaxKind.TemplateHead + | SyntaxKind.TemplateMiddle + | SyntaxKind.TemplateTail + ; + + export type PunctuationSyntaxKind = + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.OpenParenToken + | SyntaxKind.CloseParenToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.DotToken + | SyntaxKind.DotDotDotToken + | SyntaxKind.SemicolonToken + | SyntaxKind.CommaToken + | SyntaxKind.QuestionDotToken + | SyntaxKind.LessThanToken + | SyntaxKind.LessThanSlashToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.LessThanEqualsToken + | SyntaxKind.GreaterThanEqualsToken + | SyntaxKind.EqualsEqualsToken + | SyntaxKind.ExclamationEqualsToken + | SyntaxKind.EqualsEqualsEqualsToken + | SyntaxKind.ExclamationEqualsEqualsToken + | SyntaxKind.EqualsGreaterThanToken + | SyntaxKind.PlusToken + | SyntaxKind.MinusToken + | SyntaxKind.AsteriskToken + | SyntaxKind.AsteriskAsteriskToken + | SyntaxKind.SlashToken + | SyntaxKind.PercentToken + | SyntaxKind.PlusPlusToken + | SyntaxKind.MinusMinusToken + | SyntaxKind.LessThanLessThanToken + | SyntaxKind.GreaterThanGreaterThanToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanToken + | SyntaxKind.AmpersandToken + | SyntaxKind.BarToken + | SyntaxKind.CaretToken + | SyntaxKind.ExclamationToken + | SyntaxKind.TildeToken + | SyntaxKind.AmpersandAmpersandToken + | SyntaxKind.BarBarToken + | SyntaxKind.QuestionQuestionToken + | SyntaxKind.QuestionToken + | SyntaxKind.ColonToken + | SyntaxKind.AtToken + | SyntaxKind.BacktickToken + | SyntaxKind.EqualsToken + | SyntaxKind.PlusEqualsToken + | SyntaxKind.MinusEqualsToken + | SyntaxKind.AsteriskEqualsToken + | SyntaxKind.AsteriskAsteriskEqualsToken + | SyntaxKind.SlashEqualsToken + | SyntaxKind.PercentEqualsToken + | SyntaxKind.LessThanLessThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken + | SyntaxKind.AmpersandEqualsToken + | SyntaxKind.BarEqualsToken + | SyntaxKind.CaretEqualsToken + ; + + export type KeywordSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AnyKeyword + | SyntaxKind.AsKeyword + | SyntaxKind.AssertsKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.AwaitKeyword + | SyntaxKind.BigIntKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.BreakKeyword + | SyntaxKind.CaseKeyword + | SyntaxKind.CatchKeyword + | SyntaxKind.ClassKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.ConstructorKeyword + | SyntaxKind.ContinueKeyword + | SyntaxKind.DebuggerKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.DeleteKeyword + | SyntaxKind.DoKeyword + | SyntaxKind.ElseKeyword + | SyntaxKind.EnumKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.ExtendsKeyword + | SyntaxKind.FalseKeyword + | SyntaxKind.FinallyKeyword + | SyntaxKind.ForKeyword + | SyntaxKind.FromKeyword + | SyntaxKind.FunctionKeyword + | SyntaxKind.GetKeyword + | SyntaxKind.GlobalKeyword + | SyntaxKind.IfKeyword + | SyntaxKind.ImplementsKeyword + | SyntaxKind.ImportKeyword + | SyntaxKind.InferKeyword + | SyntaxKind.InKeyword + | SyntaxKind.InstanceOfKeyword + | SyntaxKind.InterfaceKeyword + | SyntaxKind.IsKeyword + | SyntaxKind.KeyOfKeyword + | SyntaxKind.LetKeyword + | SyntaxKind.ModuleKeyword + | SyntaxKind.NamespaceKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NewKeyword + | SyntaxKind.NullKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.OfKeyword + | SyntaxKind.PackageKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.RequireKeyword + | SyntaxKind.ReturnKeyword + | SyntaxKind.SetKeyword + | SyntaxKind.StaticKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SuperKeyword + | SyntaxKind.SwitchKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.ThisKeyword + | SyntaxKind.ThrowKeyword + | SyntaxKind.TrueKeyword + | SyntaxKind.TryKeyword + | SyntaxKind.TypeKeyword + | SyntaxKind.TypeOfKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UniqueKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VarKeyword + | SyntaxKind.VoidKeyword + | SyntaxKind.WhileKeyword + | SyntaxKind.WithKeyword + | SyntaxKind.YieldKeyword + ; + + export type ModifierSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.StaticKeyword + ; + + export type KeywordTypeSyntaxKind = + | SyntaxKind.AnyKeyword + | SyntaxKind.BigIntKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VoidKeyword + ; + + /* @internal */ + export type TypeNodeSyntaxKind = + | KeywordTypeSyntaxKind + | SyntaxKind.TypePredicate + | SyntaxKind.TypeReference + | SyntaxKind.FunctionType + | SyntaxKind.ConstructorType + | SyntaxKind.TypeQuery + | SyntaxKind.TypeLiteral + | SyntaxKind.ArrayType + | SyntaxKind.TupleType + | SyntaxKind.OptionalType + | SyntaxKind.RestType + | SyntaxKind.UnionType + | SyntaxKind.IntersectionType + | SyntaxKind.ConditionalType + | SyntaxKind.InferType + | SyntaxKind.ParenthesizedType + | SyntaxKind.ThisType + | SyntaxKind.TypeOperator + | SyntaxKind.IndexedAccessType + | SyntaxKind.MappedType + | SyntaxKind.LiteralType + | SyntaxKind.ImportType + | SyntaxKind.ExpressionWithTypeArguments + | SyntaxKind.JSDocTypeExpression + | SyntaxKind.JSDocAllType + | SyntaxKind.JSDocUnknownType + | SyntaxKind.JSDocNonNullableType + | SyntaxKind.JSDocNullableType + | SyntaxKind.JSDocOptionalType + | SyntaxKind.JSDocFunctionType + | SyntaxKind.JSDocVariadicType + | SyntaxKind.JSDocNamepathType + | SyntaxKind.JSDocSignature + | SyntaxKind.JSDocTypeLiteral + ; + + export type TokenSyntaxKind = + | SyntaxKind.Unknown + | SyntaxKind.EndOfFileToken + | TriviaSyntaxKind + | LiteralSyntaxKind + | PseudoLiteralSyntaxKind + | PunctuationSyntaxKind + | SyntaxKind.Identifier + | KeywordSyntaxKind + ; + + export type JsxTokenSyntaxKind = + | SyntaxKind.LessThanSlashToken + | SyntaxKind.EndOfFileToken + | SyntaxKind.ConflictMarkerTrivia + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.OpenBraceToken + | SyntaxKind.LessThanToken + ; + + export type JSDocSyntaxKind = + | SyntaxKind.EndOfFileToken + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.AtToken + | SyntaxKind.NewLineTrivia + | SyntaxKind.AsteriskToken + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.LessThanToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.EqualsToken + | SyntaxKind.CommaToken + | SyntaxKind.DotToken + | SyntaxKind.Identifier + | SyntaxKind.BacktickToken + | SyntaxKind.Unknown + | KeywordSyntaxKind + ; + export const enum NodeFlags { None = 0, Let = 1 << 0, // Variable declaration @@ -683,12 +848,16 @@ namespace ts { | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration + | ImportDeclaration + | NamespaceExportDeclaration + | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration - | EndOfFileToken; + | EndOfFileToken + ; export type HasType = | SignatureDeclaration @@ -706,14 +875,16 @@ namespace ts { | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType - | JSDocVariadicType; + | JSDocVariadicType + ; export type HasInitializer = | HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement - | JsxAttribute; + | JsxAttribute + ; export type HasExpressionInitializer = | VariableDeclaration @@ -722,7 +893,8 @@ namespace ts { | PropertySignature | PropertyDeclaration | PropertyAssignment - | EnumMember; + | EnumMember + ; /* @internal */ export type MutableNodeArray = NodeArray & T[]; @@ -732,38 +904,89 @@ namespace ts { /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined } + // TODO(rbuckton): Constraint 'TKind' to 'TokenSyntaxKind' export interface Token extends Node { kind: TKind; } - export type DotToken = Token; - export type DotDotDotToken = Token; - export type QuestionToken = Token; - export type QuestionDotToken = Token; - export type ExclamationToken = Token; - export type ColonToken = Token; - export type EqualsToken = Token; - export type AsteriskToken = Token; - export type EqualsGreaterThanToken = Token; export type EndOfFileToken = Token & JSDocContainer; - export type ReadonlyToken = Token; - export type AwaitKeywordToken = Token; - export type PlusToken = Token; - export type MinusToken = Token; - export type AssertsToken = Token; - - export type Modifier - = Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token + + // Punctuation + export interface PunctuationToken extends Token { + } + + export type DotToken = PunctuationToken; + export type DotDotDotToken = PunctuationToken; + export type QuestionToken = PunctuationToken; + export type ExclamationToken = PunctuationToken; + export type ColonToken = PunctuationToken; + export type EqualsToken = PunctuationToken; + export type AsteriskToken = PunctuationToken; + export type EqualsGreaterThanToken = PunctuationToken; + export type PlusToken = PunctuationToken; + export type MinusToken = PunctuationToken; + export type QuestionDotToken = PunctuationToken; + + // Keywords + export interface KeywordToken extends Token { + } + + export type AssertsKeyword = KeywordToken; + export type AwaitKeyword = KeywordToken; + + /** @deprecated Use `AwaitKeyword` instead. */ + export type AwaitKeywordToken = AwaitKeyword; + + /** @deprecated Use `AssertsKeyword` instead. */ + export type AssertsToken = AssertsKeyword; + + export interface ModifierToken extends KeywordToken { + } + + export type AbstractKeyword = ModifierToken; + export type AsyncKeyword = ModifierToken; + export type ConstKeyword = ModifierToken; + export type DeclareKeyword = ModifierToken; + export type DefaultKeyword = ModifierToken; + export type ExportKeyword = ModifierToken; + export type PrivateKeyword = ModifierToken; + export type ProtectedKeyword = ModifierToken; + export type PublicKeyword = ModifierToken; + export type ReadonlyKeyword = ModifierToken; + export type StaticKeyword = ModifierToken; + + /** @deprecated Use `ReadonlyKeyword` instead. */ + export type ReadonlyToken = ReadonlyKeyword; + + export type Modifier = + | AbstractKeyword + | AsyncKeyword + | ConstKeyword + | DeclareKeyword + | DefaultKeyword + | ExportKeyword + | PrivateKeyword + | ProtectedKeyword + | PublicKeyword + | ReadonlyKeyword + | StaticKeyword + ; + + export type AccessibilityModifier = + | PublicKeyword + | PrivateKeyword + | ProtectedKeyword + ; + + export type ParameterPropertyModifier = + | AccessibilityModifier + | ReadonlyKeyword + ; + + export type ClassMemberModifier = + | AccessibilityModifier + | ReadonlyKeyword + | StaticKeyword ; export type ModifiersArray = NodeArray; @@ -1004,7 +1227,8 @@ namespace ts { parent: ObjectLiteralExpression; kind: SyntaxKind.PropertyAssignment; name: PropertyName; - questionToken?: QuestionToken; + questionToken?: QuestionToken; // Present for use with reporting a grammar error + exclamationToken?: ExclamationToken; // Present for use with reporting a grammar error initializer: Expression; } @@ -1158,21 +1382,13 @@ namespace ts { _typeNodeBrand: any; } - export interface KeywordTypeNode extends TypeNode { - kind: - | SyntaxKind.AnyKeyword - | SyntaxKind.UnknownKeyword - | SyntaxKind.NumberKeyword - | SyntaxKind.BigIntKeyword - | SyntaxKind.ObjectKeyword - | SyntaxKind.BooleanKeyword - | SyntaxKind.StringKeyword - | SyntaxKind.SymbolKeyword - | SyntaxKind.ThisKeyword - | SyntaxKind.VoidKeyword - | SyntaxKind.UndefinedKeyword - | SyntaxKind.NullKeyword - | SyntaxKind.NeverKeyword; + /* @internal */ + export interface TypeNode extends Node { + kind: TypeNodeSyntaxKind; + } + + export interface KeywordTypeNode extends KeywordToken, TypeNode { + kind: TKind; } export interface ImportTypeNode extends NodeWithTypeArguments { @@ -1311,7 +1527,7 @@ namespace ts { export interface LiteralTypeNode extends TypeNode { kind: SyntaxKind.LiteralType; - literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression; + literal: NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; } export interface StringLiteral extends LiteralExpression, Declaration { @@ -1322,6 +1538,7 @@ namespace ts { } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; + export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing. // Consider 'Expression'. Without the brand, 'Expression' is actually no different @@ -1395,15 +1612,21 @@ namespace ts { _primaryExpressionBrand: any; } - export interface NullLiteral extends PrimaryExpression, TypeNode { + export interface NullLiteral extends PrimaryExpression { kind: SyntaxKind.NullKeyword; } - export interface BooleanLiteral extends PrimaryExpression, TypeNode { - kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword; + export interface TrueLiteral extends PrimaryExpression { + kind: SyntaxKind.TrueKeyword; } - export interface ThisExpression extends PrimaryExpression, KeywordTypeNode { + export interface FalseLiteral extends PrimaryExpression { + kind: SyntaxKind.FalseKeyword; + } + + export type BooleanLiteral = TrueLiteral | FalseLiteral; + + export interface ThisExpression extends PrimaryExpression { kind: SyntaxKind.ThisKeyword; } @@ -1617,10 +1840,19 @@ namespace ts { export type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration + | ObjectBindingOrAssignmentElement + | ArrayBindingOrAssignmentElement + ; + + export type ObjectBindingOrAssignmentElement = | BindingElement | PropertyAssignment // AssignmentProperty | ShorthandPropertyAssignment // AssignmentProperty | SpreadAssignment // AssignmentRestProperty + ; + + export type ArrayBindingOrAssignmentElement = + | BindingElement | OmittedExpression // Elision | SpreadElement // AssignmentRestElement | ArrayLiteralExpression // ArrayAssignmentPattern @@ -1637,7 +1869,12 @@ namespace ts { | SpreadAssignment // AssignmentRestProperty ; - export type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Identifier | PropertyAccessExpression | ElementAccessExpression | OmittedExpression; + export type BindingOrAssignmentElementTarget = + | BindingOrAssignmentPattern + | Identifier + | PropertyAccessExpression + | ElementAccessExpression + | OmittedExpression; export type ObjectBindingOrAssignmentPattern = ObjectBindingPattern @@ -1741,6 +1978,15 @@ namespace ts { kind: SyntaxKind.BigIntLiteral; } + export type LiteralToken = + | NumericLiteral + | BigIntLiteral + | StringLiteral + | JsxText + | RegularExpressionLiteral + | NoSubstitutionTemplateLiteral + ; + export interface TemplateHead extends TemplateLiteralLikeNode { kind: SyntaxKind.TemplateHead; parent: TemplateExpression; @@ -1756,7 +2002,16 @@ namespace ts { parent: TemplateSpan; } - export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; + export type PseudoLiteralToken = + | TemplateHead + | TemplateMiddle + | TemplateTail + ; + + export type TemplateLiteralToken = + | NoSubstitutionTemplateLiteral + | PseudoLiteralToken + ; export interface TemplateExpression extends PrimaryExpression { kind: SyntaxKind.TemplateExpression; @@ -1764,6 +2019,11 @@ namespace ts { templateSpans: NodeArray; } + export type TemplateLiteral = + | TemplateExpression + | NoSubstitutionTemplateLiteral + ; + // Each of these corresponds to a substitution expression and a template literal, in that order. // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. export interface TemplateSpan extends Node { @@ -2421,7 +2681,7 @@ namespace ts { // import "mod" => importClause = undefined, moduleSpecifier = "mod" // In rest of the cases, module specifier is string literal corresponding to module // ImportClause information is shown at its declaration below. - export interface ImportDeclaration extends Statement { + export interface ImportDeclaration extends Statement, JSDocContainer { kind: SyntaxKind.ImportDeclaration; parent: SourceFile | ModuleBlock; importClause?: ImportClause; @@ -2450,7 +2710,7 @@ namespace ts { name: Identifier; } - export interface NamespaceExportDeclaration extends DeclarationStatement { + export interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.NamespaceExportDeclaration; name: Identifier; } @@ -2498,7 +2758,7 @@ namespace ts { * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ - export interface ExportAssignment extends DeclarationStatement { + export interface ExportAssignment extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ExportAssignment; parent: SourceFile; isExportEquals?: boolean; @@ -4872,6 +5132,7 @@ namespace ts { source?: string; relatedInformation?: DiagnosticRelatedInformation[]; } + export interface DiagnosticRelatedInformation { category: DiagnosticCategory; code: number; @@ -4880,12 +5141,20 @@ namespace ts { length: number | undefined; messageText: string | DiagnosticMessageChain; } + export interface DiagnosticWithLocation extends Diagnostic { file: SourceFile; start: number; length: number; } + /* @internal*/ + export interface DiagnosticWithDetachedLocation extends Diagnostic { + file: undefined; + start: number; + length: number; + } + export enum DiagnosticCategory { Warning, Error, @@ -5752,9 +6021,708 @@ namespace ts { set?: Expression; } - export interface TransformationContext { - /*@internal*/ getEmitResolver(): EmitResolver; - /*@internal*/ getEmitHost(): EmitHost; + export const enum OuterExpressionKinds { + Parentheses = 1 << 0, + Assertions = 1 << 1, + PartiallyEmittedExpressions = 1 << 2, + + All = Parentheses | Assertions | PartiallyEmittedExpressions + } + + export type TypeOfTag = "undefined" | "number" | "bigint" | "boolean" | "string" | "symbol" | "object" | "function"; + + /* @internal */ + export interface CallBinding { + target: LeftHandSideExpression; + thisArg: Expression; + } + + /* @internal */ + export interface ParenthesizerRules { + parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression; + parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression | undefined, rightSide: Expression): Expression; + parenthesizeExpressionOfComputedPropertyName(expression: Expression): Expression; + parenthesizeConditionOfConditionalExpression(condition: Expression): Expression; + parenthesizeBranchOfConditionalExpression(branch: Expression): Expression; + parenthesizeExpressionOfExportDefault(expression: Expression): Expression; + parenthesizeExpressionOfNew(expression: Expression): LeftHandSideExpression; + parenthesizeLeftSideOfAccess(expression: Expression): LeftHandSideExpression; + parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression; + parenthesizeOperandOfPrefixUnary(operand: Expression): UnaryExpression; + parenthesizeExpressionsOfCommaDelimitedList(elements: readonly Expression[]): NodeArray; + parenthesizeExpressionForDisallowedComma(expression: Expression): Expression; + parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression; + parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody; + parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode; + parenthesizeMemberOfElementType(member: TypeNode): TypeNode; + parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode; + parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray; + parenthesizeTypeArguments(typeParameters: readonly TypeNode[] | undefined): NodeArray | undefined; + } + + /* @internal */ + export interface NodeConverters { + convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block; + convertToFunctionExpression(node: FunctionDeclaration): FunctionExpression; + convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement): Expression; + convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement): ObjectLiteralElementLike; + convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern; + convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern): ObjectLiteralExpression; + convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern): ArrayLiteralExpression; + convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression; + } + + export interface NodeFactory { + /* @internal */ readonly parenthesizer: ParenthesizerRules; + /* @internal */ readonly converters: NodeConverters; + createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; + + /** + * This is used by the parser to skip transform flag aggregation in Declaration files or other contexts. + * @returns The previous value. + */ + /* @internal */ setSkipTransformationFlags(value: boolean): boolean; + /** + * Tracks setting an extraneous node on a parent. This is primarily used by the parser to add invalid nodes for grammar reporting purposes and is needed to + * correctly update transform flags after a node has been created. + */ + /* @internal */ trackExtraneousChildNode(parent: Node, child: Node | undefined): void; + /** + * Tracks setting an extraneous node array on a parent. This is primarily used by the parser to add invalid nodes for grammar reporting purposes and is needed to + * correctly update transform flags after a node has been created. + */ + /* @internal */ trackExtraneousChildNodes(parent: Node, children: NodeArray | undefined): void; + + // + // Literals + // + + createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; + createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; + createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; + /* @internal*/ createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral; // eslint-disable-line @typescript-eslint/unified-signatures + createStringLiteralFromNode(sourceNode: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; + createRegularExpressionLiteral(text: string): RegularExpressionLiteral; + + // + // Identifiers + // + + createIdentifier(text: string): Identifier; + /* @internal */ createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + /* @internal */ updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; + + /** Create a unique temporary variable. */ + createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /* @internal */ createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + + /** Create a unique temporary variable for use in a loop. */ + createLoopVariable(): Identifier; + + /** Create a unique name based on the supplied text. */ + createUniqueName(text: string): Identifier; + + /** Create a unique name based on the supplied text. */ + createOptimisticUniqueName(text: string): Identifier; + + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ + createFileLevelUniqueName(text: string): Identifier; + + /** Create a unique name generated for a node. */ + getGeneratedNameForNode(node: Node | undefined): Identifier; + /* @internal */ getGeneratedNameForNode(node: Node | undefined, flags?: GeneratedIdentifierFlags): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + + // + // Punctuation + // + + createToken(token: SyntaxKind.SuperKeyword): SuperExpression; + createToken(token: SyntaxKind.ThisKeyword): ThisExpression; + createToken(token: SyntaxKind.NullKeyword): NullLiteral; + createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; + createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: TKind): PunctuationToken; + createToken(token: TKind): KeywordTypeNode; + createToken(token: TKind): ModifierToken; + createToken(token: TKind): KeywordToken; + createToken(token: TKind): Token; + /*@internal*/ createToken(token: TKind): Token; + + // + // Reserved words + // + + createSuper(): SuperExpression; + createThis(): ThisExpression; + createNull(): NullLiteral; + createTrue(): TrueLiteral; + createFalse(): FalseLiteral; + + // + // Modifiers + // + + createModifier(kind: T): ModifierToken; + createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[]; + + // + // Names + // + + createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName; + updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; + createComputedPropertyName(expression: Expression): ComputedPropertyName; + updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; + + // + // Signature elements + // + + createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; + updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; + createParameterDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; + updateParameterDeclaration(node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createDecorator(expression: Expression): Decorator; + updateDecorator(node: Decorator, expression: Expression): Decorator; + + // + // Type Elements + // + + createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + createPropertyDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + updatePropertyDeclaration(node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; + updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; + createMethodDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; + updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; + createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; + updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; + createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + /* @internal */ createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): IndexSignatureDeclaration; // eslint-disable-line @typescript-eslint/unified-signatures + updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + + // + // Types + // + + createKeywordTypeNode(kind: TKind): KeywordTypeNode; + createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; + updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; + updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; + createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode; + updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode; + createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode; + updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; + createTypeQueryNode(exprName: EntityName): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; + updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; + createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; + updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; + createTupleTypeNode(elementTypes: readonly TypeNode[]): TupleTypeNode; + updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]): TupleTypeNode; + createOptionalTypeNode(type: TypeNode): OptionalTypeNode; + updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; + createRestTypeNode(type: TypeNode): RestTypeNode; + updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode; + createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode; + updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; + createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; + updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; + createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; + updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; + createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; + updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; + createThisTypeNode(): ThisTypeNode; + createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; + createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; + updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + + // + // Binding Patterns + // + + createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; + updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; + createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; + updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + + // + // Expression + // + + createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; + updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; + createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; + updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; + updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier): PropertyAccessChain; + updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier): PropertyAccessChain; + createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; + updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; + createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; + updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; + createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; + updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; + createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; + updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; + createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; + updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; + createParen(expression: Expression): ParenthesizedExpression; + updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; + createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; + updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; + createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createDelete(expression: Expression): DeleteExpression; + updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression; + createTypeOf(expression: Expression): TypeOfExpression; + updateTypeOf(node: TypeOfExpression, expression: Expression): TypeOfExpression; + createVoid(expression: Expression): VoidExpression; + updateVoid(node: VoidExpression, expression: Expression): VoidExpression; + createAwait(expression: Expression): AwaitExpression; + updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; + createPrefix(operator: PrefixUnaryOperator, operand: Expression): PrefixUnaryExpression; + updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; + createPostfix(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; + updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; + createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; + updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken): BinaryExpression; + createConditional(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression): ConditionalExpression; + updateConditional(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + createTemplateHead(text: string, rawText?: string): TemplateHead; + createTemplateHead(text: string | undefined, rawText: string): TemplateHead; + createTemplateMiddle(text: string, rawText?: string): TemplateMiddle; + createTemplateMiddle(text: string | undefined, rawText: string): TemplateMiddle; + createTemplateTail(text: string, rawText?: string): TemplateTail; + createTemplateTail(text: string | undefined, rawText: string): TemplateTail; + createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; + createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; + /* @internal */ createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken; + /* @internal */ createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string): TemplateLiteralLikeNode; + createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + createYield(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; + /* @internal */ createYield(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; // eslint-disable-line @typescript-eslint/unified-signatures + updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + createSpread(expression: Expression): SpreadElement; + updateSpread(node: SpreadElement, expression: Expression): SpreadElement; + createClassExpression(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + updateClassExpression(node: ClassExpression, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createOmittedExpression(): OmittedExpression; + createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createAsExpression(expression: Expression, type: TypeNode): AsExpression; + updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; + createNonNullExpression(expression: Expression): NonNullExpression; + updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression; + createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; + updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + + // + // Misc + // + + createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + createSemicolonClassElement(): SemicolonClassElement; + + // + // Element + // + + createBlock(statements: readonly Statement[], multiLine?: boolean): Block; + updateBlock(node: Block, statements: readonly Statement[]): Block; + createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; + updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createEmptyStatement(): EmptyStatement; + createExpressionStatement(expression: Expression): ExpressionStatement; + updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; + updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + createDo(statement: Statement, expression: Expression): DoStatement; + updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; + createWhile(expression: Expression, statement: Statement): WhileStatement; + updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; + createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + createForOf(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForOf(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + createContinue(label?: string | Identifier): ContinueStatement; + updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; + createBreak(label?: string | Identifier): BreakStatement; + updateBreak(node: BreakStatement, label: Identifier | undefined): BreakStatement; + createReturn(expression?: Expression): ReturnStatement; + updateReturn(node: ReturnStatement, expression: Expression | undefined): ReturnStatement; + createWith(expression: Expression, statement: Statement): WithStatement; + updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; + createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement; + updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; + createLabel(label: string | Identifier, statement: Statement): LabeledStatement; + updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; + createThrow(expression: Expression): ThrowStatement; + updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; + createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createDebuggerStatement(): DebuggerStatement; + createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; + updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; + updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; + createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + updateFunctionDeclaration(node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + createClassDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + updateClassDeclaration(node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + createInterfaceDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + createTypeAliasDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + createEnumDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; + updateEnumDeclaration(node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; + createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; + updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createModuleBlock(statements: readonly Statement[]): ModuleBlock; + updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; + createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; + updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; + createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; + updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + createNamespaceImport(name: Identifier): NamespaceImport; + updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; + createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; + updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; + createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; + updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression): ExportAssignment; + createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; + updateExportDeclaration(node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; + createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; + updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; + createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; + updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + /* @internal*/ createMissingDeclaration(): MissingDeclaration; + + // + // Module references + // + + createExternalModuleReference(expression: Expression): ExternalModuleReference; + updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; + + // + // JSDoc + // + + /* @internal */ createJSDocAllType(): JSDocAllType; + /* @internal */ createJSDocUnknownType(): JSDocUnknownType; + /* @internal */ createJSDocNonNullableType(type: TypeNode): JSDocNonNullableType; + /* @internal */ createJSDocNullableType(type: TypeNode): JSDocNullableType; + /* @internal */ createJSDocOptionalType(type: TypeNode): JSDocOptionalType; + /* @internal */ createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; + /* @internal */ createJSDocVariadicType(type: TypeNode): JSDocVariadicType; + /* @internal */ createJSDocNamepathType(type: TypeNode): JSDocNamepathType; + /* @internal */ createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression; + /* @internal */ createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; + /* @internal */ createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; + /* @internal */ createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[]): JSDocTemplateTag; + /* @internal */ createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocTypedefTag; + /* @internal */ createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag; + /* @internal */ createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag; + /* @internal */ createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocThisTag; + /* @internal */ createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag; + /* @internal */ createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"]): JSDocAugmentsTag; + /* @internal */ createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag; + /* @internal */ createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag; + /* @internal */ createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag; + /* @internal */ createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag; + /* @internal */ createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag; + /* @internal */ createJSDocUnknownTag(tagName: Identifier): JSDocUnknownTag; + /* @internal */ createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined): JSDoc; + + // + // JSX + // + + createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; + updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; + createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + createJsxOpeningFragment(): JsxOpeningFragment; + createJsxJsxClosingFragment(): JsxClosingFragment; + updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; + updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; + createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; + updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; + createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; + updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; + + // + // Clauses + // + + createCaseClause(expression: Expression, statements: readonly Statement[]): CaseClause; + updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; + createDefaultClause(statements: readonly Statement[]): DefaultClause; + updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; + createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; + updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; + createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block): CatchClause; + updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + + // + // Property assignments + // + + createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; + updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; + createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + createSpreadAssignment(expression: Expression): SpreadAssignment; + updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; + + // + // Enum + // + + createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; + updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; + + // + // Top-level nodes + // + + createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile; + updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + + // + // Transformation nodes + // + + createNotEmittedStatement(original: Node): NotEmittedStatement; + /* @internal */ createEndOfDeclarationMarker(original: Node): EndOfDeclarationMarker; + /* @internal */ createMergeDeclarationMarker(original: Node): MergeDeclarationMarker; + createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; + updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + /* @internal */ createSyntheticReferenceExpression(expression: Expression, thisArg: Expression): SyntheticReferenceExpression; + /* @internal */ updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression): SyntheticReferenceExpression; + createCommaList(elements: readonly Expression[]): CommaListExpression; + updateCommaList(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; + createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + + // + // Common operators + // + + createComma(left: Expression, right: Expression): BinaryExpression; + createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment(left: Expression, right: Expression): AssignmentExpression; + createLogicalOr(left: Expression, right: Expression): BinaryExpression; + createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + createBitwiseOr(left: Expression, right: Expression): BinaryExpression; + createBitwiseXor(left: Expression, right: Expression): BinaryExpression; + createBitwiseAnd(left: Expression, right: Expression): BinaryExpression; + createStrictEquality(left: Expression, right: Expression): BinaryExpression; + createStrictInequality(left: Expression, right: Expression): BinaryExpression; + createEquality(left: Expression, right: Expression): BinaryExpression; + createInequality(left: Expression, right: Expression): BinaryExpression; + createLessThan(left: Expression, right: Expression): BinaryExpression; + createLessThanEquals(left: Expression, right: Expression): BinaryExpression; + createGreaterThan(left: Expression, right: Expression): BinaryExpression; + createGreaterThanEquals(left: Expression, right: Expression): BinaryExpression; + createLeftShift(left: Expression, right: Expression): BinaryExpression; + createRightShift(left: Expression, right: Expression): BinaryExpression; + createUnsignedRightShift(left: Expression, right: Expression): BinaryExpression; + createAdd(left: Expression, right: Expression): BinaryExpression; + createSubtract(left: Expression, right: Expression): BinaryExpression; + createMultiply(left: Expression, right: Expression): BinaryExpression; + createDivide(left: Expression, right: Expression): BinaryExpression; + createModulo(left: Expression, right: Expression): BinaryExpression; + createExponent(left: Expression, right: Expression): BinaryExpression; + createPrefixPlus(operand: Expression): PrefixUnaryExpression; + createPrefixMinus(operand: Expression): PrefixUnaryExpression; + createPrefixIncrement(operand: Expression): PrefixUnaryExpression; + createPrefixDecrement(operand: Expression): PrefixUnaryExpression; + createBitwiseNot(operand: Expression): PrefixUnaryExpression; + createLogicalNot(operand: Expression): PrefixUnaryExpression; + createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + createPostfixDecrement(operand: Expression): PostfixUnaryExpression; + + // + // Compound Nodes + // + + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + + + createVoidZero(): VoidExpression; + createExportDefault(expression: Expression): ExportAssignment; + createExternalModuleExport(exportName: Identifier): ExportDeclaration; + + /* @internal */ createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; + /* @internal */ createTypeCheck(value: Expression, tag: TypeOfTag): Expression; + /* @internal */ createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]): CallExpression; + /* @internal */ createGlobalMethodCall(globalObjectName: string, globalMethodName: string, argumentsList: readonly Expression[]): CallExpression; + /* @internal */ createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]): CallExpression; + /* @internal */ createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]): CallExpression; + /* @internal */ createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression): CallExpression; + /* @internal */ createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression): CallExpression; + /* @internal */ createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean): ObjectLiteralExpression; + /* @internal */ createArraySliceCall(array: Expression, start?: number | Expression): CallExpression; + /* @internal */ createArrayConcatCall(array: Expression, values: readonly Expression[]): CallExpression; + /* @internal */ createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding; + /* @internal */ inlineExpressions(expressions: readonly Expression[]): Expression; + /** + * Gets the internal name of a declaration. This is primarily used for declarations that can be + * referred to by name in the body of an ES5 class function body. An internal name will *never* + * be prefixed with an module or namespace export modifier like "exports." when emitted as an + * expression. An internal name will also *never* be renamed due to a collision with a block + * scoped variable. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier; + /** + * Gets the local name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A + * local name will *never* be prefixed with an module or namespace export modifier like + * "exports." when emitted as an expression. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier; + /** + * Gets the export name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An + * export name will *always* be prefixed with a module or namespace export modifier like + * `"exports."` when emitted as an expression if the name points to an exported symbol. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier; + /** + * Gets the name of a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getDeclarationName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier; + /** + * Gets a namespace-qualified name for use in expressions. + * + * @param ns The namespace identifier. + * @param name The name. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression; + /** + * Gets the exported name of a declaration for use in expressions. + * + * An exported name will *always* be prefixed with an module or namespace export modifier like + * "exports." if the name points to an exported symbol. + * + * @param ns The namespace identifier. + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + /* @internal */ getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression; + + // + // Utilities + // + + restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + /* @internal */ restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement; + /* @internal */ createUseStrictPrologue(): PrologueDirective; + /** + * Copies any necessary standard and custom prologue-directives into target array. + * @param source origin statements array + * @param target result statements array + * @param ensureUseStrict boolean determining whether the function need to add prologue-directives + * @param visitor Optional callback used to visit any custom prologue directives. + */ + /* @internal */ copyPrologue(source: readonly Statement[], target: Push, ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number; + /** + * Copies only the standard (string-expression) prologue-directives into the target statement-array. + * @param source origin statements array + * @param target result statements array + * @param ensureUseStrict boolean determining whether the function need to add prologue-directives + */ + /* @internal */ copyStandardPrologue(source: readonly Statement[], target: Push, ensureUseStrict?: boolean): number; + /** + * Copies only the custom prologue-directives into target statement-array. + * @param source origin statements array + * @param target result statements array + * @param statementOffset The offset at which to begin the copy. + * @param visitor Optional callback used to visit any custom prologue directives. + */ + /* @internal */ copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number, visitor?: (node: Node) => VisitResult): number; + /* @internal */ copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined; + /* @internal */ ensureUseStrict(statements: NodeArray): NodeArray; + /* @internal */ liftToBlock(nodes: readonly Node[]): Statement; + } + + export interface CoreTransformationContext { + readonly factory: NodeFactory; /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; @@ -5776,6 +6744,12 @@ namespace ts { /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + } + + export interface TransformationContext extends CoreTransformationContext { + /*@internal*/ getEmitResolver(): EmitResolver; + /*@internal*/ getEmitHost(): EmitHost; + /*@internal*/ getEmitHelperFactory(): EmitHelperFactory; /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5e40405817ec1..6eced2ec774b0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1570,8 +1570,9 @@ namespace ts { ? (node).expression : undefined; - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: + // TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s. + case SyntaxKind.Identifier as TypeNodeSyntaxKind: + case SyntaxKind.QualifiedName as TypeNodeSyntaxKind: return (node); } @@ -2941,7 +2942,6 @@ namespace ts { } } - export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral { switch (node.kind) { case SyntaxKind.Identifier: @@ -3079,24 +3079,217 @@ namespace ts { } } + export const enum OperatorPrecedence { + // Expression: + // AssignmentExpression + // Expression `,` AssignmentExpression + Comma, + + // NOTE: `Spread` is higher than `Comma` due to how it is parsed in |ElementList| + // SpreadElement: + // `...` AssignmentExpression + Spread, + + // AssignmentExpression: + // ConditionalExpression + // YieldExpression + // ArrowFunction + // AsyncArrowFunction + // LeftHandSideExpression `=` AssignmentExpression + // LeftHandSideExpression AssignmentOperator AssignmentExpression + // + // NOTE: AssignmentExpression is broken down into several precedences due to the requirements + // of the parenthesizer rules. + + // AssignmentExpression: YieldExpression + // YieldExpression: + // `yield` + // `yield` AssignmentExpression + // `yield` `*` AssignmentExpression + Yield, + + // AssignmentExpression: LeftHandSideExpression `=` AssignmentExpression + // AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression + // AssignmentOperator: one of + // `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=` + Assignment, + + // NOTE: `Conditional` is considered higher than `Assignment` here, but in reality they have + // the same precedence. + // AssignmentExpression: ConditionalExpression + // ConditionalExpression: + // ShortCircuitExpression + // ShortCircuitExpression `?` AssignmentExpression `:` AssignmentExpression + // ShortCircuitExpression: + // LogicalORExpression + // CoalesceExpression + Conditional, + + // CoalesceExpression: + // CoalesceExpressionHead `??` BitwiseORExpression + // CoalesceExpressionHead: + // CoalesceExpression + // BitwiseORExpression + Coalesce = Conditional, // NOTE: This is wrong + + // LogicalORExpression: + // LogicalANDExpression + // LogicalORExpression `||` LogicalANDExpression + LogicalOR, + + // LogicalANDExpression: + // BitwiseORExpression + // LogicalANDExprerssion `&&` BitwiseORExpression + LogicalAND, + + // BitwiseORExpression: + // BitwiseXORExpression + // BitwiseORExpression `^` BitwiseXORExpression + BitwiseOR, + + // BitwiseXORExpression: + // BitwiseANDExpression + // BitwiseXORExpression `^` BitwiseANDExpression + BitwiseXOR, + + // BitwiseANDExpression: + // EqualityExpression + // BitwiseANDExpression `^` EqualityExpression + BitwiseAND, + + // EqualityExpression: + // RelationalExpression + // EqualityExpression `==` RelationalExpression + // EqualityExpression `!=` RelationalExpression + // EqualityExpression `===` RelationalExpression + // EqualityExpression `!==` RelationalExpression + Equality, + + // RelationalExpression: + // ShiftExpression + // RelationalExpression `<` ShiftExpression + // RelationalExpression `>` ShiftExpression + // RelationalExpression `<=` ShiftExpression + // RelationalExpression `>=` ShiftExpression + // RelationalExpression `instanceof` ShiftExpression + // RelationalExpression `in` ShiftExpression + // [+TypeScript] RelationalExpression `as` Type + Relational, + + // ShiftExpression: + // AdditiveExpression + // ShiftExpression `<<` AdditiveExpression + // ShiftExpression `>>` AdditiveExpression + // ShiftExpression `>>>` AdditiveExpression + Shift, + + // AdditiveExpression: + // MultiplicativeExpression + // AdditiveExpression `+` MultiplicativeExpression + // AdditiveExpression `-` MultiplicativeExpression + Additive, + + // MultiplicativeExpression: + // ExponentiationExpression + // MultiplicativeExpression MultiplicativeOperator ExponentiationExpression + // MultiplicativeOperator: one of `*`, `/`, `%` + Multiplicative, + + // ExponentiationExpression: + // UnaryExpression + // UpdateExpression `**` ExponentiationExpression + Exponentiation, + + // UnaryExpression: + // UpdateExpression + // `delete` UnaryExpression + // `void` UnaryExpression + // `typeof` UnaryExpression + // `+` UnaryExpression + // `-` UnaryExpression + // `~` UnaryExpression + // `!` UnaryExpression + // AwaitExpression + // UpdateExpression: // TODO: Do we need to investigate the precedence here? + // `++` UnaryExpression + // `--` UnaryExpression + Unary, + + + // UpdateExpression: + // LeftHandSideExpression + // LeftHandSideExpression `++` + // LeftHandSideExpression `--` + Update, + + // LeftHandSideExpression: + // NewExpression + // CallExpression + // NewExpression: + // MemberExpression + // `new` NewExpression + LeftHandSide, + + // CallExpression: + // CoverCallExpressionAndAsyncArrowHead + // SuperCall + // ImportCall + // CallExpression Arguments + // CallExpression `[` Expression `]` + // CallExpression `.` IdentifierName + // CallExpression TemplateLiteral + // MemberExpression: + // PrimaryExpression + // MemberExpression `[` Expression `]` + // MemberExpression `.` IdentifierName + // MemberExpression TemplateLiteral + // SuperProperty + // MetaProperty + // `new` MemberExpression Arguments + Member, + + // TODO: JSXElement? + // PrimaryExpression: + // `this` + // IdentifierReference + // Literal + // ArrayLiteral + // ObjectLiteral + // FunctionExpression + // ClassExpression + // GeneratorExpression + // AsyncFunctionExpression + // AsyncGeneratorExpression + // RegularExpressionLiteral + // TemplateLiteral + // CoverParenthesizedExpressionAndArrowParameterList + Primary, + + Highest = Primary, + Lowest = Comma, + // -1 is lower than all other precedences. Returning it will cause binary expression + // parsing to stop. + Invalid = -1, + } + export function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean) { switch (nodeKind) { case SyntaxKind.CommaListExpression: - return 0; + return OperatorPrecedence.Comma; case SyntaxKind.SpreadElement: - return 1; + return OperatorPrecedence.Spread; case SyntaxKind.YieldExpression: - return 2; + return OperatorPrecedence.Yield; case SyntaxKind.ConditionalExpression: - return 4; + return OperatorPrecedence.Conditional; case SyntaxKind.BinaryExpression: switch (operatorKind) { case SyntaxKind.CommaToken: - return 0; + return OperatorPrecedence.Comma; case SyntaxKind.EqualsToken: case SyntaxKind.PlusEqualsToken: @@ -3111,32 +3304,34 @@ namespace ts { case SyntaxKind.AmpersandEqualsToken: case SyntaxKind.CaretEqualsToken: case SyntaxKind.BarEqualsToken: - return 3; + return OperatorPrecedence.Assignment; default: return getBinaryOperatorPrecedence(operatorKind); } + // TODO: Should prefix `++` and `--` be moved to the `Update` precedence? + // TODO: We are missing `TypeAssertionExpression` case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.TypeOfExpression: case SyntaxKind.VoidExpression: case SyntaxKind.DeleteExpression: case SyntaxKind.AwaitExpression: - return 16; + return OperatorPrecedence.Unary; case SyntaxKind.PostfixUnaryExpression: - return 17; + return OperatorPrecedence.Update; case SyntaxKind.CallExpression: - return 18; + return OperatorPrecedence.LeftHandSide; case SyntaxKind.NewExpression: - return hasArguments ? 19 : 18; + return hasArguments ? OperatorPrecedence.Member : OperatorPrecedence.LeftHandSide; case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: - return 19; + return OperatorPrecedence.Member; case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: @@ -3152,40 +3347,40 @@ namespace ts { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: case SyntaxKind.ClassExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxFragment: case SyntaxKind.RegularExpressionLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.TemplateExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.OmittedExpression: - return 20; + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: + return OperatorPrecedence.Primary; default: - return -1; + return OperatorPrecedence.Invalid; } } - export function getBinaryOperatorPrecedence(kind: SyntaxKind): number { + export function getBinaryOperatorPrecedence(kind: SyntaxKind): OperatorPrecedence { switch (kind) { case SyntaxKind.QuestionQuestionToken: - return 4; + return OperatorPrecedence.Coalesce; case SyntaxKind.BarBarToken: - return 5; + return OperatorPrecedence.LogicalOR; case SyntaxKind.AmpersandAmpersandToken: - return 6; + return OperatorPrecedence.LogicalAND; case SyntaxKind.BarToken: - return 7; + return OperatorPrecedence.BitwiseOR; case SyntaxKind.CaretToken: - return 8; + return OperatorPrecedence.BitwiseXOR; case SyntaxKind.AmpersandToken: - return 9; + return OperatorPrecedence.BitwiseAND; case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - return 10; + return OperatorPrecedence.Equality; case SyntaxKind.LessThanToken: case SyntaxKind.GreaterThanToken: case SyntaxKind.LessThanEqualsToken: @@ -3193,20 +3388,20 @@ namespace ts { case SyntaxKind.InstanceOfKeyword: case SyntaxKind.InKeyword: case SyntaxKind.AsKeyword: - return 11; + return OperatorPrecedence.Relational; case SyntaxKind.LessThanLessThanToken: case SyntaxKind.GreaterThanGreaterThanToken: case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - return 12; + return OperatorPrecedence.Shift; case SyntaxKind.PlusToken: case SyntaxKind.MinusToken: - return 13; + return OperatorPrecedence.Additive; case SyntaxKind.AsteriskToken: case SyntaxKind.SlashToken: case SyntaxKind.PercentToken: - return 14; + return OperatorPrecedence.Multiplicative; case SyntaxKind.AsteriskAsteriskToken: - return 15; + return OperatorPrecedence.Exponentiation; } // -1 is lower than all other precedences. Returning it will cause binary expression @@ -4128,12 +4323,7 @@ namespace ts { } export function getModifierFlagsNoCache(node: Node): ModifierFlags { - let flags = ModifierFlags.None; - if (node.modifiers) { - for (const modifier of node.modifiers) { - flags |= modifierToFlag(modifier.kind); - } - } + let flags = modifiersToFlags(node.modifiers); if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (node).isInJSDocNamespace)) { flags |= ModifierFlags.Export; @@ -4142,6 +4332,16 @@ namespace ts { return flags; } + export function modifiersToFlags(modifiers: NodeArray | undefined) { + let flags = ModifierFlags.None; + if (modifiers) { + for (const modifier of modifiers) { + flags |= modifierToFlag(modifier.kind); + } + } + return flags; + } + export function modifierToFlag(token: SyntaxKind): ModifierFlags { switch (token) { case SyntaxKind.StaticKeyword: return ModifierFlags.Static; @@ -4860,7 +5060,7 @@ namespace ts { return isClassLike(node) || isInterfaceDeclaration(node) || isTypeLiteralNode(node); } - export function isTypeNodeKind(kind: SyntaxKind) { + export function isTypeNodeKind(kind: SyntaxKind): kind is TypeNodeSyntaxKind { return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) || kind === SyntaxKind.AnyKeyword || kind === SyntaxKind.UnknownKeyword @@ -4870,10 +5070,8 @@ namespace ts { || kind === SyntaxKind.BooleanKeyword || kind === SyntaxKind.StringKeyword || kind === SyntaxKind.SymbolKeyword - || kind === SyntaxKind.ThisKeyword || kind === SyntaxKind.VoidKeyword || kind === SyntaxKind.UndefinedKeyword - || kind === SyntaxKind.NullKeyword || kind === SyntaxKind.NeverKeyword || kind === SyntaxKind.ExpressionWithTypeArguments || kind === SyntaxKind.JSDocAllType @@ -4902,6 +5100,43 @@ namespace ts { export function getDotOrQuestionDotToken(node: PropertyAccessExpression) { return node.questionDotToken || createNode(SyntaxKind.DotToken, node.expression.end, node.name.pos) as DotToken; } + + export function getLeftmostExpression(node: Expression, stopAtCallExpressions: boolean) { + while (true) { + switch (node.kind) { + case SyntaxKind.PostfixUnaryExpression: + node = (node).operand; + continue; + + case SyntaxKind.BinaryExpression: + node = (node).left; + continue; + + case SyntaxKind.ConditionalExpression: + node = (node).condition; + continue; + + case SyntaxKind.TaggedTemplateExpression: + node = (node).tag; + continue; + + case SyntaxKind.CallExpression: + if (stopAtCallExpressions) { + return node; + } + // falls through + case SyntaxKind.AsExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.PartiallyEmittedExpression: + node = (node).expression; + continue; + } + + return node; + } + } } namespace ts { @@ -5309,7 +5544,7 @@ namespace ts { * @param node The original node. * @returns The original parse tree node if found; otherwise, undefined. */ - export function getParseTreeNode(node: Node): Node; + export function getParseTreeNode(node: Node | undefined): Node | undefined; /** * Gets the original parse tree node for a node. @@ -5318,18 +5553,19 @@ namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + export function getParseTreeNode(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined; export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => boolean): Node | undefined { if (node === undefined || isParseTreeNode(node)) { return node; } - node = getOriginalNode(node); - - if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) { - return node; + node = node.original; + while (node) { + if (isParseTreeNode(node)) { + return !nodeTest || nodeTest(node) ? node : undefined; + } + node = node.original; } - return undefined; } @@ -5700,682 +5936,375 @@ namespace ts { } } -// Simple node tests of the form `node.kind === SyntaxKind.Foo`. namespace ts { - // Literals - export function isNumericLiteral(node: Node): node is NumericLiteral { - return node.kind === SyntaxKind.NumericLiteral; + export function setTextRange(range: T, location: TextRange | undefined): T { + if (location) { + range.pos = location.pos; + range.end = location.end; + } + return range; } - export function isBigIntLiteral(node: Node): node is BigIntLiteral { - return node.kind === SyntaxKind.BigIntLiteral; + export function isConstTypeReference(node: Node) { + return isTypeReferenceNode(node) && isIdentifier(node.typeName) && + node.typeName.escapedText === "const" && !node.typeArguments; } - export function isStringLiteral(node: Node): node is StringLiteral { - return node.kind === SyntaxKind.StringLiteral; + export function skipPartiallyEmittedExpressions(node: Expression): Expression; + export function skipPartiallyEmittedExpressions(node: Node): Node; + export function skipPartiallyEmittedExpressions(node: Node) { + while (node.kind === SyntaxKind.PartiallyEmittedExpression) { + node = (node).expression; + } + + return node; } - export function isJsxText(node: Node): node is JsxText { - return node.kind === SyntaxKind.JsxText; + /* @internal */ + export function isAsyncModifier(node: Modifier): node is AsyncKeyword { + return node.kind === SyntaxKind.AsyncKeyword; } - export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral { - return node.kind === SyntaxKind.RegularExpressionLiteral; + /* @internal */ + export function isStaticModifier(node: Modifier): node is StaticKeyword { + return node.kind === SyntaxKind.StaticKeyword; } - export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral { - return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; + export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { + return node.kind === SyntaxKind.JSDocPropertyTag || node.kind === SyntaxKind.JSDocParameterTag; } - // Pseudo-literals + // Groups - export function isTemplateHead(node: Node): node is TemplateHead { - return node.kind === SyntaxKind.TemplateHead; + // used in 'TemplateSpan' + export function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail { + const kind = node.kind; + return kind === SyntaxKind.TemplateMiddle + || kind === SyntaxKind.TemplateTail; } - export function isTemplateMiddle(node: Node): node is TemplateMiddle { - return node.kind === SyntaxKind.TemplateMiddle; + // used in 'ModifiersArray' + export function isModifier(node: Node): node is Modifier { + return isModifierKind(node.kind); } - export function isTemplateTail(node: Node): node is TemplateTail { - return node.kind === SyntaxKind.TemplateTail; + // used in 'QualifiedName' + export function isEntityName(node: Node): node is EntityName { + const kind = node.kind; + return kind === SyntaxKind.QualifiedName + || kind === SyntaxKind.Identifier; } - export function isIdentifier(node: Node): node is Identifier { - return node.kind === SyntaxKind.Identifier; + // used in 'ClassElement', 'TypeElement', and 'ObjectLiteralElement' + export function isPropertyName(node: Node): node is PropertyName { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral + || kind === SyntaxKind.ComputedPropertyName; } - // Names + // used in 'VariableDeclaration', 'ParameterDeclaration', and 'BindingElement' + export function isBindingName(node: Node): node is BindingName { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.ObjectBindingPattern + || kind === SyntaxKind.ArrayBindingPattern; + } - export function isQualifiedName(node: Node): node is QualifiedName { - return node.kind === SyntaxKind.QualifiedName; + // used in 'ClassDeclaration' and 'ClassExpression' + // TODO(rbuckton): Change return type to 'ClassElementNode' + export function isClassElement(node: Node): node is ClassElement { + const kind = node.kind; + return kind === SyntaxKind.Constructor + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.IndexSignature + || kind === SyntaxKind.SemicolonClassElement; } - export function isComputedPropertyName(node: Node): node is ComputedPropertyName { - return node.kind === SyntaxKind.ComputedPropertyName; + // used in 'InterfaceDeclaration' and 'TypeLiteralNode' + // TODO(rbuckton): Change return type to 'TypeElementNode' + export function isTypeElement(node: Node): node is TypeElement { + const kind = node.kind; + return kind === SyntaxKind.ConstructSignature + || kind === SyntaxKind.CallSignature + || kind === SyntaxKind.PropertySignature + || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.IndexSignature; } - // Signature elements + // used in 'ObjectLiteralExpression' and 'JsxAttributes' + // TODO(rbuckton): Rename to 'isObjectLiteralElement' + export function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike { + const kind = node.kind; + return kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.SpreadAssignment + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor; + } - export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { - return node.kind === SyntaxKind.TypeParameter; + // TODO(rbuckton): Rename to 'isJsxAttributesElement' + export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { + return node.kind === SyntaxKind.JsxAttribute + || node.kind === SyntaxKind.JsxSpreadAttribute + || isObjectLiteralElementLike(node); } - export function isParameter(node: Node): node is ParameterDeclaration { - return node.kind === SyntaxKind.Parameter; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + // used in type annotations, type arguments, and complex types + export function isTypeNode(node: Node): node is TypeNode { + return isTypeNodeKind(node.kind); } - export function isDecorator(node: Node): node is Decorator { - return node.kind === SyntaxKind.Decorator; + // used in 'TaggedTemplateExpression' + export function isTemplateLiteral(node: Node): node is TemplateLiteral { + const kind = node.kind; + return kind === SyntaxKind.TemplateExpression + || kind === SyntaxKind.NoSubstitutionTemplateLiteral; } - // TypeMember + function isPrimaryExpressionKind(kind: SyntaxKind): boolean { + // PrimaryExpression: + // `this` + // IdentifierReference + // Literal + // ArrayLiteral + // ObjectLiteral + // FunctionExpression + // ClassExpression + // GeneratorExpression + // AsyncFunctionExpression + // AsyncGeneratorExpression + // RegularExpressionLiteral + // TemplateLiteral + // CoverParenthesizedExpressionAndArrowParameterList (ParenthesizedExpression) + // + // Literal: + // NullLiteral + // BooleanLiteral + // NumericLiteral + // BigIntLiteral + // StringLiteral + // + // TemplateLiteral: + // NoSubstitutionTemplate + // SubstitutionTemplate (i.e. TemplateExpression) - export function isPropertySignature(node: Node): node is PropertySignature { - return node.kind === SyntaxKind.PropertySignature; + switch (kind) { + // ECMAScript + case SyntaxKind.ThisKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.SuperKeyword: // `super(...)` or `super.prop` + case SyntaxKind.ImportKeyword: // `import(...)` + // JSX + // falls through + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: + return true; + default: + return false; + } } - export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { - return node.kind === SyntaxKind.PropertyDeclaration; + function isMemberExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.MetaProperty: + return true; + default: + return isPrimaryExpressionKind(kind); + } } - export function isMethodSignature(node: Node): node is MethodSignature { - return node.kind === SyntaxKind.MethodSignature; + function isLeftHandSideExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.NewExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.TaggedTemplateExpression: + return true; + default: + return isMemberExpressionOrHigherKind(kind); + } } - export function isMethodDeclaration(node: Node): node is MethodDeclaration { - return node.kind === SyntaxKind.MethodDeclaration; + function isUpdateExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + return true; + default: + return isLeftHandSideExpressionOrHigherKind(kind); + } } - export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { - return node.kind === SyntaxKind.Constructor; + function isUnaryExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + return true; + default: + return isUpdateExpressionOrHigherKind(kind); + } } - export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { - return node.kind === SyntaxKind.GetAccessor; + function isBinaryExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.BinaryExpression: + return true; + default: + return isUnaryExpressionOrHigherKind(kind); + } } - export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor; + function isAssignmentExpressionOrHigherKind(kind: SyntaxKind) { + switch (kind) { + // ECMAScript + case SyntaxKind.ConditionalExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.OmittedExpression: // when used in an array literal + case SyntaxKind.SpreadElement: // when used in an array literal or argument list + // TypeScript + // falls through + case SyntaxKind.AsExpression: + return true; + default: + return isBinaryExpressionOrHigherKind(kind); + } } - export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { - return node.kind === SyntaxKind.CallSignature; + function isExpressionKind(kind: SyntaxKind): boolean { + switch (kind) { + // ECMAScript + case SyntaxKind.CommaListExpression: + // TypeScript + // falls through + case SyntaxKind.PartiallyEmittedExpression: + return true; + default: + return isAssignmentExpressionOrHigherKind(kind); + } } - export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration { - return node.kind === SyntaxKind.ConstructSignature; + /* @internal */ + export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { + return isLeftHandSideExpressionOrHigherKind(skipPartiallyEmittedExpressions(node).kind); } - export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration { - return node.kind === SyntaxKind.IndexSignature; + /* @internal */ + export function isUnaryExpression(node: Node): node is UnaryExpression { + return isUnaryExpressionOrHigherKind(skipPartiallyEmittedExpressions(node).kind); } + // TODO(rbuckton): Make this public /* @internal */ - export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; + /** + * Determines whether a node is an expression based only on its kind. + * Use `isExpressionNode` if not in transforms. + */ + export function isExpression(node: Node): node is Expression { + return isExpressionKind(skipPartiallyEmittedExpressions(node).kind); } - // Type - - export function isTypePredicateNode(node: Node): node is TypePredicateNode { - return node.kind === SyntaxKind.TypePredicate; + // used in 'ArrowFunction' + // TODO(rbuckton): Make this public + /* @internal */ + export function isConciseBody(node: Node): node is ConciseBody { + return isBlock(node) + || isExpression(node); } - export function isTypeReferenceNode(node: Node): node is TypeReferenceNode { - return node.kind === SyntaxKind.TypeReference; + // used in functions + // TODO(rbuckton): Make this public + /* @internal */ + export function isFunctionBody(node: Node): node is FunctionBody { + return isBlock(node); } - export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { - return node.kind === SyntaxKind.FunctionType; + // used in 'ForStatement', 'ForInStatement', 'ForOfStatement' + // TODO(rbuckton): Make this public + /* @internal */ + export function isForInitializer(node: Node): node is ForInitializer { + return isVariableDeclarationList(node) + || isExpression(node); } - export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode { - return node.kind === SyntaxKind.ConstructorType; + // used in 'ModuleDeclaration' + /* @internal */ + export function isModuleBody(node: Node): node is ModuleBody { + const kind = node.kind; + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.Identifier; } - export function isTypeQueryNode(node: Node): node is TypeQueryNode { - return node.kind === SyntaxKind.TypeQuery; + // used in 'NamespaceDeclaration' + /* @internal */ + export function isNamespaceBody(node: Node): node is NamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration; } - export function isTypeLiteralNode(node: Node): node is TypeLiteralNode { - return node.kind === SyntaxKind.TypeLiteral; + // used in 'JSDocNamespace' + /* @internal */ + export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.ModuleDeclaration; } - export function isArrayTypeNode(node: Node): node is ArrayTypeNode { - return node.kind === SyntaxKind.ArrayType; + // used in 'ImportClause' + /* @internal */ + export function isNamedImportBindings(node: Node): node is NamedImportBindings { + const kind = node.kind; + return kind === SyntaxKind.NamedImports + || kind === SyntaxKind.NamespaceImport; } - export function isTupleTypeNode(node: Node): node is TupleTypeNode { - return node.kind === SyntaxKind.TupleType; - } + // TODO(rbuckton): Move 'isStatement' here and remove dependence on 'parent' pointer. - export function isUnionTypeNode(node: Node): node is UnionTypeNode { - return node.kind === SyntaxKind.UnionType; + // used in 'CaseBlock' + export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { + const kind = node.kind; + return kind === SyntaxKind.CaseClause + || kind === SyntaxKind.DefaultClause; } - export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode { - return node.kind === SyntaxKind.IntersectionType; - } - - export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode { - return node.kind === SyntaxKind.ConditionalType; - } - - export function isInferTypeNode(node: Node): node is InferTypeNode { - return node.kind === SyntaxKind.InferType; - } - - export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode { - return node.kind === SyntaxKind.ParenthesizedType; - } - - export function isThisTypeNode(node: Node): node is ThisTypeNode { - return node.kind === SyntaxKind.ThisType; - } - - export function isTypeOperatorNode(node: Node): node is TypeOperatorNode { - return node.kind === SyntaxKind.TypeOperator; - } - - export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode { - return node.kind === SyntaxKind.IndexedAccessType; - } - - export function isMappedTypeNode(node: Node): node is MappedTypeNode { - return node.kind === SyntaxKind.MappedType; - } - - export function isLiteralTypeNode(node: Node): node is LiteralTypeNode { - return node.kind === SyntaxKind.LiteralType; - } - - export function isImportTypeNode(node: Node): node is ImportTypeNode { - return node.kind === SyntaxKind.ImportType; - } - - // Binding patterns - - export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { - return node.kind === SyntaxKind.ObjectBindingPattern; - } - - export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { - return node.kind === SyntaxKind.ArrayBindingPattern; - } - - export function isBindingElement(node: Node): node is BindingElement { - return node.kind === SyntaxKind.BindingElement; - } - - // Expression - - export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { - return node.kind === SyntaxKind.ArrayLiteralExpression; - } - - export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { - return node.kind === SyntaxKind.ObjectLiteralExpression; - } - - export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { - return node.kind === SyntaxKind.PropertyAccessExpression; - } - - export function isPropertyAccessChain(node: Node): node is PropertyAccessChain { - return isPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); - } - - export function isElementAccessExpression(node: Node): node is ElementAccessExpression { - return node.kind === SyntaxKind.ElementAccessExpression; - } - - export function isElementAccessChain(node: Node): node is ElementAccessChain { - return isElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); - } - - export function isCallExpression(node: Node): node is CallExpression { - return node.kind === SyntaxKind.CallExpression; - } - - export function isCallChain(node: Node): node is CallChain { - return isCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); - } - - export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain { - const kind = node.kind; - return !!(node.flags & NodeFlags.OptionalChain) && - (kind === SyntaxKind.PropertyAccessExpression - || kind === SyntaxKind.ElementAccessExpression - || kind === SyntaxKind.CallExpression); - } - - /* @internal */ - export function isOptionalChainRoot(node: Node): node is OptionalChainRoot { - return isOptionalChain(node) && !!node.questionDotToken; - } - - /** - * Determines whether a node is the expression preceding an optional chain (i.e. `a` in `a?.b`). - */ - /* @internal */ - export function isExpressionOfOptionalChainRoot(node: Node): node is Expression & { parent: OptionalChainRoot } { - return isOptionalChainRoot(node.parent) && node.parent.expression === node; - } - - /** - * Determines whether a node is the outermost `OptionalChain` in an ECMAScript `OptionalExpression`: - * - * 1. For `a?.b.c`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.`) - * 2. For `(a?.b.c).d`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.` since parens end the chain) - * 3. For `a?.b.c?.d`, both `a?.b.c` and `a?.b.c?.d` are outermost (`c` is the end of the chain starting at `a?.`, and `d` is - * the end of the chain starting at `c?.`) - * 4. For `a?.(b?.c).d`, both `b?.c` and `a?.(b?.c)d` are outermost (`c` is the end of the chain starting at `b`, and `d` is - * the end of the chain starting at `a?.`) - */ - /* @internal */ - export function isOutermostOptionalChain(node: OptionalChain) { - return !isOptionalChain(node.parent) // cases 1 and 2 - || isOptionalChainRoot(node.parent) // case 3 - || node !== node.parent.expression; // case 4 - } - - export function isNullishCoalesce(node: Node) { - return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken; - } - - export function isNewExpression(node: Node): node is NewExpression { - return node.kind === SyntaxKind.NewExpression; - } - - export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { - return node.kind === SyntaxKind.TaggedTemplateExpression; - } - - export function isTypeAssertion(node: Node): node is TypeAssertion { - return node.kind === SyntaxKind.TypeAssertionExpression; - } - - export function isConstTypeReference(node: Node) { - return isTypeReferenceNode(node) && isIdentifier(node.typeName) && - node.typeName.escapedText === "const" && !node.typeArguments; - } - - export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { - return node.kind === SyntaxKind.ParenthesizedExpression; - } - - export function skipPartiallyEmittedExpressions(node: Expression): Expression; - export function skipPartiallyEmittedExpressions(node: Node): Node; - export function skipPartiallyEmittedExpressions(node: Node) { - while (node.kind === SyntaxKind.PartiallyEmittedExpression) { - node = (node).expression; - } - - return node; - } - - export function isFunctionExpression(node: Node): node is FunctionExpression { - return node.kind === SyntaxKind.FunctionExpression; - } - - export function isArrowFunction(node: Node): node is ArrowFunction { - return node.kind === SyntaxKind.ArrowFunction; - } - - export function isDeleteExpression(node: Node): node is DeleteExpression { - return node.kind === SyntaxKind.DeleteExpression; - } - - export function isTypeOfExpression(node: Node): node is TypeOfExpression { - return node.kind === SyntaxKind.TypeOfExpression; - } - - export function isVoidExpression(node: Node): node is VoidExpression { - return node.kind === SyntaxKind.VoidExpression; - } - - export function isAwaitExpression(node: Node): node is AwaitExpression { - return node.kind === SyntaxKind.AwaitExpression; - } - - export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { - return node.kind === SyntaxKind.PrefixUnaryExpression; - } - - export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { - return node.kind === SyntaxKind.PostfixUnaryExpression; - } - - export function isBinaryExpression(node: Node): node is BinaryExpression { - return node.kind === SyntaxKind.BinaryExpression; - } - - export function isConditionalExpression(node: Node): node is ConditionalExpression { - return node.kind === SyntaxKind.ConditionalExpression; - } - - export function isTemplateExpression(node: Node): node is TemplateExpression { - return node.kind === SyntaxKind.TemplateExpression; - } - - export function isYieldExpression(node: Node): node is YieldExpression { - return node.kind === SyntaxKind.YieldExpression; - } - - export function isSpreadElement(node: Node): node is SpreadElement { - return node.kind === SyntaxKind.SpreadElement; - } - - export function isClassExpression(node: Node): node is ClassExpression { - return node.kind === SyntaxKind.ClassExpression; - } - - export function isOmittedExpression(node: Node): node is OmittedExpression { - return node.kind === SyntaxKind.OmittedExpression; - } - - export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { - return node.kind === SyntaxKind.ExpressionWithTypeArguments; - } - - export function isAsExpression(node: Node): node is AsExpression { - return node.kind === SyntaxKind.AsExpression; - } - - export function isNonNullExpression(node: Node): node is NonNullExpression { - return node.kind === SyntaxKind.NonNullExpression; - } - - export function isMetaProperty(node: Node): node is MetaProperty { - return node.kind === SyntaxKind.MetaProperty; - } - - // Misc - - export function isTemplateSpan(node: Node): node is TemplateSpan { - return node.kind === SyntaxKind.TemplateSpan; - } - - export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { - return node.kind === SyntaxKind.SemicolonClassElement; - } - - // Block - - export function isBlock(node: Node): node is Block { - return node.kind === SyntaxKind.Block; - } - - export function isVariableStatement(node: Node): node is VariableStatement { - return node.kind === SyntaxKind.VariableStatement; - } - - export function isEmptyStatement(node: Node): node is EmptyStatement { - return node.kind === SyntaxKind.EmptyStatement; - } - - export function isExpressionStatement(node: Node): node is ExpressionStatement { - return node.kind === SyntaxKind.ExpressionStatement; - } - - export function isIfStatement(node: Node): node is IfStatement { - return node.kind === SyntaxKind.IfStatement; - } - - export function isDoStatement(node: Node): node is DoStatement { - return node.kind === SyntaxKind.DoStatement; - } - - export function isWhileStatement(node: Node): node is WhileStatement { - return node.kind === SyntaxKind.WhileStatement; - } - - export function isForStatement(node: Node): node is ForStatement { - return node.kind === SyntaxKind.ForStatement; - } - - export function isForInStatement(node: Node): node is ForInStatement { - return node.kind === SyntaxKind.ForInStatement; - } - - export function isForOfStatement(node: Node): node is ForOfStatement { - return node.kind === SyntaxKind.ForOfStatement; - } - - export function isContinueStatement(node: Node): node is ContinueStatement { - return node.kind === SyntaxKind.ContinueStatement; - } - - export function isBreakStatement(node: Node): node is BreakStatement { - return node.kind === SyntaxKind.BreakStatement; - } - - export function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement { - return node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement; - } - - export function isReturnStatement(node: Node): node is ReturnStatement { - return node.kind === SyntaxKind.ReturnStatement; - } - - export function isWithStatement(node: Node): node is WithStatement { - return node.kind === SyntaxKind.WithStatement; - } - - export function isSwitchStatement(node: Node): node is SwitchStatement { - return node.kind === SyntaxKind.SwitchStatement; - } - - export function isLabeledStatement(node: Node): node is LabeledStatement { - return node.kind === SyntaxKind.LabeledStatement; - } - - export function isThrowStatement(node: Node): node is ThrowStatement { - return node.kind === SyntaxKind.ThrowStatement; - } - - export function isTryStatement(node: Node): node is TryStatement { - return node.kind === SyntaxKind.TryStatement; - } - - export function isDebuggerStatement(node: Node): node is DebuggerStatement { - return node.kind === SyntaxKind.DebuggerStatement; - } - - export function isVariableDeclaration(node: Node): node is VariableDeclaration { - return node.kind === SyntaxKind.VariableDeclaration; - } - - export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { - return node.kind === SyntaxKind.VariableDeclarationList; - } - - export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { - return node.kind === SyntaxKind.FunctionDeclaration; - } - - export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node.kind === SyntaxKind.ClassDeclaration; - } - - export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { - return node.kind === SyntaxKind.InterfaceDeclaration; - } - - export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { - return node.kind === SyntaxKind.TypeAliasDeclaration; - } - - export function isEnumDeclaration(node: Node): node is EnumDeclaration { - return node.kind === SyntaxKind.EnumDeclaration; - } - - export function isModuleDeclaration(node: Node): node is ModuleDeclaration { - return node.kind === SyntaxKind.ModuleDeclaration; - } - - export function isModuleBlock(node: Node): node is ModuleBlock { - return node.kind === SyntaxKind.ModuleBlock; - } - - export function isCaseBlock(node: Node): node is CaseBlock { - return node.kind === SyntaxKind.CaseBlock; - } - - export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration { - return node.kind === SyntaxKind.NamespaceExportDeclaration; - } - - export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { - return node.kind === SyntaxKind.ImportEqualsDeclaration; - } - - export function isImportDeclaration(node: Node): node is ImportDeclaration { - return node.kind === SyntaxKind.ImportDeclaration; - } - - export function isImportClause(node: Node): node is ImportClause { - return node.kind === SyntaxKind.ImportClause; - } - - export function isNamespaceImport(node: Node): node is NamespaceImport { - return node.kind === SyntaxKind.NamespaceImport; - } - - export function isNamedImports(node: Node): node is NamedImports { - return node.kind === SyntaxKind.NamedImports; - } - - export function isImportSpecifier(node: Node): node is ImportSpecifier { - return node.kind === SyntaxKind.ImportSpecifier; - } - - export function isExportAssignment(node: Node): node is ExportAssignment { - return node.kind === SyntaxKind.ExportAssignment; - } - - export function isExportDeclaration(node: Node): node is ExportDeclaration { - return node.kind === SyntaxKind.ExportDeclaration; - } - - export function isNamedExports(node: Node): node is NamedExports { - return node.kind === SyntaxKind.NamedExports; - } - - export function isExportSpecifier(node: Node): node is ExportSpecifier { - return node.kind === SyntaxKind.ExportSpecifier; - } - - export function isMissingDeclaration(node: Node): node is MissingDeclaration { - return node.kind === SyntaxKind.MissingDeclaration; - } - - // Module References - - export function isExternalModuleReference(node: Node): node is ExternalModuleReference { - return node.kind === SyntaxKind.ExternalModuleReference; - } - - // JSX - - export function isJsxElement(node: Node): node is JsxElement { - return node.kind === SyntaxKind.JsxElement; - } - - export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { - return node.kind === SyntaxKind.JsxSelfClosingElement; - } - - export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { - return node.kind === SyntaxKind.JsxOpeningElement; - } - - export function isJsxClosingElement(node: Node): node is JsxClosingElement { - return node.kind === SyntaxKind.JsxClosingElement; - } - - export function isJsxFragment(node: Node): node is JsxFragment { - return node.kind === SyntaxKind.JsxFragment; - } - - export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { - return node.kind === SyntaxKind.JsxOpeningFragment; - } - - export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { - return node.kind === SyntaxKind.JsxClosingFragment; - } - - export function isJsxAttribute(node: Node): node is JsxAttribute { - return node.kind === SyntaxKind.JsxAttribute; - } - - export function isJsxAttributes(node: Node): node is JsxAttributes { - return node.kind === SyntaxKind.JsxAttributes; - } - - export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { - return node.kind === SyntaxKind.JsxSpreadAttribute; - } - - export function isJsxExpression(node: Node): node is JsxExpression { - return node.kind === SyntaxKind.JsxExpression; - } - - // Clauses - - export function isCaseClause(node: Node): node is CaseClause { - return node.kind === SyntaxKind.CaseClause; - } - - export function isDefaultClause(node: Node): node is DefaultClause { - return node.kind === SyntaxKind.DefaultClause; - } - - export function isHeritageClause(node: Node): node is HeritageClause { - return node.kind === SyntaxKind.HeritageClause; - } - - export function isCatchClause(node: Node): node is CatchClause { - return node.kind === SyntaxKind.CatchClause; - } - - // Property assignments - - export function isPropertyAssignment(node: Node): node is PropertyAssignment { - return node.kind === SyntaxKind.PropertyAssignment; - } - - export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { - return node.kind === SyntaxKind.ShorthandPropertyAssignment; - } - - export function isSpreadAssignment(node: Node): node is SpreadAssignment { - return node.kind === SyntaxKind.SpreadAssignment; - } - - // Enum - - export function isEnumMember(node: Node): node is EnumMember { - return node.kind === SyntaxKind.EnumMember; - } - - // Top-level nodes - export function isSourceFile(node: Node): node is SourceFile { - return node.kind === SyntaxKind.SourceFile; - } - - export function isBundle(node: Node): node is Bundle { - return node.kind === SyntaxKind.Bundle; - } - - export function isUnparsedSource(node: Node): node is UnparsedSource { - return node.kind === SyntaxKind.UnparsedSource; - } - - export function isUnparsedPrepend(node: Node): node is UnparsedPrepend { - return node.kind === SyntaxKind.UnparsedPrepend; + export function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement { + return node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement; } export function isUnparsedTextLike(node: Node): node is UnparsedTextLike { @@ -6394,115 +6323,6 @@ namespace ts { node.kind === SyntaxKind.UnparsedSyntheticReference; } - // JSDoc - - export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { - return node.kind === SyntaxKind.JSDocTypeExpression; - } - - export function isJSDocAllType(node: Node): node is JSDocAllType { - return node.kind === SyntaxKind.JSDocAllType; - } - - export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { - return node.kind === SyntaxKind.JSDocUnknownType; - } - - export function isJSDocNullableType(node: Node): node is JSDocNullableType { - return node.kind === SyntaxKind.JSDocNullableType; - } - - export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { - return node.kind === SyntaxKind.JSDocNonNullableType; - } - - export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { - return node.kind === SyntaxKind.JSDocOptionalType; - } - - export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { - return node.kind === SyntaxKind.JSDocFunctionType; - } - - export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { - return node.kind === SyntaxKind.JSDocVariadicType; - } - - export function isJSDoc(node: Node): node is JSDoc { - return node.kind === SyntaxKind.JSDocComment; - } - - export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { - return node.kind === SyntaxKind.JSDocAuthorTag; - } - - export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { - return node.kind === SyntaxKind.JSDocAugmentsTag; - } - - export function isJSDocClassTag(node: Node): node is JSDocClassTag { - return node.kind === SyntaxKind.JSDocClassTag; - } - - export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { - return node.kind === SyntaxKind.JSDocEnumTag; - } - - export function isJSDocThisTag(node: Node): node is JSDocThisTag { - return node.kind === SyntaxKind.JSDocThisTag; - } - - export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { - return node.kind === SyntaxKind.JSDocParameterTag; - } - - export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { - return node.kind === SyntaxKind.JSDocReturnTag; - } - - export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { - return node.kind === SyntaxKind.JSDocTypeTag; - } - - export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { - return node.kind === SyntaxKind.JSDocTemplateTag; - } - - export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { - return node.kind === SyntaxKind.JSDocTypedefTag; - } - - export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag { - return node.kind === SyntaxKind.JSDocPropertyTag; - } - - export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { - return node.kind === SyntaxKind.JSDocPropertyTag || node.kind === SyntaxKind.JSDocParameterTag; - } - - export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { - return node.kind === SyntaxKind.JSDocTypeLiteral; - } - - export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag { - return node.kind === SyntaxKind.JSDocCallbackTag; - } - - export function isJSDocSignature(node: Node): node is JSDocSignature { - return node.kind === SyntaxKind.JSDocSignature; - } -} - -// Node tests -// -// All node tests in the following list should *not* reference parent pointers so that -// they may be used with transformations. -namespace ts { - /* @internal */ - export function isSyntaxList(n: Node): n is SyntaxList { - return n.kind === SyntaxKind.SyntaxList; - } - /* @internal */ export function isNode(node: Node) { return isNodeKind(node.kind); @@ -6518,6 +6338,7 @@ namespace ts { * For example, this is true for an IfKeyword but not for an IfStatement. * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. */ + // TODO(rbuckton): Rename to 'isTokenKind' and change return type to 'n is TokenSyntaxKind' export function isToken(n: Node): boolean { return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken; } @@ -6532,7 +6353,7 @@ namespace ts { // Literals /* @internal */ - export function isLiteralKind(kind: SyntaxKind): boolean { + export function isLiteralKind(kind: SyntaxKind): kind is LiteralToken["kind"] { return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken; } @@ -6543,25 +6364,19 @@ namespace ts { // Pseudo-literals /* @internal */ - export function isTemplateLiteralKind(kind: SyntaxKind): boolean { + export function isTemplateLiteralKind(kind: SyntaxKind): kind is TemplateLiteralToken["kind"] { return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken; } - export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail; export function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken { return isTemplateLiteralKind(node.kind); } - export function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail { - const kind = node.kind; - return kind === SyntaxKind.TemplateMiddle - || kind === SyntaxKind.TemplateTail; - } - export function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier { return isImportSpecifier(node) || isExportSpecifier(node); } + // TODO(rbuckton): Rename to 'isStringLiteralOrTemplateLiteralToken' export function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken { return node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind); } @@ -6595,38 +6410,14 @@ namespace ts { } /* @internal */ - export function isParameterPropertyModifier(kind: SyntaxKind): boolean { + export function isParameterPropertyModifierKind(kind: SyntaxKind): boolean { return !!(modifierToFlag(kind) & ModifierFlags.ParameterPropertyModifier); } /* @internal */ + // TODO(rbuckton): Rename to 'isClassMemberModifierKind' export function isClassMemberModifier(idToken: SyntaxKind): boolean { - return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.StaticKeyword; - } - - export function isModifier(node: Node): node is Modifier { - return isModifierKind(node.kind); - } - - export function isEntityName(node: Node): node is EntityName { - const kind = node.kind; - return kind === SyntaxKind.QualifiedName - || kind === SyntaxKind.Identifier; - } - - export function isPropertyName(node: Node): node is PropertyName { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.StringLiteral - || kind === SyntaxKind.NumericLiteral - || kind === SyntaxKind.ComputedPropertyName; - } - - export function isBindingName(node: Node): node is BindingName { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.ObjectBindingPattern - || kind === SyntaxKind.ArrayBindingPattern; + return isParameterPropertyModifierKind(idToken) || idToken === SyntaxKind.StaticKeyword; } // Functions @@ -6678,25 +6469,22 @@ namespace ts { } // Classes - export function isClassElement(node: Node): node is ClassElement { - const kind = node.kind; - return kind === SyntaxKind.Constructor - || kind === SyntaxKind.PropertyDeclaration - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.IndexSignature - || kind === SyntaxKind.SemicolonClassElement; - } export function isClassLike(node: Node): node is ClassLikeDeclaration { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } + // TODO(rbuckton): Rename to 'isAccessorDeclaration' + /* @internal */ + export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; + } + export function isAccessor(node: Node): node is AccessorDeclaration { return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor); } + // TODO(rbuckton): Rename to 'isMethodOrAccessorDeclaration' /* @internal */ export function isMethodOrAccessor(node: Node): node is MethodDeclaration | AccessorDeclaration { switch (node.kind) { @@ -6711,40 +6499,12 @@ namespace ts { // Type members - export function isTypeElement(node: Node): node is TypeElement { - const kind = node.kind; - return kind === SyntaxKind.ConstructSignature - || kind === SyntaxKind.CallSignature - || kind === SyntaxKind.PropertySignature - || kind === SyntaxKind.MethodSignature - || kind === SyntaxKind.IndexSignature; - } - export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement { return isTypeElement(node) || isClassElement(node); } - export function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike { - const kind = node.kind; - return kind === SyntaxKind.PropertyAssignment - || kind === SyntaxKind.ShorthandPropertyAssignment - || kind === SyntaxKind.SpreadAssignment - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor; - } - // Type - /** - * Node test that determines whether a node is a valid type node. - * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* - * of a TypeNode. - */ - export function isTypeNode(node: Node): node is TypeNode { - return isTypeNodeKind(node.kind); - } - export function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode { switch (node.kind) { case SyntaxKind.FunctionType: @@ -6757,6 +6517,7 @@ namespace ts { // Binding patterns + // TODO(rbuckton): Remove the '| undefined' and make this public /* @internal */ export function isBindingPattern(node: Node | undefined): node is BindingPattern { if (node) { @@ -6856,85 +6617,18 @@ namespace ts { switch (node.kind) { case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.Decorator: - return true; - default: - return false; - } - } - - export function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression { - return node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.NewExpression; - } - - export function isTemplateLiteral(node: Node): node is TemplateLiteral { - const kind = node.kind; - return kind === SyntaxKind.TemplateExpression - || kind === SyntaxKind.NoSubstitutionTemplateLiteral; - } - - /* @internal */ - export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { - return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxFragment: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ClassExpression: - case SyntaxKind.FunctionExpression: - case SyntaxKind.Identifier: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.BigIntLiteral: - case SyntaxKind.StringLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateExpression: - case SyntaxKind.FalseKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.ThisKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.SuperKeyword: - case SyntaxKind.NonNullExpression: - case SyntaxKind.MetaProperty: - case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.Decorator: return true; default: return false; } } - /* @internal */ - export function isUnaryExpression(node: Node): node is UnaryExpression { - return isUnaryExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isUnaryExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: - case SyntaxKind.DeleteExpression: - case SyntaxKind.TypeOfExpression: - case SyntaxKind.VoidExpression: - case SyntaxKind.AwaitExpression: - case SyntaxKind.TypeAssertionExpression: - return true; - default: - return isLeftHandSideExpressionKind(kind); - } + export function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression { + return node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.NewExpression; } /* @internal */ @@ -6950,53 +6644,12 @@ namespace ts { } } - /* @internal */ - /** - * Determines whether a node is an expression based only on its kind. - * Use `isExpressionNode` if not in transforms. - */ - export function isExpression(node: Node): node is Expression { - return isExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.ConditionalExpression: - case SyntaxKind.YieldExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.BinaryExpression: - case SyntaxKind.SpreadElement: - case SyntaxKind.AsExpression: - case SyntaxKind.OmittedExpression: - case SyntaxKind.CommaListExpression: - case SyntaxKind.PartiallyEmittedExpression: - return true; - default: - return isUnaryExpressionKind(kind); - } - } - export function isAssertionExpression(node: Node): node is AssertionExpression { const kind = node.kind; return kind === SyntaxKind.TypeAssertionExpression || kind === SyntaxKind.AsExpression; } - /* @internal */ - export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression { - return node.kind === SyntaxKind.PartiallyEmittedExpression; - } - - /* @internal */ - export function isNotEmittedStatement(node: Node): node is NotEmittedStatement { - return node.kind === SyntaxKind.NotEmittedStatement; - } - - /* @internal */ - export function isSyntheticReference(node: Node): node is SyntheticReferenceExpression { - return node.kind === SyntaxKind.SyntheticReferenceExpression; - } - /* @internal */ export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression { return isNotEmittedStatement(node) @@ -7022,27 +6675,6 @@ namespace ts { return false; } - /* @internal */ - export function isScopeMarker(node: Node) { - return isExportAssignment(node) || isExportDeclaration(node); - } - - /* @internal */ - export function hasScopeMarker(statements: readonly Statement[]) { - return some(statements, isScopeMarker); - } - - /* @internal */ - export function needsScopeMarker(result: Statement) { - return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result); - } - - /* @internal */ - export function isExternalModuleIndicator(result: Statement) { - // Exported top-level member indicates moduleness - return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export); - } - /* @internal */ export function isForInOrOfStatement(node: Node): node is ForInOrOfStatement { return node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement; @@ -7050,52 +6682,6 @@ namespace ts { // Element - /* @internal */ - export function isConciseBody(node: Node): node is ConciseBody { - return isBlock(node) - || isExpression(node); - } - - /* @internal */ - export function isFunctionBody(node: Node): node is FunctionBody { - return isBlock(node); - } - - /* @internal */ - export function isForInitializer(node: Node): node is ForInitializer { - return isVariableDeclarationList(node) - || isExpression(node); - } - - /* @internal */ - export function isModuleBody(node: Node): node is ModuleBody { - const kind = node.kind; - return kind === SyntaxKind.ModuleBlock - || kind === SyntaxKind.ModuleDeclaration - || kind === SyntaxKind.Identifier; - } - - /* @internal */ - export function isNamespaceBody(node: Node): node is NamespaceBody { - const kind = node.kind; - return kind === SyntaxKind.ModuleBlock - || kind === SyntaxKind.ModuleDeclaration; - } - - /* @internal */ - export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.ModuleDeclaration; - } - - /* @internal */ - export function isNamedImportBindings(node: Node): node is NamedImportBindings { - const kind = node.kind; - return kind === SyntaxKind.NamedImports - || kind === SyntaxKind.NamespaceImport; - } - /* @internal */ export function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration { return node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration; @@ -7198,6 +6784,17 @@ namespace ts { return isStatementKindButNotDeclarationKind(node.kind); } + /** + * NOTE: This is similar to `isStatement` but does not access parent pointers. + */ + /* @internal */ + export function isStatementOrBlock(node: Node): node is Statement | Block { + const kind = node.kind; + return isStatementKindButNotDeclarationKind(kind) + || isDeclarationStatementKind(kind) + || kind === SyntaxKind.Block; + } + /* @internal */ export function isStatement(node: Node): node is Statement { const kind = node.kind; @@ -7266,14 +6863,6 @@ namespace ts { || kind === SyntaxKind.JsxSelfClosingElement; } - // Clauses - - export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { - const kind = node.kind; - return kind === SyntaxKind.CaseClause - || kind === SyntaxKind.DefaultClause; - } - // JSDoc /** True if node is of some JSDoc syntax kind. */ @@ -7293,10 +6882,12 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode; } + // TODO(rbuckton): Deprecate export function isSetAccessor(node: Node): node is SetAccessorDeclaration { return node.kind === SyntaxKind.SetAccessor; } + // TODO(rbuckton): Deprecate export function isGetAccessor(node: Node): node is GetAccessorDeclaration { return node.kind === SyntaxKind.GetAccessor; } @@ -7309,6 +6900,19 @@ namespace ts { return !!jsDoc && jsDoc.length > 0; } + /* @internal */ + export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) { + if (fullName) { + let rightNode = fullName; + while (true) { + if (isIdentifier(rightNode) || !rightNode.body) { + return isIdentifier(rightNode) ? rightNode : rightNode.name; + } + rightNode = rightNode.body; + } + } + } + /** True if has type node attached to it. */ /* @internal */ export function hasType(node: Node): node is HasType { @@ -7327,10 +6931,6 @@ namespace ts { return hasInitializer(node) && !isForStatement(node) && !isForInStatement(node) && !isForOfStatement(node) && !isJsxAttribute(node); } - export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { - return node.kind === SyntaxKind.JsxAttribute || node.kind === SyntaxKind.JsxSpreadAttribute || isObjectLiteralElementLike(node); - } - /* @internal */ export function isTypeReferenceType(node: Node): node is TypeReferenceType { return node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ExpressionWithTypeArguments; @@ -7365,6 +6965,92 @@ namespace ts { } } +// Simple node tests of the form `node.kind === SyntaxKind.Foo`. +namespace ts { + export function isPropertyAccessChain(node: Node): node is PropertyAccessChain { + return isPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); + } + + export function isElementAccessChain(node: Node): node is ElementAccessChain { + return isElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); + } + + export function isCallChain(node: Node): node is CallChain { + return isCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); + } + + export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain { + const kind = node.kind; + return !!(node.flags & NodeFlags.OptionalChain) && + (kind === SyntaxKind.PropertyAccessExpression + || kind === SyntaxKind.ElementAccessExpression + || kind === SyntaxKind.CallExpression); + } + + /* @internal */ + export function isOptionalChainRoot(node: Node): node is OptionalChainRoot { + return isOptionalChain(node) && !!node.questionDotToken; + } + + /** + * Determines whether a node is the expression preceding an optional chain (i.e. `a` in `a?.b`). + */ + /* @internal */ + export function isExpressionOfOptionalChainRoot(node: Node): node is Expression & { parent: OptionalChainRoot } { + return isOptionalChainRoot(node.parent) && node.parent.expression === node; + } + + /** + * Determines whether a node is the outermost `OptionalChain` in an ECMAScript `OptionalExpression`: + * + * 1. For `a?.b.c`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.`) + * 2. For `(a?.b.c).d`, the outermost chain is `a?.b.c` (`c` is the end of the chain starting at `a?.` since parens end the chain) + * 3. For `a?.b.c?.d`, both `a?.b.c` and `a?.b.c?.d` are outermost (`c` is the end of the chain starting at `a?.`, and `d` is + * the end of the chain starting at `c?.`) + * 4. For `a?.(b?.c).d`, both `b?.c` and `a?.(b?.c)d` are outermost (`c` is the end of the chain starting at `b`, and `d` is + * the end of the chain starting at `a?.`) + */ + /* @internal */ + export function isOutermostOptionalChain(node: OptionalChain) { + return !isOptionalChain(node.parent) // cases 1 and 2 + || isOptionalChainRoot(node.parent) // case 3 + || node !== node.parent.expression; // case 4 + } + + export function isNullishCoalesce(node: Node) { + return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.QuestionQuestionToken; + } + +} + +// Node tests +// +// All node tests in the following list should *not* reference parent pointers so that +// they may be used with transformations. +/* @internal */ +namespace ts { + export function isParameterPropertyModifier(kind: SyntaxKind): boolean { + return !!(modifierToFlag(kind) & ModifierFlags.ParameterPropertyModifier); + } + + export function isScopeMarker(node: Node) { + return isExportAssignment(node) || isExportDeclaration(node); + } + + export function hasScopeMarker(statements: readonly Statement[]) { + return some(statements, isScopeMarker); + } + + export function needsScopeMarker(result: Statement) { + return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result); + } + + export function isExternalModuleIndicator(result: Statement) { + // Exported top-level member indicates moduleness + return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export); + } +} + /* @internal */ namespace ts { export function isNamedImportsOrExports(node: Node): node is NamedImportsOrExports { @@ -7446,6 +7132,38 @@ namespace ts { return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message; } + export function createDetachedDiagnostic(start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithDetachedLocation; + export function createDetachedDiagnostic(start: number, length: number, message: DiagnosticMessage): DiagnosticWithDetachedLocation { + Debug.assertGreaterThanOrEqual(start, 0); + Debug.assertGreaterThanOrEqual(length, 0); + + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 3) { + text = formatStringFromArgs(text, arguments, 3); + } + + return { + file: undefined, + start, + length, + + messageText: text, + category: message.category, + code: message.code, + reportsUnnecessary: message.reportsUnnecessary, + }; + } + + export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocation[], file: SourceFile): DiagnosticWithLocation[] { + for (const diagnostic of diagnostics) { + Debug.assertLessThanOrEqual(diagnostic.start, file.text.length); + Debug.assertLessThanOrEqual(diagnostic.start + diagnostic.length, file.text.length); + (diagnostic as Diagnostic).file = file; + } + return diagnostics as Diagnostic[] as DiagnosticWithLocation[]; + } + export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation { Debug.assertGreaterThanOrEqual(start, 0); @@ -7614,6 +7332,11 @@ namespace ts { return Comparison.EqualTo; } + export function getLanguageVariant(scriptKind: ScriptKind) { + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; + } + export function getEmitScriptTarget(compilerOptions: CompilerOptions) { return compilerOptions.target || ScriptTarget.ES3; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 4f36ccb1b900f..44e1c56e3e42f 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -26,7 +26,6 @@ namespace ts { return node; } - aggregateTransformFlags(node); const visited = visitor(node); if (visited === node) { return node; @@ -44,7 +43,6 @@ namespace ts { } Debug.assertNode(visitedNode, test); - aggregateTransformFlags(visitedNode!); return visitedNode; } @@ -84,7 +82,7 @@ namespace ts { return nodes; } - let updated: MutableNodeArray | undefined; + let updated: T[] | undefined; // Ensure start and count have valid values const length = nodes.length; @@ -96,42 +94,53 @@ namespace ts { count = length - start; } + let hasTrailingComma: boolean | undefined; + let pos = -1; + let end = -1; if (start > 0 || count < length) { // If we are not visiting all of the original nodes, we must always create a new array. // Since this is a fragment of a node array, we do not copy over the previous location // and will only copy over `hasTrailingComma` if we are including the last element. - updated = createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + updated = []; + hasTrailingComma = nodes.hasTrailingComma && start + count === length; } // Visit each original node. for (let i = 0; i < count; i++) { const node = nodes[i + start]; - aggregateTransformFlags(node); const visited = node !== undefined ? visitor(node) : undefined; if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { // Ensure we have a copy of `nodes`, up to the current index. - updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); - setTextRange(updated, nodes); + updated = nodes.slice(0, i); + hasTrailingComma = nodes.hasTrailingComma; + pos = nodes.pos; + end = nodes.end; } if (visited) { if (isArray(visited)) { for (const visitedNode of visited) { Debug.assertNode(visitedNode, test); - aggregateTransformFlags(visitedNode); updated.push(visitedNode); } } else { Debug.assertNode(visited, test); - aggregateTransformFlags(visited); updated.push(visited); } } } } - return updated || nodes; + if (updated) { + // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. + const updatedArray = factory.createNodeArray(updated, hasTrailingComma); + updatedArray.pos = pos; + updatedArray.end = end; + return updatedArray; + } + + return nodes; } /** @@ -141,8 +150,8 @@ namespace ts { export function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean) { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, isStatement, start); - if (ensureUseStrict) statements = ts.ensureUseStrict(statements); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier - return mergeLexicalEnvironment(statements, context.endLexicalEnvironment()); + if (ensureUseStrict) statements = context.factory.ensureUseStrict(statements); + return mergeLexicalEnvironment(statements, context.endLexicalEnvironment(), context.factory); } /** @@ -176,9 +185,9 @@ namespace ts { const updated = visitNode(node, visitor, isConciseBody); const declarations = context.endLexicalEnvironment(); if (some(declarations)) { - const block = convertToFunctionBody(updated); + const block = context.factory.converters.convertToFunctionBlock(updated); const statements = mergeLexicalEnvironment(block.statements, declarations); - return updateBlock(block, statements); + return context.factory.updateBlock(block, statements); } return updated; } @@ -213,30 +222,31 @@ namespace ts { return node; } + const factory = context.factory; switch (kind) { // Names case SyntaxKind.Identifier: - return updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); + return factory.updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); case SyntaxKind.QualifiedName: - return updateQualifiedName(node, + return factory.updateQualifiedName(node, visitNode((node).left, visitor, isEntityName), visitNode((node).right, visitor, isIdentifier)); case SyntaxKind.ComputedPropertyName: - return updateComputedPropertyName(node, + return factory.updateComputedPropertyName(node, visitNode((node).expression, visitor, isExpression)); // Signature elements case SyntaxKind.TypeParameter: - return updateTypeParameterDeclaration(node, + return factory.updateTypeParameterDeclaration(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).constraint, visitor, isTypeNode), visitNode((node).default, visitor, isTypeNode)); case SyntaxKind.Parameter: - return updateParameter(node, + return factory.updateParameterDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).dotDotDotToken, tokenVisitor, isToken), @@ -246,20 +256,19 @@ namespace ts { visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.Decorator: - return updateDecorator(node, + return factory.updateDecorator(node, visitNode((node).expression, visitor, isExpression)); // Type elements case SyntaxKind.PropertySignature: - return updatePropertySignature((node), + return factory.updatePropertySignature((node), nodesVisitor((node).modifiers, visitor, isToken), visitNode((node).name, visitor, isPropertyName), visitNode((node).questionToken, tokenVisitor, isToken), - visitNode((node).type, visitor, isTypeNode), - visitNode((node).initializer, visitor, isExpression)); + visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.PropertyDeclaration: - return updateProperty(node, + return factory.updatePropertyDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), @@ -269,15 +278,16 @@ namespace ts { visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.MethodSignature: - return updateMethodSignature(node, + return factory.updateMethodSignature(node, + nodesVisitor((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isPropertyName), + visitNode((node).questionToken, tokenVisitor, isToken), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), - visitNode((node).type, visitor, isTypeNode), - visitNode((node).name, visitor, isPropertyName), - visitNode((node).questionToken, tokenVisitor, isToken)); + visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.MethodDeclaration: - return updateMethod(node, + return factory.updateMethodDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), @@ -289,14 +299,14 @@ namespace ts { visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.Constructor: - return updateConstructor(node, + return factory.updateConstructorDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.GetAccessor: - return updateGetAccessor(node, + return factory.updateGetAccessorDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), @@ -305,7 +315,7 @@ namespace ts { visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.SetAccessor: - return updateSetAccessor(node, + return factory.updateSetAccessorDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), @@ -313,19 +323,19 @@ namespace ts { visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.CallSignature: - return updateCallSignature(node, + return factory.updateCallSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructSignature: - return updateConstructSignature(node, + return factory.updateConstructSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.IndexSignature: - return updateIndexSignature(node, + return factory.updateIndexSignature(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), nodesVisitor((node).parameters, visitor, isParameterDeclaration), @@ -333,73 +343,73 @@ namespace ts { // Types case SyntaxKind.TypePredicate: - return updateTypePredicateNodeWithModifier(node, + return factory.updateTypePredicateNode(node, visitNode((node).assertsModifier, visitor), visitNode((node).parameterName, visitor), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeReference: - return updateTypeReferenceNode(node, + return factory.updateTypeReferenceNode(node, visitNode((node).typeName, visitor, isEntityName), nodesVisitor((node).typeArguments, visitor, isTypeNode)); case SyntaxKind.FunctionType: - return updateFunctionTypeNode(node, + return factory.updateFunctionTypeNode(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.ConstructorType: - return updateConstructorTypeNode(node, + return factory.updateConstructorTypeNode(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).parameters, visitor, isParameterDeclaration), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeQuery: - return updateTypeQueryNode((node), + return factory.updateTypeQueryNode((node), visitNode((node).exprName, visitor, isEntityName)); case SyntaxKind.TypeLiteral: - return updateTypeLiteralNode((node), + return factory.updateTypeLiteralNode((node), nodesVisitor((node).members, visitor, isTypeElement)); case SyntaxKind.ArrayType: - return updateArrayTypeNode(node, + return factory.updateArrayTypeNode(node, visitNode((node).elementType, visitor, isTypeNode)); case SyntaxKind.TupleType: - return updateTupleTypeNode((node), + return factory.updateTupleTypeNode((node), nodesVisitor((node).elementTypes, visitor, isTypeNode)); case SyntaxKind.OptionalType: - return updateOptionalTypeNode((node), + return factory.updateOptionalTypeNode((node), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.RestType: - return updateRestTypeNode((node), + return factory.updateRestTypeNode((node), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.UnionType: - return updateUnionTypeNode(node, + return factory.updateUnionTypeNode(node, nodesVisitor((node).types, visitor, isTypeNode)); case SyntaxKind.IntersectionType: - return updateIntersectionTypeNode(node, + return factory.updateIntersectionTypeNode(node, nodesVisitor((node).types, visitor, isTypeNode)); case SyntaxKind.ConditionalType: - return updateConditionalTypeNode(node, + return factory.updateConditionalTypeNode(node, visitNode((node).checkType, visitor, isTypeNode), visitNode((node).extendsType, visitor, isTypeNode), visitNode((node).trueType, visitor, isTypeNode), visitNode((node).falseType, visitor, isTypeNode)); case SyntaxKind.InferType: - return updateInferTypeNode(node, + return factory.updateInferTypeNode(node, visitNode((node).typeParameter, visitor, isTypeParameterDeclaration)); case SyntaxKind.ImportType: - return updateImportTypeNode(node, + return factory.updateImportTypeNode(node, visitNode((node).argument, visitor, isTypeNode), visitNode((node).qualifier, visitor, isEntityName), visitNodes((node).typeArguments, visitor, isTypeNode), @@ -407,40 +417,40 @@ namespace ts { ); case SyntaxKind.ParenthesizedType: - return updateParenthesizedType(node, + return factory.updateParenthesizedType(node, visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.TypeOperator: - return updateTypeOperatorNode(node, + return factory.updateTypeOperatorNode(node, visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.IndexedAccessType: - return updateIndexedAccessTypeNode((node), + return factory.updateIndexedAccessTypeNode((node), visitNode((node).objectType, visitor, isTypeNode), visitNode((node).indexType, visitor, isTypeNode)); case SyntaxKind.MappedType: - return updateMappedTypeNode((node), + return factory.updateMappedTypeNode((node), visitNode((node).readonlyToken, tokenVisitor, isToken), visitNode((node).typeParameter, visitor, isTypeParameterDeclaration), visitNode((node).questionToken, tokenVisitor, isToken), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.LiteralType: - return updateLiteralTypeNode(node, + return factory.updateLiteralTypeNode(node, visitNode((node).literal, visitor, isExpression)); // Binding patterns case SyntaxKind.ObjectBindingPattern: - return updateObjectBindingPattern(node, + return factory.updateObjectBindingPattern(node, nodesVisitor((node).elements, visitor, isBindingElement)); case SyntaxKind.ArrayBindingPattern: - return updateArrayBindingPattern(node, + return factory.updateArrayBindingPattern(node, nodesVisitor((node).elements, visitor, isArrayBindingElement)); case SyntaxKind.BindingElement: - return updateBindingElement(node, + return factory.updateBindingElement(node, visitNode((node).dotDotDotToken, tokenVisitor, isToken), visitNode((node).propertyName, visitor, isPropertyName), visitNode((node).name, visitor, isBindingName), @@ -448,71 +458,71 @@ namespace ts { // Expression case SyntaxKind.ArrayLiteralExpression: - return updateArrayLiteral(node, + return factory.updateArrayLiteral(node, nodesVisitor((node).elements, visitor, isExpression)); case SyntaxKind.ObjectLiteralExpression: - return updateObjectLiteral(node, + return factory.updateObjectLiteral(node, nodesVisitor((node).properties, visitor, isObjectLiteralElementLike)); case SyntaxKind.PropertyAccessExpression: if (node.flags & NodeFlags.OptionalChain) { - return updatePropertyAccessChain(node, + return factory.updatePropertyAccessChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, visitor, isToken), visitNode((node).name, visitor, isIdentifier)); } - return updatePropertyAccess(node, + return factory.updatePropertyAccess(node, visitNode((node).expression, visitor, isExpression), visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.ElementAccessExpression: if (node.flags & NodeFlags.OptionalChain) { - return updateElementAccessChain(node, + return factory.updateElementAccessChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, visitor, isToken), visitNode((node).argumentExpression, visitor, isExpression)); } - return updateElementAccess(node, + return factory.updateElementAccess(node, visitNode((node).expression, visitor, isExpression), visitNode((node).argumentExpression, visitor, isExpression)); case SyntaxKind.CallExpression: if (node.flags & NodeFlags.OptionalChain) { - return updateCallChain(node, + return factory.updateCallChain(node, visitNode((node).expression, visitor, isExpression), visitNode((node).questionDotToken, visitor, isToken), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); } - return updateCall(node, + return factory.updateCall(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); case SyntaxKind.NewExpression: - return updateNew(node, + return factory.updateNew(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isExpression)); case SyntaxKind.TaggedTemplateExpression: - return updateTaggedTemplate(node, + return factory.updateTaggedTemplate(node, visitNode((node).tag, visitor, isExpression), visitNodes((node).typeArguments, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); case SyntaxKind.TypeAssertionExpression: - return updateTypeAssertion(node, + return factory.updateTypeAssertion(node, visitNode((node).type, visitor, isTypeNode), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ParenthesizedExpression: - return updateParen(node, + return factory.updateParen(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.FunctionExpression: - return updateFunctionExpression(node, + return factory.updateFunctionExpression(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).name, visitor, isIdentifier), @@ -522,7 +532,7 @@ namespace ts { visitFunctionBody((node).body, visitor, context)); case SyntaxKind.ArrowFunction: - return updateArrowFunction(node, + return factory.updateArrowFunction(node, nodesVisitor((node).modifiers, visitor, isModifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), @@ -531,37 +541,37 @@ namespace ts { visitFunctionBody((node).body, visitor, context)); case SyntaxKind.DeleteExpression: - return updateDelete(node, + return factory.updateDelete(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.TypeOfExpression: - return updateTypeOf(node, + return factory.updateTypeOf(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.VoidExpression: - return updateVoid(node, + return factory.updateVoid(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.AwaitExpression: - return updateAwait(node, + return factory.updateAwait(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.PrefixUnaryExpression: - return updatePrefix(node, + return factory.updatePrefix(node, visitNode((node).operand, visitor, isExpression)); case SyntaxKind.PostfixUnaryExpression: - return updatePostfix(node, + return factory.updatePostfix(node, visitNode((node).operand, visitor, isExpression)); case SyntaxKind.BinaryExpression: - return updateBinary(node, + return factory.updateBinary(node, visitNode((node).left, visitor, isExpression), visitNode((node).right, visitor, isExpression), visitNode((node).operatorToken, visitor, isToken)); case SyntaxKind.ConditionalExpression: - return updateConditional(node, + return factory.updateConditional(node, visitNode((node).condition, visitor, isExpression), visitNode((node).questionToken, visitor, isToken), visitNode((node).whenTrue, visitor, isExpression), @@ -569,150 +579,152 @@ namespace ts { visitNode((node).whenFalse, visitor, isExpression)); case SyntaxKind.TemplateExpression: - return updateTemplateExpression(node, + return factory.updateTemplateExpression(node, visitNode((node).head, visitor, isTemplateHead), nodesVisitor((node).templateSpans, visitor, isTemplateSpan)); case SyntaxKind.YieldExpression: - return updateYield(node, + return factory.updateYield(node, visitNode((node).asteriskToken, tokenVisitor, isToken), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.SpreadElement: - return updateSpread(node, + return factory.updateSpread(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ClassExpression: - return updateClassExpression(node, - nodesVisitor((node).modifiers, visitor, isModifier), + return factory.updateClassExpression(node, + nodesVisitor((node).decorators, visitor, isDecorator), + nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor((node).heritageClauses, visitor, isHeritageClause), nodesVisitor((node).members, visitor, isClassElement)); case SyntaxKind.ExpressionWithTypeArguments: - return updateExpressionWithTypeArguments(node, - nodesVisitor((node).typeArguments, visitor, isTypeNode), - visitNode((node).expression, visitor, isExpression)); + return factory.updateExpressionWithTypeArguments(node, + visitNode((node).expression, visitor, isExpression), + nodesVisitor((node).typeArguments, visitor, isTypeNode)); case SyntaxKind.AsExpression: - return updateAsExpression(node, + return factory.updateAsExpression(node, visitNode((node).expression, visitor, isExpression), visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.NonNullExpression: - return updateNonNullExpression(node, + return factory.updateNonNullExpression(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.MetaProperty: - return updateMetaProperty(node, + return factory.updateMetaProperty(node, visitNode((node).name, visitor, isIdentifier)); // Misc case SyntaxKind.TemplateSpan: - return updateTemplateSpan(node, + return factory.updateTemplateSpan(node, visitNode((node).expression, visitor, isExpression), visitNode((node).literal, visitor, isTemplateMiddleOrTemplateTail)); // Element case SyntaxKind.Block: - return updateBlock(node, + return factory.updateBlock(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.VariableStatement: - return updateVariableStatement(node, + return factory.updateVariableStatement(node, nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).declarationList, visitor, isVariableDeclarationList)); case SyntaxKind.ExpressionStatement: - return updateExpressionStatement(node, + return factory.updateExpressionStatement(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.IfStatement: - return updateIf(node, + return factory.updateIf(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).thenStatement, visitor, isStatement, liftToBlock), - visitNode((node).elseStatement, visitor, isStatement, liftToBlock)); + visitNode((node).thenStatement, visitor, isStatement, factory.liftToBlock), + visitNode((node).elseStatement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.DoStatement: - return updateDo(node, - visitNode((node).statement, visitor, isStatement, liftToBlock), + return factory.updateDo(node, + visitNode((node).statement, visitor, isStatement, factory.liftToBlock), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.WhileStatement: - return updateWhile(node, + return factory.updateWhile(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.ForStatement: - return updateFor(node, + return factory.updateFor(node, visitNode((node).initializer, visitor, isForInitializer), visitNode((node).condition, visitor, isExpression), visitNode((node).incrementor, visitor, isExpression), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.ForInStatement: - return updateForIn(node, + return factory.updateForIn(node, visitNode((node).initializer, visitor, isForInitializer), visitNode((node).expression, visitor, isExpression), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.ForOfStatement: - return updateForOf(node, + return factory.updateForOf(node, visitNode((node).awaitModifier, visitor, isToken), visitNode((node).initializer, visitor, isForInitializer), visitNode((node).expression, visitor, isExpression), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.ContinueStatement: - return updateContinue(node, + return factory.updateContinue(node, visitNode((node).label, visitor, isIdentifier)); case SyntaxKind.BreakStatement: - return updateBreak(node, + return factory.updateBreak(node, visitNode((node).label, visitor, isIdentifier)); case SyntaxKind.ReturnStatement: - return updateReturn(node, + return factory.updateReturn(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.WithStatement: - return updateWith(node, + return factory.updateWith(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.SwitchStatement: - return updateSwitch(node, + return factory.updateSwitch(node, visitNode((node).expression, visitor, isExpression), visitNode((node).caseBlock, visitor, isCaseBlock)); case SyntaxKind.LabeledStatement: - return updateLabel(node, + return factory.updateLabel(node, visitNode((node).label, visitor, isIdentifier), - visitNode((node).statement, visitor, isStatement, liftToBlock)); + visitNode((node).statement, visitor, isStatement, factory.liftToBlock)); case SyntaxKind.ThrowStatement: - return updateThrow(node, + return factory.updateThrow(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.TryStatement: - return updateTry(node, + return factory.updateTry(node, visitNode((node).tryBlock, visitor, isBlock), visitNode((node).catchClause, visitor, isCatchClause), visitNode((node).finallyBlock, visitor, isBlock)); case SyntaxKind.VariableDeclaration: - return updateVariableDeclaration(node, + return factory.updateVariableDeclaration(node, visitNode((node).name, visitor, isBindingName), + visitNode((node).exclamationToken, visitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.VariableDeclarationList: - return updateVariableDeclarationList(node, + return factory.updateVariableDeclarationList(node, nodesVisitor((node).declarations, visitor, isVariableDeclaration)); case SyntaxKind.FunctionDeclaration: - return updateFunctionDeclaration(node, + return factory.updateFunctionDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).asteriskToken, tokenVisitor, isToken), @@ -723,7 +735,7 @@ namespace ts { visitFunctionBody((node).body, visitor, context)); case SyntaxKind.ClassDeclaration: - return updateClassDeclaration(node, + return factory.updateClassDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), @@ -732,7 +744,7 @@ namespace ts { nodesVisitor((node).members, visitor, isClassElement)); case SyntaxKind.InterfaceDeclaration: - return updateInterfaceDeclaration(node, + return factory.updateInterfaceDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), @@ -741,7 +753,7 @@ namespace ts { nodesVisitor((node).members, visitor, isTypeElement)); case SyntaxKind.TypeAliasDeclaration: - return updateTypeAliasDeclaration(node, + return factory.updateTypeAliasDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), @@ -749,188 +761,188 @@ namespace ts { visitNode((node).type, visitor, isTypeNode)); case SyntaxKind.EnumDeclaration: - return updateEnumDeclaration(node, + return factory.updateEnumDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), nodesVisitor((node).members, visitor, isEnumMember)); case SyntaxKind.ModuleDeclaration: - return updateModuleDeclaration(node, + return factory.updateModuleDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), visitNode((node).body, visitor, isModuleBody)); case SyntaxKind.ModuleBlock: - return updateModuleBlock(node, + return factory.updateModuleBlock(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.CaseBlock: - return updateCaseBlock(node, + return factory.updateCaseBlock(node, nodesVisitor((node).clauses, visitor, isCaseOrDefaultClause)); case SyntaxKind.NamespaceExportDeclaration: - return updateNamespaceExportDeclaration(node, + return factory.updateNamespaceExportDeclaration(node, visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.ImportEqualsDeclaration: - return updateImportEqualsDeclaration(node, + return factory.updateImportEqualsDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isIdentifier), visitNode((node).moduleReference, visitor, isModuleReference)); case SyntaxKind.ImportDeclaration: - return updateImportDeclaration(node, + return factory.updateImportDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).importClause, visitor, isImportClause), visitNode((node).moduleSpecifier, visitor, isExpression)); case SyntaxKind.ImportClause: - return updateImportClause(node, + return factory.updateImportClause(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).namedBindings, visitor, isNamedImportBindings)); case SyntaxKind.NamespaceImport: - return updateNamespaceImport(node, + return factory.updateNamespaceImport(node, visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.NamedImports: - return updateNamedImports(node, + return factory.updateNamedImports(node, nodesVisitor((node).elements, visitor, isImportSpecifier)); case SyntaxKind.ImportSpecifier: - return updateImportSpecifier(node, + return factory.updateImportSpecifier(node, visitNode((node).propertyName, visitor, isIdentifier), visitNode((node).name, visitor, isIdentifier)); case SyntaxKind.ExportAssignment: - return updateExportAssignment(node, + return factory.updateExportAssignment(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).expression, visitor, isExpression)); case SyntaxKind.ExportDeclaration: - return updateExportDeclaration(node, + return factory.updateExportDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).exportClause, visitor, isNamedExports), visitNode((node).moduleSpecifier, visitor, isExpression)); case SyntaxKind.NamedExports: - return updateNamedExports(node, + return factory.updateNamedExports(node, nodesVisitor((node).elements, visitor, isExportSpecifier)); case SyntaxKind.ExportSpecifier: - return updateExportSpecifier(node, + return factory.updateExportSpecifier(node, visitNode((node).propertyName, visitor, isIdentifier), visitNode((node).name, visitor, isIdentifier)); // Module references case SyntaxKind.ExternalModuleReference: - return updateExternalModuleReference(node, + return factory.updateExternalModuleReference(node, visitNode((node).expression, visitor, isExpression)); // JSX case SyntaxKind.JsxElement: - return updateJsxElement(node, + return factory.updateJsxElement(node, visitNode((node).openingElement, visitor, isJsxOpeningElement), nodesVisitor((node).children, visitor, isJsxChild), visitNode((node).closingElement, visitor, isJsxClosingElement)); case SyntaxKind.JsxSelfClosingElement: - return updateJsxSelfClosingElement(node, + return factory.updateJsxSelfClosingElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), visitNode((node).attributes, visitor, isJsxAttributes)); case SyntaxKind.JsxOpeningElement: - return updateJsxOpeningElement(node, + return factory.updateJsxOpeningElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression), nodesVisitor((node).typeArguments, visitor, isTypeNode), visitNode((node).attributes, visitor, isJsxAttributes)); case SyntaxKind.JsxClosingElement: - return updateJsxClosingElement(node, + return factory.updateJsxClosingElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression)); case SyntaxKind.JsxFragment: - return updateJsxFragment(node, + return factory.updateJsxFragment(node, visitNode((node).openingFragment, visitor, isJsxOpeningFragment), nodesVisitor((node).children, visitor, isJsxChild), visitNode((node).closingFragment, visitor, isJsxClosingFragment)); case SyntaxKind.JsxAttribute: - return updateJsxAttribute(node, + return factory.updateJsxAttribute(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).initializer, visitor, isStringLiteralOrJsxExpression)); case SyntaxKind.JsxAttributes: - return updateJsxAttributes(node, + return factory.updateJsxAttributes(node, nodesVisitor((node).properties, visitor, isJsxAttributeLike)); case SyntaxKind.JsxSpreadAttribute: - return updateJsxSpreadAttribute(node, + return factory.updateJsxSpreadAttribute(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.JsxExpression: - return updateJsxExpression(node, + return factory.updateJsxExpression(node, visitNode((node).expression, visitor, isExpression)); // Clauses case SyntaxKind.CaseClause: - return updateCaseClause(node, + return factory.updateCaseClause(node, visitNode((node).expression, visitor, isExpression), nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.DefaultClause: - return updateDefaultClause(node, + return factory.updateDefaultClause(node, nodesVisitor((node).statements, visitor, isStatement)); case SyntaxKind.HeritageClause: - return updateHeritageClause(node, + return factory.updateHeritageClause(node, nodesVisitor((node).types, visitor, isExpressionWithTypeArguments)); case SyntaxKind.CatchClause: - return updateCatchClause(node, + return factory.updateCatchClause(node, visitNode((node).variableDeclaration, visitor, isVariableDeclaration), visitNode((node).block, visitor, isBlock)); // Property assignments case SyntaxKind.PropertyAssignment: - return updatePropertyAssignment(node, + return factory.updatePropertyAssignment(node, visitNode((node).name, visitor, isPropertyName), visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.ShorthandPropertyAssignment: - return updateShorthandPropertyAssignment(node, + return factory.updateShorthandPropertyAssignment(node, visitNode((node).name, visitor, isIdentifier), visitNode((node).objectAssignmentInitializer, visitor, isExpression)); case SyntaxKind.SpreadAssignment: - return updateSpreadAssignment(node, + return factory.updateSpreadAssignment(node, visitNode((node).expression, visitor, isExpression)); // Enum case SyntaxKind.EnumMember: - return updateEnumMember(node, + return factory.updateEnumMember(node, visitNode((node).name, visitor, isPropertyName), visitNode((node).initializer, visitor, isExpression)); // Top-level nodes case SyntaxKind.SourceFile: - return updateSourceFileNode(node, + return factory.updateSourceFile(node, visitLexicalEnvironment((node).statements, visitor, context)); // Transformation nodes case SyntaxKind.PartiallyEmittedExpression: - return updatePartiallyEmittedExpression(node, + return factory.updatePartiallyEmittedExpression(node, visitNode((node).expression, visitor, isExpression)); case SyntaxKind.CommaListExpression: - return updateCommaList(node, + return factory.updateCommaList(node, nodesVisitor((node).elements, visitor, isExpression)); default: @@ -1472,19 +1484,19 @@ namespace ts { /** * Merges generated lexical declarations into a new statement list. */ - export function mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined): NodeArray; + export function mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined, factory?: NodeFactory): NodeArray; /** * Appends generated lexical declarations to an array of statements. */ - export function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[]; - export function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: readonly Statement[] | undefined) { + export function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined, factory?: NodeFactory): Statement[]; + export function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: readonly Statement[] | undefined, factory = ts.factory) { if (!some(declarations)) { return statements; } return isNodeArray(statements) - ? setTextRange(createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements) + ? setTextRange(factory.createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements) : insertStatementsAfterStandardPrologue(statements, declarations); } @@ -1493,74 +1505,8 @@ namespace ts { * * @param nodes The NodeArray. */ - export function liftToBlock(nodes: readonly Node[]): Statement { + export function liftToBlock(nodes: readonly Node[], factory = ts.factory): Statement { Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block."); - return singleOrUndefined(nodes) || createBlock(>nodes); - } - - /** - * Aggregates the TransformFlags for a Node and its subtree. - */ - export function aggregateTransformFlags(node: T): T { - aggregateTransformFlagsForNode(node); - return node; - } - - /** - * Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are - * computed first, then the transform flags for the current node are computed from the subtree - * flags and the state of the current node. Finally, the transform flags of the node are - * returned, excluding any flags that should not be included in its parent node's subtree - * flags. - */ - function aggregateTransformFlagsForNode(node: Node): TransformFlags { - if (node === undefined) { - return TransformFlags.None; - } - if (node.transformFlags & TransformFlags.HasComputedFlags) { - return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); - } - const subtreeFlags = aggregateTransformFlagsForSubtree(node); - return computeTransformFlagsForNode(node, subtreeFlags); - } - - function aggregateTransformFlagsForNodeArray(nodes: NodeArray): TransformFlags { - if (nodes === undefined) { - return TransformFlags.None; - } - let subtreeFlags = TransformFlags.None; - let nodeArrayFlags = TransformFlags.None; - for (const node of nodes) { - subtreeFlags |= aggregateTransformFlagsForNode(node); - nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags; - } - nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags; - return subtreeFlags; - } - - /** - * Aggregates the transform flags for the subtree of a node. - */ - function aggregateTransformFlagsForSubtree(node: Node): TransformFlags { - // We do not transform ambient declarations or types, so there is no need to - // recursively aggregate transform flags. - if (hasModifier(node, ModifierFlags.Ambient) || (isTypeNode(node) && node.kind !== SyntaxKind.ExpressionWithTypeArguments)) { - return TransformFlags.None; - } - - // Aggregate the transform flags of each child. - return reduceEachChild(node, TransformFlags.None, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes); - } - - /** - * Aggregates the TransformFlags of a child node with the TransformFlags of its - * siblings. - */ - function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, node: Node): TransformFlags { - return transformFlags | aggregateTransformFlagsForNode(node); - } - - function aggregateTransformFlagsForChildNodes(transformFlags: TransformFlags, nodes: NodeArray): TransformFlags { - return transformFlags | aggregateTransformFlagsForNodeArray(nodes); + return singleOrUndefined(nodes) || factory.createBlock(>nodes); } } diff --git a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts index c70de5033034e..40d00549a90d8 100644 --- a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts +++ b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts @@ -14,10 +14,10 @@ namespace ts.codefix { function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) { const token = getTokenAtPosition(sourceFile, pos); - const assertion = Debug.assertDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertion(n)), "Expected to find an assertion expression"); + const assertion = Debug.assertDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertionExpression(n)), "Expected to find an assertion expression"); const replacement = isAsExpression(assertion) - ? createAsExpression(assertion.expression, createKeywordTypeNode(SyntaxKind.UnknownKeyword)) - : createTypeAssertion(createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression); + ? factory.createAsExpression(assertion.expression, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)) + : factory.createTypeAssertion(factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression); changeTracker.replaceNode(sourceFile, assertion.expression, replacement); } } diff --git a/src/services/codefixes/addMissingAwait.ts b/src/services/codefixes/addMissingAwait.ts index 96cf09ed08a75..3db74e1547063 100644 --- a/src/services/codefixes/addMissingAwait.ts +++ b/src/services/codefixes/addMissingAwait.ts @@ -242,7 +242,7 @@ namespace ts.codefix { } } const type = checker.getTypeAtLocation(side); - const newNode = checker.getPromisedTypeOfPromise(type) ? createAwait(side) : side; + const newNode = checker.getPromisedTypeOfPromise(type) ? factory.createAwait(side) : side; changeTracker.replaceNode(sourceFile, side, newNode); } } @@ -256,7 +256,7 @@ namespace ts.codefix { changeTracker.replaceNode( sourceFile, insertionSite.parent.expression, - createParen(createAwait(insertionSite.parent.expression))); + factory.createParen(factory.createAwait(insertionSite.parent.expression))); insertLeadingSemicolonIfNeeded(changeTracker, insertionSite.parent.expression, sourceFile); } else if (contains(callableConstructableErrorCodes, errorCode) && isCallOrNewExpression(insertionSite.parent)) { @@ -266,7 +266,7 @@ namespace ts.codefix { return; } } - changeTracker.replaceNode(sourceFile, insertionSite, createParen(createAwait(insertionSite))); + changeTracker.replaceNode(sourceFile, insertionSite, factory.createParen(factory.createAwait(insertionSite))); insertLeadingSemicolonIfNeeded(changeTracker, insertionSite, sourceFile); } else { @@ -276,7 +276,7 @@ namespace ts.codefix { return; } } - changeTracker.replaceNode(sourceFile, insertionSite, createAwait(insertionSite)); + changeTracker.replaceNode(sourceFile, insertionSite, factory.createAwait(insertionSite)); } } diff --git a/src/services/codefixes/addMissingInvocationForDecorator.ts b/src/services/codefixes/addMissingInvocationForDecorator.ts index 25100870623db..4e5190ba571a9 100644 --- a/src/services/codefixes/addMissingInvocationForDecorator.ts +++ b/src/services/codefixes/addMissingInvocationForDecorator.ts @@ -16,7 +16,7 @@ namespace ts.codefix { const token = getTokenAtPosition(sourceFile, pos); const decorator = findAncestor(token, isDecorator)!; Debug.assert(!!decorator, "Expected position to be owned by a decorator."); - const replacement = createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + const replacement = factory.createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); changeTracker.replaceNode(sourceFile, decorator.expression, replacement); } } diff --git a/src/services/codefixes/addNameToNamelessParameter.ts b/src/services/codefixes/addNameToNamelessParameter.ts index 3339f71900845..07bc1bea7e3c6 100644 --- a/src/services/codefixes/addNameToNamelessParameter.ts +++ b/src/services/codefixes/addNameToNamelessParameter.ts @@ -24,13 +24,13 @@ namespace ts.codefix { const i = param.parent.parameters.indexOf(param); Debug.assert(!param.type, "Tried to add a parameter name to a parameter that already had one."); Debug.assert(i > -1, "Parameter not found in parent parameter list."); - const replacement = createParameter( + const replacement = factory.createParameterDeclaration( /*decorators*/ undefined, param.modifiers, param.dotDotDotToken, "arg" + i, param.questionToken, - createTypeReferenceNode(token, /*typeArguments*/ undefined), + factory.createTypeReferenceNode(token, /*typeArguments*/ undefined), param.initializer); changeTracker.replaceNode(sourceFile, token, replacement); } diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index 3428a60201fd9..c55a0d0f4b42c 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -46,14 +46,14 @@ namespace ts.codefix { if (typeParameters.length) changes.insertTypeParameters(sourceFile, decl, typeParameters); } const needParens = isArrowFunction(decl) && !findChildOfKind(decl, SyntaxKind.OpenParenToken, sourceFile); - if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), createToken(SyntaxKind.OpenParenToken)); + if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), factory.createToken(SyntaxKind.OpenParenToken)); for (const param of decl.parameters) { if (!param.type) { const paramType = getJSDocType(param); if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, transformJSDocType(paramType)); } } - if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), createToken(SyntaxKind.CloseParenToken)); + if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), factory.createToken(SyntaxKind.CloseParenToken)); if (!decl.type) { const returnType = getJSDocReturnType(decl); if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType)); @@ -77,7 +77,7 @@ namespace ts.codefix { switch (node.kind) { case SyntaxKind.JSDocAllType: case SyntaxKind.JSDocUnknownType: - return createTypeReferenceNode("any", emptyArray); + return factory.createTypeReferenceNode("any", emptyArray); case SyntaxKind.JSDocOptionalType: return transformJSDocOptionalType(node as JSDocOptionalType); case SyntaxKind.JSDocNonNullableType: @@ -91,34 +91,34 @@ namespace ts.codefix { case SyntaxKind.TypeReference: return transformJSDocTypeReference(node as TypeReferenceNode); default: - const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined!); // TODO: GH#18217 + const visited = visitEachChild(node, transformJSDocType, nullTransformationContext); setEmitFlags(visited, EmitFlags.SingleLine); return visited; } } function transformJSDocOptionalType(node: JSDocOptionalType) { - return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("undefined", emptyArray)]); + return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("undefined", emptyArray)]); } function transformJSDocNullableType(node: JSDocNullableType) { - return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("null", emptyArray)]); + return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("null", emptyArray)]); } function transformJSDocVariadicType(node: JSDocVariadicType) { - return createArrayTypeNode(visitNode(node.type, transformJSDocType)); + return factory.createArrayTypeNode(visitNode(node.type, transformJSDocType)); } function transformJSDocFunctionType(node: JSDocFunctionType) { - return createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type); + return factory.createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type); } function transformJSDocParameter(node: ParameterDeclaration) { const index = node.parent.parameters.indexOf(node); const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217 const name = node.name || (isRest ? "rest" : "arg" + index); - const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken; - return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer); + const dotdotdot = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken; + return factory.createParameterDeclaration(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer); } function transformJSDocTypeReference(node: TypeReferenceNode) { @@ -142,27 +142,27 @@ namespace ts.codefix { text = text[0].toUpperCase() + text.slice(1); break; } - name = createIdentifier(text); + name = factory.createIdentifier(text); if ((text === "Array" || text === "Promise") && !node.typeArguments) { - args = createNodeArray([createTypeReferenceNode("any", emptyArray)]); + args = factory.createNodeArray([factory.createTypeReferenceNode("any", emptyArray)]); } else { args = visitNodes(node.typeArguments, transformJSDocType); } } - return createTypeReferenceNode(name, args); + return factory.createTypeReferenceNode(name, args); } function transformJSDocIndexSignature(node: TypeReferenceNode) { - const index = createParameter( + const index = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "n" : "s", /*questionToken*/ undefined, - createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), + factory.createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), /*initializer*/ undefined); - const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]); + const indexSignature = factory.createTypeLiteralNode([factory.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]); setEmitFlags(indexSignature, EmitFlags.SingleLine); return indexSignature; } diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index 0769cb26162b7..712e02a258ec2 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -68,7 +68,7 @@ namespace ts.codefix { // all static members are stored in the "exports" array of symbol if (symbol.exports) { symbol.exports.forEach(member => { - const memberElement = createClassElement(member, [createToken(SyntaxKind.StaticKeyword)]); + const memberElement = createClassElement(member, [factory.createToken(SyntaxKind.StaticKeyword)]); if (memberElement) { memberElements.push(memberElement); } @@ -102,7 +102,7 @@ namespace ts.codefix { changes.delete(sourceFile, nodeToDelete); if (!assignmentBinaryExpression.right) { - return createProperty([], modifiers, symbol.name, /*questionToken*/ undefined, + return factory.createPropertyDeclaration([], modifiers, symbol.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined); } @@ -110,7 +110,7 @@ namespace ts.codefix { case SyntaxKind.FunctionExpression: { const functionExpression = assignmentBinaryExpression.right as FunctionExpression; const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword)); - const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + const method = factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; @@ -127,10 +127,10 @@ namespace ts.codefix { } // case 2: () => [1,2,3] else { - bodyBlock = createBlock([createReturn(arrowFunctionBody)]); + bodyBlock = factory.createBlock([factory.createReturn(arrowFunctionBody)]); } const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword)); - const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + const method = factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); copyLeadingComments(assignmentBinaryExpression, method, sourceFile); return method; @@ -141,7 +141,7 @@ namespace ts.codefix { if (isSourceFileJS(sourceFile)) { return; } - const prop = createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, + const prop = factory.createPropertyDeclaration(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentBinaryExpression.right); copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; @@ -162,11 +162,11 @@ namespace ts.codefix { const memberElements = createClassElementsFromSymbol(node.symbol); if (initializer.body) { - memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); + memberElements.unshift(factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } const modifiers = getModifierKindFromSource(precedingNode!, SyntaxKind.ExportKeyword); - const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + const cls = factory.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place return cls; @@ -175,11 +175,11 @@ namespace ts.codefix { function createClassFromFunctionDeclaration(node: FunctionDeclaration): ClassDeclaration { const memberElements = createClassElementsFromSymbol(ctorSymbol); if (node.body) { - memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); + memberElements.unshift(factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } const modifiers = getModifierKindFromSource(node, SyntaxKind.ExportKeyword); - const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + const cls = factory.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place return cls; diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 935f665440925..20a9381b98b8a 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -197,7 +197,7 @@ namespace ts.codefix { // Note - the choice of the last call signature is arbitrary if (lastCallSignature && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) { const firstParameter = firstOrUndefined(lastCallSignature.parameters); - const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); + const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || factory.createOptimisticUniqueName("result"); const synthName = getNewNameIfConflict(ident, collidingSymbolMap); synthNamesMap.set(symbolIdString, synthName); allVarNames.push({ identifier: synthName.identifier, symbol }); @@ -275,7 +275,7 @@ namespace ts.codefix { function getNewNameIfConflict(name: Identifier, originalNames: ReadonlyMap): SynthIdentifier { const numVarsSameName = (originalNames.get(name.text) || emptyArray).length; const numberOfAssignmentsOriginal = 0; - const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName); + const identifier = numVarsSameName === 0 ? name : factory.createIdentifier(name.text + "_" + numVarsSameName); return createSynthIdentifier(identifier, [], numberOfAssignmentsOriginal); } @@ -328,7 +328,7 @@ namespace ts.codefix { }); } else { - possibleNameForVarDecl = createSynthIdentifier(createOptimisticUniqueName("result"), prevArgName.types); + possibleNameForVarDecl = createSynthIdentifier(factory.createOptimisticUniqueName("result"), prevArgName.types); } possibleNameForVarDecl.numberOfAssignmentsOriginal = 2; // Try block and catch block @@ -338,12 +338,12 @@ namespace ts.codefix { } } - const tryBlock = createBlock(transformExpression(node.expression, transformer, node, possibleNameForVarDecl)); + const tryBlock = factory.createBlock(transformExpression(node.expression, transformer, node, possibleNameForVarDecl)); const transformationBody = getTransformationBody(func, possibleNameForVarDecl, argName, node, transformer); const catchArg = argName ? isSynthIdentifier(argName) ? argName.identifier.text : argName.bindingPattern : "e"; - const catchVariableDeclaration = createVariableDeclaration(catchArg); - const catchClause = createCatchClause(catchVariableDeclaration, createBlock(transformationBody)); + const catchVariableDeclaration = factory.createVariableDeclaration(catchArg); + const catchClause = factory.createCatchClause(catchVariableDeclaration, factory.createBlock(transformationBody)); /* In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block) @@ -355,13 +355,13 @@ namespace ts.codefix { const typeArray: Type[] = possibleNameForVarDecl.types; const unionType = transformer.checker.getUnionType(typeArray, UnionReduction.Subtype); const unionTypeNode = transformer.isInJSFile ? undefined : transformer.checker.typeToTypeNode(unionType); - const varDecl = [createVariableDeclaration(varDeclIdentifier, unionTypeNode)]; - varDeclList = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList(varDecl, NodeFlags.Let)); + const varDecl = [factory.createVariableDeclaration(varDeclIdentifier, /*exclamationToken*/ undefined, unionTypeNode)]; + varDeclList = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList(varDecl, NodeFlags.Let)); } - const tryStatement = createTry(tryBlock, catchClause, /*finallyBlock*/ undefined); + const tryStatement = factory.createTry(tryBlock, catchClause, /*finallyBlock*/ undefined); const destructuredResult = prevArgName && varDeclIdentifier && isSynthBindingPattern(prevArgName) - && createVariableStatement(/* modifiers */ undefined, createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepCloneWithRenames(prevArgName.bindingPattern), /* type */ undefined, varDeclIdentifier)], NodeFlags.Const)); + && factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(getSynthesizedDeepCloneWithRenames(prevArgName.bindingPattern), /*exclamationToken*/ undefined, /*type*/ undefined, varDeclIdentifier)], NodeFlags.Const)); return compact([varDeclList, tryStatement, destructuredResult]); } @@ -374,7 +374,7 @@ namespace ts.codefix { } function createUniqueSynthName(prevArgName: SynthIdentifier): SynthIdentifier { - const renamedPrevArg = createOptimisticUniqueName(prevArgName.identifier.text); + const renamedPrevArg = factory.createOptimisticUniqueName(prevArgName.identifier.text); return createSynthIdentifier(renamedPrevArg); } @@ -391,15 +391,15 @@ namespace ts.codefix { if (rej) { const argNameRej = getArgBindingName(rej, transformer); - const tryBlock = createBlock(transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody)); + const tryBlock = factory.createBlock(transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody)); const transformationBody2 = getTransformationBody(rej, prevArgName, argNameRej, node, transformer); const catchArg = argNameRej ? isSynthIdentifier(argNameRej) ? argNameRej.identifier.text : argNameRej.bindingPattern : "e"; - const catchVariableDeclaration = createVariableDeclaration(catchArg); - const catchClause = createCatchClause(catchVariableDeclaration, createBlock(transformationBody2)); + const catchVariableDeclaration = factory.createVariableDeclaration(catchArg); + const catchClause = factory.createCatchClause(catchVariableDeclaration, factory.createBlock(transformationBody2)); - return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined)]; + return [factory.createTry(tryBlock, catchClause, /* finallyBlock */ undefined)]; } return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody); @@ -416,28 +416,28 @@ namespace ts.codefix { // the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call const originalNodeParent = node.original ? node.original.parent : node.parent; if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { - return createTransformedStatement(prevArgName, createAwait(node), transformer); + return createTransformedStatement(prevArgName, factory.createAwait(node), transformer); } else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) { - return [createStatement(createAwait(node))]; + return [factory.createExpressionStatement(factory.createAwait(node))]; } - return [createReturn(getSynthesizedDeepClone(node))]; + return [factory.createReturn(getSynthesizedDeepClone(node))]; } function createTransformedStatement(prevArgName: SynthBindingName | undefined, rightHandSide: Expression, transformer: Transformer): readonly Statement[] { if (!prevArgName || isEmpty(prevArgName)) { // if there's no argName to assign to, there still might be side effects - return [createStatement(rightHandSide)]; + return [factory.createExpressionStatement(rightHandSide)]; } if (isSynthIdentifier(prevArgName) && prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) { // if the variable has already been declared, we don't need "let" or "const" - return [createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]; + return [factory.createExpressionStatement(factory.createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]; } - return [createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(getNode(prevArgName)), /*type*/ undefined, rightHandSide)], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))]; + return [factory.createVariableStatement(/*modifiers*/ undefined, + (factory.createVariableDeclarationList([factory.createVariableDeclaration(getSynthesizedDeepClone(getNode(prevArgName)), /*exclamationToken*/ undefined, /*type*/ undefined, rightHandSide)], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))]; } // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts @@ -454,9 +454,9 @@ namespace ts.codefix { break; } - const synthCall = createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, isSynthIdentifier(argName) ? [argName.identifier] : []); + const synthCall = factory.createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, isSynthIdentifier(argName) ? [argName.identifier] : []); if (shouldReturn) { - return [createReturn(synthCall)]; + return [factory.createReturn(synthCall)]; } const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func); @@ -467,7 +467,7 @@ namespace ts.codefix { break; } const returnType = callSignatures[0].getReturnType(); - const varDeclOrAssignment = createTransformedStatement(prevArgName, createAwait(synthCall), transformer); + const varDeclOrAssignment = createTransformedStatement(prevArgName, factory.createAwait(synthCall), transformer); if (prevArgName) { prevArgName.types.push(returnType); } @@ -502,7 +502,7 @@ namespace ts.codefix { seenReturnStatement); } else { - const innerRetStmts = isFixablePromiseHandler(funcBody) ? [createReturn(funcBody)] : emptyArray; + const innerRetStmts = isFixablePromiseHandler(funcBody) ? [factory.createReturn(funcBody)] : emptyArray; const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName); if (innerCbBody.length > 0) { @@ -512,7 +512,7 @@ namespace ts.codefix { const type = transformer.checker.getTypeAtLocation(func); const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); const rightHandSide = getSynthesizedDeepClone(funcBody); - const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? createAwait(rightHandSide) : rightHandSide; + const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? factory.createAwait(rightHandSide) : rightHandSide; if (!shouldReturn) { const transformedStatement = createTransformedStatement(prevArgName, possiblyAwaitedRightHandSide, transformer); if (prevArgName) { @@ -521,7 +521,7 @@ namespace ts.codefix { return transformedStatement; } else { - return [createReturn(possiblyAwaitedRightHandSide)]; + return [factory.createReturn(possiblyAwaitedRightHandSide)]; } } } @@ -544,13 +544,13 @@ namespace ts.codefix { for (const stmt of stmts) { if (isReturnStatement(stmt)) { if (stmt.expression) { - const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression; + const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? factory.createAwait(stmt.expression) : stmt.expression; if (prevArgName === undefined) { - ret.push(createExpressionStatement(possiblyAwaitedExpression)); + ret.push(factory.createExpressionStatement(possiblyAwaitedExpression)); } else { - ret.push(createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))); + ret.push(factory.createVariableStatement(/*modifiers*/ undefined, + (factory.createVariableDeclarationList([factory.createVariableDeclaration(getNode(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))); } } } @@ -561,8 +561,8 @@ namespace ts.codefix { // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables if (!seenReturnStatement && prevArgName !== undefined) { - ret.push(createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, createIdentifier("undefined"))], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))); + ret.push(factory.createVariableStatement(/*modifiers*/ undefined, + (factory.createVariableDeclarationList([factory.createVariableDeclaration(getNode(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, factory.createIdentifier("undefined"))], getFlagOfBindingName(prevArgName, transformer.constIdentifiers))))); } return ret; diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 25c42288355f3..4b81ae71a42a4 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -31,7 +31,7 @@ namespace ts.codefix { break; case SyntaxKind.CallExpression: if (isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) { - changes.replaceNode(importingFile, importNode, createPropertyAccess(getSynthesizedDeepClone(importNode), "default")); + changes.replaceNode(importingFile, importNode, factory.createPropertyAccess(getSynthesizedDeepClone(importNode), "default")); } break; } @@ -81,7 +81,7 @@ namespace ts.codefix { return; } const { text } = node.name; - changes.replaceNode(sourceFile, node, createIdentifier(exports.get(text) || text)); + changes.replaceNode(sourceFile, node, factory.createIdentifier(exports.get(text) || text)); }); } @@ -154,7 +154,7 @@ namespace ts.codefix { } } // Move it out to its own variable statement. (This will not be used if `!foundImport`) - return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([decl], declarationList.flags)); + return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([decl], declarationList.flags)); }); if (foundImport) { // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement. @@ -171,7 +171,7 @@ namespace ts.codefix { const tmp = makeUniqueName(propertyName, identifiers); return [ makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference), - makeConst(/*modifiers*/ undefined, name, createIdentifier(tmp)), + makeConst(/*modifiers*/ undefined, name, factory.createIdentifier(tmp)), ]; } case SyntaxKind.Identifier: @@ -237,7 +237,7 @@ namespace ts.codefix { case SyntaxKind.PropertyAssignment: return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer); case SyntaxKind.MethodDeclaration: - return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [createToken(SyntaxKind.ExportKeyword)], prop); + return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [factory.createToken(SyntaxKind.ExportKeyword)], prop); default: Debug.assertNever(prop, `Convert to ES6 got invalid prop kind ${(prop as ObjectLiteralElementLike).kind}`); } @@ -261,7 +261,7 @@ namespace ts.codefix { */ const newNodes = [ makeConst(/*modifiers*/ undefined, rename, assignment.right), - makeExportDeclaration([createExportSpecifier(rename, text)]), + makeExportDeclaration([factory.createExportSpecifier(rename, text)]), ]; changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes); } @@ -284,14 +284,14 @@ namespace ts.codefix { return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier); } function reExportDefault(moduleSpecifier: string): ExportDeclaration { - return makeExportDeclaration([createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier); + return makeExportDeclaration([factory.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier); } function convertExportsPropertyAssignment({ left, right, parent }: BinaryExpression & { left: PropertyAccessExpression }, sourceFile: SourceFile, changes: textChanges.ChangeTracker): void { const name = left.name.text; if ((isFunctionExpression(right) || isArrowFunction(right) || isClassExpression(right)) && (!right.name || right.name.text === name)) { // `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`. - changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, createToken(SyntaxKind.ExportKeyword), { suffix: " " }); + changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, factory.createToken(SyntaxKind.ExportKeyword), { suffix: " " }); if (!right.name) changes.insertName(sourceFile, right, name); @@ -301,14 +301,14 @@ namespace ts.codefix { else { // `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const ` changes.replaceNodeRangeWithNodes(sourceFile, left.expression, findChildOfKind(left, SyntaxKind.DotToken, sourceFile)!, - [createToken(SyntaxKind.ExportKeyword), createToken(SyntaxKind.ConstKeyword)], + [factory.createToken(SyntaxKind.ExportKeyword), factory.createToken(SyntaxKind.ConstKeyword)], { joiner: " ", suffix: " " }); } } // TODO: GH#22492 this will cause an error if a change has been made inside the body of the node. function convertExportsDotXEquals_replaceNode(name: string | undefined, exported: Expression): Statement { - const modifiers = [createToken(SyntaxKind.ExportKeyword)]; + const modifiers = [factory.createToken(SyntaxKind.ExportKeyword)]; switch (exported.kind) { case SyntaxKind.FunctionExpression: { const { name: expressionName } = exported as FunctionExpression; @@ -331,7 +331,7 @@ namespace ts.codefix { function exportConst() { // `exports.x = 0;` --> `export const x = 0;` - return makeConst(modifiers, createIdentifier(name!), exported); // TODO: GH#18217 + return makeConst(modifiers, factory.createIdentifier(name!), exported); // TODO: GH#18217 } } @@ -370,8 +370,8 @@ namespace ts.codefix { */ const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers); return [ - makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference), - makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), createIdentifier(tmp)), + makeImport(factory.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference), + makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), factory.createIdentifier(tmp)), ]; } case SyntaxKind.Identifier: @@ -407,7 +407,7 @@ namespace ts.codefix { idName = makeUniqueName(propertyName, identifiers); namedBindingsNames.set(propertyName, idName); } - changes.replaceNode(file, parent, createIdentifier(idName)); + changes.replaceNode(file, parent, factory.createIdentifier(idName)); } else { needDefaultImport = true; @@ -415,7 +415,7 @@ namespace ts.codefix { } const namedBindings = namedBindingsNames.size === 0 ? undefined : arrayFrom(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => - createImportSpecifier(propertyName === idName ? undefined : createIdentifier(propertyName), createIdentifier(idName)))); + factory.createImportSpecifier(propertyName === idName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(idName)))); if (!namedBindings) { // If it was unused, ensure that we at least import *something*. needDefaultImport = true; @@ -477,7 +477,7 @@ namespace ts.codefix { // Node helpers function functionExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], fn: FunctionExpression | ArrowFunction | MethodDeclaration): FunctionDeclaration { - return createFunctionDeclaration( + return factory.createFunctionDeclaration( getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal. concatenate(additionalModifiers, getSynthesizedDeepClones(fn.modifiers)), getSynthesizedDeepClone(fn.asteriskToken), @@ -485,11 +485,11 @@ namespace ts.codefix { getSynthesizedDeepClones(fn.typeParameters), getSynthesizedDeepClones(fn.parameters), getSynthesizedDeepClone(fn.type), - convertToFunctionBody(getSynthesizedDeepClone(fn.body!))); + factory.converters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); } function classExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], cls: ClassExpression): ClassDeclaration { - return createClassDeclaration( + return factory.createClassDeclaration( getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal. concatenate(additionalModifiers, getSynthesizedDeepClones(cls.modifiers)), name, @@ -500,27 +500,27 @@ namespace ts.codefix { function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike, quotePreference: QuotePreference): ImportDeclaration { return propertyName === "default" - ? makeImport(createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) + ? makeImport(factory.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) : makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); } function makeImportSpecifier(propertyName: string | undefined, name: string): ImportSpecifier { - return createImportSpecifier(propertyName !== undefined && propertyName !== name ? createIdentifier(propertyName) : undefined, createIdentifier(name)); + return factory.createImportSpecifier(propertyName !== undefined && propertyName !== name ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(name)); } function makeConst(modifiers: readonly Modifier[] | undefined, name: string | BindingName, init: Expression): VariableStatement { - return createVariableStatement( + return factory.createVariableStatement( modifiers, - createVariableDeclarationList( - [createVariableDeclaration(name, /*type*/ undefined, init)], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, init)], NodeFlags.Const)); } function makeExportDeclaration(exportSpecifiers: ExportSpecifier[] | undefined, moduleSpecifier?: string): ExportDeclaration { - return createExportDeclaration( + return factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - exportSpecifiers && createNamedExports(exportSpecifiers), - moduleSpecifier === undefined ? undefined : createLiteral(moduleSpecifier)); + exportSpecifiers && factory.createNamedExports(exportSpecifiers), + moduleSpecifier === undefined ? undefined : factory.createStringLiteral(moduleSpecifier)); } } diff --git a/src/services/codefixes/convertToMappedObjectType.ts b/src/services/codefixes/convertToMappedObjectType.ts index 0d79d6363c0ae..d6effb0603e57 100644 --- a/src/services/codefixes/convertToMappedObjectType.ts +++ b/src/services/codefixes/convertToMappedObjectType.ts @@ -33,23 +33,23 @@ namespace ts.codefix { } function createTypeAliasFromInterface(declaration: FixableDeclaration, type: TypeNode): TypeAliasDeclaration { - return createTypeAliasDeclaration(declaration.decorators, declaration.modifiers, declaration.name, declaration.typeParameters, type); + return factory.createTypeAliasDeclaration(declaration.decorators, declaration.modifiers, declaration.name, declaration.typeParameters, type); } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { indexSignature, container }: Info): void { const members = isInterfaceDeclaration(container) ? container.members : (container.type).members; const otherMembers = members.filter(member => !isIndexSignatureDeclaration(member)); const parameter = first(indexSignature.parameters); - const mappedTypeParameter = createTypeParameterDeclaration(cast(parameter.name, isIdentifier), parameter.type); - const mappedIntersectionType = createMappedTypeNode( - hasReadonlyModifier(indexSignature) ? createModifier(SyntaxKind.ReadonlyKeyword) : undefined, + const mappedTypeParameter = factory.createTypeParameterDeclaration(cast(parameter.name, isIdentifier), parameter.type); + const mappedIntersectionType = factory.createMappedTypeNode( + hasReadonlyModifier(indexSignature) ? factory.createModifier(SyntaxKind.ReadonlyKeyword) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type); - const intersectionType = createIntersectionTypeNode([ + const intersectionType = factory.createIntersectionTypeNode([ ...getAllSuperTypeNodes(container), mappedIntersectionType, - ...(otherMembers.length ? [createTypeLiteralNode(otherMembers)] : emptyArray), + ...(otherMembers.length ? [factory.createTypeLiteralNode(otherMembers)] : emptyArray), ]); changes.replaceNode(sourceFile, container, createTypeAliasFromInterface(container, intersectionType)); } diff --git a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts index 02ccbfd1d64cc..d2462546c6220 100644 --- a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts +++ b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts @@ -28,9 +28,9 @@ namespace ts.codefix { function doChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, qualifiedName: QualifiedName): void { const rightText = qualifiedName.right.text; - const replacement = createIndexedAccessTypeNode( - createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), - createLiteralTypeNode(createLiteral(rightText))); + const replacement = factory.createIndexedAccessTypeNode( + factory.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), + factory.createLiteralTypeNode(factory.createStringLiteral(rightText))); changeTracker.replaceNode(sourceFile, qualifiedName, replacement); } } diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 2e24fd2253dd2..57224677d6ae2 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -157,7 +157,7 @@ namespace ts.codefix { return; } const className = classDeclaration.name!.getText(); - const staticInitialization = initializePropertyToUndefined(createIdentifier(className), tokenName); + const staticInitialization = initializePropertyToUndefined(factory.createIdentifier(className), tokenName); changeTracker.insertNodeAfter(declSourceFile, classDeclaration, staticInitialization); } else { @@ -165,13 +165,13 @@ namespace ts.codefix { if (!classConstructor) { return; } - const propertyInitialization = initializePropertyToUndefined(createThis(), tokenName); + const propertyInitialization = initializePropertyToUndefined(factory.createThis(), tokenName); changeTracker.insertNodeAtConstructorEnd(declSourceFile, classConstructor, propertyInitialization); } } function initializePropertyToUndefined(obj: Expression, propertyName: string) { - return createStatement(createAssignment(createPropertyAccess(obj, propertyName), createIdentifier("undefined"))); + return factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccess(obj, propertyName), factory.createIdentifier("undefined"))); } function getActionsForAddMissingMemberInTypeScriptFile(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, token: Identifier, makeStatic: boolean): CodeFixAction[] | undefined { @@ -192,7 +192,7 @@ namespace ts.codefix { const contextualType = checker.getContextualType(token.parent as Expression); typeNode = contextualType ? checker.typeToTypeNode(contextualType) : undefined; } - return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword); + return typeNode || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } function createAddPropertyDeclarationAction(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, makeStatic: boolean, tokenName: string, typeNode: TypeNode): CodeFixAction { @@ -201,9 +201,9 @@ namespace ts.codefix { } function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode, makeStatic: boolean): void { - const property = createProperty( + const property = factory.createPropertyDeclaration( /*decorators*/ undefined, - /*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, + /*modifiers*/ makeStatic ? [factory.createToken(SyntaxKind.StaticKeyword)] : undefined, tokenName, /*questionToken*/ undefined, typeNode, @@ -230,8 +230,8 @@ namespace ts.codefix { function createAddIndexSignatureAction(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode): CodeFixAction { // Index signatures cannot have the static modifier. - const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword); - const indexingParameter = createParameter( + const stringTypeNode = factory.createKeywordTypeNode(SyntaxKind.StringKeyword); + const indexingParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -239,7 +239,7 @@ namespace ts.codefix { /*questionToken*/ undefined, stringTypeNode, /*initializer*/ undefined); - const indexSignature = createIndexSignature( + const indexSignature = factory.createIndexSignature( /*decorators*/ undefined, /*modifiers*/ undefined, [indexingParameter], @@ -297,8 +297,8 @@ namespace ts.codefix { return !!(type && type.flags & TypeFlags.StringLike); }); - const enumMember = createEnumMember(token, hasStringInitializer ? createStringLiteral(token.text) : undefined); - changes.replaceNode(enumDeclaration.getSourceFile(), enumDeclaration, updateEnumDeclaration( + const enumMember = factory.createEnumMember(token, hasStringInitializer ? factory.createStringLiteral(token.text) : undefined); + changes.replaceNode(enumDeclaration.getSourceFile(), enumDeclaration, factory.updateEnumDeclaration( enumDeclaration, enumDeclaration.decorators, enumDeclaration.modifiers, diff --git a/src/services/codefixes/fixAddMissingNewOperator.ts b/src/services/codefixes/fixAddMissingNewOperator.ts index 5acaf6eb82ede..f4dd821500782 100644 --- a/src/services/codefixes/fixAddMissingNewOperator.ts +++ b/src/services/codefixes/fixAddMissingNewOperator.ts @@ -16,7 +16,7 @@ namespace ts.codefix { function addMissingNewOperator(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan): void { const call = cast(findAncestorMatchingSpan(sourceFile, span), isCallExpression); - const newExpression = createNew(call.expression, call.typeArguments, call.arguments); + const newExpression = factory.createNew(call.expression, call.typeArguments, call.arguments); changes.replaceNode(sourceFile, call, newExpression); } diff --git a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts index b5d107398d837..e90bbad826861 100644 --- a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts +++ b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts @@ -25,7 +25,7 @@ namespace ts.codefix { } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importType: ImportTypeNode) { - const newTypeNode = updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true); + const newTypeNode = factory.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true); changes.replaceNode(sourceFile, importType, newTypeNode); } } diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 55dd4bd05567f..94cfd194dbc42 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -73,7 +73,7 @@ namespace ts.codefix { if (returnType) { const entityName = getEntityNameFromTypeNode(returnType); if (!entityName || entityName.kind !== SyntaxKind.Identifier || entityName.text !== "Promise") { - changes.replaceNode(sourceFile, returnType, createTypeReferenceNode("Promise", createNodeArray([returnType]))); + changes.replaceNode(sourceFile, returnType, factory.createTypeReferenceNode("Promise", factory.createNodeArray([returnType]))); } } changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore); diff --git a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts index 4fb14545a2004..b5fdf045870d4 100644 --- a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts +++ b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts @@ -22,7 +22,7 @@ namespace ts.codefix { } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, ctr: ConstructorDeclaration) { - const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray)); + const superCall = factory.createExpressionStatement(factory.createCall(factory.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray)); changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall); } } diff --git a/src/services/codefixes/fixEnableExperimentalDecorators.ts b/src/services/codefixes/fixEnableExperimentalDecorators.ts index 8ab1c2769104d..1cafb7d12006f 100644 --- a/src/services/codefixes/fixEnableExperimentalDecorators.ts +++ b/src/services/codefixes/fixEnableExperimentalDecorators.ts @@ -26,6 +26,6 @@ namespace ts.codefix { }); function doChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { - setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", createTrue()); + setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", factory.createTrue()); } } diff --git a/src/services/codefixes/fixEnableJsxFlag.ts b/src/services/codefixes/fixEnableJsxFlag.ts index 728366392f1ea..71030edab0dea 100644 --- a/src/services/codefixes/fixEnableJsxFlag.ts +++ b/src/services/codefixes/fixEnableJsxFlag.ts @@ -30,6 +30,6 @@ namespace ts.codefix { }); function doChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { - setJsonCompilerOptionValue(changeTracker, configFile, "jsx", createStringLiteral("react")); + setJsonCompilerOptionValue(changeTracker, configFile, "jsx", factory.createStringLiteral("react")); } } diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 1e2af29f63ed1..f8621e1f93d6f 100644 --- a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -27,7 +27,7 @@ namespace ts.codefix { } function doChanges(changes: textChanges.ChangeTracker, sourceFile: SourceFile, extendsToken: Node, heritageClauses: readonly HeritageClause[]): void { - changes.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword)); + changes.replaceNode(sourceFile, extendsToken, factory.createToken(SyntaxKind.ImplementsKeyword)); // If there is already an implements clause, replace the implements keyword with a comma. if (heritageClauses.length === 2 && @@ -36,7 +36,7 @@ namespace ts.codefix { const implementsToken = heritageClauses[1].getFirstToken()!; const implementsFullStart = implementsToken.getFullStart(); - changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, createToken(SyntaxKind.CommaToken)); + changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, factory.createToken(SyntaxKind.CommaToken)); // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive. // (Trailing because leading might be indentation, which is more sensitive.) diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index e5f58885e1c83..d488fa2314a64 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -34,6 +34,6 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void { // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper suppressLeadingAndTrailingTrivia(node); - changes.replaceNode(sourceFile, node, createPropertyAccess(className ? createIdentifier(className) : createThis(), node)); + changes.replaceNode(sourceFile, node, factory.createPropertyAccess(className ? factory.createIdentifier(className) : factory.createThis(), node)); } } diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index dc37aeff12b33..a26f00748c294 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -13,11 +13,11 @@ namespace ts.codefix { if (getEmitModuleKind(opts) === ModuleKind.CommonJS) { // import Bluebird = require("bluebird"); - variations.push(createAction(context, sourceFile, node, createImportEqualsDeclaration( + variations.push(createAction(context, sourceFile, node, factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, namespace.name, - createExternalModuleReference(node.moduleSpecifier) + factory.createExternalModuleReference(node.moduleSpecifier) ))); } @@ -88,7 +88,7 @@ namespace ts.codefix { } if (isExpression(expr) && !(isNamedDeclaration(expr.parent) && expr.parent.name === expr)) { const sourceFile = context.sourceFile; - const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, createPropertyAccess(expr, "default"), {})); + const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, factory.createPropertyAccess(expr, "default"), {})); fixes.push(createCodeFixActionNoFixId(fixName, changes, Diagnostics.Use_synthetic_default_member)); } return fixes; diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index 5bd57fb8fc969..39b0b6e53bf8f 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -60,10 +60,10 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: Node, suggestion: string, target: ScriptTarget) { if (!isIdentifierText(suggestion, target) && isPropertyAccessExpression(node.parent)) { - changes.replaceNode(sourceFile, node.parent, createElementAccess(node.parent.expression, createLiteral(suggestion))); + changes.replaceNode(sourceFile, node.parent, factory.createElementAccess(node.parent.expression, factory.createStringLiteral(suggestion))); } else { - changes.replaceNode(sourceFile, node, createIdentifier(suggestion)); + changes.replaceNode(sourceFile, node, factory.createIdentifier(suggestion)); } } diff --git a/src/services/codefixes/fixStrictClassInitialization.ts b/src/services/codefixes/fixStrictClassInitialization.ts index 15c57c604ddf1..ae347dc2260d9 100644 --- a/src/services/codefixes/fixStrictClassInitialization.ts +++ b/src/services/codefixes/fixStrictClassInitialization.ts @@ -58,12 +58,12 @@ namespace ts.codefix { } function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { - const property = updateProperty( + const property = factory.updatePropertyDeclaration( propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, - createToken(SyntaxKind.ExclamationToken), + factory.createToken(SyntaxKind.ExclamationToken), propertyDeclaration.type, propertyDeclaration.initializer ); @@ -76,10 +76,10 @@ namespace ts.codefix { } function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { - const undefinedTypeNode = createKeywordTypeNode(SyntaxKind.UndefinedKeyword); + const undefinedTypeNode = factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword); const type = propertyDeclaration.type!; // TODO: GH#18217 const types = isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode]; - changeTracker.replaceNode(propertyDeclarationSourceFile, type, createUnionTypeNode(types)); + changeTracker.replaceNode(propertyDeclarationSourceFile, type, factory.createUnionTypeNode(types)); } function getActionForAddMissingInitializer(context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction | undefined { @@ -92,7 +92,7 @@ namespace ts.codefix { } function addInitializer (changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, initializer: Expression): void { - const property = updateProperty( + const property = factory.updatePropertyDeclaration( propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, @@ -108,12 +108,18 @@ namespace ts.codefix { return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type!)); // TODO: GH#18217 } - function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined { + function getDefaultValueFromType(checker: TypeChecker, type: Type): Expression | undefined { if (type.flags & TypeFlags.BooleanLiteral) { - return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? createFalse() : createTrue(); + return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? factory.createFalse() : factory.createTrue(); } - else if (type.isLiteral()) { - return createLiteral(type.value); + else if (type.isStringLiteral()) { + return factory.createStringLiteral(type.value); + } + else if (type.isNumberLiteral()) { + return factory.createNumericLiteral(type.value); + } + else if (type.flags & TypeFlags.BigIntLiteral) { + return factory.createBigIntLiteral((type as BigIntLiteralType).value); } else if (type.isUnion()) { return firstDefined(type.types, t => getDefaultValueFromType(checker, t)); @@ -125,10 +131,10 @@ namespace ts.codefix { const constructorDeclaration = getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; - return createNew(createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + return factory.createNew(factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } else if (checker.isArrayLikeType(type)) { - return createArrayLiteral(); + return factory.createArrayLiteral(); } return undefined; } diff --git a/src/services/codefixes/fixUnreachableCode.ts b/src/services/codefixes/fixUnreachableCode.ts index c8cd5650969c0..082bffdb7980e 100644 --- a/src/services/codefixes/fixUnreachableCode.ts +++ b/src/services/codefixes/fixUnreachableCode.ts @@ -26,7 +26,7 @@ namespace ts.codefix { break; } else { - changes.replaceNode(sourceFile, statement, createBlock(emptyArray)); + changes.replaceNode(sourceFile, statement, factory.createBlock(emptyArray)); } return; } diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index 316142df0b6c2..110d11c018c52 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -109,7 +109,7 @@ namespace ts.codefix { }); function changeInferToUnknown(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node): void { - changes.replaceNode(sourceFile, token.parent, createKeywordTypeNode(SyntaxKind.UnknownKeyword)); + changes.replaceNode(sourceFile, token.parent, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)); } function createDeleteFix(changes: FileTextChanges[], diag: DiagnosticAndArguments): CodeFixAction { @@ -153,7 +153,7 @@ namespace ts.codefix { token = cast(token.parent, isInferTypeNode).typeParameter.name; } if (isIdentifier(token) && canPrefix(token)) { - changes.replaceNode(sourceFile, token, createIdentifier(`_${token.text}`)); + changes.replaceNode(sourceFile, token, factory.createIdentifier(`_${token.text}`)); } } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index b127fa240487f..cc58db24a7c01 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -52,7 +52,7 @@ namespace ts.codefix { const declaration = declarations[0]; const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName; const visibilityModifier = createVisibilityModifier(getModifierFlags(declaration)); - const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined; + const modifiers = visibilityModifier ? factory.createNodeArray([visibilityModifier]) : undefined; const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); const optional = !!(symbol.flags & SymbolFlags.Optional); const ambient = !!(enclosingDeclaration.flags & NodeFlags.Ambient); @@ -61,11 +61,11 @@ namespace ts.codefix { case SyntaxKind.PropertySignature: case SyntaxKind.PropertyDeclaration: const typeNode = checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context)); - out(createProperty( - /*decorators*/undefined, + out(factory.createPropertyDeclaration( + /*decorators*/ undefined, modifiers, name, - optional ? createToken(SyntaxKind.QuestionToken) : undefined, + optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, typeNode, /*initializer*/ undefined)); break; @@ -78,7 +78,7 @@ namespace ts.codefix { : [allAccessors.firstAccessor]; for (const accessor of orderedAccessors) { if (isGetAccessorDeclaration(accessor)) { - out(createGetAccessor( + out(factory.createGetAccessorDeclaration( /*decorators*/ undefined, modifiers, name, @@ -90,7 +90,7 @@ namespace ts.codefix { Debug.assertNode(accessor, isSetAccessorDeclaration, "The counterpart to a getter should be a setter"); const parameter = getSetAccessorValueParameter(accessor); const parameterName = parameter && isIdentifier(parameter.name) ? idText(parameter.name) : undefined; - out(createSetAccessor( + out(factory.createSetAccessorDeclaration( /*decorators*/ undefined, modifiers, name, @@ -163,7 +163,7 @@ namespace ts.codefix { signatureDeclaration.decorators = undefined; signatureDeclaration.modifiers = modifiers; signatureDeclaration.name = name; - signatureDeclaration.questionToken = optional ? createToken(SyntaxKind.QuestionToken) : undefined; + signatureDeclaration.questionToken = optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; signatureDeclaration.body = body; return signatureDeclaration; } @@ -188,14 +188,14 @@ namespace ts.codefix { isIdentifier(arg) ? arg.text : isPropertyAccessExpression(arg) ? arg.name.text : undefined); const contextualType = checker.getContextualType(call); const returnType = (inJs || !contextualType) ? undefined : checker.typeToTypeNode(contextualType, contextNode, /*flags*/ undefined, tracker); - return createMethod( + return factory.createMethodDeclaration( /*decorators*/ undefined, - /*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined, - /*asteriskToken*/ isYieldExpression(parent) ? createToken(SyntaxKind.AsteriskToken) : undefined, + /*modifiers*/ makeStatic ? [factory.createToken(SyntaxKind.StaticKeyword)] : undefined, + /*asteriskToken*/ isYieldExpression(parent) ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, methodName, /*questionToken*/ undefined, /*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) => - createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)), + factory.createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)), /*parameters*/ createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, inJs), /*type*/ returnType, body ? createStubbedMethodBody(preferences) : undefined); @@ -204,13 +204,13 @@ namespace ts.codefix { function createDummyParameters(argCount: number, names: (string | undefined)[] | undefined, types: (TypeNode | undefined)[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] { const parameters: ParameterDeclaration[] = []; for (let i = 0; i < argCount; i++) { - const newParameter = createParameter( + const newParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ names && names[i] || `arg${i}`, - /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined, - /*type*/ inJs ? undefined : types && types[i] || createKeywordTypeNode(SyntaxKind.AnyKeyword), + /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + /*type*/ inJs ? undefined : types && types[i] || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); parameters.push(newParameter); } @@ -246,13 +246,13 @@ namespace ts.codefix { const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, /* types */ undefined, minArgumentCount, /*inJs*/ false); if (someSigHasRestParameter) { - const anyArrayType = createArrayTypeNode(createKeywordTypeNode(SyntaxKind.AnyKeyword)); - const restParameter = createParameter( + const anyArrayType = factory.createArrayTypeNode(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)); + const restParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createToken(SyntaxKind.DotDotDotToken), + factory.createToken(SyntaxKind.DotDotDotToken), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", - /*questionToken*/ maxNonRestArgs >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined, + /*questionToken*/ maxNonRestArgs >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined, anyArrayType, /*initializer*/ undefined); parameters.push(restParameter); @@ -277,12 +277,12 @@ namespace ts.codefix { returnType: TypeNode | undefined, preferences: UserPreferences ): MethodDeclaration { - return createMethod( + return factory.createMethodDeclaration( /*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, name, - optional ? createToken(SyntaxKind.QuestionToken) : undefined, + optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, typeParameters, parameters, returnType, @@ -290,22 +290,22 @@ namespace ts.codefix { } function createStubbedMethodBody(preferences: UserPreferences): Block { - return createBlock( - [createThrow( - createNew( - createIdentifier("Error"), + return factory.createBlock( + [factory.createThrow( + factory.createNew( + factory.createIdentifier("Error"), /*typeArguments*/ undefined, // TODO Handle auto quote preference. - [createLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))], + [factory.createStringLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))], /*multiline*/ true); } function createVisibilityModifier(flags: ModifierFlags): Modifier | undefined { if (flags & ModifierFlags.Public) { - return createToken(SyntaxKind.PublicKeyword); + return factory.createToken(SyntaxKind.PublicKeyword); } else if (flags & ModifierFlags.Protected) { - return createToken(SyntaxKind.ProtectedKeyword); + return factory.createToken(SyntaxKind.ProtectedKeyword); } return undefined; } @@ -323,7 +323,7 @@ namespace ts.codefix { if (compilerOptionsProperty === undefined) { changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment( "compilerOptions", - createObjectLiteral([ + factory.createObjectLiteral([ createJsonPropertyAssignment(optionName, optionValue), ]))); return; @@ -345,7 +345,7 @@ namespace ts.codefix { } export function createJsonPropertyAssignment(name: string, initializer: Expression) { - return createPropertyAssignment(createStringLiteral(name), initializer); + return factory.createPropertyAssignment(factory.createStringLiteral(name), initializer); } export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index a43aa7f6f9d3c..baee89debbced 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -544,11 +544,11 @@ namespace ts.codefix { function doAddExistingFix(changes: textChanges.ChangeTracker, sourceFile: SourceFile, clause: ImportClause, defaultImport: string | undefined, namedImports: readonly string[]): void { if (defaultImport) { Debug.assert(!clause.name, "Default imports can't have names"); - changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), createIdentifier(defaultImport), { suffix: ", " }); + changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), factory.createIdentifier(defaultImport), { suffix: ", " }); } if (namedImports.length) { - const specifiers = namedImports.map(name => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))); + const specifiers = namedImports.map(name => factory.createImportSpecifier(/*propertyName*/ undefined, factory.createIdentifier(name))); if (clause.namedBindings && cast(clause.namedBindings, isNamedImports).elements.length) { for (const spec of specifiers) { changes.insertNodeInListAfter(sourceFile, last(cast(clause.namedBindings, isNamedImports).elements), spec); @@ -556,7 +556,7 @@ namespace ts.codefix { } else { if (specifiers.length) { - const namedImports = createNamedImports(specifiers); + const namedImports = factory.createNamedImports(specifiers); if (clause.namedBindings) { changes.replaceNode(sourceFile, clause.namedBindings, namedImports); } @@ -594,25 +594,26 @@ namespace ts.codefix { if (defaultImport !== undefined || namedImports.length) { insertImport(changes, sourceFile, makeImport( - defaultImport === undefined ? undefined : createIdentifier(defaultImport), - namedImports.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference)); + defaultImport === undefined ? undefined : factory.createIdentifier(defaultImport), + namedImports.map(n => factory.createImportSpecifier(/*propertyName*/ undefined, factory.createIdentifier(n))), moduleSpecifier, quotePreference)); } if (namespaceLikeImport) { insertImport( changes, sourceFile, - namespaceLikeImport.importKind === ImportKind.Equals ? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(namespaceLikeImport.name), createExternalModuleReference(quotedModuleSpecifier)) : + namespaceLikeImport.importKind === ImportKind.Equals ? factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createIdentifier(namespaceLikeImport.name), factory.createExternalModuleReference(quotedModuleSpecifier)) : namespaceLikeImport.importKind === ImportKind.ConstEquals ? createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier) : - createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier)); + factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(/*name*/ undefined, factory.createNamespaceImport(factory.createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier)); } } function createConstEqualsRequireDeclaration(name: string, quotedModuleSpecifier: StringLiteral): VariableStatement { - return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([ - createVariableDeclaration( - createIdentifier(name), + return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + factory.createIdentifier(name), + /*exclamationToken*/ undefined, /*type*/ undefined, - createCall(createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]) + factory.createCall(factory.createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]) ) ], NodeFlags.Const)); } diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index acd2a295d5862..3392439b4f91d 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -126,7 +126,7 @@ namespace ts.codefix { const typeNode = getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags - const typeTag = createJSDocTypeTag(createJSDocTypeExpression(typeNode), /*comment*/ ""); + const typeTag = factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode), /*comment*/ ""); addJSDocTags(changes, sourceFile, cast(parent.parent.parent, isExpressionStatement), [typeTag]); } return parent; @@ -232,13 +232,13 @@ namespace ts.codefix { } else { const needParens = isArrowFunction(containingFunction) && !findChildOfKind(containingFunction, SyntaxKind.OpenParenToken, sourceFile); - if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), createToken(SyntaxKind.OpenParenToken)); + if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), factory.createToken(SyntaxKind.OpenParenToken)); for (const { declaration, type } of parameterInferences) { if (declaration && !declaration.type && !declaration.initializer) { annotate(changes, sourceFile, declaration, type, program, host, formatContext, preferences); } } - if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), createToken(SyntaxKind.CloseParenToken)); + if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), factory.createToken(SyntaxKind.CloseParenToken)); } } @@ -263,7 +263,7 @@ namespace ts.codefix { function annotateJSDocThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: FunctionLike, typeNode: TypeNode) { addJSDocTags(changes, sourceFile, containingFunction, [ - createJSDocThisTag(createJSDocTypeExpression(typeNode)), + factory.createJSDocThisTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode)), ]); } @@ -300,8 +300,8 @@ namespace ts.codefix { if (!parent) { return; } - const typeExpression = createJSDocTypeExpression(typeNode); - const typeTag = isGetAccessorDeclaration(declaration) ? createJSDocReturnTag(typeExpression, "") : createJSDocTypeTag(typeExpression, ""); + const typeExpression = factory.createJSDocTypeExpression(typeNode); + const typeTag = isGetAccessorDeclaration(declaration) ? factory.createJSDocReturnTag(/*tagName*/ undefined, typeExpression, "") : factory.createJSDocTypeTag(/*tagName*/ undefined, typeExpression, ""); addJSDocTags(changes, sourceFile, parent, [typeTag]); } else if (!tryReplaceImportTypeNodeWithAutoImport(typeNode, changes, sourceFile, declaration, type, program, host, formatContext, preferences)) { @@ -328,7 +328,7 @@ namespace ts.codefix { declaration.pos, preferences, ); - if (action.codeAction.changes.length && changes.tryInsertTypeAnnotation(sourceFile, declaration, createTypeReferenceNode(typeNode.qualifier, typeNode.typeArguments))) { + if (action.codeAction.changes.length && changes.tryInsertTypeAnnotation(sourceFile, declaration, factory.createTypeReferenceNode(typeNode.qualifier, typeNode.typeArguments))) { for (const change of action.codeAction.changes) { const file = sourceFile.fileName === change.fileName ? sourceFile : Debug.assertDefined(program.getSourceFile(change.fileName)); changes.pushRaw(file, change); @@ -353,7 +353,7 @@ namespace ts.codefix { const typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host); const name = getSynthesizedClone(param.name); setEmitFlags(name, EmitFlags.NoComments | EmitFlags.NoNestedComments); - return typeNode && createJSDocParamTag(name, !!inference.isOptional, createJSDocTypeExpression(typeNode), ""); + return typeNode && factory.createJSDocParameterTag(/*tagName*/ undefined, name, !!inference.isOptional, factory.createJSDocTypeExpression(typeNode), /*isNameFirst*/ undefined, ""); }); addJSDocTags(changes, sourceFile, signature, paramTags); } @@ -366,7 +366,7 @@ namespace ts.codefix { if (merged) oldTags[i] = merged; return !!merged; })); - const tag = createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); + const tag = factory.createJSDocComment(comments.join("\n"), factory.createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent; jsDocNode.jsDoc = parent.jsDoc; jsDocNode.jsDocCache = parent.jsDocCache; @@ -389,11 +389,11 @@ namespace ts.codefix { const oldParam = oldTag as JSDocParameterTag; const newParam = newTag as JSDocParameterTag; return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText - ? createJSDocParamTag(newParam.name, newParam.isBracketed, newParam.typeExpression, oldParam.comment) + ? factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, newParam.isBracketed, newParam.typeExpression, /*isNameFirst*/ undefined, oldParam.comment) : undefined; } case SyntaxKind.JSDocReturnTag: - return createJSDocReturnTag((newTag as JSDocReturnTag).typeExpression, oldTag.comment); + return factory.createJSDocReturnTag(/*tagName*/ undefined, (newTag as JSDocReturnTag).typeExpression, oldTag.comment); } } diff --git a/src/services/codefixes/requireInTs.ts b/src/services/codefixes/requireInTs.ts index ee2a898147d6f..1528b6910a7c2 100644 --- a/src/services/codefixes/requireInTs.ts +++ b/src/services/codefixes/requireInTs.ts @@ -15,8 +15,8 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, program: Program) { const { statement, name, required } = getInfo(sourceFile, pos); changes.replaceNode(sourceFile, statement, getAllowSyntheticDefaultImports(program.getCompilerOptions()) - ? createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(name, /*namedBindings*/ undefined), required) - : createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, name, createExternalModuleReference(required))); + ? factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(name, /*namedBindings*/ undefined), required) + : factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, name, factory.createExternalModuleReference(required))); } interface Info { readonly statement: VariableStatement; readonly name: Identifier; readonly required: StringLiteralLike; } diff --git a/src/services/codefixes/useBigintLiteral.ts b/src/services/codefixes/useBigintLiteral.ts index 0749cc1a677b6..f521386f85e2f 100644 --- a/src/services/codefixes/useBigintLiteral.ts +++ b/src/services/codefixes/useBigintLiteral.ts @@ -28,6 +28,6 @@ namespace ts.codefix { // We use .getText to overcome parser inaccuracies: https://github.com/microsoft/TypeScript/issues/33298 const newText = numericLiteral.getText(sourceFile) + "n"; - changeTracker.replaceNode(sourceFile, numericLiteral, createBigIntLiteral(newText)); + changeTracker.replaceNode(sourceFile, numericLiteral, factory.createBigIntLiteral(newText)); } } diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index 9ab8410f51aeb..38cecda6d8f9c 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -65,7 +65,7 @@ namespace ts { // If there isn't some include for this, add a new one. if (getRegexFromPattern(Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) && !getRegexFromPattern(Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) { - changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), createStringLiteral(relativePath(newFileOrDirPath))); + changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), factory.createStringLiteral(relativePath(newFileOrDirPath))); } } break; diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index ba369f975fbe5..59dad143db722 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -376,7 +376,7 @@ namespace ts.NavigationBar { const memberName = defineCall.arguments[1]; const [depth, classNameIdentifier] = startNestedNodes(node, className); startNode(node, classNameIdentifier); - startNode(node, setTextRange(createIdentifier(memberName.text), memberName)); + startNode(node, setTextRange(factory.createIdentifier(memberName.text), memberName)); addChildrenRecursively((node as CallExpression).arguments[2]); endNode(); endNode(); @@ -508,7 +508,7 @@ namespace ts.NavigationBar { if (ctorFunction !== undefined) { const ctorNode = setTextRange( - createConstructor(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined), + factory.createConstructorDeclaration(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined), ctorFunction); const ctor = emptyNavigationBarNode(ctorNode); ctor.indent = a.indent + 1; @@ -525,10 +525,10 @@ namespace ts.NavigationBar { } } - lastANode = a.node = setTextRange(createClassDeclaration( + lastANode = a.node = setTextRange(factory.createClassDeclaration( /* decorators */ undefined, /* modifiers */ undefined, - a.name as Identifier || createIdentifier("__class__"), + a.name as Identifier || factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, [] @@ -553,10 +553,10 @@ namespace ts.NavigationBar { } else { if (!a.additionalNodes) a.additionalNodes = []; - a.additionalNodes.push(setTextRange(createClassDeclaration( + a.additionalNodes.push(setTextRange(factory.createClassDeclaration( /* decorators */ undefined, /* modifiers */ undefined, - a.name as Identifier || createIdentifier("__class__"), + a.name as Identifier || factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, [] diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 6db5c9eeadc8c..8664ec255733f 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -116,7 +116,7 @@ namespace ts.OrganizeImports { const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.name)); if (newElements.length < namedBindings.elements.length) { namedBindings = newElements.length - ? updateNamedImports(namedBindings, newElements) + ? factory.updateNamedImports(namedBindings, newElements) : undefined; } } @@ -129,7 +129,7 @@ namespace ts.OrganizeImports { else if (hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier)) { // If we’re in a declaration file, it’s safe to remove the import clause from it if (sourceFile.isDeclarationFile) { - usedImports.push(createImportDeclaration( + usedImports.push(factory.createImportDeclaration( importDecl.decorators, importDecl.modifiers, /*importClause*/ undefined, @@ -214,7 +214,7 @@ namespace ts.OrganizeImports { else { for (const defaultImport of defaultImports) { newImportSpecifiers.push( - createImportSpecifier(createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217 + factory.createImportSpecifier(factory.createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217 } } @@ -229,10 +229,10 @@ namespace ts.OrganizeImports { const newNamedImports = sortedImportSpecifiers.length === 0 ? newDefaultImport ? undefined - : createNamedImports(emptyArray) + : factory.createNamedImports(emptyArray) : namedImports.length === 0 - ? createNamedImports(sortedImportSpecifiers) - : updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217 + ? factory.createNamedImports(sortedImportSpecifiers) + : factory.updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217 coalescedImports.push( updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports)); @@ -313,11 +313,11 @@ namespace ts.OrganizeImports { const exportDecl = namedExports[0]; coalescedExports.push( - updateExportDeclaration( + factory.updateExportDeclaration( exportDecl, exportDecl.decorators, exportDecl.modifiers, - updateNamedExports(exportDecl.exportClause!, sortedExportSpecifiers), + factory.updateNamedExports(exportDecl.exportClause!, sortedExportSpecifiers), exportDecl.moduleSpecifier)); return coalescedExports; @@ -354,11 +354,11 @@ namespace ts.OrganizeImports { name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { - return updateImportDeclaration( + return factory.updateImportDeclaration( importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, - updateImportClause(importDeclaration.importClause!, name, namedBindings), // TODO: GH#18217 + factory.updateImportClause(importDeclaration.importClause!, name, namedBindings), // TODO: GH#18217 importDeclaration.moduleSpecifier); } diff --git a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts index 89a03c3c23989..2abae86bfd359 100644 --- a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts +++ b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts @@ -45,14 +45,14 @@ namespace ts.refactor.addOrRemoveBracesToArrowFunction { let body: ConciseBody; if (actionName === addBracesActionName) { - const returnStatement = createReturn(expression); - body = createBlock([returnStatement], /* multiLine */ true); + const returnStatement = factory.createReturn(expression); + body = factory.createBlock([returnStatement], /* multiLine */ true); suppressLeadingAndTrailingTrivia(body); copyLeadingComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { - const actualExpression = expression || createVoidZero(); - body = needsParentheses(actualExpression) ? createParen(actualExpression) : actualExpression; + const actualExpression = expression || factory.createVoidZero(); + body = needsParentheses(actualExpression) ? factory.createParen(actualExpression) : actualExpression; suppressLeadingAndTrailingTrivia(body); copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); } diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index 66f893dd0a022..0af2cce8a9fb4 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -86,13 +86,13 @@ namespace ts.refactor { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: - changes.insertNodeAfter(exportingSourceFile, exportKeyword, createToken(SyntaxKind.DefaultKeyword)); + changes.insertNodeAfter(exportingSourceFile, exportKeyword, factory.createToken(SyntaxKind.DefaultKeyword)); break; case SyntaxKind.VariableStatement: // If 'x' isn't used in this file, `export const x = 0;` --> `export default 0;` if (!FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile)) { // We checked in `getInfo` that an initializer exists. - changes.replaceNode(exportingSourceFile, exportNode, createExportDefault(Debug.assertDefined(first(exportNode.declarationList.declarations).initializer, "Initializer was previously known to be present"))); + changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDefault(Debug.assertDefined(first(exportNode.declarationList.declarations).initializer, "Initializer was previously known to be present"))); break; } // falls through @@ -101,7 +101,7 @@ namespace ts.refactor { case SyntaxKind.ModuleDeclaration: // `export type T = number;` -> `type T = number; export default T;` changes.deleteModifier(exportingSourceFile, exportKeyword); - changes.insertNodeAfter(exportingSourceFile, exportNode, createExportDefault(createIdentifier(exportName.text))); + changes.insertNodeAfter(exportingSourceFile, exportNode, factory.createExportDefault(factory.createIdentifier(exportName.text))); break; default: Debug.assertNever(exportNode, `Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`); @@ -128,7 +128,7 @@ namespace ts.refactor { switch (parent.kind) { case SyntaxKind.PropertyAccessExpression: // `a.default` --> `a.foo` - changes.replaceNode(importingSourceFile, ref, createIdentifier(exportName)); + changes.replaceNode(importingSourceFile, ref, factory.createIdentifier(exportName)); break; case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: { @@ -144,7 +144,7 @@ namespace ts.refactor { const { namedBindings } = clause; if (!namedBindings) { // `import foo from "./a";` --> `import { foo } from "./a";` - changes.replaceNode(importingSourceFile, ref, createNamedImports([spec])); + changes.replaceNode(importingSourceFile, ref, factory.createNamedImports([spec])); } else if (namedBindings.kind === SyntaxKind.NamespaceImport) { // `import foo, * as a from "./a";` --> `import * as a from ".a/"; import { foo } from "./a";` @@ -170,12 +170,12 @@ namespace ts.refactor { switch (parent.kind) { case SyntaxKind.PropertyAccessExpression: // `a.foo` --> `a.default` - changes.replaceNode(importingSourceFile, ref, createIdentifier("default")); + changes.replaceNode(importingSourceFile, ref, factory.createIdentifier("default")); break; case SyntaxKind.ImportSpecifier: { // `import { foo } from "./a";` --> `import foo from "./a";` // `import { foo as bar } from "./a";` --> `import bar from "./a";` - const defaultImport = createIdentifier(parent.name.text); + const defaultImport = factory.createIdentifier(parent.name.text); if (parent.parent.elements.length === 1) { changes.replaceNode(importingSourceFile, parent.parent, defaultImport); } @@ -200,10 +200,10 @@ namespace ts.refactor { } function makeImportSpecifier(propertyName: string, name: string): ImportSpecifier { - return createImportSpecifier(propertyName === name ? undefined : createIdentifier(propertyName), createIdentifier(name)); + return factory.createImportSpecifier(propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); } function makeExportSpecifier(propertyName: string, name: string): ExportSpecifier { - return createExportSpecifier(propertyName === name ? undefined : createIdentifier(propertyName), createIdentifier(name)); + return factory.createExportSpecifier(propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); } } diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index f87e90dba4ac2..1b796b42ae044 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -69,12 +69,12 @@ namespace ts.refactor { if (importName === undefined) { exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? getUniqueName(exportName, sourceFile) : exportName); } - changes.replaceNode(sourceFile, propertyAccess, createIdentifier(importName)); + changes.replaceNode(sourceFile, propertyAccess, factory.createIdentifier(importName)); } const importSpecifiers: ImportSpecifier[] = []; exportNameToImportName.forEach((name, propertyName) => { - importSpecifiers.push(createImportSpecifier(name === propertyName ? undefined : createIdentifier(propertyName), createIdentifier(name))); + importSpecifiers.push(factory.createImportSpecifier(name === propertyName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name))); }); const importDecl = toConvert.parent.parent; @@ -83,7 +83,7 @@ namespace ts.refactor { changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers)); } else { - changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); + changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); } } @@ -102,13 +102,13 @@ namespace ts.refactor { for (const element of toConvert.elements) { const propertyName = (element.propertyName || element.name).text; FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, id => { - const access = createPropertyAccess(createIdentifier(namespaceImportName), propertyName); + const access = factory.createPropertyAccess(factory.createIdentifier(namespaceImportName), propertyName); if (isShorthandPropertyAssignment(id.parent)) { - changes.replaceNode(sourceFile, id.parent, createPropertyAssignment(id.text, access)); + changes.replaceNode(sourceFile, id.parent, factory.createPropertyAssignment(id.text, access)); } else if (isExportSpecifier(id.parent) && !id.parent.propertyName) { if (!neededNamedImports.some(n => n.name === element.name)) { - neededNamedImports.push(createImportSpecifier(element.propertyName && createIdentifier(element.propertyName.text), createIdentifier(element.name.text))); + neededNamedImports.push(factory.createImportSpecifier(element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); } } else { @@ -117,14 +117,14 @@ namespace ts.refactor { }); } - changes.replaceNode(sourceFile, toConvert, createNamespaceImport(createIdentifier(namespaceImportName))); + changes.replaceNode(sourceFile, toConvert, factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); if (neededNamedImports.length) { changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, neededNamedImports)); } } function updateImport(old: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration { - return createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, - createImportClause(defaultImportName, elements && elements.length ? createNamedImports(elements) : undefined), old.moduleSpecifier); + return factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, + factory.createImportClause(defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined), old.moduleSpecifier); } } diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts index 6778eeb79c5e6..15dc64a8c228f 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -356,16 +356,16 @@ namespace ts.refactor.convertParamsToDestructuredObject { function getRefactorableParameters(parameters: NodeArray): NodeArray { if (hasThisParameter(parameters)) { - parameters = createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + parameters = factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); } return parameters; } function createPropertyOrShorthandAssignment(name: string, initializer: Expression): PropertyAssignment | ShorthandPropertyAssignment { if (isIdentifier(initializer) && getTextOfIdentifierOrLiteral(initializer) === name) { - return createShorthandPropertyAssignment(name); + return factory.createShorthandPropertyAssignment(name); } - return createPropertyAssignment(name, initializer); + return factory.createPropertyAssignment(name, initializer); } function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: NodeArray): ObjectLiteralExpression { @@ -384,11 +384,11 @@ namespace ts.refactor.convertParamsToDestructuredObject { if (hasRestParameter && functionArguments.length >= parameters.length) { const restArguments = functionArguments.slice(parameters.length - 1); - const restProperty = createPropertyAssignment(getParameterName(last(parameters)), createArrayLiteral(restArguments)); + const restProperty = factory.createPropertyAssignment(getParameterName(last(parameters)), factory.createArrayLiteral(restArguments)); properties.push(restProperty); } - const objectLiteral = createObjectLiteral(properties, /*multiLine*/ false); + const objectLiteral = factory.createObjectLiteral(properties, /*multiLine*/ false); return objectLiteral; } @@ -396,16 +396,16 @@ namespace ts.refactor.convertParamsToDestructuredObject { const checker = program.getTypeChecker(); const refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); const bindingElements = map(refactorableParameters, createBindingElementFromParameterDeclaration); - const objectParameterName = createObjectBindingPattern(bindingElements); + const objectParameterName = factory.createObjectBindingPattern(bindingElements); const objectParameterType = createParameterTypeNode(refactorableParameters); let objectInitializer: Expression | undefined; // If every parameter in the original function was optional, add an empty object initializer to the new object parameter if (every(refactorableParameters, isOptionalParameter)) { - objectInitializer = createObjectLiteral(); + objectInitializer = factory.createObjectLiteral(); } - const objectParameter = createParameter( + const objectParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -416,7 +416,7 @@ namespace ts.refactor.convertParamsToDestructuredObject { if (hasThisParameter(functionDeclaration.parameters)) { const thisParameter = functionDeclaration.parameters[0]; - const newThisParameter = createParameter( + const newThisParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -431,16 +431,16 @@ namespace ts.refactor.convertParamsToDestructuredObject { copyComments(thisParameter.type, newThisParameter.type!); } - return createNodeArray([newThisParameter, objectParameter]); + return factory.createNodeArray([newThisParameter, objectParameter]); } - return createNodeArray([objectParameter]); + return factory.createNodeArray([objectParameter]); function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement { - const element = createBindingElement( + const element = factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, getParameterName(parameterDeclaration), - isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? createArrayLiteral() : parameterDeclaration.initializer); + isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? factory.createArrayLiteral() : parameterDeclaration.initializer); suppressLeadingAndTrailingTrivia(element); if (parameterDeclaration.initializer && element.initializer) { @@ -451,7 +451,7 @@ namespace ts.refactor.convertParamsToDestructuredObject { function createParameterTypeNode(parameters: NodeArray): TypeLiteralNode { const members = map(parameters, createPropertySignatureFromParameterDeclaration); - const typeNode = addEmitFlags(createTypeLiteralNode(members), EmitFlags.SingleLine); + const typeNode = addEmitFlags(factory.createTypeLiteralNode(members), EmitFlags.SingleLine); return typeNode; } @@ -461,12 +461,11 @@ namespace ts.refactor.convertParamsToDestructuredObject { parameterType = getTypeNode(parameterDeclaration); } - const propertySignature = createPropertySignature( + const propertySignature = factory.createPropertySignature( /*modifiers*/ undefined, getParameterName(parameterDeclaration), - isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken, - parameterType, - /*initializer*/ undefined); + isOptionalParameter(parameterDeclaration) ? factory.createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken, + parameterType); suppressLeadingAndTrailingTrivia(propertySignature); copyComments(parameterDeclaration.name, propertySignature.name); diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index e7f57a57351c4..5534624135bf0 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -724,7 +724,7 @@ namespace ts.refactor.extractSymbol { const functionNameText = getUniqueName(isClassLike(scope) ? "newMethod" : "newFunction", file); const isJS = isInJSFile(scope); - const functionName = createIdentifier(functionNameText); + const functionName = factory.createIdentifier(functionNameText); let returnType: TypeNode | undefined; const parameters: ParameterDeclaration[] = []; @@ -739,7 +739,7 @@ namespace ts.refactor.extractSymbol { typeNode = checker.typeToTypeNode(type, scope, NodeBuilderFlags.NoTruncation); } - const paramDecl = createParameter( + const paramDecl = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -751,7 +751,7 @@ namespace ts.refactor.extractSymbol { if (usage.usage === Usage.Write) { (writes || (writes = [])).push(usage); } - callArguments.push(createIdentifier(name)); + callArguments.push(factory.createIdentifier(name)); }); const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values()).map(type => ({ type, declaration: getFirstDeclaration(type) })); @@ -764,7 +764,7 @@ namespace ts.refactor.extractSymbol { // Strictly speaking, we should check whether each name actually binds to the appropriate type // parameter. In cases of shadowing, they may not. const callTypeArguments: readonly TypeNode[] | undefined = typeParameters !== undefined - ? typeParameters.map(decl => createTypeReferenceNode(decl.name, /*typeArguments*/ undefined)) + ? typeParameters.map(decl => factory.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined)) : undefined; // Provide explicit return types for contextually-typed functions @@ -781,17 +781,17 @@ namespace ts.refactor.extractSymbol { if (isClassLike(scope)) { // always create private method in TypeScript files - const modifiers: Modifier[] = isJS ? [] : [createToken(SyntaxKind.PrivateKeyword)]; + const modifiers: Modifier[] = isJS ? [] : [factory.createModifier(SyntaxKind.PrivateKeyword)]; if (range.facts & RangeFacts.InStaticRegion) { - modifiers.push(createToken(SyntaxKind.StaticKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.StaticKeyword)); } if (range.facts & RangeFacts.IsAsyncFunction) { - modifiers.push(createToken(SyntaxKind.AsyncKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.AsyncKeyword)); } - newFunction = createMethod( + newFunction = factory.createMethodDeclaration( /*decorators*/ undefined, modifiers.length ? modifiers : undefined, - range.facts & RangeFacts.IsGenerator ? createToken(SyntaxKind.AsteriskToken) : undefined, + range.facts & RangeFacts.IsGenerator ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, functionName, /*questionToken*/ undefined, typeParameters, @@ -801,10 +801,10 @@ namespace ts.refactor.extractSymbol { ); } else { - newFunction = createFunctionDeclaration( + newFunction = factory.createFunctionDeclaration( /*decorators*/ undefined, - range.facts & RangeFacts.IsAsyncFunction ? [createToken(SyntaxKind.AsyncKeyword)] : undefined, - range.facts & RangeFacts.IsGenerator ? createToken(SyntaxKind.AsteriskToken) : undefined, + range.facts & RangeFacts.IsAsyncFunction ? [factory.createToken(SyntaxKind.AsyncKeyword)] : undefined, + range.facts & RangeFacts.IsGenerator ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, functionName, typeParameters, parameters, @@ -827,15 +827,15 @@ namespace ts.refactor.extractSymbol { // replace range with function call const called = getCalledExpression(scope, range, functionNameText); - let call: Expression = createCall( + let call: Expression = factory.createCall( called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference callArguments); if (range.facts & RangeFacts.IsGenerator) { - call = createYield(createToken(SyntaxKind.AsteriskToken), call); + call = factory.createYield(factory.createToken(SyntaxKind.AsteriskToken), call); } if (range.facts & RangeFacts.IsAsyncFunction) { - call = createAwait(call); + call = factory.createAwait(call); } if (exposedVariableDeclarations.length && !writes) { @@ -848,10 +848,10 @@ namespace ts.refactor.extractSymbol { if (exposedVariableDeclarations.length === 1) { // Declaring exactly one variable: let x = newFunction(); const variableDeclaration = exposedVariableDeclarations[0]; - newNodes.push(createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns variableDeclaration.parent.flags))); } else { @@ -862,7 +862,7 @@ namespace ts.refactor.extractSymbol { let commonNodeFlags = exposedVariableDeclarations[0].parent.flags; let sawExplicitType = false; for (const variableDeclaration of exposedVariableDeclarations) { - bindingElements.push(createBindingElement( + bindingElements.push(factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, /*name*/ getSynthesizedDeepClone(variableDeclaration.name))); @@ -873,26 +873,26 @@ namespace ts.refactor.extractSymbol { scope, NodeBuilderFlags.NoTruncation); - typeElements.push(createPropertySignature( + typeElements.push(factory.createPropertySignature( /*modifiers*/ undefined, /*name*/ variableDeclaration.symbol.name, /*questionToken*/ undefined, - /*type*/ variableType, - /*initializer*/ undefined)); + /*type*/ variableType)); sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined; commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } - const typeLiteral: TypeLiteralNode | undefined = sawExplicitType ? createTypeLiteralNode(typeElements) : undefined; + const typeLiteral: TypeLiteralNode | undefined = sawExplicitType ? factory.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { setEmitFlags(typeLiteral, EmitFlags.SingleLine); } - newNodes.push(createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration( - createObjectBindingPattern(bindingElements), + factory.createVariableDeclarationList( + [factory.createVariableDeclaration( + factory.createObjectBindingPattern(bindingElements), + /*exclamationToken*/ undefined, /*type*/ typeLiteral, /*initializer*/call)], commonNodeFlags))); @@ -907,26 +907,26 @@ namespace ts.refactor.extractSymbol { flags = (flags & ~NodeFlags.Const) | NodeFlags.Let; } - newNodes.push(createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(variableDeclaration.symbol.name, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } if (returnValueProperty) { // has both writes and return, need to create variable declaration to hold return value; - newNodes.push(createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList( - [createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(returnValueProperty, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(returnType))], NodeFlags.Let))); } const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { - assignments.unshift(createShorthandPropertyAssignment(returnValueProperty)); + assignments.unshift(factory.createShorthandPropertyAssignment(returnValueProperty)); } // propagate writes back @@ -935,28 +935,28 @@ namespace ts.refactor.extractSymbol { // other assignments to make. Debug.assert(!returnValueProperty, "Shouldn't have returnValueProperty here"); - newNodes.push(createStatement(createAssignment(assignments[0].name, call))); + newNodes.push(factory.createExpressionStatement(factory.createAssignment(assignments[0].name, call))); if (range.facts & RangeFacts.HasReturn) { - newNodes.push(createReturn()); + newNodes.push(factory.createReturn()); } } else { // emit e.g. // { a, b, __return } = newFunction(a, b); // return __return; - newNodes.push(createStatement(createAssignment(createObjectLiteral(assignments), call))); + newNodes.push(factory.createExpressionStatement(factory.createAssignment(factory.createObjectLiteral(assignments), call))); if (returnValueProperty) { - newNodes.push(createReturn(createIdentifier(returnValueProperty))); + newNodes.push(factory.createReturn(factory.createIdentifier(returnValueProperty))); } } } else { if (range.facts & RangeFacts.HasReturn) { - newNodes.push(createReturn(call)); + newNodes.push(factory.createReturn(call)); } else if (isReadonlyArray(range.range)) { - newNodes.push(createStatement(call)); + newNodes.push(factory.createExpressionStatement(call)); } else { newNodes.push(call); @@ -989,7 +989,7 @@ namespace ts.refactor.extractSymbol { } return isUnionTypeNode(withoutParens) && find(withoutParens.types, t => t.kind === SyntaxKind.UndefinedKeyword) ? clone - : createUnionTypeNode([clone, createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); + : factory.createUnionTypeNode([clone, factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); } } @@ -1026,13 +1026,13 @@ namespace ts.refactor.extractSymbol { if (isClassLike(scope)) { Debug.assert(!isJS, "Cannot extract to a JS class"); // See CannotExtractToJSClass const modifiers: Modifier[] = []; - modifiers.push(createToken(SyntaxKind.PrivateKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.PrivateKeyword)); if (rangeFacts & RangeFacts.InStaticRegion) { - modifiers.push(createToken(SyntaxKind.StaticKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.StaticKeyword)); } - modifiers.push(createToken(SyntaxKind.ReadonlyKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.ReadonlyKeyword)); - const newVariable = createProperty( + const newVariable = factory.createPropertyDeclaration( /*decorators*/ undefined, modifiers, localNameText, @@ -1040,11 +1040,11 @@ namespace ts.refactor.extractSymbol { variableType, initializer); - const localReference = createPropertyAccess( + const localReference = factory.createPropertyAccess( rangeFacts & RangeFacts.InStaticRegion - ? createIdentifier(scope.name!.getText()) // TODO: GH#18217 - : createThis(), - createIdentifier(localNameText)); + ? factory.createIdentifier(scope.name!.getText()) // TODO: GH#18217 + : factory.createThis(), + factory.createIdentifier(localNameText)); // Declare const maxInsertionPos = node.pos; @@ -1055,7 +1055,7 @@ namespace ts.refactor.extractSymbol { changeTracker.replaceNode(context.file, node, localReference); } else { - const newVariableDeclaration = createVariableDeclaration(localNameText, variableType, initializer); + const newVariableDeclaration = factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, variableType, initializer); // If the node is part of an initializer in a list of variable declarations, insert a new // variable declaration into the list (in case it depends on earlier ones). @@ -1068,21 +1068,21 @@ namespace ts.refactor.extractSymbol { changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration); // Consume - const localReference = createIdentifier(localNameText); + const localReference = factory.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } else if (node.parent.kind === SyntaxKind.ExpressionStatement && scope === findAncestor(node, isScope)) { // If the parent is an expression statement and the target scope is the immediately enclosing one, // replace the statement with the declaration. - const newVariableStatement = createVariableStatement( + const newVariableStatement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); + factory.createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); changeTracker.replaceNode(context.file, node.parent, newVariableStatement); } else { - const newVariableStatement = createVariableStatement( + const newVariableStatement = factory.createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); + factory.createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); // Declare const nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope); @@ -1099,7 +1099,7 @@ namespace ts.refactor.extractSymbol { changeTracker.delete(context.file, node.parent); } else { - const localReference = createIdentifier(localNameText); + const localReference = factory.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } } @@ -1135,7 +1135,7 @@ namespace ts.refactor.extractSymbol { const paramType = checker.getTypeAtLocation(p); if (paramType === checker.getAnyType()) hasAny = true; - parameters.push(updateParameter(p, + parameters.push(factory.updateParameterDeclaration(p, p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, NodeBuilderFlags.NoTruncation), p.initializer)); } @@ -1146,7 +1146,7 @@ namespace ts.refactor.extractSymbol { if (hasAny) return { variableType, initializer }; variableType = undefined; if (isArrowFunction(initializer)) { - initializer = updateArrowFunction(initializer, node.modifiers, initializer.typeParameters, + initializer = factory.updateArrowFunction(initializer, node.modifiers, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), initializer.equalsGreaterThanToken, @@ -1159,7 +1159,7 @@ namespace ts.refactor.extractSymbol { // Note: If this parameter was already there, it would have been previously updated with the type if not type was present if ((!firstParameter || (isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this"))) { const thisType = checker.getTypeOfSymbolAtLocation(functionSignature.thisParameter, node); - parameters.splice(0, 0, createParameter( + parameters.splice(0, 0, factory.createParameterDeclaration( /* decorators */ undefined, /* modifiers */ undefined, /* dotDotDotToken */ undefined, @@ -1169,7 +1169,7 @@ namespace ts.refactor.extractSymbol { )); } } - initializer = updateFunctionExpression(initializer, node.modifiers, initializer.asteriskToken, + initializer = factory.updateFunctionExpression(initializer, node.modifiers, initializer.asteriskToken, initializer.name, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), @@ -1222,10 +1222,10 @@ namespace ts.refactor.extractSymbol { } function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression { - const functionReference = createIdentifier(functionNameText); + const functionReference = factory.createIdentifier(functionNameText); if (isClassLike(scope)) { - const lhs = range.facts & RangeFacts.InStaticRegion ? createIdentifier(scope.name!.text) : createThis(); // TODO: GH#18217 - return createPropertyAccess(lhs, functionReference); + const lhs = range.facts & RangeFacts.InStaticRegion ? factory.createIdentifier(scope.name!.text) : factory.createThis(); // TODO: GH#18217 + return factory.createPropertyAccess(lhs, functionReference); } else { return functionReference; @@ -1236,11 +1236,11 @@ namespace ts.refactor.extractSymbol { const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { // already block, no declarations or writes to propagate back, no substitutions - can use node as is - return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; + return { body: factory.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } let returnValueProperty: string | undefined; let ignoreReturns = false; - const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(body)]); + const statements = factory.createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { const rewrittenStatements = visitNodes(statements, visitor).slice(); @@ -1249,16 +1249,16 @@ namespace ts.refactor.extractSymbol { // it is ok to know that range has at least one return since it we only allow unconditional returns const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (assignments.length === 1) { - rewrittenStatements.push(createReturn(assignments[0].name)); + rewrittenStatements.push(factory.createReturn(assignments[0].name)); } else { - rewrittenStatements.push(createReturn(createObjectLiteral(assignments))); + rewrittenStatements.push(factory.createReturn(factory.createObjectLiteral(assignments))); } } - return { body: createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty }; + return { body: factory.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty }; } else { - return { body: createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; + return { body: factory.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node: Node): VisitResult { @@ -1268,13 +1268,13 @@ namespace ts.refactor.extractSymbol { if (!returnValueProperty) { returnValueProperty = "__return"; } - assignments.unshift(createPropertyAssignment(returnValueProperty, visitNode((node).expression, visitor))); + assignments.unshift(factory.createPropertyAssignment(returnValueProperty, visitNode((node).expression, visitor))); } if (assignments.length === 1) { - return createReturn(assignments[0].name as Expression); + return factory.createReturn(assignments[0].name as Expression); } else { - return createReturn(createObjectLiteral(assignments)); + return factory.createReturn(factory.createObjectLiteral(assignments)); } } else { @@ -1392,8 +1392,8 @@ namespace ts.refactor.extractSymbol { exposedVariableDeclarations: readonly VariableDeclaration[], writes: readonly UsageEntry[] | undefined ): ShorthandPropertyAssignment[] { - const variableAssignments = map(exposedVariableDeclarations, v => createShorthandPropertyAssignment(v.symbol.name)); - const writeAssignments = map(writes, w => createShorthandPropertyAssignment(w.symbol.name)); + const variableAssignments = map(exposedVariableDeclarations, v => factory.createShorthandPropertyAssignment(v.symbol.name)); + const writeAssignments = map(writes, w => factory.createShorthandPropertyAssignment(w.symbol.name)); // TODO: GH#18217 `variableAssignments` not possibly undefined! return variableAssignments === undefined @@ -1508,7 +1508,7 @@ namespace ts.refactor.extractSymbol { } const seenUsages = createMap(); - const target = isReadonlyArray(targetRange.range) ? createBlock(targetRange.range) : targetRange.range; + const target = isReadonlyArray(targetRange.range) ? factory.createBlock(targetRange.range) : targetRange.range; const unmodifiedNode = isReadonlyArray(targetRange.range) ? first(targetRange.range) : targetRange.range; const inGenericContext = isInGenericContext(unmodifiedNode); @@ -1805,15 +1805,15 @@ namespace ts.refactor.extractSymbol { } const decls = symbol.getDeclarations(); if (decls && decls.some(d => d.parent === scopeDecl)) { - return createIdentifier(symbol.name); + return factory.createIdentifier(symbol.name); } const prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode); if (prefix === undefined) { return undefined; } return isTypeNode - ? createQualifiedName(prefix, createIdentifier(symbol.name)) - : createPropertyAccess(prefix, symbol.name); + ? factory.createQualifiedName(prefix, factory.createIdentifier(symbol.name)) + : factory.createPropertyAccess(prefix, symbol.name); } } diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index 70934ef7a7ce1..17196a118491e 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -152,21 +152,21 @@ namespace ts.refactor { function doTypeAliasChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: TypeAliasInfo) { const { firstStatement, selection, typeParameters } = info; - const newTypeNode = createTypeAliasDeclaration( + const newTypeNode = factory.createTypeAliasDeclaration( /* decorators */ undefined, /* modifiers */ undefined, name, - typeParameters.map(id => updateTypeParameterDeclaration(id, id.name, id.constraint, /* defaultType */ undefined)), + typeParameters.map(id => factory.updateTypeParameterDeclaration(id, id.name, id.constraint, /* defaultType */ undefined)), selection ); changes.insertNodeBefore(file, firstStatement, newTypeNode, /* blankLineBetween */ true); - changes.replaceNode(file, selection, createTypeReferenceNode(name, typeParameters.map(id => createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); } function doInterfaceChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: InterfaceInfo) { const { firstStatement, selection, typeParameters, typeElements } = info; - const newTypeNode = createInterfaceDeclaration( + const newTypeNode = factory.createInterfaceDeclaration( /* decorators */ undefined, /* modifiers */ undefined, name, @@ -175,34 +175,34 @@ namespace ts.refactor { typeElements ); changes.insertNodeBefore(file, firstStatement, newTypeNode, /* blankLineBetween */ true); - changes.replaceNode(file, selection, createTypeReferenceNode(name, typeParameters.map(id => createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); } function doTypedefChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: Info) { const { firstStatement, selection, typeParameters } = info; const node = createNode(SyntaxKind.JSDocTypedefTag); - node.tagName = createIdentifier("typedef"); // TODO: jsdoc factory https://github.com/Microsoft/TypeScript/pull/29539 - node.fullName = createIdentifier(name); + node.tagName = factory.createIdentifier("typedef"); // TODO: jsdoc factory https://github.com/Microsoft/TypeScript/pull/29539 + node.fullName = factory.createIdentifier(name); node.name = node.fullName; - node.typeExpression = createJSDocTypeExpression(selection); + node.typeExpression = factory.createJSDocTypeExpression(selection); const templates: JSDocTemplateTag[] = []; forEach(typeParameters, typeParameter => { const constraint = getEffectiveConstraintOfTypeParameter(typeParameter); const template = createNode(SyntaxKind.JSDocTemplateTag); - template.tagName = createIdentifier("template"); + template.tagName = factory.createIdentifier("template"); template.constraint = constraint && cast(constraint, isJSDocTypeExpression); const parameter = createNode(SyntaxKind.TypeParameter); parameter.name = typeParameter.name; - template.typeParameters = createNodeArray([parameter]); + template.typeParameters = factory.createNodeArray([parameter]); templates.push(template); }); - changes.insertNodeBefore(file, firstStatement, createJSDocComment(/* comment */ undefined, createNodeArray(concatenate(templates, [node]))), /* blankLineBetween */ true); - changes.replaceNode(file, selection, createTypeReferenceNode(name, typeParameters.map(id => createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); + changes.insertNodeBefore(file, firstStatement, factory.createJSDocComment(/* comment */ undefined, factory.createNodeArray(concatenate(templates, [node]))), /* blankLineBetween */ true); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); } } diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index a1bd32b37fc29..b979ea44359ed 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -55,7 +55,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const accessorModifiers = isInClassLike ? !modifierFlags || modifierFlags & ModifierFlags.Private ? getModifiers(isJS, isStatic, SyntaxKind.PublicKeyword) - : createNodeArray(createModifiersFromModifierFlags(modifierFlags)) + : factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined; @@ -95,21 +95,21 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { return isParameterPropertyDeclaration(node, node.parent) || isPropertyDeclaration(node) || isPropertyAssignment(node); } - function createPropertyName (name: string, originalName: AcceptedNameType) { - return isIdentifier(originalName) ? createIdentifier(name) : createLiteral(name); + function createPropertyName(name: string, originalName: AcceptedNameType) { + return isIdentifier(originalName) ? factory.createIdentifier(name) : factory.createStringLiteral(name); } function createAccessorAccessExpression (fieldName: AcceptedNameType, isStatic: boolean, container: ContainerDeclaration) { - const leftHead = isStatic ? (container).name! : createThis(); // TODO: GH#18217 - return isIdentifier(fieldName) ? createPropertyAccess(leftHead, fieldName) : createElementAccess(leftHead, createLiteral(fieldName)); + const leftHead = isStatic ? (container).name! : factory.createThis(); // TODO: GH#18217 + return isIdentifier(fieldName) ? factory.createPropertyAccess(leftHead, fieldName) : factory.createElementAccess(leftHead, factory.createStringLiteralFromNode(fieldName)); } function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray | undefined { const modifiers = append( - !isJS ? [createToken(accessModifier) as Token | Token] : undefined, - isStatic ? createToken(SyntaxKind.StaticKeyword) : undefined + !isJS ? [factory.createModifier(accessModifier) as Token | Token] : undefined, + isStatic ? factory.createModifier(SyntaxKind.StaticKeyword) : undefined ); - return modifiers && createNodeArray(modifiers); + return modifiers && factory.createNodeArray(modifiers); } function startsWithUnderscore(name: string): boolean { @@ -144,14 +144,14 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { - return createGetAccessor( + return factory.createGetAccessorDeclaration( /*decorators*/ undefined, modifiers, accessorName, /*parameters*/ undefined!, // TODO: GH#18217 type, - createBlock([ - createReturn( + factory.createBlock([ + factory.createReturn( createAccessorAccessExpression(fieldName, isStatic, container) ) ], /*multiLine*/ true) @@ -159,23 +159,23 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { - return createSetAccessor( + return factory.createSetAccessorDeclaration( /*decorators*/ undefined, modifiers, accessorName, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createIdentifier("value"), + factory.createIdentifier("value"), /*questionToken*/ undefined, type )], - createBlock([ - createStatement( - createAssignment( + factory.createBlock([ + factory.createExpressionStatement( + factory.createAssignment( createAccessorAccessExpression(fieldName, isStatic, container), - createIdentifier("value") + factory.createIdentifier("value") ) ) ], /*multiLine*/ true) @@ -183,7 +183,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) { - const property = updateProperty( + const property = factory.updatePropertyDeclaration( declaration, declaration.decorators, modifiers, @@ -196,7 +196,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function updatePropertyAssignmentDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) { - const assignment = updatePropertyAssignment(declaration, fieldName, declaration.initializer); + const assignment = factory.updatePropertyAssignment(declaration, fieldName, declaration.initializer); changeTracker.replacePropertyAssignment(file, declaration, assignment); } @@ -209,7 +209,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } else { changeTracker.replaceNode(file, declaration, - updateParameter(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer)); + factory.updateParameterDeclaration(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer)); } } @@ -227,10 +227,10 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { isStringLiteral(node.argumentExpression) && node.argumentExpression.text === originalName && isWriteAccess(node)) { - changeTracker.replaceNode(file, node.argumentExpression, createStringLiteral(fieldName)); + changeTracker.replaceNode(file, node.argumentExpression, factory.createStringLiteral(fieldName)); } if (isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword && node.name.text === originalName && isWriteAccess(node)) { - changeTracker.replaceNode(file, node.name, createIdentifier(fieldName)); + changeTracker.replaceNode(file, node.name, factory.createIdentifier(fieldName)); } if (!isFunctionLike(node) && !isClassLike(node)) { node.forEachChild(recur); diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index b187a0f953b59..d5b724520af5a 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -103,7 +103,7 @@ namespace ts.refactor { const filesProp = cfgObject && find(cfgObject.properties, (prop): prop is PropertyAssignment => isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "files"); if (filesProp && isArrayLiteralExpression(filesProp.initializer)) { - changes.insertNodeInListAfter(cfg, last(filesProp.initializer.elements), createLiteral(newFilePath), filesProp.initializer.elements); + changes.insertNodeInListAfter(cfg, last(filesProp.initializer.elements), factory.createStringLiteral(newFilePath), filesProp.initializer.elements); } } @@ -164,7 +164,7 @@ namespace ts.refactor { }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file const newModuleSpecifier = combinePaths(getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); - const newImportDeclaration = filterImport(importNode, createLiteral(newModuleSpecifier), shouldMove); + const newImportDeclaration = filterImport(importNode, factory.createStringLiteral(newModuleSpecifier), shouldMove); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); const ns = getNamespaceLikeImport(importNode); @@ -212,25 +212,25 @@ namespace ts.refactor { if (toChange.length) { const newNamespaceName = needUniqueName ? getUniqueName(preferredNewNamespaceName, sourceFile) : preferredNewNamespaceName; for (const ref of toChange) { - changes.replaceNode(sourceFile, ref, createIdentifier(newNamespaceName)); + changes.replaceNode(sourceFile, ref, factory.createIdentifier(newNamespaceName)); } changes.insertNodeAfter(sourceFile, oldImportNode, updateNamespaceLikeImportNode(oldImportNode, newModuleName, newModuleSpecifier)); } } function updateNamespaceLikeImportNode(node: SupportedImport, newNamespaceName: string, newModuleSpecifier: string): Node { - const newNamespaceId = createIdentifier(newNamespaceName); - const newModuleString = createLiteral(newModuleSpecifier); + const newNamespaceId = factory.createIdentifier(newNamespaceName); + const newModuleString = factory.createStringLiteral(newModuleSpecifier); switch (node.kind) { case SyntaxKind.ImportDeclaration: - return createImportDeclaration( + return factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createImportClause(/*name*/ undefined, createNamespaceImport(newNamespaceId)), + factory.createImportClause(/*name*/ undefined, factory.createNamespaceImport(newNamespaceId)), newModuleString); case SyntaxKind.ImportEqualsDeclaration: - return createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newNamespaceId, createExternalModuleReference(newModuleString)); + return factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newNamespaceId, factory.createExternalModuleReference(newModuleString)); case SyntaxKind.VariableDeclaration: - return createVariableDeclaration(newNamespaceId, /*type*/ undefined, createRequireCall(newModuleString)); + return factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); default: return Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); } @@ -274,7 +274,7 @@ namespace ts.refactor { const imports: string[] = []; newFileNeedExport.forEach(symbol => { if (symbol.escapedName === InternalSymbolName.Default) { - defaultImport = createIdentifier(symbolNameNoDefault(symbol)!); // TODO: GH#18217 + defaultImport = factory.createIdentifier(symbolNameNoDefault(symbol)!); // TODO: GH#18217 } else { imports.push(symbol.name); @@ -286,24 +286,24 @@ namespace ts.refactor { function makeImportOrRequire(defaultImport: Identifier | undefined, imports: readonly string[], path: string, useEs6Imports: boolean, quotePreference: QuotePreference): Statement | undefined { path = ensurePathIsNonModuleName(path); if (useEs6Imports) { - const specifiers = imports.map(i => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(i))); + const specifiers = imports.map(i => factory.createImportSpecifier(/*propertyName*/ undefined, factory.createIdentifier(i))); return makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); } else { Debug.assert(!defaultImport, "No default import should exist"); // If there's a default export, it should have been an es6 module. - const bindingElements = imports.map(i => createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i)); + const bindingElements = imports.map(i => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i)); return bindingElements.length - ? makeVariableStatement(createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(createLiteral(path))) + ? makeVariableStatement(factory.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(factory.createStringLiteral(path))) : undefined; } } function makeVariableStatement(name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined, flags: NodeFlags = NodeFlags.Const) { - return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([createVariableDeclaration(name, type, initializer)], flags)); + return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer)], flags)); } function createRequireCall(moduleSpecifier: StringLiteralLike): CallExpression { - return createCall(createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); + return factory.createCall(factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); } function addExports(sourceFile: SourceFile, toMove: readonly Statement[], needExport: ReadonlySymbolSet, useEs6Exports: boolean): readonly Statement[] { @@ -353,7 +353,7 @@ namespace ts.refactor { changes.replaceNode( sourceFile, importDecl.importClause, - updateImportClause(importDecl.importClause, name, /*namedBindings*/ undefined) + factory.updateImportClause(importDecl.importClause, name, /*namedBindings*/ undefined) ); } else if (namedBindings.kind === SyntaxKind.NamedImports) { @@ -555,7 +555,7 @@ namespace ts.refactor { const defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; const namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings - ? createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(defaultImport, namedBindings), moduleSpecifier) + ? factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(defaultImport, namedBindings), moduleSpecifier) : undefined; } case SyntaxKind.ImportEqualsDeclaration: @@ -574,7 +574,7 @@ namespace ts.refactor { } else { const newElements = namedBindings.elements.filter(e => keep(e.name)); - return newElements.length ? createNamedImports(newElements) : undefined; + return newElements.length ? factory.createNamedImports(newElements) : undefined; } } function filterBindingName(name: BindingName, keep: (name: Identifier) => boolean): BindingName | undefined { @@ -586,7 +586,7 @@ namespace ts.refactor { case SyntaxKind.ObjectBindingPattern: { // We can't handle nested destructurings or property names well here, so just copy them all. const newElements = name.elements.filter(prop => prop.propertyName || !isIdentifier(prop.name) || keep(prop.name)); - return newElements.length ? createObjectBindingPattern(newElements) : undefined; + return newElements.length ? factory.createObjectBindingPattern(newElements) : undefined; } } } @@ -747,24 +747,24 @@ namespace ts.refactor { return useEs6Exports ? [addEs6Export(decl)] : addCommonjsExport(decl); } function addEs6Export(d: TopLevelDeclarationStatement): TopLevelDeclarationStatement { - const modifiers = concatenate([createModifier(SyntaxKind.ExportKeyword)], d.modifiers); + const modifiers = concatenate([factory.createModifier(SyntaxKind.ExportKeyword)], d.modifiers); switch (d.kind) { case SyntaxKind.FunctionDeclaration: - return updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); + return factory.updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); case SyntaxKind.ClassDeclaration: - return updateClassDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); + return factory.updateClassDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); case SyntaxKind.VariableStatement: - return updateVariableStatement(d, modifiers, d.declarationList); + return factory.updateVariableStatement(d, modifiers, d.declarationList); case SyntaxKind.ModuleDeclaration: - return updateModuleDeclaration(d, d.decorators, modifiers, d.name, d.body); + return factory.updateModuleDeclaration(d, d.decorators, modifiers, d.name, d.body); case SyntaxKind.EnumDeclaration: - return updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); + return factory.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); case SyntaxKind.TypeAliasDeclaration: - return updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); + return factory.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); case SyntaxKind.InterfaceDeclaration: - return updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); + return factory.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); case SyntaxKind.ImportEqualsDeclaration: - return updateImportEqualsDeclaration(d, d.decorators, modifiers, d.name, d.moduleReference); + return factory.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.name, d.moduleReference); case SyntaxKind.ExpressionStatement: return Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: @@ -796,10 +796,10 @@ namespace ts.refactor { /** Creates `exports.x = x;` */ function createExportAssignment(name: string): Statement { - return createExpressionStatement( - createBinary( - createPropertyAccess(createIdentifier("exports"), createIdentifier(name)), + return factory.createExpressionStatement( + factory.createBinary( + factory.createPropertyAccess(factory.createIdentifier("exports"), factory.createIdentifier(name)), SyntaxKind.EqualsToken, - createIdentifier(name))); + factory.createIdentifier(name))); } } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 799fff86ecf0d..4bf9352bb8a32 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -569,7 +569,7 @@ namespace ts.SignatureHelp { const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const parameterParts = mapToDisplayParts(writer => { const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : []; - const params = createNodeArray([...thisParameter, ...checker.getExpandedParameters(candidateSignature).map(param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); + const params = factory.createNodeArray([...thisParameter, ...checker.getExpandedParameters(candidateSignature).map(param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); printer.writeList(ListFormat.CallExpressionArguments, params, sourceFile, writer); }); return { isVariadic: false, parameters, prefix: [punctuationPart(SyntaxKind.LessThanToken)], suffix: [punctuationPart(SyntaxKind.GreaterThanToken), ...parameterParts] }; @@ -580,7 +580,7 @@ namespace ts.SignatureHelp { const printer = createPrinter({ removeComments: true }); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { - const args = createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration)!)); + const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration)!)); printer.writeList(ListFormat.TypeParameters, args, sourceFile, writer); } }); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 07a75d884d9a2..7a9a7fabae7a9 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -344,7 +344,7 @@ namespace ts.textChanges { public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void { const pos = before.getStart(sourceFile); - this.insertNodeAt(sourceFile, pos, createToken(modifier), { suffix: " " }); + this.insertNodeAt(sourceFile, pos, factory.createToken(modifier), { suffix: " " }); } public insertLastModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void { @@ -354,7 +354,7 @@ namespace ts.textChanges { } const pos = before.modifiers.end; - this.insertNodeAt(sourceFile, pos, createToken(modifier), { prefix: " " }); + this.insertNodeAt(sourceFile, pos, factory.createToken(modifier), { prefix: " " }); } public insertCommentBeforeLine(sourceFile: SourceFile, lineNumber: number, position: number, commentText: string): void { @@ -463,7 +463,7 @@ namespace ts.textChanges { } private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: readonly Statement[]): void { - this.replaceNode(sourceFile, ctr.body!, createBlock(statements, /*multiLine*/ true)); + this.replaceNode(sourceFile, ctr.body!, factory.createBlock(statements, /*multiLine*/ true)); } public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void { @@ -529,7 +529,7 @@ namespace ts.textChanges { // check if previous statement ends with semicolon // if not - insert semicolon to preserve the code from changing the meaning due to ASI if (sourceFile.text.charCodeAt(after.end - 1) !== CharacterCodes.semicolon) { - this.replaceRange(sourceFile, createRange(after.end), createToken(SyntaxKind.SemicolonToken)); + this.replaceRange(sourceFile, createRange(after.end), factory.createToken(SyntaxKind.SemicolonToken)); } } const endPosition = getAdjustedEndPosition(sourceFile, after, {}); @@ -576,25 +576,25 @@ namespace ts.textChanges { const lparen = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); if (lparen) { // `() => {}` --> `function f() {}` - this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [createToken(SyntaxKind.FunctionKeyword), createIdentifier(name)], { joiner: " " }); + this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [factory.createToken(SyntaxKind.FunctionKeyword), factory.createIdentifier(name)], { joiner: " " }); deleteNode(this, sourceFile, arrow); } else { // `x => {}` -> `function f(x) {}` this.insertText(sourceFile, first(node.parameters).getStart(sourceFile), `function ${name}(`); // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)` - this.replaceRange(sourceFile, arrow, createToken(SyntaxKind.CloseParenToken)); + this.replaceRange(sourceFile, arrow, factory.createToken(SyntaxKind.CloseParenToken)); } if (node.body.kind !== SyntaxKind.Block) { // `() => 0` => `function f() { return 0; }` - this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [createToken(SyntaxKind.OpenBraceToken), createToken(SyntaxKind.ReturnKeyword)], { joiner: " ", suffix: " " }); - this.insertNodesAt(sourceFile, node.body.end, [createToken(SyntaxKind.SemicolonToken), createToken(SyntaxKind.CloseBraceToken)], { joiner: " " }); + this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [factory.createToken(SyntaxKind.OpenBraceToken), factory.createToken(SyntaxKind.ReturnKeyword)], { joiner: " ", suffix: " " }); + this.insertNodesAt(sourceFile, node.body.end, [factory.createToken(SyntaxKind.SemicolonToken), factory.createToken(SyntaxKind.CloseBraceToken)], { joiner: " " }); } } else { const pos = findChildOfKind(node, node.kind === SyntaxKind.FunctionExpression ? SyntaxKind.FunctionKeyword : SyntaxKind.ClassKeyword, sourceFile)!.end; - this.insertNodeAt(sourceFile, pos, createIdentifier(name), { prefix: " " }); + this.insertNodeAt(sourceFile, pos, factory.createIdentifier(name), { prefix: " " }); } } @@ -702,7 +702,7 @@ namespace ts.textChanges { } if (multilineList) { // insert separator immediately following the 'after' node to preserve comments in trailing trivia - this.replaceRange(sourceFile, createRange(end), createToken(separator)); + this.replaceRange(sourceFile, createRange(end), factory.createToken(separator)); // use the same indentation as 'after' item const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); // insert element before the line break on the line that contains 'after' element @@ -719,7 +719,7 @@ namespace ts.textChanges { } public parenthesizeExpression(sourceFile: SourceFile, expression: Expression) { - this.replaceRange(sourceFile, rangeOfNode(expression), createParen(expression)); + this.replaceRange(sourceFile, rangeOfNode(expression), factory.createParen(expression)); } private finishClassesWithNodesInsertedAtStart(): void { @@ -908,7 +908,7 @@ namespace ts.textChanges { return visited; } // clone nodearray if necessary - const nodeArray = visited === nodes ? createNodeArray(visited.slice(0)) : visited; + const nodeArray = visited === nodes ? factory.createNodeArray(visited.slice(0)) : visited; nodeArray.pos = getPos(nodes); nodeArray.end = getEnd(nodes); return nodeArray; @@ -1274,7 +1274,7 @@ namespace ts.textChanges { switch (gp.kind) { case SyntaxKind.ForOfStatement: case SyntaxKind.ForInStatement: - changes.replaceNode(sourceFile, node, createObjectLiteral()); + changes.replaceNode(sourceFile, node, factory.createObjectLiteral()); break; case SyntaxKind.ForStatement: diff --git a/src/services/transform.ts b/src/services/transform.ts index a3d0d7b10c3f0..c0d87f67b6f1e 100644 --- a/src/services/transform.ts +++ b/src/services/transform.ts @@ -9,7 +9,7 @@ namespace ts { const diagnostics: DiagnosticWithLocation[] = []; compilerOptions = fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217 const nodes = isArray(source) ? source : [source]; - const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); + const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, factory, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); result.diagnostics = concatenate(result.diagnostics, diagnostics); return result; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 315f61c967d92..d217e0353537b 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1322,17 +1322,17 @@ namespace ts { } export function makeImport(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string | Expression, quotePreference: QuotePreference): ImportDeclaration { - return createImportDeclaration( + return factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, defaultImport || namedImports - ? createImportClause(defaultImport, namedImports && namedImports.length ? createNamedImports(namedImports) : undefined) + ? factory.createImportClause(defaultImport, namedImports && namedImports.length ? factory.createNamedImports(namedImports) : undefined) : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier); } export function makeStringLiteral(text: string, quotePreference: QuotePreference): StringLiteral { - return createLiteral(text, quotePreference === QuotePreference.Single); + return factory.createStringLiteral(text, quotePreference === QuotePreference.Single); } export const enum QuotePreference { Single, Double } @@ -1753,7 +1753,7 @@ namespace ts { const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol))); if (renameInfo && renameInfo.text !== (node.name || node.propertyName).getText()) { - clone = createBindingElement( + clone = factory.createBindingElement( node.dotDotDotToken, node.propertyName || node.name, renameInfo, @@ -1765,7 +1765,7 @@ namespace ts { const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol))); if (renameInfo) { - clone = createIdentifier(renameInfo.text); + clone = factory.createIdentifier(renameInfo.text); } } @@ -1811,7 +1811,7 @@ namespace ts { export function getSynthesizedDeepClones(nodes: NodeArray, includeTrivia?: boolean): NodeArray; export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia?: boolean): NodeArray | undefined; export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia = true): NodeArray | undefined { - return nodes && createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); + return nodes && factory.createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); } /** diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index 11b4b88a0dbd0..14849818a126e 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -222,6 +222,12 @@ function handleTestConfig() { } function beginTests() { + ts.Debug.loggingHost = { + log(_level, s) { + console.log(s || ""); + } + }; + if (ts.Debug.isDebugging) { ts.Debug.enableDebugInfo(); } diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 6c120e3034908..4ae535f74e52f 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -176,6 +176,7 @@ "unittests/tsserver/typingsInstaller.ts", "unittests/tsserver/untitledFiles.ts", "unittests/tsserver/versionCache.ts", - "unittests/tsserver/watchEnvironment.ts" + "unittests/tsserver/watchEnvironment.ts", + "unittests/debugDeprecation.ts" ] } diff --git a/src/testRunner/unittests/asserts.ts b/src/testRunner/unittests/asserts.ts index 116a74cf17911..a0cde51a0f841 100644 --- a/src/testRunner/unittests/asserts.ts +++ b/src/testRunner/unittests/asserts.ts @@ -1,9 +1,9 @@ namespace ts { describe("unittests:: assert", () => { it("deepEqual", () => { - assert.throws(() => assert.deepEqual(createNodeArray([createIdentifier("A")]), createNodeArray([createIdentifier("B")]))); - assert.throws(() => assert.deepEqual(createNodeArray([], /*hasTrailingComma*/ true), createNodeArray([], /*hasTrailingComma*/ false))); - assert.deepEqual(createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true), createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true)); + assert.throws(() => assert.deepEqual(factory.createNodeArray([factory.createIdentifier("A")]), factory.createNodeArray([factory.createIdentifier("B")]))); + assert.throws(() => assert.deepEqual(factory.createNodeArray([], /*hasTrailingComma*/ true), factory.createNodeArray([], /*hasTrailingComma*/ false))); + assert.deepEqual(factory.createNodeArray([factory.createIdentifier("A")], /*hasTrailingComma*/ true), factory.createNodeArray([factory.createIdentifier("A")], /*hasTrailingComma*/ true)); }); it("assertNever on string has correct error", () => { assert.throws(() => Debug.assertNever("hi" as never), "Debug Failure. Illegal value: \"hi\""); diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index 2a2309d4b8786..f346ea47dd658 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -87,7 +87,7 @@ namespace ts { ` }], {before: [ context => node => visitNode(node, function visitor(node: Node): Node { - if (isStringLiteral(node) && node.text === "change") return createLiteral("changed"); + if (isStringLiteral(node) && node.text === "change") return factory.createStringLiteral("changed"); return visitEachChild(node, visitor, context); }) ]}, { @@ -143,7 +143,7 @@ namespace ts { context => { const transformSourceFile: Transformer = node => visitNode(node, function visitor(node: Node): Node { if (isIdentifier(node) && node.text === "original") { - const newNode = createIdentifier("changed"); + const newNode = factory.createIdentifier("changed"); setSourceMapRange(newNode, { pos: 0, end: 7, @@ -156,7 +156,7 @@ namespace ts { }); return { transformSourceFile, - transformBundle: node => createBundle(map(node.sourceFiles, transformSourceFile), node.prepends), + transformBundle: node => factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends), }; } ] diff --git a/src/testRunner/unittests/debugDeprecation.ts b/src/testRunner/unittests/debugDeprecation.ts new file mode 100644 index 0000000000000..6af425efdc822 --- /dev/null +++ b/src/testRunner/unittests/debugDeprecation.ts @@ -0,0 +1,88 @@ +namespace ts { + describe("unittests:: debugDeprecation", () => { + beforeEach(() => { + const loggingHost = Debug.loggingHost; + afterEach(() => { + Debug.loggingHost = loggingHost; + }); + }); + describe("deprecateFunction", () => { + it("silent deprecation", () => { + const deprecation = Debug.deprecateFunction(noop, { + warnAfter: "3.9", + typeScriptVersion: "3.8" + }); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + deprecation(); + assert.isFalse(logWritten); + }); + it("warning deprecation with warnAfter", () => { + const deprecation = Debug.deprecateFunction(noop, { + warnAfter: "3.9", + typeScriptVersion: "3.9" + }); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + deprecation(); + assert.isTrue(logWritten); + }); + it("warning deprecation without warnAfter", () => { + const deprecation = Debug.deprecateFunction(noop, { + typeScriptVersion: "3.9" + }); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + deprecation(); + assert.isTrue(logWritten); + }); + it("warning deprecation writes once", () => { + const deprecation = Debug.deprecateFunction(noop, { + typeScriptVersion: "3.9" + }); + let logWrites = 0; + Debug.loggingHost = { log() { logWrites++; } }; + deprecation(); + deprecation(); + assert.equal(logWrites, 1); + }); + it("error deprecation with errorAfter", () => { + const deprecation = Debug.deprecateFunction(noop, { + warnAfter: "3.8", + errorAfter: "3.9", + typeScriptVersion: "3.9" + }); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + expect(deprecation).throws(); + assert.isFalse(logWritten); + }); + it("error deprecation with error", () => { + const deprecation = Debug.deprecateFunction(noop, { + error: true, + }); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + expect(deprecation).throws(); + assert.isFalse(logWritten); + }); + }); + it("deprecateExport", () => { + const obj = { foo: noop }; + Debug.deprecateExport(obj, "foo"); + let logWritten = false; + Debug.loggingHost = { log() { logWritten = true; } }; + obj.foo(); + assert.isTrue(logWritten); + }); + it("deprecateExports", () => { + const obj = { foo: noop, bar: noop }; + Debug.deprecateExports(obj, ["foo", "bar"]); + let logWrites = 0; + Debug.loggingHost = { log() { logWrites++; } }; + obj.foo(); + obj.bar(); + assert.equal(logWrites, 2); + }); + }); +} \ No newline at end of file diff --git a/src/testRunner/unittests/factory.ts b/src/testRunner/unittests/factory.ts index ae4258287fedb..0959f882ddf0a 100644 --- a/src/testRunner/unittests/factory.ts +++ b/src/testRunner/unittests/factory.ts @@ -3,10 +3,10 @@ namespace ts { function assertSyntaxKind(node: Node, expected: SyntaxKind) { assert.strictEqual(node.kind, expected, `Actual: ${Debug.formatSyntaxKind(node.kind)} Expected: ${Debug.formatSyntaxKind(expected)}`); } - describe("createExportAssignment", () => { + describe("factory.createExportAssignment", () => { it("parenthesizes default export if necessary", () => { function checkExpression(expression: Expression) { - const node = createExportAssignment( + const node = factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, @@ -15,26 +15,26 @@ namespace ts { assertSyntaxKind(node.expression, SyntaxKind.ParenthesizedExpression); } - const clazz = createClassExpression(/*modifiers*/ undefined, "C", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - createProperty(/*decorators*/ undefined, [createToken(SyntaxKind.StaticKeyword)], "prop", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, createLiteral("1")), + const clazz = factory.createClassExpression(/*decorators*/ undefined, /*modifiers*/ undefined, "C", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createPropertyDeclaration(/*decorators*/ undefined, [factory.createToken(SyntaxKind.StaticKeyword)], "prop", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, factory.createStringLiteral("1")), ]); checkExpression(clazz); - checkExpression(createPropertyAccess(clazz, "prop")); + checkExpression(factory.createPropertyAccess(clazz, "prop")); - const func = createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, createBlock([])); + const func = factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, factory.createBlock([])); checkExpression(func); - checkExpression(createCall(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined)); - checkExpression(createTaggedTemplate(func, createNoSubstitutionTemplateLiteral(""))); + checkExpression(factory.createCall(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined)); + checkExpression(factory.createTaggedTemplate(func, /*typeArguments*/ undefined, factory.createNoSubstitutionTemplateLiteral(""))); - checkExpression(createBinary(createLiteral("a"), SyntaxKind.CommaToken, createLiteral("b"))); - checkExpression(createCommaList([createLiteral("a"), createLiteral("b")])); + checkExpression(factory.createBinary(factory.createStringLiteral("a"), SyntaxKind.CommaToken, factory.createStringLiteral("b"))); + checkExpression(factory.createCommaList([factory.createStringLiteral("a"), factory.createStringLiteral("b")])); }); }); - describe("createArrowFunction", () => { + describe("factory.createArrowFunction", () => { it("parenthesizes concise body if necessary", () => { function checkBody(body: ConciseBody) { - const node = createArrowFunction( + const node = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, [], @@ -45,28 +45,28 @@ namespace ts { assertSyntaxKind(node.body, SyntaxKind.ParenthesizedExpression); } - checkBody(createObjectLiteral()); - checkBody(createPropertyAccess(createObjectLiteral(), "prop")); - checkBody(createAsExpression(createPropertyAccess(createObjectLiteral(), "prop"), createTypeReferenceNode("T", /*typeArguments*/ undefined))); - checkBody(createNonNullExpression(createPropertyAccess(createObjectLiteral(), "prop"))); - checkBody(createCommaList([createLiteral("a"), createLiteral("b")])); - checkBody(createBinary(createLiteral("a"), SyntaxKind.CommaToken, createLiteral("b"))); + checkBody(factory.createObjectLiteral()); + checkBody(factory.createPropertyAccess(factory.createObjectLiteral(), "prop")); + checkBody(factory.createAsExpression(factory.createPropertyAccess(factory.createObjectLiteral(), "prop"), factory.createTypeReferenceNode("T", /*typeArguments*/ undefined))); + checkBody(factory.createNonNullExpression(factory.createPropertyAccess(factory.createObjectLiteral(), "prop"))); + checkBody(factory.createCommaList([factory.createStringLiteral("a"), factory.createStringLiteral("b")])); + checkBody(factory.createBinary(factory.createStringLiteral("a"), SyntaxKind.CommaToken, factory.createStringLiteral("b"))); }); }); describe("createBinaryExpression", () => { it("parenthesizes arrow function in RHS if necessary", () => { - const lhs = createIdentifier("foo"); - const rhs = createArrowFunction( + const lhs = factory.createIdentifier("foo"); + const rhs = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, - createBlock([]), + factory.createBlock([]), ); function checkRhs(operator: BinaryOperator, expectParens: boolean) { - const node = createBinary(lhs, operator, rhs); + const node = factory.createBinary(lhs, operator, rhs); assertSyntaxKind(node.right, expectParens ? SyntaxKind.ParenthesizedExpression : SyntaxKind.ArrowFunction); } diff --git a/src/testRunner/unittests/printer.ts b/src/testRunner/unittests/printer.ts index 1605e7edc6006..79a365fddf99d 100644 --- a/src/testRunner/unittests/printer.ts +++ b/src/testRunner/unittests/printer.ts @@ -73,7 +73,7 @@ namespace ts { const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly"); let bundle: Bundle; before(() => { - bundle = createBundle([ + bundle = factory.createBundle([ createSourceFile("a.ts", ` /*! [a.ts] */ @@ -96,16 +96,16 @@ namespace ts { const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly"); printsCorrectly("class", {}, printer => printer.printNode( EmitHint.Unspecified, - createClassDeclaration( + factory.createClassDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*name*/ createIdentifier("C"), + /*name*/ factory.createIdentifier("C"), /*typeParameters*/ undefined, /*heritageClauses*/ undefined, - [createProperty( + [factory.createPropertyDeclaration( /*decorators*/ undefined, - createNodeArray([createToken(SyntaxKind.PublicKeyword)]), - createIdentifier("prop"), + factory.createNodeArray([factory.createToken(SyntaxKind.PublicKeyword)]), + factory.createIdentifier("prop"), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined @@ -116,15 +116,15 @@ namespace ts { printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode( EmitHint.Unspecified, - createNamespaceExportDeclaration("B"), + factory.createNamespaceExportDeclaration("B"), createSourceFile("source.ts", "", ScriptTarget.ES2015) )); printsCorrectly("newExpressionWithPropertyAccessOnCallExpression", {}, printer => printer.printNode( EmitHint.Unspecified, - createNew( - createPropertyAccess( - createCall(createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), + factory.createNew( + factory.createPropertyAccess( + factory.createCall(factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), "x"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined @@ -134,11 +134,11 @@ namespace ts { printsCorrectly("newExpressionOnConditionalExpression", {}, printer => printer.printNode( EmitHint.Unspecified, - createNew( - createConditional( - createIdentifier("x"), createToken(SyntaxKind.QuestionToken), - createIdentifier("y"), createToken(SyntaxKind.ColonToken), - createIdentifier("z")), + factory.createNew( + factory.createConditional( + factory.createIdentifier("x"), factory.createToken(SyntaxKind.QuestionToken), + factory.createIdentifier("y"), factory.createToken(SyntaxKind.ColonToken), + factory.createIdentifier("z")), /*typeArguments*/ undefined, /*argumentsArray*/ undefined ), @@ -147,22 +147,22 @@ namespace ts { printsCorrectly("emptyGlobalAugmentation", {}, printer => printer.printNode( EmitHint.Unspecified, - createModuleDeclaration( + factory.createModuleDeclaration( /*decorators*/ undefined, - /*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)], - createIdentifier("global"), - createModuleBlock(emptyArray), + /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], + factory.createIdentifier("global"), + factory.createModuleBlock(emptyArray), NodeFlags.GlobalAugmentation), createSourceFile("source.ts", "", ScriptTarget.ES2015) )); printsCorrectly("emptyGlobalAugmentationWithNoDeclareKeyword", {}, printer => printer.printNode( EmitHint.Unspecified, - createModuleDeclaration( + factory.createModuleDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createIdentifier("global"), - createModuleBlock(emptyArray), + factory.createIdentifier("global"), + factory.createModuleBlock(emptyArray), NodeFlags.GlobalAugmentation), createSourceFile("source.ts", "", ScriptTarget.ES2015) )); @@ -170,30 +170,30 @@ namespace ts { // https://github.com/Microsoft/TypeScript/issues/15971 printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode( EmitHint.Unspecified, - createClassDeclaration( + factory.createClassDeclaration( /*decorators*/ undefined, - /*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)], - /*name*/ createIdentifier("X"), + /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], + /*name*/ factory.createIdentifier("X"), /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - createMethod( + factory.createMethodDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, - /*name*/ createIdentifier("method"), - /*questionToken*/ createToken(SyntaxKind.QuestionToken), + /*name*/ factory.createIdentifier("method"), + /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), /*typeParameters*/ undefined, [], - /*type*/ createKeywordTypeNode(SyntaxKind.VoidKeyword), + /*type*/ factory.createKeywordTypeNode(SyntaxKind.VoidKeyword), /*body*/ undefined ), - createProperty( + factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*name*/ createIdentifier("property"), - /*questionToken*/ createToken(SyntaxKind.QuestionToken), - /*type*/ createKeywordTypeNode(SyntaxKind.StringKeyword), + /*name*/ factory.createIdentifier("property"), + /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), + /*type*/ factory.createKeywordTypeNode(SyntaxKind.StringKeyword), /*initializer*/ undefined ), ] @@ -204,69 +204,69 @@ namespace ts { // https://github.com/Microsoft/TypeScript/issues/15651 printsCorrectly("functionTypes", {}, printer => printer.printNode( EmitHint.Unspecified, - createTupleTypeNode([ - createFunctionTypeNode( + factory.createTupleTypeNode([ + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createIdentifier("args") + factory.createIdentifier("args") )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createFunctionTypeNode( - [createTypeParameterDeclaration("T")], - [createParameter( + factory.createFunctionTypeNode( + [factory.createTypeParameterDeclaration("T")], + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createIdentifier("args") + factory.createIdentifier("args") )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createToken(SyntaxKind.DotDotDotToken), - createIdentifier("args") + factory.createToken(SyntaxKind.DotDotDotToken), + factory.createIdentifier("args") )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createIdentifier("args"), - createToken(SyntaxKind.QuestionToken) + factory.createIdentifier("args"), + factory.createToken(SyntaxKind.QuestionToken) )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createIdentifier("args"), + factory.createIdentifier("args"), /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [createParameter( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - createObjectBindingPattern([]) + factory.createObjectBindingPattern([]) )], - createKeywordTypeNode(SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), ]), createSourceFile("source.ts", "", ScriptTarget.ES2015) diff --git a/src/testRunner/unittests/services/textChanges.ts b/src/testRunner/unittests/services/textChanges.ts index 2d76b64696d64..f18e2dfca222d 100644 --- a/src/testRunner/unittests/services/textChanges.ts +++ b/src/testRunner/unittests/services/textChanges.ts @@ -82,22 +82,22 @@ namespace M }`; runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { const statements = (findChild("foo", sourceFile)).body!.statements.slice(1); - const newFunction = createFunctionDeclaration( + const newFunction = factory.createFunctionDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ "bar", /*typeParameters*/ undefined, /*parameters*/ emptyArray, - /*type*/ createKeywordTypeNode(SyntaxKind.AnyKeyword), - /*body */ createBlock(statements) + /*type*/ factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + /*body */ factory.createBlock(statements) ); changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction); // replace statements with return statement - const newStatement = createReturn( - createCall( + const newStatement = factory.createReturn( + factory.createCall( /*expression*/ newFunction.name!, /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray @@ -178,31 +178,31 @@ var a = 4; // comment 7 }); } function createTestVariableDeclaration(name: string) { - return createVariableDeclaration(name, /*type*/ undefined, createObjectLiteral([createPropertyAssignment("p1", createLiteral(1))], /*multiline*/ true)); + return factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createObjectLiteral([factory.createPropertyAssignment("p1", factory.createNumericLiteral(1))], /*multiline*/ true)); } function createTestClass() { - return createClassDeclaration( + return factory.createClassDeclaration( /*decorators*/ undefined, [ - createToken(SyntaxKind.PublicKeyword) + factory.createToken(SyntaxKind.PublicKeyword) ], "class1", /*typeParameters*/ undefined, [ - createHeritageClause( + factory.createHeritageClause( SyntaxKind.ImplementsKeyword, [ - createExpressionWithTypeArguments(/*typeArguments*/ undefined, createIdentifier("interface1")) + factory.createExpressionWithTypeArguments(factory.createIdentifier("interface1"), /*typeArguments*/ undefined) ] ) ], [ - createProperty( + factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, "property1", /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.BooleanKeyword), + factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), /*initializer*/ undefined ) ] @@ -333,12 +333,12 @@ namespace M { return find(classDecl.members, (m): m is ConstructorDeclaration => isConstructorDeclaration(m) && !!m.body)!; } function createTestSuperCall() { - const superCall = createCall( - createSuper(), + const superCall = factory.createCall( + factory.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray ); - return createStatement(superCall); + return factory.createExpressionStatement(superCall); } { @@ -484,27 +484,27 @@ function foo( const text = ` const x = 1, y = 2;`; runSingleFileTest("insertNodeInListAfter1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { const text = ` const /*x*/ x = 1, /*y*/ y = 2;`; runSingleFileTest("insertNodeInListAfter3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { const text = ` const x = 1;`; runSingleFileTest("insertNodeInListAfter5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -512,10 +512,10 @@ const x = 1;`; const x = 1, y = 2;`; runSingleFileTest("insertNodeInListAfter6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -523,10 +523,10 @@ const x = 1, const /*x*/ x = 1, /*y*/ y = 2;`; runSingleFileTest("insertNodeInListAfter8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -535,7 +535,7 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -544,7 +544,7 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -553,7 +553,8 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a"))); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); }); } { @@ -562,7 +563,8 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a"))); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); }); } { @@ -572,7 +574,7 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -582,7 +584,7 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -592,7 +594,8 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter16", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a"))); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); }); } { @@ -602,7 +605,8 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter17", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a"))); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); }); } { @@ -611,7 +615,8 @@ import { x0, x } from "bar"`; runSingleFileTest("insertNodeInListAfter18", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a"))); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a"))); }); } { @@ -623,7 +628,8 @@ class A { const newNodes = []; for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) { newNodes.push( - createProperty(undefined, undefined, i + "", undefined, undefined, undefined)); + // eslint-disable-next-line boolean-trivia + factory.createPropertyDeclaration(undefined, undefined, i + "", undefined, undefined, undefined)); } const insertAfter = findChild("x", sourceFile); for (const newNode of newNodes) { @@ -638,7 +644,8 @@ class A { } `; runSingleFileTest("insertNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); }); } { @@ -648,7 +655,8 @@ class A { } `; runSingleFileTest("insertNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); + // eslint-disable-next-line boolean-trivia + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); }); } { @@ -680,12 +688,12 @@ class A { } `; runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createProperty( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createComputedPropertyName(createLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -698,12 +706,12 @@ class A { } `; runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createProperty( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createComputedPropertyName(createLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -715,12 +723,12 @@ interface A { } `; runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createProperty( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createComputedPropertyName(createLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -732,12 +740,12 @@ interface A { } `; runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createProperty( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createComputedPropertyName(createLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - createKeywordTypeNode(SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -747,7 +755,7 @@ interface A { let x = foo `; runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createStatement(createParen(createLiteral(1))); + const newNode = factory.createExpressionStatement(factory.createParen(factory.createNumericLiteral(1))); changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode); }); } diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index bcb0c93d1a8c6..3059b8420522a 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -6,10 +6,10 @@ namespace ts { context.onSubstituteNode = (hint, node) => { node = previousOnSubstituteNode(hint, node); if (hint === EmitHint.Expression && isIdentifier(node) && node.escapedText === "undefined") { - node = createPartiallyEmittedExpression( + node = factory.createPartiallyEmittedExpression( addSyntheticTrailingComment( setTextRange( - createVoidZero(), + factory.createVoidZero(), node), SyntaxKind.MultiLineCommentTrivia, "undefined")); } @@ -20,7 +20,7 @@ namespace ts { function replaceNumberWith2(context: TransformationContext) { function visitor(node: Node): Node { if (isNumericLiteral(node)) { - return createNumericLiteral("2"); + return factory.createNumericLiteral("2"); } return visitEachChild(node, visitor, context); } @@ -33,7 +33,7 @@ namespace ts { context.onSubstituteNode = (hint, node) => { node = previousOnSubstituteNode(hint, node); if (isIdentifier(node) && node.escapedText === "oldName") { - node = setTextRange(createIdentifier("newName"), node); + node = setTextRange(factory.createIdentifier("newName"), node); } return node; }; @@ -43,7 +43,7 @@ namespace ts { function replaceIdentifiersNamedOldNameWithNewName2(context: TransformationContext) { const visitor: Visitor = (node) => { if (isIdentifier(node) && node.text === "oldName") { - return createIdentifier("newName"); + return factory.createIdentifier("newName"); } return visitEachChild(node, visitor, context); }; @@ -56,7 +56,7 @@ namespace ts { onEmitNode: transformed.emitNodeWithNotification, substituteNode: transformed.substituteNode }); - const result = printer.printBundle(createBundle(transformed.transformed)); + const result = printer.printBundle(factory.createBundle(transformed.transformed)); transformed.dispose(); return result; } @@ -175,9 +175,9 @@ namespace ts { function replaceWithClassAndNamespace() { return (sourceFile: SourceFile) => { const result = getMutableClone(sourceFile); - result.statements = createNodeArray([ - createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 - createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) + result.statements = factory.createNodeArray([ + factory.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 + factory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createIdentifier("Foo"), factory.createModuleBlock([factory.createEmptyStatement()])) ]); return result; }; @@ -191,8 +191,8 @@ namespace ts { function visitNode(node: T): T { if (node.kind === SyntaxKind.ModuleBlock) { const block = node as T & ModuleBlock; - const statements = createNodeArray([...block.statements]); - return updateModuleBlock(block, statements) as typeof block; + const statements = factory.createNodeArray([...block.statements]); + return factory.updateModuleBlock(block, statements) as typeof block; } return visitEachChild(node, visitNode, context); } @@ -218,9 +218,9 @@ namespace ts { if (node.kind === SyntaxKind.ExportDeclaration) { const ed = node as Node as ExportDeclaration; const exports = [{ name: "x" }]; - const exportSpecifiers = exports.map(e => createExportSpecifier(e.name, e.name)); - const exportClause = createNamedExports(exportSpecifiers); - const newEd = updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier); + const exportSpecifiers = exports.map(e => factory.createExportSpecifier(e.name, e.name)); + const exportClause = factory.createNamedExports(exportSpecifiers); + const newEd = factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier); return newEd as Node as T; } @@ -249,15 +249,15 @@ namespace ts { }; function visitNode(sf: SourceFile) { // produce `import * as i0 from './comp'; - const importStar = createImportDeclaration( + const importStar = factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*importClause*/ createImportClause( + /*importClause*/ factory.createImportClause( /*name*/ undefined, - createNamespaceImport(createIdentifier("i0")) + factory.createNamespaceImport(factory.createIdentifier("i0")) ), - /*moduleSpecifier*/ createLiteral("./comp1")); - return updateSourceFileNode(sf, [importStar]); + /*moduleSpecifier*/ factory.createStringLiteral("./comp1")); + return factory.updateSourceFile(sf, [importStar]); } } }); @@ -280,10 +280,10 @@ namespace ts { }; function visitNode(sf: SourceFile) { // produce `class Foo { @Bar baz() {} }`; - const classDecl = createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - createMethod([createDecorator(createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, createBlock([])) + const classDecl = factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createMethodDeclaration([factory.createDecorator(factory.createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, factory.createBlock([])) ]); - return updateSourceFileNode(sf, [classDecl]); + return factory.updateSourceFile(sf, [classDecl]); } } }); @@ -319,11 +319,11 @@ namespace ts { function visitNode(sf: SourceFile) { // produce `class Foo { constructor(@Dec private x) {} }`; // The decorator is required to trigger ts.ts transformations. - const classDecl = createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, [ - createParameter(/*decorators*/ [createDecorator(createIdentifier("Dec"))], /*modifiers*/ [createModifier(SyntaxKind.PrivateKeyword)], /*dotDotDotToken*/ undefined, "x")], createBlock([])) + const classDecl = factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, [ + factory.createParameterDeclaration(/*decorators*/ [factory.createDecorator(factory.createIdentifier("Dec"))], /*modifiers*/ [factory.createModifier(SyntaxKind.PrivateKeyword)], /*dotDotDotToken*/ undefined, "x")], factory.createBlock([])) ]); - return updateSourceFileNode(sf, [classDecl]); + return factory.updateSourceFile(sf, [classDecl]); } } }); @@ -469,7 +469,7 @@ module MyModule { }; function rootTransform(node: T): Node { if (isVariableDeclaration(node)) { - return updateVariableDeclaration(node, createIdentifier("newName"), /* type */ undefined, node.initializer); + return factory.updateVariableDeclaration(node, factory.createIdentifier("newName"), /*exclamationToken*/ undefined, /*type*/ undefined, node.initializer); } return visitEachChild(node, rootTransform, context); } @@ -495,12 +495,12 @@ module MyModule { function transformSourceFile(context: TransformationContext) { const visitor: Visitor = (node) => { if (isMethodDeclaration(node)) { - return updateMethod( + return factory.updateMethodDeclaration( node, node.decorators, node.modifiers, node.asteriskToken, - createIdentifier("foobar"), + factory.createIdentifier("foobar"), node.questionToken, node.typeParameters, node.parameters, @@ -529,7 +529,7 @@ module MyModule { function transformSourceFile(context: TransformationContext): Transformer { function visitor(node: Node): VisitResult { if (isNoSubstitutionTemplateLiteral(node)) { - return createNoSubstitutionTemplateLiteral(node.text, node.rawText); + return factory.createNoSubstitutionTemplateLiteral(node.text, node.rawText); } else { return visitEachChild(node, visitor, context); diff --git a/src/tsc/executeCommandLine.ts b/src/tsc/executeCommandLine.ts index d730de4a981d3..aad4440001948 100644 --- a/src/tsc/executeCommandLine.ts +++ b/src/tsc/executeCommandLine.ts @@ -716,6 +716,12 @@ namespace ts { } } +ts.Debug.loggingHost = { + log(_level, s) { + ts.sys.write(`${s || ""}${ts.sys.newLine}`); + } +}; + if (ts.Debug.isDebugging) { ts.Debug.enableDebugInfo(); } diff --git a/src/tsserver/tsconfig.json b/src/tsserver/tsconfig.json index 16ffd722f2d63..52f9fcc4d66f0 100644 --- a/src/tsserver/tsconfig.json +++ b/src/tsserver/tsconfig.json @@ -14,6 +14,7 @@ { "path": "../compiler", "prepend": true }, { "path": "../services", "prepend": true }, { "path": "../jsTyping", "prepend": true }, - { "path": "../server", "prepend": true } + { "path": "../server", "prepend": true }, + { "path": "../compat", "prepend": true } ] } diff --git a/src/tsserverlibrary/tsconfig.json b/src/tsserverlibrary/tsconfig.json index f9953772f1fe9..b9012d8d6fc47 100644 --- a/src/tsserverlibrary/tsconfig.json +++ b/src/tsserverlibrary/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../compiler", "prepend": true }, { "path": "../jsTyping", "prepend": true }, { "path": "../services", "prepend": true }, - { "path": "../server", "prepend": true } + { "path": "../server", "prepend": true }, + { "path": "../compat", "prepend": true } ] } diff --git a/src/typescriptServices/tsconfig.json b/src/typescriptServices/tsconfig.json index 33028aad27ce7..62b5d66f0f562 100644 --- a/src/typescriptServices/tsconfig.json +++ b/src/typescriptServices/tsconfig.json @@ -10,6 +10,7 @@ { "path": "../shims", "prepend": true }, { "path": "../compiler", "prepend": true }, { "path": "../jsTyping", "prepend": true }, - { "path": "../services", "prepend": true } + { "path": "../services", "prepend": true }, + { "path": "../compat", "prepend": true } ] } diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json index 9817af1157fb8..a07acaedb36a9 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json @@ -5,6 +5,7 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, + "comment": "{@link first link}\nInside {@link link text} thing", "tags": { "0": { "kind": "JSDocTag", @@ -25,6 +26,5 @@ "length": 1, "pos": 63, "end": 68 - }, - "comment": "{@link first link}\nInside {@link link text} thing" + } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json index 05eb12758911d..d9b8e28465213 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Doc doc", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 34, @@ -32,8 +33,8 @@ "end": 64, "modifierFlagsCache": 0, "transformFlags": 0, - "jsDocPropertyTags": [ - { + "jsDocPropertyTags": { + "0": { "kind": "JSDocParameterTag", "pos": 34, "end": 64, @@ -47,6 +48,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Doc for f", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 41, @@ -85,10 +87,13 @@ } }, "isNameFirst": false, - "isBracketed": false, - "comment": "Doc for f" - } - ] + "isBracketed": false + }, + "length": 1, + "pos": -1, + "end": -1 + }, + "isArrayType": false } }, "name": { @@ -100,8 +105,7 @@ "escapedText": "o" }, "isNameFirst": true, - "isBracketed": false, - "comment": "Doc doc" + "isBracketed": false }, "length": 1, "pos": 6, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json index 3a6ee3365dcfc..3e253bc7357b1 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argSynonymForParamTag.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "arg" }, + "comment": "Description", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 13, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": false, - "isBracketed": false, - "comment": "Description" + "isBracketed": false }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json index 2fa5734c1a36b..3f4cba67e1dac 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.argumentSynonymForParamTag.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "argument" }, + "comment": "Description", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 18, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": false, - "isBracketed": false, - "comment": "Description" + "isBracketed": false }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.less-than and greater-than characters.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.less-than and greater-than characters.json index e0a57b72e9386..16c0da9d8bfe5 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.less-than and greater-than characters.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.less-than and greater-than characters.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "hi\n< > still part of the previous comment", "name": { "kind": "Identifier", "pos": 14, @@ -29,8 +30,7 @@ "escapedText": "x" }, "isNameFirst": true, - "isBracketed": false, - "comment": "hi\n< > still part of the previous comment" + "isBracketed": false }, "length": 1, "pos": 7, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json index 712ac49a36f19..05bf95a8c4f75 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Description text follows", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": false, - "isBracketed": false, - "comment": "Description text follows" + "isBracketed": false }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json index 3eebbc73ba904..7e6a7f86ee148 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Description text follows", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": false, - "isBracketed": true, - "comment": "Description text follows" + "isBracketed": true }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json index d864cbeafd23e..03ecb9d4e8588 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Description text follows", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 15, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": false, - "isBracketed": true, - "comment": "Description text follows" + "isBracketed": true }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json index 4c29e477e1078..e8e72f69a0f09 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "param" }, + "comment": "Description", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 21, @@ -43,8 +44,7 @@ "escapedText": "name1" }, "isNameFirst": true, - "isBracketed": false, - "comment": "Description" + "isBracketed": false }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json index 5fe9854187d2e..42f6bd6512f06 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json @@ -21,6 +21,7 @@ "originalKeywordKind": "ReturnKeyword", "escapedText": "return" }, + "comment": "Description text follows", "typeExpression": { "kind": "JSDocTypeExpression", "pos": 16, @@ -34,8 +35,7 @@ "modifierFlagsCache": 0, "transformFlags": 0 } - }, - "comment": "Description text follows" + } }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json index c3e885082a69e..c02a2652988e7 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json @@ -20,6 +20,7 @@ "transformFlags": 0, "escapedText": "template" }, + "comment": "Description of type parameters.", "typeParameters": { "0": { "kind": "TypeParameter", @@ -54,8 +55,7 @@ "length": 2, "pos": 18, "end": 24 - }, - "comment": "Description of type parameters." + } }, "length": 1, "pos": 8, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json index 623073917980d..1f96a67a0d9ce 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -20,30 +20,14 @@ "transformFlags": 0, "escapedText": "typedef" }, - "fullName": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "modifierFlagsCache": 0, - "transformFlags": 0, - "escapedText": "People" - }, - "name": { - "kind": "Identifier", - "pos": 17, - "end": 23, - "modifierFlagsCache": 0, - "transformFlags": 0, - "escapedText": "People" - }, "typeExpression": { "kind": "JSDocTypeLiteral", "pos": 8, "end": 100, "modifierFlagsCache": 0, "transformFlags": 0, - "jsDocPropertyTags": [ - { + "jsDocPropertyTags": { + "0": { "kind": "JSDocPropertyTag", "pos": 47, "end": 74, @@ -82,7 +66,7 @@ "isNameFirst": false, "isBracketed": false }, - { + "1": { "kind": "JSDocPropertyTag", "pos": 74, "end": 100, @@ -120,8 +104,27 @@ }, "isNameFirst": false, "isBracketed": false - } - ] + }, + "length": 2, + "pos": -1, + "end": -1 + } + }, + "fullName": { + "kind": "Identifier", + "pos": 17, + "end": 23, + "modifierFlagsCache": 0, + "transformFlags": 0, + "escapedText": "People" + }, + "name": { + "kind": "Identifier", + "pos": 17, + "end": 23, + "modifierFlagsCache": 0, + "transformFlags": 0, + "escapedText": "People" } }, "length": 1, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json index 4259856647a0b..f4acddf47c92b 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json @@ -1,8 +1,16 @@ { - "kind": "NullKeyword", + "kind": "LiteralType", "pos": 1, "end": 5, "flags": "JSDoc", "modifierFlagsCache": 0, - "transformFlags": 0 + "transformFlags": 0, + "literal": { + "kind": "NullKeyword", + "pos": 1, + "end": 5, + "flags": "JSDoc", + "modifierFlagsCache": 0, + "transformFlags": 0 + } } \ No newline at end of file diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 94c856cfd0401..0a4feee687f92 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -72,9 +72,6 @@ declare namespace ts { pos: number; end: number; } - export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; - export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; export enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -434,6 +431,16 @@ declare namespace ts { FirstJSDocTagNode = 304, LastJSDocTagNode = 316, } + export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; + export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; + export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; + export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.StaticKeyword; + export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; + export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; + export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; + export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; export enum NodeFlags { None = 0, Let = 1, @@ -502,7 +509,7 @@ declare namespace ts { } export interface JSDocContainer { } - export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | EndOfFileToken; + export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | EndOfFileToken; export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertySignature | PropertyDeclaration | PropertyAssignment | EnumMember; @@ -512,22 +519,47 @@ declare namespace ts { export interface Token extends Node { kind: TKind; } - export type DotToken = Token; - export type DotDotDotToken = Token; - export type QuestionToken = Token; - export type QuestionDotToken = Token; - export type ExclamationToken = Token; - export type ColonToken = Token; - export type EqualsToken = Token; - export type AsteriskToken = Token; - export type EqualsGreaterThanToken = Token; export type EndOfFileToken = Token & JSDocContainer; - export type ReadonlyToken = Token; - export type AwaitKeywordToken = Token; - export type PlusToken = Token; - export type MinusToken = Token; - export type AssertsToken = Token; - export type Modifier = Token | Token | Token | Token | Token | Token | Token | Token | Token | Token | Token; + export interface PunctuationToken extends Token { + } + export type DotToken = PunctuationToken; + export type DotDotDotToken = PunctuationToken; + export type QuestionToken = PunctuationToken; + export type ExclamationToken = PunctuationToken; + export type ColonToken = PunctuationToken; + export type EqualsToken = PunctuationToken; + export type AsteriskToken = PunctuationToken; + export type EqualsGreaterThanToken = PunctuationToken; + export type PlusToken = PunctuationToken; + export type MinusToken = PunctuationToken; + export type QuestionDotToken = PunctuationToken; + export interface KeywordToken extends Token { + } + export type AssertsKeyword = KeywordToken; + export type AwaitKeyword = KeywordToken; + /** @deprecated Use `AwaitKeyword` instead. */ + export type AwaitKeywordToken = AwaitKeyword; + /** @deprecated Use `AssertsKeyword` instead. */ + export type AssertsToken = AssertsKeyword; + export interface ModifierToken extends KeywordToken { + } + export type AbstractKeyword = ModifierToken; + export type AsyncKeyword = ModifierToken; + export type ConstKeyword = ModifierToken; + export type DeclareKeyword = ModifierToken; + export type DefaultKeyword = ModifierToken; + export type ExportKeyword = ModifierToken; + export type PrivateKeyword = ModifierToken; + export type ProtectedKeyword = ModifierToken; + export type PublicKeyword = ModifierToken; + export type ReadonlyKeyword = ModifierToken; + export type StaticKeyword = ModifierToken; + /** @deprecated Use `ReadonlyKeyword` instead. */ + export type ReadonlyToken = ReadonlyKeyword; + export type Modifier = AbstractKeyword | AsyncKeyword | ConstKeyword | DeclareKeyword | DefaultKeyword | ExportKeyword | PrivateKeyword | ProtectedKeyword | PublicKeyword | ReadonlyKeyword | StaticKeyword; + export type AccessibilityModifier = PublicKeyword | PrivateKeyword | ProtectedKeyword; + export type ParameterPropertyModifier = AccessibilityModifier | ReadonlyKeyword; + export type ClassMemberModifier = AccessibilityModifier | ReadonlyKeyword | StaticKeyword; export type ModifiersArray = NodeArray; export interface Identifier extends PrimaryExpression, Declaration { kind: SyntaxKind.Identifier; @@ -650,6 +682,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; + exclamationToken?: ExclamationToken; initializer: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { @@ -746,8 +779,8 @@ declare namespace ts { export interface TypeNode extends Node { _typeNodeBrand: any; } - export interface KeywordTypeNode extends TypeNode { - kind: SyntaxKind.AnyKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.NumberKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.VoidKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.NullKeyword | SyntaxKind.NeverKeyword; + export interface KeywordTypeNode extends KeywordToken, TypeNode { + kind: TKind; } export interface ImportTypeNode extends NodeWithTypeArguments { kind: SyntaxKind.ImportType; @@ -851,12 +884,13 @@ declare namespace ts { } export interface LiteralTypeNode extends TypeNode { kind: SyntaxKind.LiteralType; - literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression; + literal: NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; } export interface StringLiteral extends LiteralExpression, Declaration { kind: SyntaxKind.StringLiteral; } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; + export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; export interface Expression extends Node { _expressionBrand: any; } @@ -896,13 +930,17 @@ declare namespace ts { export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } - export interface NullLiteral extends PrimaryExpression, TypeNode { + export interface NullLiteral extends PrimaryExpression { kind: SyntaxKind.NullKeyword; } - export interface BooleanLiteral extends PrimaryExpression, TypeNode { - kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword; + export interface TrueLiteral extends PrimaryExpression { + kind: SyntaxKind.TrueKeyword; } - export interface ThisExpression extends PrimaryExpression, KeywordTypeNode { + export interface FalseLiteral extends PrimaryExpression { + kind: SyntaxKind.FalseKeyword; + } + export type BooleanLiteral = TrueLiteral | FalseLiteral; + export interface ThisExpression extends PrimaryExpression { kind: SyntaxKind.ThisKeyword; } export interface SuperExpression extends PrimaryExpression { @@ -975,7 +1013,9 @@ declare namespace ts { left: ArrayLiteralExpression; } export type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment; - export type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; + export type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | ObjectBindingOrAssignmentElement | ArrayBindingOrAssignmentElement; + export type ObjectBindingOrAssignmentElement = BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment; + export type ArrayBindingOrAssignmentElement = BindingElement | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; export type BindingOrAssignmentElementRestIndicator = DotDotDotToken | SpreadElement | SpreadAssignment; export type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Identifier | PropertyAccessExpression | ElementAccessExpression | OmittedExpression; export type ObjectBindingOrAssignmentPattern = ObjectBindingPattern | ObjectLiteralExpression; @@ -1034,6 +1074,7 @@ declare namespace ts { export interface BigIntLiteral extends LiteralExpression { kind: SyntaxKind.BigIntLiteral; } + export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { kind: SyntaxKind.TemplateHead; parent: TemplateExpression; @@ -1046,12 +1087,14 @@ declare namespace ts { kind: SyntaxKind.TemplateTail; parent: TemplateSpan; } - export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; + export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; + export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; export interface TemplateExpression extends PrimaryExpression { kind: SyntaxKind.TemplateExpression; head: TemplateHead; templateSpans: NodeArray; } + export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; export interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; parent: TemplateExpression; @@ -1473,7 +1516,7 @@ declare namespace ts { parent: ImportEqualsDeclaration; expression: Expression; } - export interface ImportDeclaration extends Statement { + export interface ImportDeclaration extends Statement, JSDocContainer { kind: SyntaxKind.ImportDeclaration; parent: SourceFile | ModuleBlock; importClause?: ImportClause; @@ -1492,7 +1535,7 @@ declare namespace ts { parent: ImportClause; name: Identifier; } - export interface NamespaceExportDeclaration extends DeclarationStatement { + export interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.NamespaceExportDeclaration; name: Identifier; } @@ -1532,7 +1575,7 @@ declare namespace ts { * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ - export interface ExportAssignment extends DeclarationStatement { + export interface ExportAssignment extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ExportAssignment; parent: SourceFile; isExportEquals?: boolean; @@ -2915,7 +2958,376 @@ declare namespace ts { Unspecified = 4, EmbeddedStatement = 5 } - export interface TransformationContext { + export enum OuterExpressionKinds { + Parentheses = 1, + Assertions = 2, + PartiallyEmittedExpressions = 4, + All = 7 + } + export type TypeOfTag = "undefined" | "number" | "bigint" | "boolean" | "string" | "symbol" | "object" | "function"; + export interface NodeFactory { + createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; + createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; + createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; + createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; + createStringLiteralFromNode(sourceNode: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; + createRegularExpressionLiteral(text: string): RegularExpressionLiteral; + createIdentifier(text: string): Identifier; + /** Create a unique temporary variable. */ + createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** Create a unique temporary variable for use in a loop. */ + createLoopVariable(): Identifier; + /** Create a unique name based on the supplied text. */ + createUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. */ + createOptimisticUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ + createFileLevelUniqueName(text: string): Identifier; + /** Create a unique name generated for a node. */ + getGeneratedNameForNode(node: Node | undefined): Identifier; + createToken(token: SyntaxKind.SuperKeyword): SuperExpression; + createToken(token: SyntaxKind.ThisKeyword): ThisExpression; + createToken(token: SyntaxKind.NullKeyword): NullLiteral; + createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; + createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: TKind): PunctuationToken; + createToken(token: TKind): KeywordTypeNode; + createToken(token: TKind): ModifierToken; + createToken(token: TKind): KeywordToken; + createToken(token: TKind): Token; + createSuper(): SuperExpression; + createThis(): ThisExpression; + createNull(): NullLiteral; + createTrue(): TrueLiteral; + createFalse(): FalseLiteral; + createModifier(kind: T): ModifierToken; + createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[]; + createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName; + updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; + createComputedPropertyName(expression: Expression): ComputedPropertyName; + updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; + createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; + updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; + createParameterDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; + updateParameterDeclaration(node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createDecorator(expression: Expression): Decorator; + updateDecorator(node: Decorator, expression: Expression): Decorator; + createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + createPropertyDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + updatePropertyDeclaration(node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; + updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; + createMethodDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; + updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; + createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; + updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; + createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createKeywordTypeNode(kind: TKind): KeywordTypeNode; + createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; + updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; + updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; + createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode; + updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode; + createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode; + updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; + createTypeQueryNode(exprName: EntityName): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; + updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; + createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; + updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; + createTupleTypeNode(elementTypes: readonly TypeNode[]): TupleTypeNode; + updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]): TupleTypeNode; + createOptionalTypeNode(type: TypeNode): OptionalTypeNode; + updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; + createRestTypeNode(type: TypeNode): RestTypeNode; + updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode; + createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode; + updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; + createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; + updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; + createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; + updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; + createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; + updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; + createThisTypeNode(): ThisTypeNode; + createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; + createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; + updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; + updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; + createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; + updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; + updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; + createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; + updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; + updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier): PropertyAccessChain; + updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier): PropertyAccessChain; + createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; + updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; + createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; + updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; + createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; + updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; + createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; + updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; + createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; + updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; + createParen(expression: Expression): ParenthesizedExpression; + updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; + createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; + updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; + createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createDelete(expression: Expression): DeleteExpression; + updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression; + createTypeOf(expression: Expression): TypeOfExpression; + updateTypeOf(node: TypeOfExpression, expression: Expression): TypeOfExpression; + createVoid(expression: Expression): VoidExpression; + updateVoid(node: VoidExpression, expression: Expression): VoidExpression; + createAwait(expression: Expression): AwaitExpression; + updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; + createPrefix(operator: PrefixUnaryOperator, operand: Expression): PrefixUnaryExpression; + updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; + createPostfix(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; + updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; + createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; + updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken): BinaryExpression; + createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + updateConditional(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + createTemplateHead(text: string, rawText?: string): TemplateHead; + createTemplateHead(text: string | undefined, rawText: string): TemplateHead; + createTemplateMiddle(text: string, rawText?: string): TemplateMiddle; + createTemplateMiddle(text: string | undefined, rawText: string): TemplateMiddle; + createTemplateTail(text: string, rawText?: string): TemplateTail; + createTemplateTail(text: string | undefined, rawText: string): TemplateTail; + createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; + createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; + createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + createYield(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; + updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + createSpread(expression: Expression): SpreadElement; + updateSpread(node: SpreadElement, expression: Expression): SpreadElement; + createClassExpression(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + updateClassExpression(node: ClassExpression, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createOmittedExpression(): OmittedExpression; + createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createAsExpression(expression: Expression, type: TypeNode): AsExpression; + updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; + createNonNullExpression(expression: Expression): NonNullExpression; + updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression; + createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; + updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + createSemicolonClassElement(): SemicolonClassElement; + createBlock(statements: readonly Statement[], multiLine?: boolean): Block; + updateBlock(node: Block, statements: readonly Statement[]): Block; + createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; + updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createEmptyStatement(): EmptyStatement; + createExpressionStatement(expression: Expression): ExpressionStatement; + updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; + updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + createDo(statement: Statement, expression: Expression): DoStatement; + updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; + createWhile(expression: Expression, statement: Statement): WhileStatement; + updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; + createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + createForOf(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForOf(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + createContinue(label?: string | Identifier): ContinueStatement; + updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; + createBreak(label?: string | Identifier): BreakStatement; + updateBreak(node: BreakStatement, label: Identifier | undefined): BreakStatement; + createReturn(expression?: Expression): ReturnStatement; + updateReturn(node: ReturnStatement, expression: Expression | undefined): ReturnStatement; + createWith(expression: Expression, statement: Statement): WithStatement; + updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; + createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement; + updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; + createLabel(label: string | Identifier, statement: Statement): LabeledStatement; + updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; + createThrow(expression: Expression): ThrowStatement; + updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; + createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createDebuggerStatement(): DebuggerStatement; + createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; + updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; + updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; + createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + updateFunctionDeclaration(node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + createClassDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + updateClassDeclaration(node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + createInterfaceDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + createTypeAliasDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + createEnumDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; + updateEnumDeclaration(node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; + createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; + updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createModuleBlock(statements: readonly Statement[]): ModuleBlock; + updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; + createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; + updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; + createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; + updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + createNamespaceImport(name: Identifier): NamespaceImport; + updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; + createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; + updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; + createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; + updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression): ExportAssignment; + createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; + updateExportDeclaration(node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; + createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; + updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; + createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; + updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExternalModuleReference(expression: Expression): ExternalModuleReference; + updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; + createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; + updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; + createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + createJsxOpeningFragment(): JsxOpeningFragment; + createJsxJsxClosingFragment(): JsxClosingFragment; + updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; + updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; + createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; + updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; + createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; + updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; + createCaseClause(expression: Expression, statements: readonly Statement[]): CaseClause; + updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; + createDefaultClause(statements: readonly Statement[]): DefaultClause; + updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; + createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; + updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; + createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block): CatchClause; + updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; + updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; + createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + createSpreadAssignment(expression: Expression): SpreadAssignment; + updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; + createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; + updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; + createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile; + updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + createNotEmittedStatement(original: Node): NotEmittedStatement; + createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; + updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + createCommaList(elements: readonly Expression[]): CommaListExpression; + updateCommaList(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; + createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + createComma(left: Expression, right: Expression): BinaryExpression; + createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment(left: Expression, right: Expression): AssignmentExpression; + createLogicalOr(left: Expression, right: Expression): BinaryExpression; + createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + createBitwiseOr(left: Expression, right: Expression): BinaryExpression; + createBitwiseXor(left: Expression, right: Expression): BinaryExpression; + createBitwiseAnd(left: Expression, right: Expression): BinaryExpression; + createStrictEquality(left: Expression, right: Expression): BinaryExpression; + createStrictInequality(left: Expression, right: Expression): BinaryExpression; + createEquality(left: Expression, right: Expression): BinaryExpression; + createInequality(left: Expression, right: Expression): BinaryExpression; + createLessThan(left: Expression, right: Expression): BinaryExpression; + createLessThanEquals(left: Expression, right: Expression): BinaryExpression; + createGreaterThan(left: Expression, right: Expression): BinaryExpression; + createGreaterThanEquals(left: Expression, right: Expression): BinaryExpression; + createLeftShift(left: Expression, right: Expression): BinaryExpression; + createRightShift(left: Expression, right: Expression): BinaryExpression; + createUnsignedRightShift(left: Expression, right: Expression): BinaryExpression; + createAdd(left: Expression, right: Expression): BinaryExpression; + createSubtract(left: Expression, right: Expression): BinaryExpression; + createMultiply(left: Expression, right: Expression): BinaryExpression; + createDivide(left: Expression, right: Expression): BinaryExpression; + createModulo(left: Expression, right: Expression): BinaryExpression; + createExponent(left: Expression, right: Expression): BinaryExpression; + createPrefixPlus(operand: Expression): PrefixUnaryExpression; + createPrefixMinus(operand: Expression): PrefixUnaryExpression; + createPrefixIncrement(operand: Expression): PrefixUnaryExpression; + createPrefixDecrement(operand: Expression): PrefixUnaryExpression; + createBitwiseNot(operand: Expression): PrefixUnaryExpression; + createLogicalNot(operand: Expression): PrefixUnaryExpression; + createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + createPostfixDecrement(operand: Expression): PostfixUnaryExpression; + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createVoidZero(): VoidExpression; + createExportDefault(expression: Expression): ExportAssignment; + createExternalModuleExport(exportName: Identifier): ExportDeclaration; + restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + } + export interface CoreTransformationContext { + readonly factory: NodeFactory; /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; /** Starts a new lexical environment. */ @@ -2930,6 +3342,8 @@ declare namespace ts { hoistFunctionDeclaration(node: FunctionDeclaration): void; /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + } + export interface TransformationContext extends CoreTransformationContext { /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; /** Gets and resets the requested non-scoped emit helpers. */ @@ -3372,7 +3786,7 @@ declare namespace ts { * @param node The original node. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node): Node; + function getParseTreeNode(node: Node | undefined): Node | undefined; /** * Gets the original parse tree node for a node. * @@ -3380,7 +3794,7 @@ declare namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + function getParseTreeNode(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined; /** Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' */ function escapeLeadingUnderscores(identifier: string): __String; /** @@ -3469,6 +3883,155 @@ declare namespace ts { function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; } +declare namespace ts { + function setTextRange(range: T, location: TextRange | undefined): T; + function isConstTypeReference(node: Node): boolean; + function skipPartiallyEmittedExpressions(node: Expression): Expression; + function skipPartiallyEmittedExpressions(node: Node): Node; + function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag; + function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; + function isModifier(node: Node): node is Modifier; + function isEntityName(node: Node): node is EntityName; + function isPropertyName(node: Node): node is PropertyName; + function isBindingName(node: Node): node is BindingName; + function isClassElement(node: Node): node is ClassElement; + function isTypeElement(node: Node): node is TypeElement; + function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + function isObjectLiteralElement(node: Node): node is ObjectLiteralElement; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node: Node): node is TypeNode; + function isTemplateLiteral(node: Node): node is TemplateLiteral; + function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement; + function isUnparsedTextLike(node: Node): node is UnparsedTextLike; + function isUnparsedNode(node: Node): node is UnparsedNode; + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ + function isToken(n: Node): boolean; + function isLiteralExpression(node: Node): node is LiteralExpression; + function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; + function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; + function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; + function isFunctionLike(node: Node): node is SignatureDeclaration; + function isClassLike(node: Node): node is ClassLikeDeclaration; + function isAccessor(node: Node): node is AccessorDeclaration; + function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; + function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; + function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; + function isCallLikeExpression(node: Node): node is CallLikeExpression; + function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; + function isAssertionExpression(node: Node): node is AssertionExpression; + function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; + function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; + function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; + /** True if node is of a kind that may contain comment text. */ + function isJSDocCommentContainingNode(node: Node): boolean; + function isSetAccessor(node: Node): node is SetAccessorDeclaration; + function isGetAccessor(node: Node): node is GetAccessorDeclaration; + function isStringLiteralLike(node: Node): node is StringLiteralLike; +} +declare namespace ts { + function isPropertyAccessChain(node: Node): node is PropertyAccessChain; + function isElementAccessChain(node: Node): node is ElementAccessChain; + function isCallChain(node: Node): node is CallChain; + function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain; + function isNullishCoalesce(node: Node): boolean; +} +declare namespace ts { + const factory: NodeFactory; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node: T): T; + function createUnparsedSourceFile(text: string): UnparsedSource; + function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; + function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; + function createInputFiles(javascriptText: string, declarationText: string): InputFiles; + function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; + function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; + /** + * Create an external source map source file reference + */ + function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + function setOriginalNode(node: T, original: Node | undefined): T; +} +declare namespace ts { + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile: SourceFile | undefined): void; + /** + * Sets flags that control emit behavior of a node. + */ + function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Gets a custom text range to use when emitting source maps. + */ + function getSourceMapRange(node: Node): SourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ + function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ + function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ + function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; + /** + * Gets a custom text range to use when emitting comments. + */ + function getCommentRange(node: Node): TextRange; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node: T, range: TextRange): T; + function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; + function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; + function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; + function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; + function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function moveSyntheticComments(node: T, original: Node): T; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression; + /** + * Adds an EmitHelper to a node. + */ + function addEmitHelper(node: T, helper: EmitHelper): T; + /** + * Add EmitHelpers to a node. + */ + function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; + /** + * Removes an EmitHelper from a node. + */ + function removeEmitHelper(node: Node, helper: EmitHelper): boolean; + /** + * Gets the EmitHelpers of a node. + */ + function getEmitHelpers(node: Node): EmitHelper[] | undefined; + /** + * Moves matching emit helpers from a source node to a target node. + */ + function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; +} declare namespace ts { function isNumericLiteral(node: Node): node is NumericLiteral; function isBigIntLiteral(node: Node): node is BigIntLiteral; @@ -3503,6 +4066,8 @@ declare namespace ts { function isTypeLiteralNode(node: Node): node is TypeLiteralNode; function isArrayTypeNode(node: Node): node is ArrayTypeNode; function isTupleTypeNode(node: Node): node is TupleTypeNode; + function isOptionalTypeNode(node: Node): node is OptionalTypeNode; + function isRestTypeNode(node: Node): node is RestTypeNode; function isUnionTypeNode(node: Node): node is UnionTypeNode; function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode; function isConditionalTypeNode(node: Node): node is ConditionalTypeNode; @@ -3520,20 +4085,12 @@ declare namespace ts { function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression; function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression; function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; - function isPropertyAccessChain(node: Node): node is PropertyAccessChain; function isElementAccessExpression(node: Node): node is ElementAccessExpression; - function isElementAccessChain(node: Node): node is ElementAccessChain; function isCallExpression(node: Node): node is CallExpression; - function isCallChain(node: Node): node is CallChain; - function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain; - function isNullishCoalesce(node: Node): boolean; function isNewExpression(node: Node): node is NewExpression; function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression; - function isTypeAssertion(node: Node): node is TypeAssertion; - function isConstTypeReference(node: Node): boolean; + function isTypeAssertionExpression(node: Node): node is TypeAssertion; function isParenthesizedExpression(node: Node): node is ParenthesizedExpression; - function skipPartiallyEmittedExpressions(node: Expression): Expression; - function skipPartiallyEmittedExpressions(node: Node): Node; function isFunctionExpression(node: Node): node is FunctionExpression; function isArrowFunction(node: Node): node is ArrowFunction; function isDeleteExpression(node: Node): node is DeleteExpression; @@ -3553,6 +4110,9 @@ declare namespace ts { function isAsExpression(node: Node): node is AsExpression; function isNonNullExpression(node: Node): node is NonNullExpression; function isMetaProperty(node: Node): node is MetaProperty; + function isSyntheticExpression(node: Node): node is SyntheticExpression; + function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression; + function isCommaListExpression(node: Node): node is CommaListExpression; function isTemplateSpan(node: Node): node is TemplateSpan; function isSemicolonClassElement(node: Node): node is SemicolonClassElement; function isBlock(node: Node): node is Block; @@ -3567,7 +4127,6 @@ declare namespace ts { function isForOfStatement(node: Node): node is ForOfStatement; function isContinueStatement(node: Node): node is ContinueStatement; function isBreakStatement(node: Node): node is BreakStatement; - function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement; function isReturnStatement(node: Node): node is ReturnStatement; function isWithStatement(node: Node): node is WithStatement; function isSwitchStatement(node: Node): node is SwitchStatement; @@ -3597,6 +4156,7 @@ declare namespace ts { function isNamedExports(node: Node): node is NamedExports; function isExportSpecifier(node: Node): node is ExportSpecifier; function isMissingDeclaration(node: Node): node is MissingDeclaration; + function isNotEmittedStatement(node: Node): node is NotEmittedStatement; function isExternalModuleReference(node: Node): node is ExternalModuleReference; function isJsxElement(node: Node): node is JsxElement; function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement; @@ -3617,12 +4177,10 @@ declare namespace ts { function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment; function isSpreadAssignment(node: Node): node is SpreadAssignment; function isEnumMember(node: Node): node is EnumMember; + function isUnparsedPrepend(node: Node): node is UnparsedPrepend; function isSourceFile(node: Node): node is SourceFile; function isBundle(node: Node): node is Bundle; function isUnparsedSource(node: Node): node is UnparsedSource; - function isUnparsedPrepend(node: Node): node is UnparsedPrepend; - function isUnparsedTextLike(node: Node): node is UnparsedTextLike; - function isUnparsedNode(node: Node): node is UnparsedNode; function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression; function isJSDocAllType(node: Node): node is JSDocAllType; function isJSDocUnknownType(node: Node): node is JSDocUnknownType; @@ -3631,69 +4189,23 @@ declare namespace ts { function isJSDocOptionalType(node: Node): node is JSDocOptionalType; function isJSDocFunctionType(node: Node): node is JSDocFunctionType; function isJSDocVariadicType(node: Node): node is JSDocVariadicType; + function isJSDocNamepathType(node: Node): node is JSDocNamepathType; function isJSDoc(node: Node): node is JSDoc; - function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; + function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; + function isJSDocSignature(node: Node): node is JSDocSignature; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; + function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; + function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; - function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocParameterTag(node: Node): node is JSDocParameterTag; function isJSDocReturnTag(node: Node): node is JSDocReturnTag; + function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocTypeTag(node: Node): node is JSDocTypeTag; function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag; function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag; + function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag; function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag; - function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag; - function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; - function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; - function isJSDocSignature(node: Node): node is JSDocSignature; -} -declare namespace ts { - /** - * True if node is of some token syntax kind. - * For example, this is true for an IfKeyword but not for an IfStatement. - * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. - */ - function isToken(n: Node): boolean; - function isLiteralExpression(node: Node): node is LiteralExpression; - type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail; - function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; - function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; - function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; - function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; - function isModifier(node: Node): node is Modifier; - function isEntityName(node: Node): node is EntityName; - function isPropertyName(node: Node): node is PropertyName; - function isBindingName(node: Node): node is BindingName; - function isFunctionLike(node: Node): node is SignatureDeclaration; - function isClassElement(node: Node): node is ClassElement; - function isClassLike(node: Node): node is ClassLikeDeclaration; - function isAccessor(node: Node): node is AccessorDeclaration; - function isTypeElement(node: Node): node is TypeElement; - function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; - function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; - /** - * Node test that determines whether a node is a valid type node. - * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* - * of a TypeNode. - */ - function isTypeNode(node: Node): node is TypeNode; - function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; - function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; - function isCallLikeExpression(node: Node): node is CallLikeExpression; - function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; - function isTemplateLiteral(node: Node): node is TemplateLiteral; - function isAssertionExpression(node: Node): node is AssertionExpression; - function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; - function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; - function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; - /** True if node is of a kind that may contain comment text. */ - function isJSDocCommentContainingNode(node: Node): boolean; - function isSetAccessor(node: Node): node is SetAccessorDeclaration; - function isGetAccessor(node: Node): node is GetAccessorDeclaration; - function isObjectLiteralElement(node: Node): node is ObjectLiteralElement; - function isStringLiteralLike(node: Node): node is StringLiteralLike; } declare namespace ts { export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; @@ -3851,442 +4363,6 @@ declare namespace ts { function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; } -declare namespace ts { - function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; - /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ - function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; - function createLiteral(value: number | PseudoBigInt): NumericLiteral; - function createLiteral(value: boolean): BooleanLiteral; - function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; - function createNumericLiteral(value: string, numericLiteralFlags?: TokenFlags): NumericLiteral; - function createBigIntLiteral(value: string): BigIntLiteral; - function createStringLiteral(text: string): StringLiteral; - function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; - function createIdentifier(text: string): Identifier; - function updateIdentifier(node: Identifier): Identifier; - /** Create a unique temporary variable. */ - function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; - /** Create a unique temporary variable for use in a loop. */ - function createLoopVariable(): Identifier; - /** Create a unique name based on the supplied text. */ - function createUniqueName(text: string): Identifier; - /** Create a unique name based on the supplied text. */ - function createOptimisticUniqueName(text: string): Identifier; - /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ - function createFileLevelUniqueName(text: string): Identifier; - /** Create a unique name generated for a node. */ - function getGeneratedNameForNode(node: Node | undefined): Identifier; - function createToken(token: TKind): Token; - function createSuper(): SuperExpression; - function createThis(): ThisExpression & Token; - function createNull(): NullLiteral & Token; - function createTrue(): BooleanLiteral & Token; - function createFalse(): BooleanLiteral & Token; - function createModifier(kind: T): Token; - function createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[]; - function createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName; - function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; - function createComputedPropertyName(expression: Expression): ComputedPropertyName; - function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; - function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; - function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; - function createParameter(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; - function updateParameter(node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; - function createDecorator(expression: Expression): Decorator; - function updateDecorator(node: Decorator, expression: Expression): Decorator; - function createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; - function updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; - function createProperty(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - function updateProperty(node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - function createMethodSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): MethodSignature; - function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined): MethodSignature; - function createMethod(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - function updateMethod(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - function createConstructor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - function updateConstructor(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - function createGetAccessor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - function updateGetAccessor(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - function createSetAccessor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - function updateSetAccessor(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - function createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; - function updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; - function createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; - function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - function updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode; - function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode; - function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; - function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode; - function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; - function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined): TypeReferenceNode; - function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; - function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode; - function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode; - function createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode; - function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; - function createTypeQueryNode(exprName: EntityName): TypeQueryNode; - function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; - function createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; - function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; - function createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; - function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; - function createTupleTypeNode(elementTypes: readonly TypeNode[]): TupleTypeNode; - function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]): TupleTypeNode; - function createOptionalTypeNode(type: TypeNode): OptionalTypeNode; - function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; - function createRestTypeNode(type: TypeNode): RestTypeNode; - function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode; - function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode; - function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; - function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; - function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]): UnionOrIntersectionTypeNode; - function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - function createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; - function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; - function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - function createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; - function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; - function createThisTypeNode(): ThisTypeNode; - function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; - function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; - function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - function createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - function createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; - function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; - function createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; - function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; - function createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; - function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; - function createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; - function updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; - function createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; - function updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; - function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier): PropertyAccessChain; - function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier): PropertyAccessChain; - function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; - function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; - function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; - function createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; - function updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; - function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; - function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; - function createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - function updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - /** @deprecated */ function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - /** @deprecated */ function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; - function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; - function createParen(expression: Expression): ParenthesizedExpression; - function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - function createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; - function updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; - function createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; - function updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: Token, body: ConciseBody): ArrowFunction; - function createDelete(expression: Expression): DeleteExpression; - function updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression; - function createTypeOf(expression: Expression): TypeOfExpression; - function updateTypeOf(node: TypeOfExpression, expression: Expression): TypeOfExpression; - function createVoid(expression: Expression): VoidExpression; - function updateVoid(node: VoidExpression, expression: Expression): VoidExpression; - function createAwait(expression: Expression): AwaitExpression; - function updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; - function createPrefix(operator: PrefixUnaryOperator, operand: Expression): PrefixUnaryExpression; - function updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; - function createPostfix(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; - function updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; - function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - function updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken): BinaryExpression; - /** @deprecated */ function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; - function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; - function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: Token, whenTrue: Expression, colonToken: Token, whenFalse: Expression): ConditionalExpression; - function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - function createTemplateHead(text: string, rawText?: string): TemplateHead; - function createTemplateMiddle(text: string, rawText?: string): TemplateMiddle; - function createTemplateTail(text: string, rawText?: string): TemplateTail; - function createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; - function createYield(expression?: Expression): YieldExpression; - function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; - function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; - function createSpread(expression: Expression): SpreadElement; - function updateSpread(node: SpreadElement, expression: Expression): SpreadElement; - function createClassExpression(modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - function updateClassExpression(node: ClassExpression, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - function createOmittedExpression(): OmittedExpression; - function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; - function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; - function createAsExpression(expression: Expression, type: TypeNode): AsExpression; - function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; - function createNonNullExpression(expression: Expression): NonNullExpression; - function updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression; - function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; - function updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; - function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - function createSemicolonClassElement(): SemicolonClassElement; - function createBlock(statements: readonly Statement[], multiLine?: boolean): Block; - function updateBlock(node: Block, statements: readonly Statement[]): Block; - function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; - function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList): VariableStatement; - function createEmptyStatement(): EmptyStatement; - function createExpressionStatement(expression: Expression): ExpressionStatement; - function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; - /** @deprecated Use `createExpressionStatement` instead. */ - const createStatement: typeof createExpressionStatement; - /** @deprecated Use `updateExpressionStatement` instead. */ - const updateStatement: typeof updateExpressionStatement; - function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; - function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; - function createDo(statement: Statement, expression: Expression): DoStatement; - function updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; - function createWhile(expression: Expression, statement: Statement): WhileStatement; - function updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; - function createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function createContinue(label?: string | Identifier): ContinueStatement; - function updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; - function createBreak(label?: string | Identifier): BreakStatement; - function updateBreak(node: BreakStatement, label: Identifier | undefined): BreakStatement; - function createReturn(expression?: Expression): ReturnStatement; - function updateReturn(node: ReturnStatement, expression: Expression | undefined): ReturnStatement; - function createWith(expression: Expression, statement: Statement): WithStatement; - function updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; - function createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement; - function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; - function createLabel(label: string | Identifier, statement: Statement): LabeledStatement; - function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; - function createThrow(expression: Expression): ThrowStatement; - function updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; - function createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - function createDebuggerStatement(): DebuggerStatement; - function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; - function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; - function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; - function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; - function createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function updateFunctionDeclaration(node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function createClassDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - function updateClassDeclaration(node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - function createInterfaceDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - function createTypeAliasDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - function updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - function createEnumDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; - function updateEnumDeclaration(node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; - function createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; - function updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; - function createModuleBlock(statements: readonly Statement[]): ModuleBlock; - function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; - function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; - function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; - function createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; - function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - function createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - function createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - function createNamespaceImport(name: Identifier): NamespaceImport; - function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; - function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; - function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; - function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; - function updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression): ExportAssignment; - function createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; - function updateExportDeclaration(node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; - function createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; - function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; - function createExternalModuleReference(expression: Expression): ExternalModuleReference; - function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; - function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; - function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; - function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; - function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; - function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; - function createJsxOpeningFragment(): JsxOpeningFragment; - function createJsxJsxClosingFragment(): JsxClosingFragment; - function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; - function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; - function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; - function createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; - function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; - function createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; - function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; - function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; - function updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; - function createCaseClause(expression: Expression, statements: readonly Statement[]): CaseClause; - function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; - function createDefaultClause(statements: readonly Statement[]): DefaultClause; - function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; - function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; - function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; - function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block): CatchClause; - function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; - function createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; - function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; - function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; - function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; - function createSpreadAssignment(expression: Expression): SpreadAssignment; - function updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; - function createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; - function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; - function updateSourceFileNode(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: SourceFile["referencedFiles"], typeReferences?: SourceFile["typeReferenceDirectives"], hasNoDefaultLib?: boolean, libReferences?: SourceFile["libReferenceDirectives"]): SourceFile; - /** - * Creates a shallow, memberwise clone of a node for mutation. - */ - function getMutableClone(node: T): T; - /** - * Creates a synthetic statement to act as a placeholder for a not-emitted statement in - * order to preserve comments. - * - * @param original The original statement. - */ - function createNotEmittedStatement(original: Node): NotEmittedStatement; - /** - * Creates a synthetic expression to act as a placeholder for a not-emitted expression in - * order to preserve comments or sourcemap positions. - * - * @param expression The inner expression to emit. - * @param original The original outer expression. - * @param location The location for the expression. Defaults to the positions from "original" if provided. - */ - function createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; - function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; - function createCommaList(elements: readonly Expression[]): CommaListExpression; - function updateCommaList(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; - function createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; - function createUnparsedSourceFile(text: string): UnparsedSource; - function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; - function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; - function createInputFiles(javascriptText: string, declarationText: string): InputFiles; - function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; - function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; - function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - function createComma(left: Expression, right: Expression): Expression; - function createLessThan(left: Expression, right: Expression): Expression; - function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; - function createAssignment(left: Expression, right: Expression): BinaryExpression; - function createStrictEquality(left: Expression, right: Expression): BinaryExpression; - function createStrictInequality(left: Expression, right: Expression): BinaryExpression; - function createAdd(left: Expression, right: Expression): BinaryExpression; - function createSubtract(left: Expression, right: Expression): BinaryExpression; - function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; - function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; - function createLogicalOr(left: Expression, right: Expression): BinaryExpression; - function createNullishCoalesce(left: Expression, right: Expression): BinaryExpression; - function createLogicalNot(operand: Expression): PrefixUnaryExpression; - function createVoidZero(): VoidExpression; - function createExportDefault(expression: Expression): ExportAssignment; - function createExternalModuleExport(exportName: Identifier): ExportDeclaration; - /** - * Clears any EmitNode entries from parse-tree nodes. - * @param sourceFile A source file. - */ - function disposeEmitNodes(sourceFile: SourceFile): void; - function setTextRange(range: T, location: TextRange | undefined): T; - /** - * Sets flags that control emit behavior of a node. - */ - function setEmitFlags(node: T, emitFlags: EmitFlags): T; - /** - * Gets a custom text range to use when emitting source maps. - */ - function getSourceMapRange(node: Node): SourceMapRange; - /** - * Sets a custom text range to use when emitting source maps. - */ - function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; - /** - * Create an external source map source file reference - */ - function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; - /** - * Sets the TextRange to use for source maps for a token of a node. - */ - function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; - /** - * Gets a custom text range to use when emitting comments. - */ - function getCommentRange(node: Node): TextRange; - /** - * Sets a custom text range to use when emitting comments. - */ - function setCommentRange(node: T, range: TextRange): T; - function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; - function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; - function moveSyntheticComments(node: T, original: Node): T; - /** - * Gets the constant value to emit for an expression. - */ - function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; - /** - * Sets the constant value to emit for an expression. - */ - function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression; - /** - * Adds an EmitHelper to a node. - */ - function addEmitHelper(node: T, helper: EmitHelper): T; - /** - * Add EmitHelpers to a node. - */ - function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; - /** - * Removes an EmitHelper from a node. - */ - function removeEmitHelper(node: Node, helper: EmitHelper): boolean; - /** - * Gets the EmitHelpers of a node. - */ - function getEmitHelpers(node: Node): EmitHelper[] | undefined; - /** - * Moves matching emit helpers from a source node to a target node. - */ - function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; - function setOriginalNode(node: T, original: Node | undefined): T; -} declare namespace ts { /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. @@ -9355,6 +9431,1295 @@ declare namespace ts.server { responseRequired?: boolean; } } +declare namespace ts { + const + /** + * @deprecated Use `factory.createNodeArray` or the factory supplied by your transformation context instead. + */ + createNodeArray: (elements?: readonly T[] | undefined, hasTrailingComma?: boolean | undefined) => NodeArray, + /** + * @deprecated Use `factory.createNumericLiteral` or the factory supplied by your transformation context instead. + */ + createNumericLiteral: (value: string | number, numericLiteralFlags?: TokenFlags | undefined) => NumericLiteral, + /** + * @deprecated Use `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + createBigIntLiteral: (value: string | PseudoBigInt) => BigIntLiteral, + /** + * @deprecated Use `factory.createStringLiteral` or the factory supplied by your transformation context instead. + */ + createStringLiteral: { + (text: string, isSingleQuote?: boolean | undefined): StringLiteral; + (text: string, isSingleQuote?: boolean | undefined, hasExtendedUnicodeEscape?: boolean | undefined): StringLiteral; + }, + /** + * @deprecated Use `factory.createStringLiteralFromNode` or the factory supplied by your transformation context instead. + */ + createStringLiteralFromNode: (sourceNode: Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral, isSingleQuote?: boolean | undefined) => StringLiteral, + /** + * @deprecated Use `factory.createRegularExpressionLiteral` or the factory supplied by your transformation context instead. + */ + createRegularExpressionLiteral: (text: string) => RegularExpressionLiteral, + /** + * @deprecated Use `factory.createLoopVariable` or the factory supplied by your transformation context instead. + */ + createLoopVariable: () => Identifier, + /** + * @deprecated Use `factory.createUniqueName` or the factory supplied by your transformation context instead. + */ + createUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createOptimisticUniqueName` or the factory supplied by your transformation context instead. + */ + createOptimisticUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createFileLevelUniqueName` or the factory supplied by your transformation context instead. + */ + createFileLevelUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createSuper` or the factory supplied by your transformation context instead. + */ + createSuper: () => SuperExpression, + /** + * @deprecated Use `factory.createThis` or the factory supplied by your transformation context instead. + */ + createThis: () => ThisExpression, + /** + * @deprecated Use `factory.createNull` or the factory supplied by your transformation context instead. + */ + createNull: () => NullLiteral, + /** + * @deprecated Use `factory.createTrue` or the factory supplied by your transformation context instead. + */ + createTrue: () => TrueLiteral, + /** + * @deprecated Use `factory.createFalse` or the factory supplied by your transformation context instead. + */ + createFalse: () => FalseLiteral, + /** + * @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. + */ + createModifier: (kind: T) => ModifierToken, + /** + * @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. + */ + createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[], + /** + * @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. + */ + createQualifiedName: (left: EntityName, right: string | Identifier) => QualifiedName, + /** + * @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. + */ + updateQualifiedName: (node: QualifiedName, left: EntityName, right: Identifier) => QualifiedName, + /** + * @deprecated Use `factory.createComputedPropertyName` or the factory supplied by your transformation context instead. + */ + createComputedPropertyName: (expression: Expression) => ComputedPropertyName, + /** + * @deprecated Use `factory.updateComputedPropertyName` or the factory supplied by your transformation context instead. + */ + updateComputedPropertyName: (node: ComputedPropertyName, expression: Expression) => ComputedPropertyName, + /** + * @deprecated Use `factory.createTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeParameterDeclaration: (name: string | Identifier, constraint?: TypeNode | undefined, defaultType?: TypeNode | undefined) => TypeParameterDeclaration, + /** + * @deprecated Use `factory.updateTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeParameterDeclaration: (node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) => TypeParameterDeclaration, createParameter: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, questionToken?: QuestionToken | undefined, type?: TypeNode | undefined, initializer?: Expression | undefined) => ParameterDeclaration, updateParameter: (node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => ParameterDeclaration, + /** + * @deprecated Use `factory.createDecorator` or the factory supplied by your transformation context instead. + */ + createDecorator: (expression: Expression) => Decorator, + /** + * @deprecated Use `factory.updateDecorator` or the factory supplied by your transformation context instead. + */ + updateDecorator: (node: Decorator, expression: Expression) => Decorator, createProperty: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => PropertyDeclaration, updateProperty: (node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => PropertyDeclaration, createMethod: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => MethodDeclaration, updateMethod: (node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => MethodDeclaration, createConstructor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration, updateConstructor: (node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration, createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration, updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration, createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration, updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration, + /** + * @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. + */ + createCallSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => CallSignatureDeclaration, + /** + * @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. + */ + updateCallSignature: (node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => CallSignatureDeclaration, + /** + * @deprecated Use `factory.createConstructSignature` or the factory supplied by your transformation context instead. + */ + createConstructSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => ConstructSignatureDeclaration, + /** + * @deprecated Use `factory.updateConstructSignature` or the factory supplied by your transformation context instead. + */ + updateConstructSignature: (node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => ConstructSignatureDeclaration, + /** + * @deprecated Use `factory.updateIndexSignature` or the factory supplied by your transformation context instead. + */ + updateIndexSignature: (node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode) => IndexSignatureDeclaration, + /** + * @deprecated Use `factory.createKeywordTypeNode` or the factory supplied by your transformation context instead. + */ + createKeywordTypeNode: (kind: TKind) => KeywordTypeNode, createTypePredicateNodeWithModifier: (assertsModifier: AssertsKeyword | undefined, parameterName: string | Identifier | ThisTypeNode, type: TypeNode | undefined) => TypePredicateNode, updateTypePredicateNodeWithModifier: (node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) => TypePredicateNode, + /** + * @deprecated Use `factory.createTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + createTypeReferenceNode: (typeName: string | Identifier | QualifiedName, typeArguments?: readonly TypeNode[] | undefined) => TypeReferenceNode, + /** + * @deprecated Use `factory.updateTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + updateTypeReferenceNode: (node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) => TypeReferenceNode, + /** + * @deprecated Use `factory.createFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + createFunctionTypeNode: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => FunctionTypeNode, + /** + * @deprecated Use `factory.updateFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + updateFunctionTypeNode: (node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => FunctionTypeNode, + /** + * @deprecated Use `factory.createConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + createConstructorTypeNode: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => ConstructorTypeNode, + /** + * @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + updateConstructorTypeNode: (node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => ConstructorTypeNode, + /** + * @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. + */ + createTypeQueryNode: (exprName: EntityName) => TypeQueryNode, + /** + * @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. + */ + updateTypeQueryNode: (node: TypeQueryNode, exprName: EntityName) => TypeQueryNode, + /** + * @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + createTypeLiteralNode: (members: readonly TypeElement[] | undefined) => TypeLiteralNode, + /** + * @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + updateTypeLiteralNode: (node: TypeLiteralNode, members: NodeArray) => TypeLiteralNode, + /** + * @deprecated Use `factory.createArrayTypeNode` or the factory supplied by your transformation context instead. + */ + createArrayTypeNode: (elementType: TypeNode) => ArrayTypeNode, + /** + * @deprecated Use `factory.updateArrayTypeNode` or the factory supplied by your transformation context instead. + */ + updateArrayTypeNode: (node: ArrayTypeNode, elementType: TypeNode) => ArrayTypeNode, + /** + * @deprecated Use `factory.createTupleTypeNode` or the factory supplied by your transformation context instead. + */ + createTupleTypeNode: (elementTypes: readonly TypeNode[]) => TupleTypeNode, + /** + * @deprecated Use `factory.updateTupleTypeNode` or the factory supplied by your transformation context instead. + */ + updateTupleTypeNode: (node: TupleTypeNode, elementTypes: readonly TypeNode[]) => TupleTypeNode, + /** + * @deprecated Use `factory.createOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + createOptionalTypeNode: (type: TypeNode) => OptionalTypeNode, + /** + * @deprecated Use `factory.updateOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateOptionalTypeNode: (node: OptionalTypeNode, type: TypeNode) => OptionalTypeNode, + /** + * @deprecated Use `factory.createRestTypeNode` or the factory supplied by your transformation context instead. + */ + createRestTypeNode: (type: TypeNode) => RestTypeNode, + /** + * @deprecated Use `factory.updateRestTypeNode` or the factory supplied by your transformation context instead. + */ + updateRestTypeNode: (node: RestTypeNode, type: TypeNode) => RestTypeNode, + /** + * @deprecated Use `factory.createUnionTypeNode` or the factory supplied by your transformation context instead. + */ + createUnionTypeNode: (types: readonly TypeNode[]) => UnionTypeNode, + /** + * @deprecated Use `factory.updateUnionTypeNode` or the factory supplied by your transformation context instead. + */ + updateUnionTypeNode: (node: UnionTypeNode, types: NodeArray) => UnionTypeNode, + /** + * @deprecated Use `factory.createIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + createIntersectionTypeNode: (types: readonly TypeNode[]) => IntersectionTypeNode, + /** + * @deprecated Use `factory.updateIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + updateIntersectionTypeNode: (node: IntersectionTypeNode, types: NodeArray) => IntersectionTypeNode, + /** + * @deprecated Use `factory.createConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + createConditionalTypeNode: (checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) => ConditionalTypeNode, + /** + * @deprecated Use `factory.updateConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateConditionalTypeNode: (node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) => ConditionalTypeNode, + /** + * @deprecated Use `factory.createInferTypeNode` or the factory supplied by your transformation context instead. + */ + createInferTypeNode: (typeParameter: TypeParameterDeclaration) => InferTypeNode, + /** + * @deprecated Use `factory.updateInferTypeNode` or the factory supplied by your transformation context instead. + */ + updateInferTypeNode: (node: InferTypeNode, typeParameter: TypeParameterDeclaration) => InferTypeNode, + /** + * @deprecated Use `factory.createImportTypeNode` or the factory supplied by your transformation context instead. + */ + createImportTypeNode: (argument: TypeNode, qualifier?: Identifier | QualifiedName | undefined, typeArguments?: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined) => ImportTypeNode, + /** + * @deprecated Use `factory.updateImportTypeNode` or the factory supplied by your transformation context instead. + */ + updateImportTypeNode: (node: ImportTypeNode, argument: TypeNode, qualifier?: Identifier | QualifiedName | undefined, typeArguments?: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined) => ImportTypeNode, + /** + * @deprecated Use `factory.createParenthesizedType` or the factory supplied by your transformation context instead. + */ + createParenthesizedType: (type: TypeNode) => ParenthesizedTypeNode, + /** + * @deprecated Use `factory.updateParenthesizedType` or the factory supplied by your transformation context instead. + */ + updateParenthesizedType: (node: ParenthesizedTypeNode, type: TypeNode) => ParenthesizedTypeNode, + /** + * @deprecated Use `factory.createThisTypeNode` or the factory supplied by your transformation context instead. + */ + createThisTypeNode: () => ThisTypeNode, + /** + * @deprecated Use `factory.updateTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + updateTypeOperatorNode: (node: TypeOperatorNode, type: TypeNode) => TypeOperatorNode, + /** + * @deprecated Use `factory.createIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + createIndexedAccessTypeNode: (objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode, + /** + * @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + updateIndexedAccessTypeNode: (node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode, + /** + * @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. + */ + createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode, + /** + * @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. + */ + updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode, + /** + * @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + createLiteralTypeNode: (literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode, + /** + * @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + updateLiteralTypeNode: (node: LiteralTypeNode, literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode, + /** + * @deprecated Use `factory.createObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + createObjectBindingPattern: (elements: readonly BindingElement[]) => ObjectBindingPattern, + /** + * @deprecated Use `factory.updateObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + updateObjectBindingPattern: (node: ObjectBindingPattern, elements: readonly BindingElement[]) => ObjectBindingPattern, + /** + * @deprecated Use `factory.createArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + createArrayBindingPattern: (elements: readonly ArrayBindingElement[]) => ArrayBindingPattern, + /** + * @deprecated Use `factory.updateArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + updateArrayBindingPattern: (node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) => ArrayBindingPattern, + /** + * @deprecated Use `factory.createBindingElement` or the factory supplied by your transformation context instead. + */ + createBindingElement: (dotDotDotToken: DotDotDotToken | undefined, propertyName: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, initializer?: Expression | undefined) => BindingElement, + /** + * @deprecated Use `factory.updateBindingElement` or the factory supplied by your transformation context instead. + */ + updateBindingElement: (node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | undefined, name: BindingName, initializer: Expression | undefined) => BindingElement, + /** + * @deprecated Use `factory.createArrayLiteral` or the factory supplied by your transformation context instead. + */ + createArrayLiteral: (elements?: readonly Expression[] | undefined, multiLine?: boolean | undefined) => ArrayLiteralExpression, + /** + * @deprecated Use `factory.updateArrayLiteral` or the factory supplied by your transformation context instead. + */ + updateArrayLiteral: (node: ArrayLiteralExpression, elements: readonly Expression[]) => ArrayLiteralExpression, + /** + * @deprecated Use `factory.createObjectLiteral` or the factory supplied by your transformation context instead. + */ + createObjectLiteral: (properties?: readonly ObjectLiteralElementLike[] | undefined, multiLine?: boolean | undefined) => ObjectLiteralExpression, + /** + * @deprecated Use `factory.updateObjectLiteral` or the factory supplied by your transformation context instead. + */ + updateObjectLiteral: (node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) => ObjectLiteralExpression, + /** + * @deprecated Use `factory.createPropertyAccess` or the factory supplied by your transformation context instead. + */ + createPropertyAccess: (expression: Expression, name: string | Identifier) => PropertyAccessExpression, + /** + * @deprecated Use `factory.updatePropertyAccess` or the factory supplied by your transformation context instead. + */ + updatePropertyAccess: (node: PropertyAccessExpression, expression: Expression, name: Identifier) => PropertyAccessExpression, + /** + * @deprecated Use `factory.createPropertyAccessChain` or the factory supplied by your transformation context instead. + */ + createPropertyAccessChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier) => PropertyAccessChain, + /** + * @deprecated Use `factory.updatePropertyAccessChain` or the factory supplied by your transformation context instead. + */ + updatePropertyAccessChain: (node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier) => PropertyAccessChain, + /** + * @deprecated Use `factory.createElementAccess` or the factory supplied by your transformation context instead. + */ + createElementAccess: (expression: Expression, index: number | Expression) => ElementAccessExpression, + /** + * @deprecated Use `factory.updateElementAccess` or the factory supplied by your transformation context instead. + */ + updateElementAccess: (node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) => ElementAccessExpression, + /** + * @deprecated Use `factory.createElementAccessChain` or the factory supplied by your transformation context instead. + */ + createElementAccessChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) => ElementAccessChain, + /** + * @deprecated Use `factory.updateElementAccessChain` or the factory supplied by your transformation context instead. + */ + updateElementAccessChain: (node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) => ElementAccessChain, + /** + * @deprecated Use `factory.createCall` or the factory supplied by your transformation context instead. + */ + createCall: (expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => CallExpression, + /** + * @deprecated Use `factory.updateCall` or the factory supplied by your transformation context instead. + */ + updateCall: (node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) => CallExpression, + /** + * @deprecated Use `factory.createCallChain` or the factory supplied by your transformation context instead. + */ + createCallChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => CallChain, + /** + * @deprecated Use `factory.updateCallChain` or the factory supplied by your transformation context instead. + */ + updateCallChain: (node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) => CallChain, + /** + * @deprecated Use `factory.createNew` or the factory supplied by your transformation context instead. + */ + createNew: (expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => NewExpression, + /** + * @deprecated Use `factory.updateNew` or the factory supplied by your transformation context instead. + */ + updateNew: (node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => NewExpression, + /** + * @deprecated Use `factory.createTypeAssertion` or the factory supplied by your transformation context instead. + */ + createTypeAssertion: (type: TypeNode, expression: Expression) => TypeAssertion, + /** + * @deprecated Use `factory.updateTypeAssertion` or the factory supplied by your transformation context instead. + */ + updateTypeAssertion: (node: TypeAssertion, type: TypeNode, expression: Expression) => TypeAssertion, + /** + * @deprecated Use `factory.createParen` or the factory supplied by your transformation context instead. + */ + createParen: (expression: Expression) => ParenthesizedExpression, + /** + * @deprecated Use `factory.updateParen` or the factory supplied by your transformation context instead. + */ + updateParen: (node: ParenthesizedExpression, expression: Expression) => ParenthesizedExpression, + /** + * @deprecated Use `factory.createFunctionExpression` or the factory supplied by your transformation context instead. + */ + createFunctionExpression: (modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block) => FunctionExpression, + /** + * @deprecated Use `factory.updateFunctionExpression` or the factory supplied by your transformation context instead. + */ + updateFunctionExpression: (node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block) => FunctionExpression, + /** + * @deprecated Use `factory.createArrowFunction` or the factory supplied by your transformation context instead. + */ + createArrowFunction: { + (modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + (modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + }, + /** + * @deprecated Use `factory.updateArrowFunction` or the factory supplied by your transformation context instead. + */ + updateArrowFunction: { + (node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + (node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + }, + /** + * @deprecated Use `factory.createDelete` or the factory supplied by your transformation context instead. + */ + createDelete: (expression: Expression) => DeleteExpression, + /** + * @deprecated Use `factory.updateDelete` or the factory supplied by your transformation context instead. + */ + updateDelete: (node: DeleteExpression, expression: Expression) => DeleteExpression, + /** + * @deprecated Use `factory.createTypeOf` or the factory supplied by your transformation context instead. + */ + createTypeOf: (expression: Expression) => TypeOfExpression, + /** + * @deprecated Use `factory.updateTypeOf` or the factory supplied by your transformation context instead. + */ + updateTypeOf: (node: TypeOfExpression, expression: Expression) => TypeOfExpression, + /** + * @deprecated Use `factory.createVoid` or the factory supplied by your transformation context instead. + */ + createVoid: (expression: Expression) => VoidExpression, + /** + * @deprecated Use `factory.updateVoid` or the factory supplied by your transformation context instead. + */ + updateVoid: (node: VoidExpression, expression: Expression) => VoidExpression, + /** + * @deprecated Use `factory.createAwait` or the factory supplied by your transformation context instead. + */ + createAwait: (expression: Expression) => AwaitExpression, + /** + * @deprecated Use `factory.updateAwait` or the factory supplied by your transformation context instead. + */ + updateAwait: (node: AwaitExpression, expression: Expression) => AwaitExpression, + /** + * @deprecated Use `factory.createPrefix` or the factory supplied by your transformation context instead. + */ + createPrefix: (operator: PrefixUnaryOperator, operand: Expression) => PrefixUnaryExpression, + /** + * @deprecated Use `factory.updatePrefix` or the factory supplied by your transformation context instead. + */ + updatePrefix: (node: PrefixUnaryExpression, operand: Expression) => PrefixUnaryExpression, + /** + * @deprecated Use `factory.createPostfix` or the factory supplied by your transformation context instead. + */ + createPostfix: (operand: Expression, operator: PostfixUnaryOperator) => PostfixUnaryExpression, + /** + * @deprecated Use `factory.updatePostfix` or the factory supplied by your transformation context instead. + */ + updatePostfix: (node: PostfixUnaryExpression, operand: Expression) => PostfixUnaryExpression, + /** + * @deprecated Use `factory.createBinary` or the factory supplied by your transformation context instead. + */ + createBinary: (left: Expression, operator: SyntaxKind.CommaToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | BinaryOperatorToken, right: Expression) => BinaryExpression, + /** + * @deprecated Use `factory.updateBinary` or the factory supplied by your transformation context instead. + */ + updateBinary: (node: BinaryExpression, left: Expression, right: Expression, operator?: SyntaxKind.CommaToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | BinaryOperatorToken | undefined) => BinaryExpression, + /** + * @deprecated Use `factory.updateConditional` or the factory supplied by your transformation context instead. + */ + updateConditional: { + (node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + (node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + }, + /** + * @deprecated Use `factory.createTemplateExpression` or the factory supplied by your transformation context instead. + */ + createTemplateExpression: (head: TemplateHead, templateSpans: readonly TemplateSpan[]) => TemplateExpression, + /** + * @deprecated Use `factory.updateTemplateExpression` or the factory supplied by your transformation context instead. + */ + updateTemplateExpression: (node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) => TemplateExpression, + /** + * @deprecated Use `factory.createTemplateHead` or the factory supplied by your transformation context instead. + */ + createTemplateHead: { + (text: string, rawText?: string | undefined): TemplateHead; + (text: string | undefined, rawText: string): TemplateHead; + }, + /** + * @deprecated Use `factory.createTemplateMiddle` or the factory supplied by your transformation context instead. + */ + createTemplateMiddle: { + (text: string, rawText?: string | undefined): TemplateMiddle; + (text: string | undefined, rawText: string): TemplateMiddle; + }, + /** + * @deprecated Use `factory.createTemplateTail` or the factory supplied by your transformation context instead. + */ + createTemplateTail: { + (text: string, rawText?: string | undefined): TemplateTail; + (text: string | undefined, rawText: string): TemplateTail; + }, + /** + * @deprecated Use `factory.createNoSubstitutionTemplateLiteral` or the factory supplied by your transformation context instead. + */ + createNoSubstitutionTemplateLiteral: { + (text: string, rawText?: string | undefined): NoSubstitutionTemplateLiteral; + (text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; + }, + /** + * @deprecated Use `factory.updateYield` or the factory supplied by your transformation context instead. + */ + updateYield: (node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined) => YieldExpression, + /** + * @deprecated Use `factory.createSpread` or the factory supplied by your transformation context instead. + */ + createSpread: (expression: Expression) => SpreadElement, + /** + * @deprecated Use `factory.updateSpread` or the factory supplied by your transformation context instead. + */ + updateSpread: (node: SpreadElement, expression: Expression) => SpreadElement, + /** + * @deprecated Use `factory.createOmittedExpression` or the factory supplied by your transformation context instead. + */ + createOmittedExpression: () => OmittedExpression, + /** + * @deprecated Use `factory.createAsExpression` or the factory supplied by your transformation context instead. + */ + createAsExpression: (expression: Expression, type: TypeNode) => AsExpression, + /** + * @deprecated Use `factory.updateAsExpression` or the factory supplied by your transformation context instead. + */ + updateAsExpression: (node: AsExpression, expression: Expression, type: TypeNode) => AsExpression, + /** + * @deprecated Use `factory.createNonNullExpression` or the factory supplied by your transformation context instead. + */ + createNonNullExpression: (expression: Expression) => NonNullExpression, + /** + * @deprecated Use `factory.updateNonNullExpression` or the factory supplied by your transformation context instead. + */ + updateNonNullExpression: (node: NonNullExpression, expression: Expression) => NonNullExpression, + /** + * @deprecated Use `factory.createMetaProperty` or the factory supplied by your transformation context instead. + */ + createMetaProperty: (keywordToken: SyntaxKind.ImportKeyword | SyntaxKind.NewKeyword, name: Identifier) => MetaProperty, + /** + * @deprecated Use `factory.updateMetaProperty` or the factory supplied by your transformation context instead. + */ + updateMetaProperty: (node: MetaProperty, name: Identifier) => MetaProperty, + /** + * @deprecated Use `factory.createTemplateSpan` or the factory supplied by your transformation context instead. + */ + createTemplateSpan: (expression: Expression, literal: TemplateMiddle | TemplateTail) => TemplateSpan, + /** + * @deprecated Use `factory.updateTemplateSpan` or the factory supplied by your transformation context instead. + */ + updateTemplateSpan: (node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) => TemplateSpan, + /** + * @deprecated Use `factory.createSemicolonClassElement` or the factory supplied by your transformation context instead. + */ + createSemicolonClassElement: () => SemicolonClassElement, + /** + * @deprecated Use `factory.createBlock` or the factory supplied by your transformation context instead. + */ + createBlock: (statements: readonly Statement[], multiLine?: boolean | undefined) => Block, + /** + * @deprecated Use `factory.updateBlock` or the factory supplied by your transformation context instead. + */ + updateBlock: (node: Block, statements: readonly Statement[]) => Block, + /** + * @deprecated Use `factory.createVariableStatement` or the factory supplied by your transformation context instead. + */ + createVariableStatement: (modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) => VariableStatement, + /** + * @deprecated Use `factory.updateVariableStatement` or the factory supplied by your transformation context instead. + */ + updateVariableStatement: (node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) => VariableStatement, + /** + * @deprecated Use `factory.createEmptyStatement` or the factory supplied by your transformation context instead. + */ + createEmptyStatement: () => EmptyStatement, + /** + * @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. + */ + createExpressionStatement: (expression: Expression) => ExpressionStatement, + /** + * @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. + */ + updateExpressionStatement: (node: ExpressionStatement, expression: Expression) => ExpressionStatement, createStatement: (expression: Expression) => ExpressionStatement, updateStatement: (node: ExpressionStatement, expression: Expression) => ExpressionStatement, + /** + * @deprecated Use `factory.createIf` or the factory supplied by your transformation context instead. + */ + createIf: (expression: Expression, thenStatement: Statement, elseStatement?: Statement | undefined) => IfStatement, + /** + * @deprecated Use `factory.updateIf` or the factory supplied by your transformation context instead. + */ + updateIf: (node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) => IfStatement, + /** + * @deprecated Use `factory.createDo` or the factory supplied by your transformation context instead. + */ + createDo: (statement: Statement, expression: Expression) => DoStatement, + /** + * @deprecated Use `factory.updateDo` or the factory supplied by your transformation context instead. + */ + updateDo: (node: DoStatement, statement: Statement, expression: Expression) => DoStatement, + /** + * @deprecated Use `factory.createWhile` or the factory supplied by your transformation context instead. + */ + createWhile: (expression: Expression, statement: Statement) => WhileStatement, + /** + * @deprecated Use `factory.updateWhile` or the factory supplied by your transformation context instead. + */ + updateWhile: (node: WhileStatement, expression: Expression, statement: Statement) => WhileStatement, + /** + * @deprecated Use `factory.createFor` or the factory supplied by your transformation context instead. + */ + createFor: (initializer: Expression | VariableDeclarationList | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) => ForStatement, + /** + * @deprecated Use `factory.updateFor` or the factory supplied by your transformation context instead. + */ + updateFor: (node: ForStatement, initializer: Expression | VariableDeclarationList | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) => ForStatement, + /** + * @deprecated Use `factory.createForIn` or the factory supplied by your transformation context instead. + */ + createForIn: (initializer: ForInitializer, expression: Expression, statement: Statement) => ForInStatement, + /** + * @deprecated Use `factory.updateForIn` or the factory supplied by your transformation context instead. + */ + updateForIn: (node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) => ForInStatement, + /** + * @deprecated Use `factory.createForOf` or the factory supplied by your transformation context instead. + */ + createForOf: (awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) => ForOfStatement, + /** + * @deprecated Use `factory.updateForOf` or the factory supplied by your transformation context instead. + */ + updateForOf: (node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) => ForOfStatement, + /** + * @deprecated Use `factory.createContinue` or the factory supplied by your transformation context instead. + */ + createContinue: (label?: string | Identifier | undefined) => ContinueStatement, + /** + * @deprecated Use `factory.updateContinue` or the factory supplied by your transformation context instead. + */ + updateContinue: (node: ContinueStatement, label: Identifier | undefined) => ContinueStatement, + /** + * @deprecated Use `factory.createBreak` or the factory supplied by your transformation context instead. + */ + createBreak: (label?: string | Identifier | undefined) => BreakStatement, + /** + * @deprecated Use `factory.updateBreak` or the factory supplied by your transformation context instead. + */ + updateBreak: (node: BreakStatement, label: Identifier | undefined) => BreakStatement, + /** + * @deprecated Use `factory.createReturn` or the factory supplied by your transformation context instead. + */ + createReturn: (expression?: Expression | undefined) => ReturnStatement, + /** + * @deprecated Use `factory.updateReturn` or the factory supplied by your transformation context instead. + */ + updateReturn: (node: ReturnStatement, expression: Expression | undefined) => ReturnStatement, + /** + * @deprecated Use `factory.createWith` or the factory supplied by your transformation context instead. + */ + createWith: (expression: Expression, statement: Statement) => WithStatement, + /** + * @deprecated Use `factory.updateWith` or the factory supplied by your transformation context instead. + */ + updateWith: (node: WithStatement, expression: Expression, statement: Statement) => WithStatement, + /** + * @deprecated Use `factory.createSwitch` or the factory supplied by your transformation context instead. + */ + createSwitch: (expression: Expression, caseBlock: CaseBlock) => SwitchStatement, + /** + * @deprecated Use `factory.updateSwitch` or the factory supplied by your transformation context instead. + */ + updateSwitch: (node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) => SwitchStatement, + /** + * @deprecated Use `factory.createLabel` or the factory supplied by your transformation context instead. + */ + createLabel: (label: string | Identifier, statement: Statement) => LabeledStatement, + /** + * @deprecated Use `factory.updateLabel` or the factory supplied by your transformation context instead. + */ + updateLabel: (node: LabeledStatement, label: Identifier, statement: Statement) => LabeledStatement, + /** + * @deprecated Use `factory.createThrow` or the factory supplied by your transformation context instead. + */ + createThrow: (expression: Expression) => ThrowStatement, + /** + * @deprecated Use `factory.updateThrow` or the factory supplied by your transformation context instead. + */ + updateThrow: (node: ThrowStatement, expression: Expression) => ThrowStatement, + /** + * @deprecated Use `factory.createTry` or the factory supplied by your transformation context instead. + */ + createTry: (tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) => TryStatement, + /** + * @deprecated Use `factory.updateTry` or the factory supplied by your transformation context instead. + */ + updateTry: (node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) => TryStatement, + /** + * @deprecated Use `factory.createDebuggerStatement` or the factory supplied by your transformation context instead. + */ + createDebuggerStatement: () => DebuggerStatement, + /** + * @deprecated Use `factory.createVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + createVariableDeclarationList: (declarations: readonly VariableDeclaration[], flags?: NodeFlags | undefined) => VariableDeclarationList, + /** + * @deprecated Use `factory.updateVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + updateVariableDeclarationList: (node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) => VariableDeclarationList, + /** + * @deprecated Use `factory.createFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + createFunctionDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => FunctionDeclaration, + /** + * @deprecated Use `factory.updateFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + updateFunctionDeclaration: (node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => FunctionDeclaration, + /** + * @deprecated Use `factory.createClassDeclaration` or the factory supplied by your transformation context instead. + */ + createClassDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]) => ClassDeclaration, + /** + * @deprecated Use `factory.updateClassDeclaration` or the factory supplied by your transformation context instead. + */ + updateClassDeclaration: (node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]) => ClassDeclaration, + /** + * @deprecated Use `factory.createInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + createInterfaceDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]) => InterfaceDeclaration, + /** + * @deprecated Use `factory.updateInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + updateInterfaceDeclaration: (node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]) => InterfaceDeclaration, + /** + * @deprecated Use `factory.createTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeAliasDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode) => TypeAliasDeclaration, + /** + * @deprecated Use `factory.updateTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeAliasDeclaration: (node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode) => TypeAliasDeclaration, + /** + * @deprecated Use `factory.createEnumDeclaration` or the factory supplied by your transformation context instead. + */ + createEnumDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]) => EnumDeclaration, + /** + * @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. + */ + updateEnumDeclaration: (node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]) => EnumDeclaration, + /** + * @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. + */ + createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration, + /** + * @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. + */ + updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration, + /** + * @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. + */ + createModuleBlock: (statements: readonly Statement[]) => ModuleBlock, + /** + * @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. + */ + updateModuleBlock: (node: ModuleBlock, statements: readonly Statement[]) => ModuleBlock, + /** + * @deprecated Use `factory.createCaseBlock` or the factory supplied by your transformation context instead. + */ + createCaseBlock: (clauses: readonly CaseOrDefaultClause[]) => CaseBlock, + /** + * @deprecated Use `factory.updateCaseBlock` or the factory supplied by your transformation context instead. + */ + updateCaseBlock: (node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) => CaseBlock, + /** + * @deprecated Use `factory.createNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + createNamespaceExportDeclaration: (name: string | Identifier) => NamespaceExportDeclaration, + /** + * @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateNamespaceExportDeclaration: (node: NamespaceExportDeclaration, name: Identifier) => NamespaceExportDeclaration, + /** + * @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration, + /** + * @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration, + /** + * @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. + */ + createImportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration, + /** + * @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportDeclaration: (node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration, + /** + * @deprecated Use `factory.createImportClause` or the factory supplied by your transformation context instead. + */ + createImportClause: (name: Identifier | undefined, namedBindings: NamespaceImport | NamedImports | undefined) => ImportClause, + /** + * @deprecated Use `factory.updateImportClause` or the factory supplied by your transformation context instead. + */ + updateImportClause: (node: ImportClause, name: Identifier | undefined, namedBindings: NamespaceImport | NamedImports | undefined) => ImportClause, + /** + * @deprecated Use `factory.createNamespaceImport` or the factory supplied by your transformation context instead. + */ + createNamespaceImport: (name: Identifier) => NamespaceImport, + /** + * @deprecated Use `factory.updateNamespaceImport` or the factory supplied by your transformation context instead. + */ + updateNamespaceImport: (node: NamespaceImport, name: Identifier) => NamespaceImport, + /** + * @deprecated Use `factory.createNamedImports` or the factory supplied by your transformation context instead. + */ + createNamedImports: (elements: readonly ImportSpecifier[]) => NamedImports, + /** + * @deprecated Use `factory.updateNamedImports` or the factory supplied by your transformation context instead. + */ + updateNamedImports: (node: NamedImports, elements: readonly ImportSpecifier[]) => NamedImports, + /** + * @deprecated Use `factory.createImportSpecifier` or the factory supplied by your transformation context instead. + */ + createImportSpecifier: (propertyName: Identifier | undefined, name: Identifier) => ImportSpecifier, + /** + * @deprecated Use `factory.updateImportSpecifier` or the factory supplied by your transformation context instead. + */ + updateImportSpecifier: (node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) => ImportSpecifier, + /** + * @deprecated Use `factory.createExportAssignment` or the factory supplied by your transformation context instead. + */ + createExportAssignment: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.updateExportAssignment` or the factory supplied by your transformation context instead. + */ + updateExportAssignment: (node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.createExportDeclaration` or the factory supplied by your transformation context instead. + */ + createExportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression | undefined) => ExportDeclaration, + /** + * @deprecated Use `factory.updateExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateExportDeclaration: (node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined) => ExportDeclaration, + /** + * @deprecated Use `factory.createNamedExports` or the factory supplied by your transformation context instead. + */ + createNamedExports: (elements: readonly ExportSpecifier[]) => NamedExports, + /** + * @deprecated Use `factory.updateNamedExports` or the factory supplied by your transformation context instead. + */ + updateNamedExports: (node: NamedExports, elements: readonly ExportSpecifier[]) => NamedExports, + /** + * @deprecated Use `factory.createExportSpecifier` or the factory supplied by your transformation context instead. + */ + createExportSpecifier: (propertyName: string | Identifier | undefined, name: string | Identifier) => ExportSpecifier, + /** + * @deprecated Use `factory.updateExportSpecifier` or the factory supplied by your transformation context instead. + */ + updateExportSpecifier: (node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) => ExportSpecifier, + /** + * @deprecated Use `factory.createExternalModuleReference` or the factory supplied by your transformation context instead. + */ + createExternalModuleReference: (expression: Expression) => ExternalModuleReference, + /** + * @deprecated Use `factory.updateExternalModuleReference` or the factory supplied by your transformation context instead. + */ + updateExternalModuleReference: (node: ExternalModuleReference, expression: Expression) => ExternalModuleReference, + /** + * @deprecated Use `factory.createJSDocTypeExpression` or the factory supplied by your transformation context instead. + */ + createJSDocTypeExpression: (type: TypeNode) => JSDocTypeExpression, + /** + * @deprecated Use `factory.createJSDocTypeTag` or the factory supplied by your transformation context instead. + */ + createJSDocTypeTag: (tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | undefined) => JSDocTypeTag, + /** + * @deprecated Use `factory.createJSDocReturnTag` or the factory supplied by your transformation context instead. + */ + createJSDocReturnTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined, comment?: string | undefined) => JSDocReturnTag, + /** + * @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. + */ + createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined) => JSDocThisTag, + /** + * @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. + */ + createJSDocComment: (comment?: string | undefined, tags?: NodeArray | undefined) => JSDoc, + /** + * @deprecated Use `factory.createJsxElement` or the factory supplied by your transformation context instead. + */ + createJsxElement: (openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) => JsxElement, + /** + * @deprecated Use `factory.updateJsxElement` or the factory supplied by your transformation context instead. + */ + updateJsxElement: (node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) => JsxElement, + /** + * @deprecated Use `factory.createJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxSelfClosingElement: (tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxSelfClosingElement, + /** + * @deprecated Use `factory.updateJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxSelfClosingElement: (node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxSelfClosingElement, + /** + * @deprecated Use `factory.createJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + createJsxOpeningElement: (tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxOpeningElement, + /** + * @deprecated Use `factory.updateJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + updateJsxOpeningElement: (node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxOpeningElement, + /** + * @deprecated Use `factory.createJsxClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxClosingElement: (tagName: JsxTagNameExpression) => JsxClosingElement, + /** + * @deprecated Use `factory.updateJsxClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxClosingElement: (node: JsxClosingElement, tagName: JsxTagNameExpression) => JsxClosingElement, + /** + * @deprecated Use `factory.createJsxFragment` or the factory supplied by your transformation context instead. + */ + createJsxFragment: (openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) => JsxFragment, + /** + * @deprecated Use `factory.createJsxText` or the factory supplied by your transformation context instead. + */ + createJsxText: (text: string, containsOnlyTriviaWhiteSpaces?: boolean | undefined) => JsxText, + /** + * @deprecated Use `factory.updateJsxText` or the factory supplied by your transformation context instead. + */ + updateJsxText: (node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean | undefined) => JsxText, + /** + * @deprecated Use `factory.createJsxOpeningFragment` or the factory supplied by your transformation context instead. + */ + createJsxOpeningFragment: () => JsxOpeningFragment, + /** + * @deprecated Use `factory.createJsxJsxClosingFragment` or the factory supplied by your transformation context instead. + */ + createJsxJsxClosingFragment: () => JsxClosingFragment, + /** + * @deprecated Use `factory.updateJsxFragment` or the factory supplied by your transformation context instead. + */ + updateJsxFragment: (node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) => JsxFragment, + /** + * @deprecated Use `factory.createJsxAttribute` or the factory supplied by your transformation context instead. + */ + createJsxAttribute: (name: Identifier, initializer: StringLiteral | JsxExpression | undefined) => JsxAttribute, + /** + * @deprecated Use `factory.updateJsxAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxAttribute: (node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) => JsxAttribute, + /** + * @deprecated Use `factory.createJsxAttributes` or the factory supplied by your transformation context instead. + */ + createJsxAttributes: (properties: readonly JsxAttributeLike[]) => JsxAttributes, + /** + * @deprecated Use `factory.updateJsxAttributes` or the factory supplied by your transformation context instead. + */ + updateJsxAttributes: (node: JsxAttributes, properties: readonly JsxAttributeLike[]) => JsxAttributes, + /** + * @deprecated Use `factory.createJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + createJsxSpreadAttribute: (expression: Expression) => JsxSpreadAttribute, + /** + * @deprecated Use `factory.updateJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxSpreadAttribute: (node: JsxSpreadAttribute, expression: Expression) => JsxSpreadAttribute, + /** + * @deprecated Use `factory.createJsxExpression` or the factory supplied by your transformation context instead. + */ + createJsxExpression: (dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) => JsxExpression, + /** + * @deprecated Use `factory.updateJsxExpression` or the factory supplied by your transformation context instead. + */ + updateJsxExpression: (node: JsxExpression, expression: Expression | undefined) => JsxExpression, + /** + * @deprecated Use `factory.createCaseClause` or the factory supplied by your transformation context instead. + */ + createCaseClause: (expression: Expression, statements: readonly Statement[]) => CaseClause, + /** + * @deprecated Use `factory.updateCaseClause` or the factory supplied by your transformation context instead. + */ + updateCaseClause: (node: CaseClause, expression: Expression, statements: readonly Statement[]) => CaseClause, + /** + * @deprecated Use `factory.createDefaultClause` or the factory supplied by your transformation context instead. + */ + createDefaultClause: (statements: readonly Statement[]) => DefaultClause, + /** + * @deprecated Use `factory.updateDefaultClause` or the factory supplied by your transformation context instead. + */ + updateDefaultClause: (node: DefaultClause, statements: readonly Statement[]) => DefaultClause, + /** + * @deprecated Use `factory.createHeritageClause` or the factory supplied by your transformation context instead. + */ + createHeritageClause: (token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword, types: readonly ExpressionWithTypeArguments[]) => HeritageClause, + /** + * @deprecated Use `factory.updateHeritageClause` or the factory supplied by your transformation context instead. + */ + updateHeritageClause: (node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) => HeritageClause, + /** + * @deprecated Use `factory.createCatchClause` or the factory supplied by your transformation context instead. + */ + createCatchClause: (variableDeclaration: string | VariableDeclaration | undefined, block: Block) => CatchClause, + /** + * @deprecated Use `factory.updateCatchClause` or the factory supplied by your transformation context instead. + */ + updateCatchClause: (node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) => CatchClause, + /** + * @deprecated Use `factory.createPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createPropertyAssignment: (name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, initializer: Expression) => PropertyAssignment, + /** + * @deprecated Use `factory.updatePropertyAssignment` or the factory supplied by your transformation context instead. + */ + updatePropertyAssignment: (node: PropertyAssignment, name: PropertyName, initializer: Expression) => PropertyAssignment, + /** + * @deprecated Use `factory.createShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createShorthandPropertyAssignment: (name: string | Identifier, objectAssignmentInitializer?: Expression | undefined) => ShorthandPropertyAssignment, + /** + * @deprecated Use `factory.updateShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + updateShorthandPropertyAssignment: (node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) => ShorthandPropertyAssignment, + /** + * @deprecated Use `factory.createSpreadAssignment` or the factory supplied by your transformation context instead. + */ + createSpreadAssignment: (expression: Expression) => SpreadAssignment, + /** + * @deprecated Use `factory.updateSpreadAssignment` or the factory supplied by your transformation context instead. + */ + updateSpreadAssignment: (node: SpreadAssignment, expression: Expression) => SpreadAssignment, + /** + * @deprecated Use `factory.createEnumMember` or the factory supplied by your transformation context instead. + */ + createEnumMember: (name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, initializer?: Expression | undefined) => EnumMember, + /** + * @deprecated Use `factory.updateEnumMember` or the factory supplied by your transformation context instead. + */ + updateEnumMember: (node: EnumMember, name: PropertyName, initializer: Expression | undefined) => EnumMember, updateSourceFileNode: (node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean | undefined, referencedFiles?: readonly FileReference[] | undefined, typeReferences?: readonly FileReference[] | undefined, hasNoDefaultLib?: boolean | undefined, libReferences?: readonly FileReference[] | undefined) => SourceFile, + /** + * @deprecated Use `factory.createNotEmittedStatement` or the factory supplied by your transformation context instead. + */ + createNotEmittedStatement: (original: Node) => NotEmittedStatement, + /** + * @deprecated Use `factory.createPartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + createPartiallyEmittedExpression: (expression: Expression, original?: Node | undefined) => PartiallyEmittedExpression, + /** + * @deprecated Use `factory.updatePartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + updatePartiallyEmittedExpression: (node: PartiallyEmittedExpression, expression: Expression) => PartiallyEmittedExpression, + /** + * @deprecated Use `factory.createCommaList` or the factory supplied by your transformation context instead. + */ + createCommaList: (elements: readonly Expression[]) => CommaListExpression, + /** + * @deprecated Use `factory.updateCommaList` or the factory supplied by your transformation context instead. + */ + updateCommaList: (node: CommaListExpression, elements: readonly Expression[]) => CommaListExpression, + /** + * @deprecated Use `factory.createBundle` or the factory supplied by your transformation context instead. + */ + createBundle: (sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[] | undefined) => Bundle, + /** + * @deprecated Use `factory.updateBundle` or the factory supplied by your transformation context instead. + */ + updateBundle: (node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[] | undefined) => Bundle, + /** + * @deprecated Use `factory.createImmediatelyInvokedFunctionExpression` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedFunctionExpression: { + (statements: readonly Statement[]): CallExpression; + (statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + }, + /** + * @deprecated Use `factory.createImmediatelyInvokedArrowFunction` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedArrowFunction: { + (statements: readonly Statement[]): CallExpression; + (statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + }, + /** + * @deprecated Use `factory.createVoidZero` or the factory supplied by your transformation context instead. + */ + createVoidZero: () => VoidExpression, + /** + * @deprecated Use `factory.createExportDefault` or the factory supplied by your transformation context instead. + */ + createExportDefault: (expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.createExternalModuleExport` or the factory supplied by your transformation context instead. + */ + createExternalModuleExport: (exportName: Identifier) => ExportDeclaration; + /** + * @deprecated Use `factory.createToken` or the factory supplied by your transformation context instead. + */ + function createToken(kind: TKind): Token; + /** + * @deprecated Use `factory.createIdentifier` or the factory supplied by your transformation context instead. + */ + function createIdentifier(text: string): Identifier; + /** + * @deprecated Use `factory.createTempVariable` or the factory supplied by your transformation context instead. + */ + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** + * @deprecated Use `factory.getGeneratedNameForNode` or the factory supplied by your transformation context instead. + */ + function getGeneratedNameForNode(node: Node | undefined): Identifier; + /** + * @deprecated Use `factory.createIndexSignature` or the factory supplied by your transformation context instead. + */ + function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + /** + * @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. + */ + function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode; + /** + * @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. + */ + function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode; + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; + /** + * @deprecated Use `factory.createNumericLiteral` or `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + function createLiteral(value: number | PseudoBigInt): NumericLiteral; + /** + * @deprecated Use `factory.createTrue` or `factory.createFalse` or the factory supplied by your transformation context instead. + */ + function createLiteral(value: boolean): BooleanLiteral; + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; + /** + * @deprecated Use `factory.createMethodSignature` or the factory supplied by your transformation context instead. + */ + function createMethodSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): MethodSignature; + /** + * @deprecated Use `factory.updateMethodSignature` or the factory supplied by your transformation context instead. + */ + function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined): MethodSignature; + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + /** @deprecated */ + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + function createYield(expression?: Expression): YieldExpression; + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; + /** + * @deprecated Use `factory.createClassExpression` or the factory supplied by your transformation context instead. + */ + function createClassExpression(modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + /** + * @deprecated Use `factory.updateClassExpression` or the factory supplied by your transformation context instead. + */ + function updateClassExpression(node: ClassExpression, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + /** + * @deprecated Use `factory.createPropertySignature` or the factory supplied by your transformation context instead. + */ + function createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer?: Expression): PropertySignature; + /** + * @deprecated Use `factory.updatePropertySignature` or the factory supplied by your transformation context instead. + */ + function updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; + /** + * @deprecated Use `factory.createExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; + /** + * @deprecated Use `factory.updateExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.createComma` or the factory supplied by your transformation context instead. + */ + function createComma(left: Expression, right: Expression): Expression; + /** + * @deprecated Use `factory.createLessThan` or the factory supplied by your transformation context instead. + */ + function createLessThan(left: Expression, right: Expression): Expression; + /** + * @deprecated Use `factory.createAssignment` or the factory supplied by your transformation context instead. + */ + function createAssignment(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createStrictEquality` or the factory supplied by your transformation context instead. + */ + function createStrictEquality(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createStrictInequality` or the factory supplied by your transformation context instead. + */ + function createStrictInequality(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createAdd` or the factory supplied by your transformation context instead. + */ + function createAdd(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createSubtract` or the factory supplied by your transformation context instead. + */ + function createSubtract(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createLogicalAnd` or the factory supplied by your transformation context instead. + */ + function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createLogicalOr` or the factory supplied by your transformation context instead. + */ + function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createPostfixIncrement` or the factory supplied by your transformation context instead. + */ + function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + /** + * @deprecated Use `factory.{0}` or the factory supplied by your transformation context instead. + */ + /** + * @deprecated Use `factory.createLogicalNot` or the factory supplied by your transformation context instead. + */ + function createLogicalNot(operand: Expression): PrefixUnaryExpression; + /** + * @deprecated Use `isTypeAssertionExpression` instead. + */ + function isTypeAssertion(node: Node): node is TypeAssertion; +} export = ts; export as namespace ts; \ No newline at end of file diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 433217ee422c7..fab0a9b93c91b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -72,9 +72,6 @@ declare namespace ts { pos: number; end: number; } - export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; - export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword; - export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; export enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -434,6 +431,16 @@ declare namespace ts { FirstJSDocTagNode = 304, LastJSDocTagNode = 316, } + export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; + export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; + export type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; + export type PunctuationSyntaxKind = SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.DotToken | SyntaxKind.DotDotDotToken | SyntaxKind.SemicolonToken | SyntaxKind.CommaToken | SyntaxKind.QuestionDotToken | SyntaxKind.LessThanToken | SyntaxKind.LessThanSlashToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.EqualsGreaterThanToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.ExclamationToken | SyntaxKind.TildeToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.QuestionToken | SyntaxKind.ColonToken | SyntaxKind.AtToken | SyntaxKind.BacktickToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken; + export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InferKeyword | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.OfKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; + export type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.StaticKeyword; + export type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; + export type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; + export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; + export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind; export enum NodeFlags { None = 0, Let = 1, @@ -502,7 +509,7 @@ declare namespace ts { } export interface JSDocContainer { } - export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | EndOfFileToken; + export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | EndOfFileToken; export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertySignature | PropertyDeclaration | PropertyAssignment | EnumMember; @@ -512,22 +519,47 @@ declare namespace ts { export interface Token extends Node { kind: TKind; } - export type DotToken = Token; - export type DotDotDotToken = Token; - export type QuestionToken = Token; - export type QuestionDotToken = Token; - export type ExclamationToken = Token; - export type ColonToken = Token; - export type EqualsToken = Token; - export type AsteriskToken = Token; - export type EqualsGreaterThanToken = Token; export type EndOfFileToken = Token & JSDocContainer; - export type ReadonlyToken = Token; - export type AwaitKeywordToken = Token; - export type PlusToken = Token; - export type MinusToken = Token; - export type AssertsToken = Token; - export type Modifier = Token | Token | Token | Token | Token | Token | Token | Token | Token | Token | Token; + export interface PunctuationToken extends Token { + } + export type DotToken = PunctuationToken; + export type DotDotDotToken = PunctuationToken; + export type QuestionToken = PunctuationToken; + export type ExclamationToken = PunctuationToken; + export type ColonToken = PunctuationToken; + export type EqualsToken = PunctuationToken; + export type AsteriskToken = PunctuationToken; + export type EqualsGreaterThanToken = PunctuationToken; + export type PlusToken = PunctuationToken; + export type MinusToken = PunctuationToken; + export type QuestionDotToken = PunctuationToken; + export interface KeywordToken extends Token { + } + export type AssertsKeyword = KeywordToken; + export type AwaitKeyword = KeywordToken; + /** @deprecated Use `AwaitKeyword` instead. */ + export type AwaitKeywordToken = AwaitKeyword; + /** @deprecated Use `AssertsKeyword` instead. */ + export type AssertsToken = AssertsKeyword; + export interface ModifierToken extends KeywordToken { + } + export type AbstractKeyword = ModifierToken; + export type AsyncKeyword = ModifierToken; + export type ConstKeyword = ModifierToken; + export type DeclareKeyword = ModifierToken; + export type DefaultKeyword = ModifierToken; + export type ExportKeyword = ModifierToken; + export type PrivateKeyword = ModifierToken; + export type ProtectedKeyword = ModifierToken; + export type PublicKeyword = ModifierToken; + export type ReadonlyKeyword = ModifierToken; + export type StaticKeyword = ModifierToken; + /** @deprecated Use `ReadonlyKeyword` instead. */ + export type ReadonlyToken = ReadonlyKeyword; + export type Modifier = AbstractKeyword | AsyncKeyword | ConstKeyword | DeclareKeyword | DefaultKeyword | ExportKeyword | PrivateKeyword | ProtectedKeyword | PublicKeyword | ReadonlyKeyword | StaticKeyword; + export type AccessibilityModifier = PublicKeyword | PrivateKeyword | ProtectedKeyword; + export type ParameterPropertyModifier = AccessibilityModifier | ReadonlyKeyword; + export type ClassMemberModifier = AccessibilityModifier | ReadonlyKeyword | StaticKeyword; export type ModifiersArray = NodeArray; export interface Identifier extends PrimaryExpression, Declaration { kind: SyntaxKind.Identifier; @@ -650,6 +682,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; + exclamationToken?: ExclamationToken; initializer: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { @@ -746,8 +779,8 @@ declare namespace ts { export interface TypeNode extends Node { _typeNodeBrand: any; } - export interface KeywordTypeNode extends TypeNode { - kind: SyntaxKind.AnyKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.NumberKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.VoidKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.NullKeyword | SyntaxKind.NeverKeyword; + export interface KeywordTypeNode extends KeywordToken, TypeNode { + kind: TKind; } export interface ImportTypeNode extends NodeWithTypeArguments { kind: SyntaxKind.ImportType; @@ -851,12 +884,13 @@ declare namespace ts { } export interface LiteralTypeNode extends TypeNode { kind: SyntaxKind.LiteralType; - literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression; + literal: NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; } export interface StringLiteral extends LiteralExpression, Declaration { kind: SyntaxKind.StringLiteral; } export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral; + export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; export interface Expression extends Node { _expressionBrand: any; } @@ -896,13 +930,17 @@ declare namespace ts { export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } - export interface NullLiteral extends PrimaryExpression, TypeNode { + export interface NullLiteral extends PrimaryExpression { kind: SyntaxKind.NullKeyword; } - export interface BooleanLiteral extends PrimaryExpression, TypeNode { - kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword; + export interface TrueLiteral extends PrimaryExpression { + kind: SyntaxKind.TrueKeyword; } - export interface ThisExpression extends PrimaryExpression, KeywordTypeNode { + export interface FalseLiteral extends PrimaryExpression { + kind: SyntaxKind.FalseKeyword; + } + export type BooleanLiteral = TrueLiteral | FalseLiteral; + export interface ThisExpression extends PrimaryExpression { kind: SyntaxKind.ThisKeyword; } export interface SuperExpression extends PrimaryExpression { @@ -975,7 +1013,9 @@ declare namespace ts { left: ArrayLiteralExpression; } export type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment; - export type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; + export type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | ObjectBindingOrAssignmentElement | ArrayBindingOrAssignmentElement; + export type ObjectBindingOrAssignmentElement = BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment; + export type ArrayBindingOrAssignmentElement = BindingElement | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; export type BindingOrAssignmentElementRestIndicator = DotDotDotToken | SpreadElement | SpreadAssignment; export type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Identifier | PropertyAccessExpression | ElementAccessExpression | OmittedExpression; export type ObjectBindingOrAssignmentPattern = ObjectBindingPattern | ObjectLiteralExpression; @@ -1034,6 +1074,7 @@ declare namespace ts { export interface BigIntLiteral extends LiteralExpression { kind: SyntaxKind.BigIntLiteral; } + export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { kind: SyntaxKind.TemplateHead; parent: TemplateExpression; @@ -1046,12 +1087,14 @@ declare namespace ts { kind: SyntaxKind.TemplateTail; parent: TemplateSpan; } - export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; + export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; + export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; export interface TemplateExpression extends PrimaryExpression { kind: SyntaxKind.TemplateExpression; head: TemplateHead; templateSpans: NodeArray; } + export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; export interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; parent: TemplateExpression; @@ -1473,7 +1516,7 @@ declare namespace ts { parent: ImportEqualsDeclaration; expression: Expression; } - export interface ImportDeclaration extends Statement { + export interface ImportDeclaration extends Statement, JSDocContainer { kind: SyntaxKind.ImportDeclaration; parent: SourceFile | ModuleBlock; importClause?: ImportClause; @@ -1492,7 +1535,7 @@ declare namespace ts { parent: ImportClause; name: Identifier; } - export interface NamespaceExportDeclaration extends DeclarationStatement { + export interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.NamespaceExportDeclaration; name: Identifier; } @@ -1532,7 +1575,7 @@ declare namespace ts { * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ - export interface ExportAssignment extends DeclarationStatement { + export interface ExportAssignment extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ExportAssignment; parent: SourceFile; isExportEquals?: boolean; @@ -2915,7 +2958,376 @@ declare namespace ts { Unspecified = 4, EmbeddedStatement = 5 } - export interface TransformationContext { + export enum OuterExpressionKinds { + Parentheses = 1, + Assertions = 2, + PartiallyEmittedExpressions = 4, + All = 7 + } + export type TypeOfTag = "undefined" | "number" | "bigint" | "boolean" | "string" | "symbol" | "object" | "function"; + export interface NodeFactory { + createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; + createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; + createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; + createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; + createStringLiteralFromNode(sourceNode: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; + createRegularExpressionLiteral(text: string): RegularExpressionLiteral; + createIdentifier(text: string): Identifier; + /** Create a unique temporary variable. */ + createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** Create a unique temporary variable for use in a loop. */ + createLoopVariable(): Identifier; + /** Create a unique name based on the supplied text. */ + createUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. */ + createOptimisticUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ + createFileLevelUniqueName(text: string): Identifier; + /** Create a unique name generated for a node. */ + getGeneratedNameForNode(node: Node | undefined): Identifier; + createToken(token: SyntaxKind.SuperKeyword): SuperExpression; + createToken(token: SyntaxKind.ThisKeyword): ThisExpression; + createToken(token: SyntaxKind.NullKeyword): NullLiteral; + createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; + createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: TKind): PunctuationToken; + createToken(token: TKind): KeywordTypeNode; + createToken(token: TKind): ModifierToken; + createToken(token: TKind): KeywordToken; + createToken(token: TKind): Token; + createSuper(): SuperExpression; + createThis(): ThisExpression; + createNull(): NullLiteral; + createTrue(): TrueLiteral; + createFalse(): FalseLiteral; + createModifier(kind: T): ModifierToken; + createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[]; + createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName; + updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; + createComputedPropertyName(expression: Expression): ComputedPropertyName; + updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; + createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; + updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; + createParameterDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; + updateParameterDeclaration(node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createDecorator(expression: Expression): Decorator; + updateDecorator(node: Decorator, expression: Expression): Decorator; + createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; + createPropertyDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + updatePropertyDeclaration(node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; + createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; + updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; + createMethodDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + updateMethodDeclaration(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; + createConstructorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + updateConstructorDeclaration(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; + createGetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + updateGetAccessorDeclaration(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; + createSetAccessorDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + updateSetAccessorDeclaration(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; + createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; + updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; + createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; + updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; + createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createKeywordTypeNode(kind: TKind): KeywordTypeNode; + createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; + updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; + updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; + createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode; + updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode; + createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode; + updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; + createTypeQueryNode(exprName: EntityName): TypeQueryNode; + updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; + createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; + updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; + createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; + updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; + createTupleTypeNode(elementTypes: readonly TypeNode[]): TupleTypeNode; + updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]): TupleTypeNode; + createOptionalTypeNode(type: TypeNode): OptionalTypeNode; + updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; + createRestTypeNode(type: TypeNode): RestTypeNode; + updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode; + createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode; + updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; + createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; + updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; + createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; + updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; + createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; + updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; + createThisTypeNode(): ThisTypeNode; + createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; + createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; + updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; + createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; + updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; + createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; + createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; + updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; + updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; + createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; + updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; + updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier): PropertyAccessChain; + updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier): PropertyAccessChain; + createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; + updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; + createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; + updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; + createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; + updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; + createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; + updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; + createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; + createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; + updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; + createParen(expression: Expression): ParenthesizedExpression; + updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; + createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; + updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; + createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createDelete(expression: Expression): DeleteExpression; + updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression; + createTypeOf(expression: Expression): TypeOfExpression; + updateTypeOf(node: TypeOfExpression, expression: Expression): TypeOfExpression; + createVoid(expression: Expression): VoidExpression; + updateVoid(node: VoidExpression, expression: Expression): VoidExpression; + createAwait(expression: Expression): AwaitExpression; + updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; + createPrefix(operator: PrefixUnaryOperator, operand: Expression): PrefixUnaryExpression; + updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; + createPostfix(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; + updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; + createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; + updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken): BinaryExpression; + createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + updateConditional(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + createTemplateHead(text: string, rawText?: string): TemplateHead; + createTemplateHead(text: string | undefined, rawText: string): TemplateHead; + createTemplateMiddle(text: string, rawText?: string): TemplateMiddle; + createTemplateMiddle(text: string | undefined, rawText: string): TemplateMiddle; + createTemplateTail(text: string, rawText?: string): TemplateTail; + createTemplateTail(text: string | undefined, rawText: string): TemplateTail; + createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; + createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; + createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + createYield(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; + updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + createSpread(expression: Expression): SpreadElement; + updateSpread(node: SpreadElement, expression: Expression): SpreadElement; + createClassExpression(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + updateClassExpression(node: ClassExpression, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createOmittedExpression(): OmittedExpression; + createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createAsExpression(expression: Expression, type: TypeNode): AsExpression; + updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; + createNonNullExpression(expression: Expression): NonNullExpression; + updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression; + createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; + updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; + createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + createSemicolonClassElement(): SemicolonClassElement; + createBlock(statements: readonly Statement[], multiLine?: boolean): Block; + updateBlock(node: Block, statements: readonly Statement[]): Block; + createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; + updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createEmptyStatement(): EmptyStatement; + createExpressionStatement(expression: Expression): ExpressionStatement; + updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; + updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + createDo(statement: Statement, expression: Expression): DoStatement; + updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; + createWhile(expression: Expression, statement: Statement): WhileStatement; + updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; + createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + createForOf(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForOf(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + createContinue(label?: string | Identifier): ContinueStatement; + updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; + createBreak(label?: string | Identifier): BreakStatement; + updateBreak(node: BreakStatement, label: Identifier | undefined): BreakStatement; + createReturn(expression?: Expression): ReturnStatement; + updateReturn(node: ReturnStatement, expression: Expression | undefined): ReturnStatement; + createWith(expression: Expression, statement: Statement): WithStatement; + updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; + createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement; + updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; + createLabel(label: string | Identifier, statement: Statement): LabeledStatement; + updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; + createThrow(expression: Expression): ThrowStatement; + updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; + createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createDebuggerStatement(): DebuggerStatement; + createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; + updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; + updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; + createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + updateFunctionDeclaration(node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; + createClassDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + updateClassDeclaration(node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; + createInterfaceDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; + createTypeAliasDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; + createEnumDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; + updateEnumDeclaration(node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; + createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; + updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createModuleBlock(statements: readonly Statement[]): ModuleBlock; + updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; + createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; + updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; + createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; + updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; + createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + createNamespaceImport(name: Identifier): NamespaceImport; + updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; + createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; + updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; + createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; + createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; + updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression): ExportAssignment; + createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; + updateExportDeclaration(node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; + createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; + updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; + createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; + updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExternalModuleReference(expression: Expression): ExternalModuleReference; + updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; + createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; + createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; + createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; + updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; + createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + createJsxOpeningFragment(): JsxOpeningFragment; + createJsxJsxClosingFragment(): JsxClosingFragment; + updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined): JsxAttribute; + createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; + updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; + createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; + updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; + createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; + updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; + createCaseClause(expression: Expression, statements: readonly Statement[]): CaseClause; + updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; + createDefaultClause(statements: readonly Statement[]): DefaultClause; + updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; + createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; + updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; + createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block): CatchClause; + updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; + updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; + createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + createSpreadAssignment(expression: Expression): SpreadAssignment; + updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; + createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; + updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; + createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile; + updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + createNotEmittedStatement(original: Node): NotEmittedStatement; + createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; + updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + createCommaList(elements: readonly Expression[]): CommaListExpression; + updateCommaList(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; + createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + createComma(left: Expression, right: Expression): BinaryExpression; + createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment(left: Expression, right: Expression): AssignmentExpression; + createLogicalOr(left: Expression, right: Expression): BinaryExpression; + createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + createBitwiseOr(left: Expression, right: Expression): BinaryExpression; + createBitwiseXor(left: Expression, right: Expression): BinaryExpression; + createBitwiseAnd(left: Expression, right: Expression): BinaryExpression; + createStrictEquality(left: Expression, right: Expression): BinaryExpression; + createStrictInequality(left: Expression, right: Expression): BinaryExpression; + createEquality(left: Expression, right: Expression): BinaryExpression; + createInequality(left: Expression, right: Expression): BinaryExpression; + createLessThan(left: Expression, right: Expression): BinaryExpression; + createLessThanEquals(left: Expression, right: Expression): BinaryExpression; + createGreaterThan(left: Expression, right: Expression): BinaryExpression; + createGreaterThanEquals(left: Expression, right: Expression): BinaryExpression; + createLeftShift(left: Expression, right: Expression): BinaryExpression; + createRightShift(left: Expression, right: Expression): BinaryExpression; + createUnsignedRightShift(left: Expression, right: Expression): BinaryExpression; + createAdd(left: Expression, right: Expression): BinaryExpression; + createSubtract(left: Expression, right: Expression): BinaryExpression; + createMultiply(left: Expression, right: Expression): BinaryExpression; + createDivide(left: Expression, right: Expression): BinaryExpression; + createModulo(left: Expression, right: Expression): BinaryExpression; + createExponent(left: Expression, right: Expression): BinaryExpression; + createPrefixPlus(operand: Expression): PrefixUnaryExpression; + createPrefixMinus(operand: Expression): PrefixUnaryExpression; + createPrefixIncrement(operand: Expression): PrefixUnaryExpression; + createPrefixDecrement(operand: Expression): PrefixUnaryExpression; + createBitwiseNot(operand: Expression): PrefixUnaryExpression; + createLogicalNot(operand: Expression): PrefixUnaryExpression; + createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + createPostfixDecrement(operand: Expression): PostfixUnaryExpression; + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; + createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createVoidZero(): VoidExpression; + createExportDefault(expression: Expression): ExportAssignment; + createExternalModuleExport(exportName: Identifier): ExportDeclaration; + restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + } + export interface CoreTransformationContext { + readonly factory: NodeFactory; /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; /** Starts a new lexical environment. */ @@ -2930,6 +3342,8 @@ declare namespace ts { hoistFunctionDeclaration(node: FunctionDeclaration): void; /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + } + export interface TransformationContext extends CoreTransformationContext { /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; /** Gets and resets the requested non-scoped emit helpers. */ @@ -3372,7 +3786,7 @@ declare namespace ts { * @param node The original node. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node): Node; + function getParseTreeNode(node: Node | undefined): Node | undefined; /** * Gets the original parse tree node for a node. * @@ -3380,7 +3794,7 @@ declare namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + function getParseTreeNode(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined; /** Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' */ function escapeLeadingUnderscores(identifier: string): __String; /** @@ -3469,6 +3883,155 @@ declare namespace ts { function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; } +declare namespace ts { + function setTextRange(range: T, location: TextRange | undefined): T; + function isConstTypeReference(node: Node): boolean; + function skipPartiallyEmittedExpressions(node: Expression): Expression; + function skipPartiallyEmittedExpressions(node: Node): Node; + function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag; + function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; + function isModifier(node: Node): node is Modifier; + function isEntityName(node: Node): node is EntityName; + function isPropertyName(node: Node): node is PropertyName; + function isBindingName(node: Node): node is BindingName; + function isClassElement(node: Node): node is ClassElement; + function isTypeElement(node: Node): node is TypeElement; + function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + function isObjectLiteralElement(node: Node): node is ObjectLiteralElement; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node: Node): node is TypeNode; + function isTemplateLiteral(node: Node): node is TemplateLiteral; + function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement; + function isUnparsedTextLike(node: Node): node is UnparsedTextLike; + function isUnparsedNode(node: Node): node is UnparsedNode; + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ + function isToken(n: Node): boolean; + function isLiteralExpression(node: Node): node is LiteralExpression; + function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; + function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; + function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; + function isFunctionLike(node: Node): node is SignatureDeclaration; + function isClassLike(node: Node): node is ClassLikeDeclaration; + function isAccessor(node: Node): node is AccessorDeclaration; + function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; + function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; + function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; + function isCallLikeExpression(node: Node): node is CallLikeExpression; + function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; + function isAssertionExpression(node: Node): node is AssertionExpression; + function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; + function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; + function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; + /** True if node is of a kind that may contain comment text. */ + function isJSDocCommentContainingNode(node: Node): boolean; + function isSetAccessor(node: Node): node is SetAccessorDeclaration; + function isGetAccessor(node: Node): node is GetAccessorDeclaration; + function isStringLiteralLike(node: Node): node is StringLiteralLike; +} +declare namespace ts { + function isPropertyAccessChain(node: Node): node is PropertyAccessChain; + function isElementAccessChain(node: Node): node is ElementAccessChain; + function isCallChain(node: Node): node is CallChain; + function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain; + function isNullishCoalesce(node: Node): boolean; +} +declare namespace ts { + const factory: NodeFactory; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node: T): T; + function createUnparsedSourceFile(text: string): UnparsedSource; + function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; + function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; + function createInputFiles(javascriptText: string, declarationText: string): InputFiles; + function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; + function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; + /** + * Create an external source map source file reference + */ + function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + function setOriginalNode(node: T, original: Node | undefined): T; +} +declare namespace ts { + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile: SourceFile | undefined): void; + /** + * Sets flags that control emit behavior of a node. + */ + function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Gets a custom text range to use when emitting source maps. + */ + function getSourceMapRange(node: Node): SourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ + function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ + function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ + function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; + /** + * Gets a custom text range to use when emitting comments. + */ + function getCommentRange(node: Node): TextRange; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node: T, range: TextRange): T; + function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; + function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; + function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; + function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; + function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function moveSyntheticComments(node: T, original: Node): T; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression; + /** + * Adds an EmitHelper to a node. + */ + function addEmitHelper(node: T, helper: EmitHelper): T; + /** + * Add EmitHelpers to a node. + */ + function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; + /** + * Removes an EmitHelper from a node. + */ + function removeEmitHelper(node: Node, helper: EmitHelper): boolean; + /** + * Gets the EmitHelpers of a node. + */ + function getEmitHelpers(node: Node): EmitHelper[] | undefined; + /** + * Moves matching emit helpers from a source node to a target node. + */ + function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; +} declare namespace ts { function isNumericLiteral(node: Node): node is NumericLiteral; function isBigIntLiteral(node: Node): node is BigIntLiteral; @@ -3503,6 +4066,8 @@ declare namespace ts { function isTypeLiteralNode(node: Node): node is TypeLiteralNode; function isArrayTypeNode(node: Node): node is ArrayTypeNode; function isTupleTypeNode(node: Node): node is TupleTypeNode; + function isOptionalTypeNode(node: Node): node is OptionalTypeNode; + function isRestTypeNode(node: Node): node is RestTypeNode; function isUnionTypeNode(node: Node): node is UnionTypeNode; function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode; function isConditionalTypeNode(node: Node): node is ConditionalTypeNode; @@ -3520,20 +4085,12 @@ declare namespace ts { function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression; function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression; function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; - function isPropertyAccessChain(node: Node): node is PropertyAccessChain; function isElementAccessExpression(node: Node): node is ElementAccessExpression; - function isElementAccessChain(node: Node): node is ElementAccessChain; function isCallExpression(node: Node): node is CallExpression; - function isCallChain(node: Node): node is CallChain; - function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain; - function isNullishCoalesce(node: Node): boolean; function isNewExpression(node: Node): node is NewExpression; function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression; - function isTypeAssertion(node: Node): node is TypeAssertion; - function isConstTypeReference(node: Node): boolean; + function isTypeAssertionExpression(node: Node): node is TypeAssertion; function isParenthesizedExpression(node: Node): node is ParenthesizedExpression; - function skipPartiallyEmittedExpressions(node: Expression): Expression; - function skipPartiallyEmittedExpressions(node: Node): Node; function isFunctionExpression(node: Node): node is FunctionExpression; function isArrowFunction(node: Node): node is ArrowFunction; function isDeleteExpression(node: Node): node is DeleteExpression; @@ -3553,6 +4110,9 @@ declare namespace ts { function isAsExpression(node: Node): node is AsExpression; function isNonNullExpression(node: Node): node is NonNullExpression; function isMetaProperty(node: Node): node is MetaProperty; + function isSyntheticExpression(node: Node): node is SyntheticExpression; + function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression; + function isCommaListExpression(node: Node): node is CommaListExpression; function isTemplateSpan(node: Node): node is TemplateSpan; function isSemicolonClassElement(node: Node): node is SemicolonClassElement; function isBlock(node: Node): node is Block; @@ -3567,7 +4127,6 @@ declare namespace ts { function isForOfStatement(node: Node): node is ForOfStatement; function isContinueStatement(node: Node): node is ContinueStatement; function isBreakStatement(node: Node): node is BreakStatement; - function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement; function isReturnStatement(node: Node): node is ReturnStatement; function isWithStatement(node: Node): node is WithStatement; function isSwitchStatement(node: Node): node is SwitchStatement; @@ -3597,6 +4156,7 @@ declare namespace ts { function isNamedExports(node: Node): node is NamedExports; function isExportSpecifier(node: Node): node is ExportSpecifier; function isMissingDeclaration(node: Node): node is MissingDeclaration; + function isNotEmittedStatement(node: Node): node is NotEmittedStatement; function isExternalModuleReference(node: Node): node is ExternalModuleReference; function isJsxElement(node: Node): node is JsxElement; function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement; @@ -3617,12 +4177,10 @@ declare namespace ts { function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment; function isSpreadAssignment(node: Node): node is SpreadAssignment; function isEnumMember(node: Node): node is EnumMember; + function isUnparsedPrepend(node: Node): node is UnparsedPrepend; function isSourceFile(node: Node): node is SourceFile; function isBundle(node: Node): node is Bundle; function isUnparsedSource(node: Node): node is UnparsedSource; - function isUnparsedPrepend(node: Node): node is UnparsedPrepend; - function isUnparsedTextLike(node: Node): node is UnparsedTextLike; - function isUnparsedNode(node: Node): node is UnparsedNode; function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression; function isJSDocAllType(node: Node): node is JSDocAllType; function isJSDocUnknownType(node: Node): node is JSDocUnknownType; @@ -3631,69 +4189,23 @@ declare namespace ts { function isJSDocOptionalType(node: Node): node is JSDocOptionalType; function isJSDocFunctionType(node: Node): node is JSDocFunctionType; function isJSDocVariadicType(node: Node): node is JSDocVariadicType; + function isJSDocNamepathType(node: Node): node is JSDocNamepathType; function isJSDoc(node: Node): node is JSDoc; - function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; + function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; + function isJSDocSignature(node: Node): node is JSDocSignature; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; + function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; + function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; - function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocParameterTag(node: Node): node is JSDocParameterTag; function isJSDocReturnTag(node: Node): node is JSDocReturnTag; + function isJSDocThisTag(node: Node): node is JSDocThisTag; function isJSDocTypeTag(node: Node): node is JSDocTypeTag; function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag; function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag; + function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag; function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag; - function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag; - function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; - function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; - function isJSDocSignature(node: Node): node is JSDocSignature; -} -declare namespace ts { - /** - * True if node is of some token syntax kind. - * For example, this is true for an IfKeyword but not for an IfStatement. - * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. - */ - function isToken(n: Node): boolean; - function isLiteralExpression(node: Node): node is LiteralExpression; - type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail; - function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; - function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; - function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; - function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; - function isModifier(node: Node): node is Modifier; - function isEntityName(node: Node): node is EntityName; - function isPropertyName(node: Node): node is PropertyName; - function isBindingName(node: Node): node is BindingName; - function isFunctionLike(node: Node): node is SignatureDeclaration; - function isClassElement(node: Node): node is ClassElement; - function isClassLike(node: Node): node is ClassLikeDeclaration; - function isAccessor(node: Node): node is AccessorDeclaration; - function isTypeElement(node: Node): node is TypeElement; - function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; - function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; - /** - * Node test that determines whether a node is a valid type node. - * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* - * of a TypeNode. - */ - function isTypeNode(node: Node): node is TypeNode; - function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; - function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; - function isCallLikeExpression(node: Node): node is CallLikeExpression; - function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; - function isTemplateLiteral(node: Node): node is TemplateLiteral; - function isAssertionExpression(node: Node): node is AssertionExpression; - function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; - function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; - function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; - /** True if node is of a kind that may contain comment text. */ - function isJSDocCommentContainingNode(node: Node): boolean; - function isSetAccessor(node: Node): node is SetAccessorDeclaration; - function isGetAccessor(node: Node): node is GetAccessorDeclaration; - function isObjectLiteralElement(node: Node): node is ObjectLiteralElement; - function isStringLiteralLike(node: Node): node is StringLiteralLike; } declare namespace ts { export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; @@ -3851,442 +4363,6 @@ declare namespace ts { function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; } -declare namespace ts { - function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; - /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ - function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; - function createLiteral(value: number | PseudoBigInt): NumericLiteral; - function createLiteral(value: boolean): BooleanLiteral; - function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; - function createNumericLiteral(value: string, numericLiteralFlags?: TokenFlags): NumericLiteral; - function createBigIntLiteral(value: string): BigIntLiteral; - function createStringLiteral(text: string): StringLiteral; - function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; - function createIdentifier(text: string): Identifier; - function updateIdentifier(node: Identifier): Identifier; - /** Create a unique temporary variable. */ - function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; - /** Create a unique temporary variable for use in a loop. */ - function createLoopVariable(): Identifier; - /** Create a unique name based on the supplied text. */ - function createUniqueName(text: string): Identifier; - /** Create a unique name based on the supplied text. */ - function createOptimisticUniqueName(text: string): Identifier; - /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ - function createFileLevelUniqueName(text: string): Identifier; - /** Create a unique name generated for a node. */ - function getGeneratedNameForNode(node: Node | undefined): Identifier; - function createToken(token: TKind): Token; - function createSuper(): SuperExpression; - function createThis(): ThisExpression & Token; - function createNull(): NullLiteral & Token; - function createTrue(): BooleanLiteral & Token; - function createFalse(): BooleanLiteral & Token; - function createModifier(kind: T): Token; - function createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[]; - function createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName; - function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; - function createComputedPropertyName(expression: Expression): ComputedPropertyName; - function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; - function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; - function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; - function createParameter(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; - function updateParameter(node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; - function createDecorator(expression: Expression): Decorator; - function updateDecorator(node: Decorator, expression: Expression): Decorator; - function createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; - function updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; - function createProperty(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - function updateProperty(node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - function createMethodSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): MethodSignature; - function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined): MethodSignature; - function createMethod(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - function updateMethod(node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - function createConstructor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - function updateConstructor(node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - function createGetAccessor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - function updateGetAccessor(node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - function createSetAccessor(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - function updateSetAccessor(node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - function createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; - function updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; - function createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; - function updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - function updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode; - function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode; - function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; - function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode; - function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; - function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined): TypeReferenceNode; - function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; - function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode; - function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode; - function createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode; - function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; - function createTypeQueryNode(exprName: EntityName): TypeQueryNode; - function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; - function createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; - function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; - function createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; - function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; - function createTupleTypeNode(elementTypes: readonly TypeNode[]): TupleTypeNode; - function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]): TupleTypeNode; - function createOptionalTypeNode(type: TypeNode): OptionalTypeNode; - function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; - function createRestTypeNode(type: TypeNode): RestTypeNode; - function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode; - function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode; - function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; - function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; - function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]): UnionOrIntersectionTypeNode; - function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - function createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; - function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; - function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - function createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; - function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; - function createThisTypeNode(): ThisTypeNode; - function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; - function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; - function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; - function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - function createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - function createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; - function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; - function createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; - function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; - function createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; - function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; - function createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; - function updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; - function createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; - function updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; - function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier): PropertyAccessChain; - function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier): PropertyAccessChain; - function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; - function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; - function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; - function createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; - function updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; - function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; - function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; - function createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - function updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - /** @deprecated */ function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - /** @deprecated */ function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; - function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; - function createParen(expression: Expression): ParenthesizedExpression; - function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - function createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; - function updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; - function createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; - function updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: Token, body: ConciseBody): ArrowFunction; - function createDelete(expression: Expression): DeleteExpression; - function updateDelete(node: DeleteExpression, expression: Expression): DeleteExpression; - function createTypeOf(expression: Expression): TypeOfExpression; - function updateTypeOf(node: TypeOfExpression, expression: Expression): TypeOfExpression; - function createVoid(expression: Expression): VoidExpression; - function updateVoid(node: VoidExpression, expression: Expression): VoidExpression; - function createAwait(expression: Expression): AwaitExpression; - function updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; - function createPrefix(operator: PrefixUnaryOperator, operand: Expression): PrefixUnaryExpression; - function updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; - function createPostfix(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; - function updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; - function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - function updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken): BinaryExpression; - /** @deprecated */ function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; - function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; - function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: Token, whenTrue: Expression, colonToken: Token, whenFalse: Expression): ConditionalExpression; - function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - function createTemplateHead(text: string, rawText?: string): TemplateHead; - function createTemplateMiddle(text: string, rawText?: string): TemplateMiddle; - function createTemplateTail(text: string, rawText?: string): TemplateTail; - function createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; - function createYield(expression?: Expression): YieldExpression; - function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; - function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; - function createSpread(expression: Expression): SpreadElement; - function updateSpread(node: SpreadElement, expression: Expression): SpreadElement; - function createClassExpression(modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - function updateClassExpression(node: ClassExpression, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - function createOmittedExpression(): OmittedExpression; - function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; - function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; - function createAsExpression(expression: Expression, type: TypeNode): AsExpression; - function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; - function createNonNullExpression(expression: Expression): NonNullExpression; - function updateNonNullExpression(node: NonNullExpression, expression: Expression): NonNullExpression; - function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; - function updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; - function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - function createSemicolonClassElement(): SemicolonClassElement; - function createBlock(statements: readonly Statement[], multiLine?: boolean): Block; - function updateBlock(node: Block, statements: readonly Statement[]): Block; - function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; - function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList): VariableStatement; - function createEmptyStatement(): EmptyStatement; - function createExpressionStatement(expression: Expression): ExpressionStatement; - function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; - /** @deprecated Use `createExpressionStatement` instead. */ - const createStatement: typeof createExpressionStatement; - /** @deprecated Use `updateExpressionStatement` instead. */ - const updateStatement: typeof updateExpressionStatement; - function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; - function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; - function createDo(statement: Statement, expression: Expression): DoStatement; - function updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; - function createWhile(expression: Expression, statement: Statement): WhileStatement; - function updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; - function createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function createContinue(label?: string | Identifier): ContinueStatement; - function updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; - function createBreak(label?: string | Identifier): BreakStatement; - function updateBreak(node: BreakStatement, label: Identifier | undefined): BreakStatement; - function createReturn(expression?: Expression): ReturnStatement; - function updateReturn(node: ReturnStatement, expression: Expression | undefined): ReturnStatement; - function createWith(expression: Expression, statement: Statement): WithStatement; - function updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; - function createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement; - function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; - function createLabel(label: string | Identifier, statement: Statement): LabeledStatement; - function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; - function createThrow(expression: Expression): ThrowStatement; - function updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; - function createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - function createDebuggerStatement(): DebuggerStatement; - function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; - function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; - function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; - function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; - function createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function updateFunctionDeclaration(node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function createClassDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - function updateClassDeclaration(node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - function createInterfaceDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - function createTypeAliasDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - function updateTypeAliasDeclaration(node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - function createEnumDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; - function updateEnumDeclaration(node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; - function createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; - function updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; - function createModuleBlock(statements: readonly Statement[]): ModuleBlock; - function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; - function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; - function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; - function createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; - function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - function createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - function createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - function createNamespaceImport(name: Identifier): NamespaceImport; - function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; - function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; - function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; - function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; - function updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression): ExportAssignment; - function createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; - function updateExportDeclaration(node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; - function createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; - function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; - function createExternalModuleReference(expression: Expression): ExternalModuleReference; - function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; - function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; - function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; - function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; - function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; - function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; - function createJsxOpeningFragment(): JsxOpeningFragment; - function createJsxJsxClosingFragment(): JsxClosingFragment; - function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; - function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; - function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; - function createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; - function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; - function createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; - function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; - function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; - function updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; - function createCaseClause(expression: Expression, statements: readonly Statement[]): CaseClause; - function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; - function createDefaultClause(statements: readonly Statement[]): DefaultClause; - function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; - function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; - function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; - function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block): CatchClause; - function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; - function createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; - function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; - function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; - function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; - function createSpreadAssignment(expression: Expression): SpreadAssignment; - function updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; - function createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; - function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; - function updateSourceFileNode(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: SourceFile["referencedFiles"], typeReferences?: SourceFile["typeReferenceDirectives"], hasNoDefaultLib?: boolean, libReferences?: SourceFile["libReferenceDirectives"]): SourceFile; - /** - * Creates a shallow, memberwise clone of a node for mutation. - */ - function getMutableClone(node: T): T; - /** - * Creates a synthetic statement to act as a placeholder for a not-emitted statement in - * order to preserve comments. - * - * @param original The original statement. - */ - function createNotEmittedStatement(original: Node): NotEmittedStatement; - /** - * Creates a synthetic expression to act as a placeholder for a not-emitted expression in - * order to preserve comments or sourcemap positions. - * - * @param expression The inner expression to emit. - * @param original The original outer expression. - * @param location The location for the expression. Defaults to the positions from "original" if provided. - */ - function createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; - function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; - function createCommaList(elements: readonly Expression[]): CommaListExpression; - function updateCommaList(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; - function createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; - function createUnparsedSourceFile(text: string): UnparsedSource; - function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; - function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; - function createInputFiles(javascriptText: string, declarationText: string): InputFiles; - function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; - function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; - function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - function createComma(left: Expression, right: Expression): Expression; - function createLessThan(left: Expression, right: Expression): Expression; - function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; - function createAssignment(left: Expression, right: Expression): BinaryExpression; - function createStrictEquality(left: Expression, right: Expression): BinaryExpression; - function createStrictInequality(left: Expression, right: Expression): BinaryExpression; - function createAdd(left: Expression, right: Expression): BinaryExpression; - function createSubtract(left: Expression, right: Expression): BinaryExpression; - function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; - function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; - function createLogicalOr(left: Expression, right: Expression): BinaryExpression; - function createNullishCoalesce(left: Expression, right: Expression): BinaryExpression; - function createLogicalNot(operand: Expression): PrefixUnaryExpression; - function createVoidZero(): VoidExpression; - function createExportDefault(expression: Expression): ExportAssignment; - function createExternalModuleExport(exportName: Identifier): ExportDeclaration; - /** - * Clears any EmitNode entries from parse-tree nodes. - * @param sourceFile A source file. - */ - function disposeEmitNodes(sourceFile: SourceFile): void; - function setTextRange(range: T, location: TextRange | undefined): T; - /** - * Sets flags that control emit behavior of a node. - */ - function setEmitFlags(node: T, emitFlags: EmitFlags): T; - /** - * Gets a custom text range to use when emitting source maps. - */ - function getSourceMapRange(node: Node): SourceMapRange; - /** - * Sets a custom text range to use when emitting source maps. - */ - function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; - /** - * Create an external source map source file reference - */ - function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; - /** - * Sets the TextRange to use for source maps for a token of a node. - */ - function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; - /** - * Gets a custom text range to use when emitting comments. - */ - function getCommentRange(node: Node): TextRange; - /** - * Sets a custom text range to use when emitting comments. - */ - function setCommentRange(node: T, range: TextRange): T; - function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; - function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; - function moveSyntheticComments(node: T, original: Node): T; - /** - * Gets the constant value to emit for an expression. - */ - function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; - /** - * Sets the constant value to emit for an expression. - */ - function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression; - /** - * Adds an EmitHelper to a node. - */ - function addEmitHelper(node: T, helper: EmitHelper): T; - /** - * Add EmitHelpers to a node. - */ - function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; - /** - * Removes an EmitHelper from a node. - */ - function removeEmitHelper(node: Node, helper: EmitHelper): boolean; - /** - * Gets the EmitHelpers of a node. - */ - function getEmitHelpers(node: Node): EmitHelper[] | undefined; - /** - * Moves matching emit helpers from a source node to a target node. - */ - function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; - function setOriginalNode(node: T, original: Node | undefined): T; -} declare namespace ts { /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. @@ -5898,5 +5974,1294 @@ declare namespace ts { */ function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult; } +declare namespace ts { + const + /** + * @deprecated Use `factory.createNodeArray` or the factory supplied by your transformation context instead. + */ + createNodeArray: (elements?: readonly T[] | undefined, hasTrailingComma?: boolean | undefined) => NodeArray, + /** + * @deprecated Use `factory.createNumericLiteral` or the factory supplied by your transformation context instead. + */ + createNumericLiteral: (value: string | number, numericLiteralFlags?: TokenFlags | undefined) => NumericLiteral, + /** + * @deprecated Use `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + createBigIntLiteral: (value: string | PseudoBigInt) => BigIntLiteral, + /** + * @deprecated Use `factory.createStringLiteral` or the factory supplied by your transformation context instead. + */ + createStringLiteral: { + (text: string, isSingleQuote?: boolean | undefined): StringLiteral; + (text: string, isSingleQuote?: boolean | undefined, hasExtendedUnicodeEscape?: boolean | undefined): StringLiteral; + }, + /** + * @deprecated Use `factory.createStringLiteralFromNode` or the factory supplied by your transformation context instead. + */ + createStringLiteralFromNode: (sourceNode: Identifier | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral, isSingleQuote?: boolean | undefined) => StringLiteral, + /** + * @deprecated Use `factory.createRegularExpressionLiteral` or the factory supplied by your transformation context instead. + */ + createRegularExpressionLiteral: (text: string) => RegularExpressionLiteral, + /** + * @deprecated Use `factory.createLoopVariable` or the factory supplied by your transformation context instead. + */ + createLoopVariable: () => Identifier, + /** + * @deprecated Use `factory.createUniqueName` or the factory supplied by your transformation context instead. + */ + createUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createOptimisticUniqueName` or the factory supplied by your transformation context instead. + */ + createOptimisticUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createFileLevelUniqueName` or the factory supplied by your transformation context instead. + */ + createFileLevelUniqueName: (text: string) => Identifier, + /** + * @deprecated Use `factory.createSuper` or the factory supplied by your transformation context instead. + */ + createSuper: () => SuperExpression, + /** + * @deprecated Use `factory.createThis` or the factory supplied by your transformation context instead. + */ + createThis: () => ThisExpression, + /** + * @deprecated Use `factory.createNull` or the factory supplied by your transformation context instead. + */ + createNull: () => NullLiteral, + /** + * @deprecated Use `factory.createTrue` or the factory supplied by your transformation context instead. + */ + createTrue: () => TrueLiteral, + /** + * @deprecated Use `factory.createFalse` or the factory supplied by your transformation context instead. + */ + createFalse: () => FalseLiteral, + /** + * @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. + */ + createModifier: (kind: T) => ModifierToken, + /** + * @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. + */ + createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[], + /** + * @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. + */ + createQualifiedName: (left: EntityName, right: string | Identifier) => QualifiedName, + /** + * @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. + */ + updateQualifiedName: (node: QualifiedName, left: EntityName, right: Identifier) => QualifiedName, + /** + * @deprecated Use `factory.createComputedPropertyName` or the factory supplied by your transformation context instead. + */ + createComputedPropertyName: (expression: Expression) => ComputedPropertyName, + /** + * @deprecated Use `factory.updateComputedPropertyName` or the factory supplied by your transformation context instead. + */ + updateComputedPropertyName: (node: ComputedPropertyName, expression: Expression) => ComputedPropertyName, + /** + * @deprecated Use `factory.createTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeParameterDeclaration: (name: string | Identifier, constraint?: TypeNode | undefined, defaultType?: TypeNode | undefined) => TypeParameterDeclaration, + /** + * @deprecated Use `factory.updateTypeParameterDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeParameterDeclaration: (node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) => TypeParameterDeclaration, createParameter: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, questionToken?: QuestionToken | undefined, type?: TypeNode | undefined, initializer?: Expression | undefined) => ParameterDeclaration, updateParameter: (node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => ParameterDeclaration, + /** + * @deprecated Use `factory.createDecorator` or the factory supplied by your transformation context instead. + */ + createDecorator: (expression: Expression) => Decorator, + /** + * @deprecated Use `factory.updateDecorator` or the factory supplied by your transformation context instead. + */ + updateDecorator: (node: Decorator, expression: Expression) => Decorator, createProperty: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => PropertyDeclaration, updateProperty: (node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) => PropertyDeclaration, createMethod: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => MethodDeclaration, updateMethod: (node: MethodDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => MethodDeclaration, createConstructor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration, updateConstructor: (node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined) => ConstructorDeclaration, createGetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration, updateGetAccessor: (node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => GetAccessorDeclaration, createSetAccessor: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration, updateSetAccessor: (node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined) => SetAccessorDeclaration, + /** + * @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. + */ + createCallSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => CallSignatureDeclaration, + /** + * @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. + */ + updateCallSignature: (node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => CallSignatureDeclaration, + /** + * @deprecated Use `factory.createConstructSignature` or the factory supplied by your transformation context instead. + */ + createConstructSignature: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => ConstructSignatureDeclaration, + /** + * @deprecated Use `factory.updateConstructSignature` or the factory supplied by your transformation context instead. + */ + updateConstructSignature: (node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => ConstructSignatureDeclaration, + /** + * @deprecated Use `factory.updateIndexSignature` or the factory supplied by your transformation context instead. + */ + updateIndexSignature: (node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode) => IndexSignatureDeclaration, + /** + * @deprecated Use `factory.createKeywordTypeNode` or the factory supplied by your transformation context instead. + */ + createKeywordTypeNode: (kind: TKind) => KeywordTypeNode, createTypePredicateNodeWithModifier: (assertsModifier: AssertsKeyword | undefined, parameterName: string | Identifier | ThisTypeNode, type: TypeNode | undefined) => TypePredicateNode, updateTypePredicateNodeWithModifier: (node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) => TypePredicateNode, + /** + * @deprecated Use `factory.createTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + createTypeReferenceNode: (typeName: string | Identifier | QualifiedName, typeArguments?: readonly TypeNode[] | undefined) => TypeReferenceNode, + /** + * @deprecated Use `factory.updateTypeReferenceNode` or the factory supplied by your transformation context instead. + */ + updateTypeReferenceNode: (node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) => TypeReferenceNode, + /** + * @deprecated Use `factory.createFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + createFunctionTypeNode: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => FunctionTypeNode, + /** + * @deprecated Use `factory.updateFunctionTypeNode` or the factory supplied by your transformation context instead. + */ + updateFunctionTypeNode: (node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => FunctionTypeNode, + /** + * @deprecated Use `factory.createConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + createConstructorTypeNode: (typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined) => ConstructorTypeNode, + /** + * @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. + */ + updateConstructorTypeNode: (node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) => ConstructorTypeNode, + /** + * @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. + */ + createTypeQueryNode: (exprName: EntityName) => TypeQueryNode, + /** + * @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. + */ + updateTypeQueryNode: (node: TypeQueryNode, exprName: EntityName) => TypeQueryNode, + /** + * @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + createTypeLiteralNode: (members: readonly TypeElement[] | undefined) => TypeLiteralNode, + /** + * @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. + */ + updateTypeLiteralNode: (node: TypeLiteralNode, members: NodeArray) => TypeLiteralNode, + /** + * @deprecated Use `factory.createArrayTypeNode` or the factory supplied by your transformation context instead. + */ + createArrayTypeNode: (elementType: TypeNode) => ArrayTypeNode, + /** + * @deprecated Use `factory.updateArrayTypeNode` or the factory supplied by your transformation context instead. + */ + updateArrayTypeNode: (node: ArrayTypeNode, elementType: TypeNode) => ArrayTypeNode, + /** + * @deprecated Use `factory.createTupleTypeNode` or the factory supplied by your transformation context instead. + */ + createTupleTypeNode: (elementTypes: readonly TypeNode[]) => TupleTypeNode, + /** + * @deprecated Use `factory.updateTupleTypeNode` or the factory supplied by your transformation context instead. + */ + updateTupleTypeNode: (node: TupleTypeNode, elementTypes: readonly TypeNode[]) => TupleTypeNode, + /** + * @deprecated Use `factory.createOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + createOptionalTypeNode: (type: TypeNode) => OptionalTypeNode, + /** + * @deprecated Use `factory.updateOptionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateOptionalTypeNode: (node: OptionalTypeNode, type: TypeNode) => OptionalTypeNode, + /** + * @deprecated Use `factory.createRestTypeNode` or the factory supplied by your transformation context instead. + */ + createRestTypeNode: (type: TypeNode) => RestTypeNode, + /** + * @deprecated Use `factory.updateRestTypeNode` or the factory supplied by your transformation context instead. + */ + updateRestTypeNode: (node: RestTypeNode, type: TypeNode) => RestTypeNode, + /** + * @deprecated Use `factory.createUnionTypeNode` or the factory supplied by your transformation context instead. + */ + createUnionTypeNode: (types: readonly TypeNode[]) => UnionTypeNode, + /** + * @deprecated Use `factory.updateUnionTypeNode` or the factory supplied by your transformation context instead. + */ + updateUnionTypeNode: (node: UnionTypeNode, types: NodeArray) => UnionTypeNode, + /** + * @deprecated Use `factory.createIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + createIntersectionTypeNode: (types: readonly TypeNode[]) => IntersectionTypeNode, + /** + * @deprecated Use `factory.updateIntersectionTypeNode` or the factory supplied by your transformation context instead. + */ + updateIntersectionTypeNode: (node: IntersectionTypeNode, types: NodeArray) => IntersectionTypeNode, + /** + * @deprecated Use `factory.createConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + createConditionalTypeNode: (checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) => ConditionalTypeNode, + /** + * @deprecated Use `factory.updateConditionalTypeNode` or the factory supplied by your transformation context instead. + */ + updateConditionalTypeNode: (node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) => ConditionalTypeNode, + /** + * @deprecated Use `factory.createInferTypeNode` or the factory supplied by your transformation context instead. + */ + createInferTypeNode: (typeParameter: TypeParameterDeclaration) => InferTypeNode, + /** + * @deprecated Use `factory.updateInferTypeNode` or the factory supplied by your transformation context instead. + */ + updateInferTypeNode: (node: InferTypeNode, typeParameter: TypeParameterDeclaration) => InferTypeNode, + /** + * @deprecated Use `factory.createImportTypeNode` or the factory supplied by your transformation context instead. + */ + createImportTypeNode: (argument: TypeNode, qualifier?: Identifier | QualifiedName | undefined, typeArguments?: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined) => ImportTypeNode, + /** + * @deprecated Use `factory.updateImportTypeNode` or the factory supplied by your transformation context instead. + */ + updateImportTypeNode: (node: ImportTypeNode, argument: TypeNode, qualifier?: Identifier | QualifiedName | undefined, typeArguments?: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined) => ImportTypeNode, + /** + * @deprecated Use `factory.createParenthesizedType` or the factory supplied by your transformation context instead. + */ + createParenthesizedType: (type: TypeNode) => ParenthesizedTypeNode, + /** + * @deprecated Use `factory.updateParenthesizedType` or the factory supplied by your transformation context instead. + */ + updateParenthesizedType: (node: ParenthesizedTypeNode, type: TypeNode) => ParenthesizedTypeNode, + /** + * @deprecated Use `factory.createThisTypeNode` or the factory supplied by your transformation context instead. + */ + createThisTypeNode: () => ThisTypeNode, + /** + * @deprecated Use `factory.updateTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + updateTypeOperatorNode: (node: TypeOperatorNode, type: TypeNode) => TypeOperatorNode, + /** + * @deprecated Use `factory.createIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + createIndexedAccessTypeNode: (objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode, + /** + * @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. + */ + updateIndexedAccessTypeNode: (node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) => IndexedAccessTypeNode, + /** + * @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. + */ + createMappedTypeNode: (readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode, + /** + * @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. + */ + updateMappedTypeNode: (node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined) => MappedTypeNode, + /** + * @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + createLiteralTypeNode: (literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode, + /** + * @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. + */ + updateLiteralTypeNode: (node: LiteralTypeNode, literal: LiteralExpression | TrueLiteral | FalseLiteral | PrefixUnaryExpression | NullLiteral) => LiteralTypeNode, + /** + * @deprecated Use `factory.createObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + createObjectBindingPattern: (elements: readonly BindingElement[]) => ObjectBindingPattern, + /** + * @deprecated Use `factory.updateObjectBindingPattern` or the factory supplied by your transformation context instead. + */ + updateObjectBindingPattern: (node: ObjectBindingPattern, elements: readonly BindingElement[]) => ObjectBindingPattern, + /** + * @deprecated Use `factory.createArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + createArrayBindingPattern: (elements: readonly ArrayBindingElement[]) => ArrayBindingPattern, + /** + * @deprecated Use `factory.updateArrayBindingPattern` or the factory supplied by your transformation context instead. + */ + updateArrayBindingPattern: (node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) => ArrayBindingPattern, + /** + * @deprecated Use `factory.createBindingElement` or the factory supplied by your transformation context instead. + */ + createBindingElement: (dotDotDotToken: DotDotDotToken | undefined, propertyName: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | undefined, name: string | Identifier | ObjectBindingPattern | ArrayBindingPattern, initializer?: Expression | undefined) => BindingElement, + /** + * @deprecated Use `factory.updateBindingElement` or the factory supplied by your transformation context instead. + */ + updateBindingElement: (node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | undefined, name: BindingName, initializer: Expression | undefined) => BindingElement, + /** + * @deprecated Use `factory.createArrayLiteral` or the factory supplied by your transformation context instead. + */ + createArrayLiteral: (elements?: readonly Expression[] | undefined, multiLine?: boolean | undefined) => ArrayLiteralExpression, + /** + * @deprecated Use `factory.updateArrayLiteral` or the factory supplied by your transformation context instead. + */ + updateArrayLiteral: (node: ArrayLiteralExpression, elements: readonly Expression[]) => ArrayLiteralExpression, + /** + * @deprecated Use `factory.createObjectLiteral` or the factory supplied by your transformation context instead. + */ + createObjectLiteral: (properties?: readonly ObjectLiteralElementLike[] | undefined, multiLine?: boolean | undefined) => ObjectLiteralExpression, + /** + * @deprecated Use `factory.updateObjectLiteral` or the factory supplied by your transformation context instead. + */ + updateObjectLiteral: (node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) => ObjectLiteralExpression, + /** + * @deprecated Use `factory.createPropertyAccess` or the factory supplied by your transformation context instead. + */ + createPropertyAccess: (expression: Expression, name: string | Identifier) => PropertyAccessExpression, + /** + * @deprecated Use `factory.updatePropertyAccess` or the factory supplied by your transformation context instead. + */ + updatePropertyAccess: (node: PropertyAccessExpression, expression: Expression, name: Identifier) => PropertyAccessExpression, + /** + * @deprecated Use `factory.createPropertyAccessChain` or the factory supplied by your transformation context instead. + */ + createPropertyAccessChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier) => PropertyAccessChain, + /** + * @deprecated Use `factory.updatePropertyAccessChain` or the factory supplied by your transformation context instead. + */ + updatePropertyAccessChain: (node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier) => PropertyAccessChain, + /** + * @deprecated Use `factory.createElementAccess` or the factory supplied by your transformation context instead. + */ + createElementAccess: (expression: Expression, index: number | Expression) => ElementAccessExpression, + /** + * @deprecated Use `factory.updateElementAccess` or the factory supplied by your transformation context instead. + */ + updateElementAccess: (node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) => ElementAccessExpression, + /** + * @deprecated Use `factory.createElementAccessChain` or the factory supplied by your transformation context instead. + */ + createElementAccessChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) => ElementAccessChain, + /** + * @deprecated Use `factory.updateElementAccessChain` or the factory supplied by your transformation context instead. + */ + updateElementAccessChain: (node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) => ElementAccessChain, + /** + * @deprecated Use `factory.createCall` or the factory supplied by your transformation context instead. + */ + createCall: (expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => CallExpression, + /** + * @deprecated Use `factory.updateCall` or the factory supplied by your transformation context instead. + */ + updateCall: (node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) => CallExpression, + /** + * @deprecated Use `factory.createCallChain` or the factory supplied by your transformation context instead. + */ + createCallChain: (expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => CallChain, + /** + * @deprecated Use `factory.updateCallChain` or the factory supplied by your transformation context instead. + */ + updateCallChain: (node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) => CallChain, + /** + * @deprecated Use `factory.createNew` or the factory supplied by your transformation context instead. + */ + createNew: (expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => NewExpression, + /** + * @deprecated Use `factory.updateNew` or the factory supplied by your transformation context instead. + */ + updateNew: (node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) => NewExpression, + /** + * @deprecated Use `factory.createTypeAssertion` or the factory supplied by your transformation context instead. + */ + createTypeAssertion: (type: TypeNode, expression: Expression) => TypeAssertion, + /** + * @deprecated Use `factory.updateTypeAssertion` or the factory supplied by your transformation context instead. + */ + updateTypeAssertion: (node: TypeAssertion, type: TypeNode, expression: Expression) => TypeAssertion, + /** + * @deprecated Use `factory.createParen` or the factory supplied by your transformation context instead. + */ + createParen: (expression: Expression) => ParenthesizedExpression, + /** + * @deprecated Use `factory.updateParen` or the factory supplied by your transformation context instead. + */ + updateParen: (node: ParenthesizedExpression, expression: Expression) => ParenthesizedExpression, + /** + * @deprecated Use `factory.createFunctionExpression` or the factory supplied by your transformation context instead. + */ + createFunctionExpression: (modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block) => FunctionExpression, + /** + * @deprecated Use `factory.updateFunctionExpression` or the factory supplied by your transformation context instead. + */ + updateFunctionExpression: (node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block) => FunctionExpression, + /** + * @deprecated Use `factory.createArrowFunction` or the factory supplied by your transformation context instead. + */ + createArrowFunction: { + (modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + (modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; + }, + /** + * @deprecated Use `factory.updateArrowFunction` or the factory supplied by your transformation context instead. + */ + updateArrowFunction: { + (node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction; + (node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + }, + /** + * @deprecated Use `factory.createDelete` or the factory supplied by your transformation context instead. + */ + createDelete: (expression: Expression) => DeleteExpression, + /** + * @deprecated Use `factory.updateDelete` or the factory supplied by your transformation context instead. + */ + updateDelete: (node: DeleteExpression, expression: Expression) => DeleteExpression, + /** + * @deprecated Use `factory.createTypeOf` or the factory supplied by your transformation context instead. + */ + createTypeOf: (expression: Expression) => TypeOfExpression, + /** + * @deprecated Use `factory.updateTypeOf` or the factory supplied by your transformation context instead. + */ + updateTypeOf: (node: TypeOfExpression, expression: Expression) => TypeOfExpression, + /** + * @deprecated Use `factory.createVoid` or the factory supplied by your transformation context instead. + */ + createVoid: (expression: Expression) => VoidExpression, + /** + * @deprecated Use `factory.updateVoid` or the factory supplied by your transformation context instead. + */ + updateVoid: (node: VoidExpression, expression: Expression) => VoidExpression, + /** + * @deprecated Use `factory.createAwait` or the factory supplied by your transformation context instead. + */ + createAwait: (expression: Expression) => AwaitExpression, + /** + * @deprecated Use `factory.updateAwait` or the factory supplied by your transformation context instead. + */ + updateAwait: (node: AwaitExpression, expression: Expression) => AwaitExpression, + /** + * @deprecated Use `factory.createPrefix` or the factory supplied by your transformation context instead. + */ + createPrefix: (operator: PrefixUnaryOperator, operand: Expression) => PrefixUnaryExpression, + /** + * @deprecated Use `factory.updatePrefix` or the factory supplied by your transformation context instead. + */ + updatePrefix: (node: PrefixUnaryExpression, operand: Expression) => PrefixUnaryExpression, + /** + * @deprecated Use `factory.createPostfix` or the factory supplied by your transformation context instead. + */ + createPostfix: (operand: Expression, operator: PostfixUnaryOperator) => PostfixUnaryExpression, + /** + * @deprecated Use `factory.updatePostfix` or the factory supplied by your transformation context instead. + */ + updatePostfix: (node: PostfixUnaryExpression, operand: Expression) => PostfixUnaryExpression, + /** + * @deprecated Use `factory.createBinary` or the factory supplied by your transformation context instead. + */ + createBinary: (left: Expression, operator: SyntaxKind.CommaToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | BinaryOperatorToken, right: Expression) => BinaryExpression, + /** + * @deprecated Use `factory.updateBinary` or the factory supplied by your transformation context instead. + */ + updateBinary: (node: BinaryExpression, left: Expression, right: Expression, operator?: SyntaxKind.CommaToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.EqualsEqualsToken | SyntaxKind.ExclamationEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.AsteriskToken | SyntaxKind.AsteriskAsteriskToken | SyntaxKind.SlashToken | SyntaxKind.PercentToken | SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken | SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken | SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken | SyntaxKind.QuestionQuestionToken | SyntaxKind.EqualsToken | SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.InKeyword | SyntaxKind.InstanceOfKeyword | BinaryOperatorToken | undefined) => BinaryExpression, + /** + * @deprecated Use `factory.updateConditional` or the factory supplied by your transformation context instead. + */ + updateConditional: { + (node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + (node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + }, + /** + * @deprecated Use `factory.createTemplateExpression` or the factory supplied by your transformation context instead. + */ + createTemplateExpression: (head: TemplateHead, templateSpans: readonly TemplateSpan[]) => TemplateExpression, + /** + * @deprecated Use `factory.updateTemplateExpression` or the factory supplied by your transformation context instead. + */ + updateTemplateExpression: (node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) => TemplateExpression, + /** + * @deprecated Use `factory.createTemplateHead` or the factory supplied by your transformation context instead. + */ + createTemplateHead: { + (text: string, rawText?: string | undefined): TemplateHead; + (text: string | undefined, rawText: string): TemplateHead; + }, + /** + * @deprecated Use `factory.createTemplateMiddle` or the factory supplied by your transformation context instead. + */ + createTemplateMiddle: { + (text: string, rawText?: string | undefined): TemplateMiddle; + (text: string | undefined, rawText: string): TemplateMiddle; + }, + /** + * @deprecated Use `factory.createTemplateTail` or the factory supplied by your transformation context instead. + */ + createTemplateTail: { + (text: string, rawText?: string | undefined): TemplateTail; + (text: string | undefined, rawText: string): TemplateTail; + }, + /** + * @deprecated Use `factory.createNoSubstitutionTemplateLiteral` or the factory supplied by your transformation context instead. + */ + createNoSubstitutionTemplateLiteral: { + (text: string, rawText?: string | undefined): NoSubstitutionTemplateLiteral; + (text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; + }, + /** + * @deprecated Use `factory.updateYield` or the factory supplied by your transformation context instead. + */ + updateYield: (node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined) => YieldExpression, + /** + * @deprecated Use `factory.createSpread` or the factory supplied by your transformation context instead. + */ + createSpread: (expression: Expression) => SpreadElement, + /** + * @deprecated Use `factory.updateSpread` or the factory supplied by your transformation context instead. + */ + updateSpread: (node: SpreadElement, expression: Expression) => SpreadElement, + /** + * @deprecated Use `factory.createOmittedExpression` or the factory supplied by your transformation context instead. + */ + createOmittedExpression: () => OmittedExpression, + /** + * @deprecated Use `factory.createAsExpression` or the factory supplied by your transformation context instead. + */ + createAsExpression: (expression: Expression, type: TypeNode) => AsExpression, + /** + * @deprecated Use `factory.updateAsExpression` or the factory supplied by your transformation context instead. + */ + updateAsExpression: (node: AsExpression, expression: Expression, type: TypeNode) => AsExpression, + /** + * @deprecated Use `factory.createNonNullExpression` or the factory supplied by your transformation context instead. + */ + createNonNullExpression: (expression: Expression) => NonNullExpression, + /** + * @deprecated Use `factory.updateNonNullExpression` or the factory supplied by your transformation context instead. + */ + updateNonNullExpression: (node: NonNullExpression, expression: Expression) => NonNullExpression, + /** + * @deprecated Use `factory.createMetaProperty` or the factory supplied by your transformation context instead. + */ + createMetaProperty: (keywordToken: SyntaxKind.ImportKeyword | SyntaxKind.NewKeyword, name: Identifier) => MetaProperty, + /** + * @deprecated Use `factory.updateMetaProperty` or the factory supplied by your transformation context instead. + */ + updateMetaProperty: (node: MetaProperty, name: Identifier) => MetaProperty, + /** + * @deprecated Use `factory.createTemplateSpan` or the factory supplied by your transformation context instead. + */ + createTemplateSpan: (expression: Expression, literal: TemplateMiddle | TemplateTail) => TemplateSpan, + /** + * @deprecated Use `factory.updateTemplateSpan` or the factory supplied by your transformation context instead. + */ + updateTemplateSpan: (node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) => TemplateSpan, + /** + * @deprecated Use `factory.createSemicolonClassElement` or the factory supplied by your transformation context instead. + */ + createSemicolonClassElement: () => SemicolonClassElement, + /** + * @deprecated Use `factory.createBlock` or the factory supplied by your transformation context instead. + */ + createBlock: (statements: readonly Statement[], multiLine?: boolean | undefined) => Block, + /** + * @deprecated Use `factory.updateBlock` or the factory supplied by your transformation context instead. + */ + updateBlock: (node: Block, statements: readonly Statement[]) => Block, + /** + * @deprecated Use `factory.createVariableStatement` or the factory supplied by your transformation context instead. + */ + createVariableStatement: (modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) => VariableStatement, + /** + * @deprecated Use `factory.updateVariableStatement` or the factory supplied by your transformation context instead. + */ + updateVariableStatement: (node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) => VariableStatement, + /** + * @deprecated Use `factory.createEmptyStatement` or the factory supplied by your transformation context instead. + */ + createEmptyStatement: () => EmptyStatement, + /** + * @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. + */ + createExpressionStatement: (expression: Expression) => ExpressionStatement, + /** + * @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. + */ + updateExpressionStatement: (node: ExpressionStatement, expression: Expression) => ExpressionStatement, createStatement: (expression: Expression) => ExpressionStatement, updateStatement: (node: ExpressionStatement, expression: Expression) => ExpressionStatement, + /** + * @deprecated Use `factory.createIf` or the factory supplied by your transformation context instead. + */ + createIf: (expression: Expression, thenStatement: Statement, elseStatement?: Statement | undefined) => IfStatement, + /** + * @deprecated Use `factory.updateIf` or the factory supplied by your transformation context instead. + */ + updateIf: (node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) => IfStatement, + /** + * @deprecated Use `factory.createDo` or the factory supplied by your transformation context instead. + */ + createDo: (statement: Statement, expression: Expression) => DoStatement, + /** + * @deprecated Use `factory.updateDo` or the factory supplied by your transformation context instead. + */ + updateDo: (node: DoStatement, statement: Statement, expression: Expression) => DoStatement, + /** + * @deprecated Use `factory.createWhile` or the factory supplied by your transformation context instead. + */ + createWhile: (expression: Expression, statement: Statement) => WhileStatement, + /** + * @deprecated Use `factory.updateWhile` or the factory supplied by your transformation context instead. + */ + updateWhile: (node: WhileStatement, expression: Expression, statement: Statement) => WhileStatement, + /** + * @deprecated Use `factory.createFor` or the factory supplied by your transformation context instead. + */ + createFor: (initializer: Expression | VariableDeclarationList | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) => ForStatement, + /** + * @deprecated Use `factory.updateFor` or the factory supplied by your transformation context instead. + */ + updateFor: (node: ForStatement, initializer: Expression | VariableDeclarationList | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) => ForStatement, + /** + * @deprecated Use `factory.createForIn` or the factory supplied by your transformation context instead. + */ + createForIn: (initializer: ForInitializer, expression: Expression, statement: Statement) => ForInStatement, + /** + * @deprecated Use `factory.updateForIn` or the factory supplied by your transformation context instead. + */ + updateForIn: (node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) => ForInStatement, + /** + * @deprecated Use `factory.createForOf` or the factory supplied by your transformation context instead. + */ + createForOf: (awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) => ForOfStatement, + /** + * @deprecated Use `factory.updateForOf` or the factory supplied by your transformation context instead. + */ + updateForOf: (node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) => ForOfStatement, + /** + * @deprecated Use `factory.createContinue` or the factory supplied by your transformation context instead. + */ + createContinue: (label?: string | Identifier | undefined) => ContinueStatement, + /** + * @deprecated Use `factory.updateContinue` or the factory supplied by your transformation context instead. + */ + updateContinue: (node: ContinueStatement, label: Identifier | undefined) => ContinueStatement, + /** + * @deprecated Use `factory.createBreak` or the factory supplied by your transformation context instead. + */ + createBreak: (label?: string | Identifier | undefined) => BreakStatement, + /** + * @deprecated Use `factory.updateBreak` or the factory supplied by your transformation context instead. + */ + updateBreak: (node: BreakStatement, label: Identifier | undefined) => BreakStatement, + /** + * @deprecated Use `factory.createReturn` or the factory supplied by your transformation context instead. + */ + createReturn: (expression?: Expression | undefined) => ReturnStatement, + /** + * @deprecated Use `factory.updateReturn` or the factory supplied by your transformation context instead. + */ + updateReturn: (node: ReturnStatement, expression: Expression | undefined) => ReturnStatement, + /** + * @deprecated Use `factory.createWith` or the factory supplied by your transformation context instead. + */ + createWith: (expression: Expression, statement: Statement) => WithStatement, + /** + * @deprecated Use `factory.updateWith` or the factory supplied by your transformation context instead. + */ + updateWith: (node: WithStatement, expression: Expression, statement: Statement) => WithStatement, + /** + * @deprecated Use `factory.createSwitch` or the factory supplied by your transformation context instead. + */ + createSwitch: (expression: Expression, caseBlock: CaseBlock) => SwitchStatement, + /** + * @deprecated Use `factory.updateSwitch` or the factory supplied by your transformation context instead. + */ + updateSwitch: (node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) => SwitchStatement, + /** + * @deprecated Use `factory.createLabel` or the factory supplied by your transformation context instead. + */ + createLabel: (label: string | Identifier, statement: Statement) => LabeledStatement, + /** + * @deprecated Use `factory.updateLabel` or the factory supplied by your transformation context instead. + */ + updateLabel: (node: LabeledStatement, label: Identifier, statement: Statement) => LabeledStatement, + /** + * @deprecated Use `factory.createThrow` or the factory supplied by your transformation context instead. + */ + createThrow: (expression: Expression) => ThrowStatement, + /** + * @deprecated Use `factory.updateThrow` or the factory supplied by your transformation context instead. + */ + updateThrow: (node: ThrowStatement, expression: Expression) => ThrowStatement, + /** + * @deprecated Use `factory.createTry` or the factory supplied by your transformation context instead. + */ + createTry: (tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) => TryStatement, + /** + * @deprecated Use `factory.updateTry` or the factory supplied by your transformation context instead. + */ + updateTry: (node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) => TryStatement, + /** + * @deprecated Use `factory.createDebuggerStatement` or the factory supplied by your transformation context instead. + */ + createDebuggerStatement: () => DebuggerStatement, + /** + * @deprecated Use `factory.createVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + createVariableDeclarationList: (declarations: readonly VariableDeclaration[], flags?: NodeFlags | undefined) => VariableDeclarationList, + /** + * @deprecated Use `factory.updateVariableDeclarationList` or the factory supplied by your transformation context instead. + */ + updateVariableDeclarationList: (node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) => VariableDeclarationList, + /** + * @deprecated Use `factory.createFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + createFunctionDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => FunctionDeclaration, + /** + * @deprecated Use `factory.updateFunctionDeclaration` or the factory supplied by your transformation context instead. + */ + updateFunctionDeclaration: (node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) => FunctionDeclaration, + /** + * @deprecated Use `factory.createClassDeclaration` or the factory supplied by your transformation context instead. + */ + createClassDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]) => ClassDeclaration, + /** + * @deprecated Use `factory.updateClassDeclaration` or the factory supplied by your transformation context instead. + */ + updateClassDeclaration: (node: ClassDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]) => ClassDeclaration, + /** + * @deprecated Use `factory.createInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + createInterfaceDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]) => InterfaceDeclaration, + /** + * @deprecated Use `factory.updateInterfaceDeclaration` or the factory supplied by your transformation context instead. + */ + updateInterfaceDeclaration: (node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]) => InterfaceDeclaration, + /** + * @deprecated Use `factory.createTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + createTypeAliasDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode) => TypeAliasDeclaration, + /** + * @deprecated Use `factory.updateTypeAliasDeclaration` or the factory supplied by your transformation context instead. + */ + updateTypeAliasDeclaration: (node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode) => TypeAliasDeclaration, + /** + * @deprecated Use `factory.createEnumDeclaration` or the factory supplied by your transformation context instead. + */ + createEnumDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[]) => EnumDeclaration, + /** + * @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. + */ + updateEnumDeclaration: (node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]) => EnumDeclaration, + /** + * @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. + */ + createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration, + /** + * @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. + */ + updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration, + /** + * @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. + */ + createModuleBlock: (statements: readonly Statement[]) => ModuleBlock, + /** + * @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. + */ + updateModuleBlock: (node: ModuleBlock, statements: readonly Statement[]) => ModuleBlock, + /** + * @deprecated Use `factory.createCaseBlock` or the factory supplied by your transformation context instead. + */ + createCaseBlock: (clauses: readonly CaseOrDefaultClause[]) => CaseBlock, + /** + * @deprecated Use `factory.updateCaseBlock` or the factory supplied by your transformation context instead. + */ + updateCaseBlock: (node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) => CaseBlock, + /** + * @deprecated Use `factory.createNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + createNamespaceExportDeclaration: (name: string | Identifier) => NamespaceExportDeclaration, + /** + * @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateNamespaceExportDeclaration: (node: NamespaceExportDeclaration, name: Identifier) => NamespaceExportDeclaration, + /** + * @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration, + /** + * @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration, + /** + * @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. + */ + createImportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration, + /** + * @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. + */ + updateImportDeclaration: (node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration, + /** + * @deprecated Use `factory.createImportClause` or the factory supplied by your transformation context instead. + */ + createImportClause: (name: Identifier | undefined, namedBindings: NamespaceImport | NamedImports | undefined) => ImportClause, + /** + * @deprecated Use `factory.updateImportClause` or the factory supplied by your transformation context instead. + */ + updateImportClause: (node: ImportClause, name: Identifier | undefined, namedBindings: NamespaceImport | NamedImports | undefined) => ImportClause, + /** + * @deprecated Use `factory.createNamespaceImport` or the factory supplied by your transformation context instead. + */ + createNamespaceImport: (name: Identifier) => NamespaceImport, + /** + * @deprecated Use `factory.updateNamespaceImport` or the factory supplied by your transformation context instead. + */ + updateNamespaceImport: (node: NamespaceImport, name: Identifier) => NamespaceImport, + /** + * @deprecated Use `factory.createNamedImports` or the factory supplied by your transformation context instead. + */ + createNamedImports: (elements: readonly ImportSpecifier[]) => NamedImports, + /** + * @deprecated Use `factory.updateNamedImports` or the factory supplied by your transformation context instead. + */ + updateNamedImports: (node: NamedImports, elements: readonly ImportSpecifier[]) => NamedImports, + /** + * @deprecated Use `factory.createImportSpecifier` or the factory supplied by your transformation context instead. + */ + createImportSpecifier: (propertyName: Identifier | undefined, name: Identifier) => ImportSpecifier, + /** + * @deprecated Use `factory.updateImportSpecifier` or the factory supplied by your transformation context instead. + */ + updateImportSpecifier: (node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) => ImportSpecifier, + /** + * @deprecated Use `factory.createExportAssignment` or the factory supplied by your transformation context instead. + */ + createExportAssignment: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.updateExportAssignment` or the factory supplied by your transformation context instead. + */ + updateExportAssignment: (node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.createExportDeclaration` or the factory supplied by your transformation context instead. + */ + createExportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression | undefined) => ExportDeclaration, + /** + * @deprecated Use `factory.updateExportDeclaration` or the factory supplied by your transformation context instead. + */ + updateExportDeclaration: (node: ExportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined) => ExportDeclaration, + /** + * @deprecated Use `factory.createNamedExports` or the factory supplied by your transformation context instead. + */ + createNamedExports: (elements: readonly ExportSpecifier[]) => NamedExports, + /** + * @deprecated Use `factory.updateNamedExports` or the factory supplied by your transformation context instead. + */ + updateNamedExports: (node: NamedExports, elements: readonly ExportSpecifier[]) => NamedExports, + /** + * @deprecated Use `factory.createExportSpecifier` or the factory supplied by your transformation context instead. + */ + createExportSpecifier: (propertyName: string | Identifier | undefined, name: string | Identifier) => ExportSpecifier, + /** + * @deprecated Use `factory.updateExportSpecifier` or the factory supplied by your transformation context instead. + */ + updateExportSpecifier: (node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) => ExportSpecifier, + /** + * @deprecated Use `factory.createExternalModuleReference` or the factory supplied by your transformation context instead. + */ + createExternalModuleReference: (expression: Expression) => ExternalModuleReference, + /** + * @deprecated Use `factory.updateExternalModuleReference` or the factory supplied by your transformation context instead. + */ + updateExternalModuleReference: (node: ExternalModuleReference, expression: Expression) => ExternalModuleReference, + /** + * @deprecated Use `factory.createJSDocTypeExpression` or the factory supplied by your transformation context instead. + */ + createJSDocTypeExpression: (type: TypeNode) => JSDocTypeExpression, + /** + * @deprecated Use `factory.createJSDocTypeTag` or the factory supplied by your transformation context instead. + */ + createJSDocTypeTag: (tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | undefined) => JSDocTypeTag, + /** + * @deprecated Use `factory.createJSDocReturnTag` or the factory supplied by your transformation context instead. + */ + createJSDocReturnTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined, comment?: string | undefined) => JSDocReturnTag, + /** + * @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. + */ + createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined) => JSDocThisTag, + /** + * @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. + */ + createJSDocComment: (comment?: string | undefined, tags?: NodeArray | undefined) => JSDoc, + /** + * @deprecated Use `factory.createJsxElement` or the factory supplied by your transformation context instead. + */ + createJsxElement: (openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) => JsxElement, + /** + * @deprecated Use `factory.updateJsxElement` or the factory supplied by your transformation context instead. + */ + updateJsxElement: (node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) => JsxElement, + /** + * @deprecated Use `factory.createJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxSelfClosingElement: (tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxSelfClosingElement, + /** + * @deprecated Use `factory.updateJsxSelfClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxSelfClosingElement: (node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxSelfClosingElement, + /** + * @deprecated Use `factory.createJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + createJsxOpeningElement: (tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxOpeningElement, + /** + * @deprecated Use `factory.updateJsxOpeningElement` or the factory supplied by your transformation context instead. + */ + updateJsxOpeningElement: (node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) => JsxOpeningElement, + /** + * @deprecated Use `factory.createJsxClosingElement` or the factory supplied by your transformation context instead. + */ + createJsxClosingElement: (tagName: JsxTagNameExpression) => JsxClosingElement, + /** + * @deprecated Use `factory.updateJsxClosingElement` or the factory supplied by your transformation context instead. + */ + updateJsxClosingElement: (node: JsxClosingElement, tagName: JsxTagNameExpression) => JsxClosingElement, + /** + * @deprecated Use `factory.createJsxFragment` or the factory supplied by your transformation context instead. + */ + createJsxFragment: (openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) => JsxFragment, + /** + * @deprecated Use `factory.createJsxText` or the factory supplied by your transformation context instead. + */ + createJsxText: (text: string, containsOnlyTriviaWhiteSpaces?: boolean | undefined) => JsxText, + /** + * @deprecated Use `factory.updateJsxText` or the factory supplied by your transformation context instead. + */ + updateJsxText: (node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean | undefined) => JsxText, + /** + * @deprecated Use `factory.createJsxOpeningFragment` or the factory supplied by your transformation context instead. + */ + createJsxOpeningFragment: () => JsxOpeningFragment, + /** + * @deprecated Use `factory.createJsxJsxClosingFragment` or the factory supplied by your transformation context instead. + */ + createJsxJsxClosingFragment: () => JsxClosingFragment, + /** + * @deprecated Use `factory.updateJsxFragment` or the factory supplied by your transformation context instead. + */ + updateJsxFragment: (node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) => JsxFragment, + /** + * @deprecated Use `factory.createJsxAttribute` or the factory supplied by your transformation context instead. + */ + createJsxAttribute: (name: Identifier, initializer: StringLiteral | JsxExpression | undefined) => JsxAttribute, + /** + * @deprecated Use `factory.updateJsxAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxAttribute: (node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) => JsxAttribute, + /** + * @deprecated Use `factory.createJsxAttributes` or the factory supplied by your transformation context instead. + */ + createJsxAttributes: (properties: readonly JsxAttributeLike[]) => JsxAttributes, + /** + * @deprecated Use `factory.updateJsxAttributes` or the factory supplied by your transformation context instead. + */ + updateJsxAttributes: (node: JsxAttributes, properties: readonly JsxAttributeLike[]) => JsxAttributes, + /** + * @deprecated Use `factory.createJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + createJsxSpreadAttribute: (expression: Expression) => JsxSpreadAttribute, + /** + * @deprecated Use `factory.updateJsxSpreadAttribute` or the factory supplied by your transformation context instead. + */ + updateJsxSpreadAttribute: (node: JsxSpreadAttribute, expression: Expression) => JsxSpreadAttribute, + /** + * @deprecated Use `factory.createJsxExpression` or the factory supplied by your transformation context instead. + */ + createJsxExpression: (dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) => JsxExpression, + /** + * @deprecated Use `factory.updateJsxExpression` or the factory supplied by your transformation context instead. + */ + updateJsxExpression: (node: JsxExpression, expression: Expression | undefined) => JsxExpression, + /** + * @deprecated Use `factory.createCaseClause` or the factory supplied by your transformation context instead. + */ + createCaseClause: (expression: Expression, statements: readonly Statement[]) => CaseClause, + /** + * @deprecated Use `factory.updateCaseClause` or the factory supplied by your transformation context instead. + */ + updateCaseClause: (node: CaseClause, expression: Expression, statements: readonly Statement[]) => CaseClause, + /** + * @deprecated Use `factory.createDefaultClause` or the factory supplied by your transformation context instead. + */ + createDefaultClause: (statements: readonly Statement[]) => DefaultClause, + /** + * @deprecated Use `factory.updateDefaultClause` or the factory supplied by your transformation context instead. + */ + updateDefaultClause: (node: DefaultClause, statements: readonly Statement[]) => DefaultClause, + /** + * @deprecated Use `factory.createHeritageClause` or the factory supplied by your transformation context instead. + */ + createHeritageClause: (token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword, types: readonly ExpressionWithTypeArguments[]) => HeritageClause, + /** + * @deprecated Use `factory.updateHeritageClause` or the factory supplied by your transformation context instead. + */ + updateHeritageClause: (node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) => HeritageClause, + /** + * @deprecated Use `factory.createCatchClause` or the factory supplied by your transformation context instead. + */ + createCatchClause: (variableDeclaration: string | VariableDeclaration | undefined, block: Block) => CatchClause, + /** + * @deprecated Use `factory.updateCatchClause` or the factory supplied by your transformation context instead. + */ + updateCatchClause: (node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) => CatchClause, + /** + * @deprecated Use `factory.createPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createPropertyAssignment: (name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, initializer: Expression) => PropertyAssignment, + /** + * @deprecated Use `factory.updatePropertyAssignment` or the factory supplied by your transformation context instead. + */ + updatePropertyAssignment: (node: PropertyAssignment, name: PropertyName, initializer: Expression) => PropertyAssignment, + /** + * @deprecated Use `factory.createShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + createShorthandPropertyAssignment: (name: string | Identifier, objectAssignmentInitializer?: Expression | undefined) => ShorthandPropertyAssignment, + /** + * @deprecated Use `factory.updateShorthandPropertyAssignment` or the factory supplied by your transformation context instead. + */ + updateShorthandPropertyAssignment: (node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) => ShorthandPropertyAssignment, + /** + * @deprecated Use `factory.createSpreadAssignment` or the factory supplied by your transformation context instead. + */ + createSpreadAssignment: (expression: Expression) => SpreadAssignment, + /** + * @deprecated Use `factory.updateSpreadAssignment` or the factory supplied by your transformation context instead. + */ + updateSpreadAssignment: (node: SpreadAssignment, expression: Expression) => SpreadAssignment, + /** + * @deprecated Use `factory.createEnumMember` or the factory supplied by your transformation context instead. + */ + createEnumMember: (name: string | Identifier | StringLiteral | NumericLiteral | ComputedPropertyName, initializer?: Expression | undefined) => EnumMember, + /** + * @deprecated Use `factory.updateEnumMember` or the factory supplied by your transformation context instead. + */ + updateEnumMember: (node: EnumMember, name: PropertyName, initializer: Expression | undefined) => EnumMember, updateSourceFileNode: (node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean | undefined, referencedFiles?: readonly FileReference[] | undefined, typeReferences?: readonly FileReference[] | undefined, hasNoDefaultLib?: boolean | undefined, libReferences?: readonly FileReference[] | undefined) => SourceFile, + /** + * @deprecated Use `factory.createNotEmittedStatement` or the factory supplied by your transformation context instead. + */ + createNotEmittedStatement: (original: Node) => NotEmittedStatement, + /** + * @deprecated Use `factory.createPartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + createPartiallyEmittedExpression: (expression: Expression, original?: Node | undefined) => PartiallyEmittedExpression, + /** + * @deprecated Use `factory.updatePartiallyEmittedExpression` or the factory supplied by your transformation context instead. + */ + updatePartiallyEmittedExpression: (node: PartiallyEmittedExpression, expression: Expression) => PartiallyEmittedExpression, + /** + * @deprecated Use `factory.createCommaList` or the factory supplied by your transformation context instead. + */ + createCommaList: (elements: readonly Expression[]) => CommaListExpression, + /** + * @deprecated Use `factory.updateCommaList` or the factory supplied by your transformation context instead. + */ + updateCommaList: (node: CommaListExpression, elements: readonly Expression[]) => CommaListExpression, + /** + * @deprecated Use `factory.createBundle` or the factory supplied by your transformation context instead. + */ + createBundle: (sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[] | undefined) => Bundle, + /** + * @deprecated Use `factory.updateBundle` or the factory supplied by your transformation context instead. + */ + updateBundle: (node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[] | undefined) => Bundle, + /** + * @deprecated Use `factory.createImmediatelyInvokedFunctionExpression` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedFunctionExpression: { + (statements: readonly Statement[]): CallExpression; + (statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + }, + /** + * @deprecated Use `factory.createImmediatelyInvokedArrowFunction` or the factory supplied by your transformation context instead. + */ + createImmediatelyInvokedArrowFunction: { + (statements: readonly Statement[]): CallExpression; + (statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + }, + /** + * @deprecated Use `factory.createVoidZero` or the factory supplied by your transformation context instead. + */ + createVoidZero: () => VoidExpression, + /** + * @deprecated Use `factory.createExportDefault` or the factory supplied by your transformation context instead. + */ + createExportDefault: (expression: Expression) => ExportAssignment, + /** + * @deprecated Use `factory.createExternalModuleExport` or the factory supplied by your transformation context instead. + */ + createExternalModuleExport: (exportName: Identifier) => ExportDeclaration; + /** + * @deprecated Use `factory.createToken` or the factory supplied by your transformation context instead. + */ + function createToken(kind: TKind): Token; + /** + * @deprecated Use `factory.createIdentifier` or the factory supplied by your transformation context instead. + */ + function createIdentifier(text: string): Identifier; + /** + * @deprecated Use `factory.createTempVariable` or the factory supplied by your transformation context instead. + */ + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** + * @deprecated Use `factory.getGeneratedNameForNode` or the factory supplied by your transformation context instead. + */ + function getGeneratedNameForNode(node: Node | undefined): Identifier; + /** + * @deprecated Use `factory.createIndexSignature` or the factory supplied by your transformation context instead. + */ + function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + /** + * @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. + */ + function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode; + /** + * @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. + */ + function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode; + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; + /** + * @deprecated Use `factory.createNumericLiteral` or `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. + */ + function createLiteral(value: number | PseudoBigInt): NumericLiteral; + /** + * @deprecated Use `factory.createTrue` or `factory.createFalse` or the factory supplied by your transformation context instead. + */ + function createLiteral(value: boolean): BooleanLiteral; + /** + * @deprecated Use `factory.createStringLiteral`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. + */ + function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression; + /** + * @deprecated Use `factory.createMethodSignature` or the factory supplied by your transformation context instead. + */ + function createMethodSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): MethodSignature; + /** + * @deprecated Use `factory.updateMethodSignature` or the factory supplied by your transformation context instead. + */ + function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined): MethodSignature; + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; + /** + * @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. + */ + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + /** @deprecated */ + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. + */ + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + /** + * @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. + */ + function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + function createYield(expression?: Expression): YieldExpression; + /** + * @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. + */ + function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; + /** + * @deprecated Use `factory.createClassExpression` or the factory supplied by your transformation context instead. + */ + function createClassExpression(modifiers: readonly Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + /** + * @deprecated Use `factory.updateClassExpression` or the factory supplied by your transformation context instead. + */ + function updateClassExpression(node: ClassExpression, modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + /** + * @deprecated Use `factory.createPropertySignature` or the factory supplied by your transformation context instead. + */ + function createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer?: Expression): PropertySignature; + /** + * @deprecated Use `factory.updatePropertySignature` or the factory supplied by your transformation context instead. + */ + function updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature; + /** + * @deprecated Use `factory.createExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; + /** + * @deprecated Use `factory.updateExpressionWithTypeArguments` or the factory supplied by your transformation context instead. + */ + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression): ExpressionWithTypeArguments; + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; + /** + * @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. + */ + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; + /** + * @deprecated Use `factory.createComma` or the factory supplied by your transformation context instead. + */ + function createComma(left: Expression, right: Expression): Expression; + /** + * @deprecated Use `factory.createLessThan` or the factory supplied by your transformation context instead. + */ + function createLessThan(left: Expression, right: Expression): Expression; + /** + * @deprecated Use `factory.createAssignment` or the factory supplied by your transformation context instead. + */ + function createAssignment(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createStrictEquality` or the factory supplied by your transformation context instead. + */ + function createStrictEquality(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createStrictInequality` or the factory supplied by your transformation context instead. + */ + function createStrictInequality(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createAdd` or the factory supplied by your transformation context instead. + */ + function createAdd(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createSubtract` or the factory supplied by your transformation context instead. + */ + function createSubtract(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createLogicalAnd` or the factory supplied by your transformation context instead. + */ + function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createLogicalOr` or the factory supplied by your transformation context instead. + */ + function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + /** + * @deprecated Use `factory.createPostfixIncrement` or the factory supplied by your transformation context instead. + */ + function createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + /** + * @deprecated Use `factory.{0}` or the factory supplied by your transformation context instead. + */ + /** + * @deprecated Use `factory.createLogicalNot` or the factory supplied by your transformation context instead. + */ + function createLogicalNot(operand: Expression): PrefixUnaryExpression; + /** + * @deprecated Use `isTypeAssertionExpression` instead. + */ + function isTypeAssertion(node: Node): node is TypeAssertion; +} export = ts; \ No newline at end of file