From 594a72954069ed048d2edf2fc3ab719271d445a3 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 10 Sep 2019 13:45:03 -0700 Subject: [PATCH] Move services to use 'factory' object --- Gulpfile.js | 2 +- .../factoryCompat.ts => compat/factory.ts} | 101 +- src/compat/tsconfig.json | 12 + src/compiler/checker.ts | 56 +- src/compiler/core.ts | 69 + src/compiler/debug.ts | 2 +- src/compiler/diagnosticMessages.json | 4 + src/compiler/emitter.ts | 10 +- src/compiler/factory.ts | 3203 ++++++++++------- src/compiler/parser.ts | 32 +- src/compiler/plugin.ts | 15 +- src/compiler/program.ts | 118 +- src/compiler/sys.ts | 27 + src/compiler/transformer.ts | 4 +- src/compiler/transformers/declarations.ts | 43 +- src/compiler/transformers/es2015.ts | 4 +- src/compiler/transformers/generators.ts | 14 +- src/compiler/transformers/jsx.ts | 4 +- src/compiler/transformers/module/system.ts | 3 +- src/compiler/transformers/ts.ts | 2 +- src/compiler/tsconfig.json | 2 +- src/compiler/types.ts | 40 +- src/compiler/utilities.ts | 25 +- src/harness/fakes.ts | 50 +- ...dConvertToUnknownForNonOverlappingTypes.ts | 4 +- src/services/codefixes/addMissingAwait.ts | 10 +- .../addMissingInvocationForDecorator.ts | 2 +- .../codefixes/addNameToNamelessParameter.ts | 4 +- .../codefixes/annotateWithTypeFromJSDoc.ts | 30 +- .../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 +- .../fixExtendsInterfaceBecomesImplements.ts | 4 +- .../fixForgottenThisPropertyAccess.ts | 2 +- .../codefixes/fixInvalidImportSyntax.ts | 6 +- src/services/codefixes/fixSpelling.ts | 4 +- .../codefixes/fixStrictClassInitialization.ts | 26 +- src/services/codefixes/fixUnreachableCode.ts | 2 +- src/services/codefixes/fixUnusedIdentifier.ts | 4 +- src/services/codefixes/helpers.ts | 56 +- src/services/codefixes/importFixes.ts | 22 +- src/services/codefixes/inferFromUsage.ts | 20 +- src/services/codefixes/requireInTs.ts | 4 +- src/services/getEditsForFileRename.ts | 2 +- src/services/organizeImports.ts | 20 +- .../addOrRemoveBracesToArrowFunction.ts | 8 +- src/services/refactors/convertExport.ts | 18 +- src/services/refactors/convertImport.ts | 18 +- .../convertParamsToDestructuredObject.ts | 29 +- src/services/refactors/extractSymbol.ts | 147 +- src/services/refactors/extractType.ts | 18 +- .../generateGetAccessorAndSetAccessor.ts | 42 +- src/services/refactors/moveToNewFile.ts | 64 +- src/services/textChanges.ts | 24 +- src/services/transform.ts | 2 +- src/services/tsconfig.json | 3 +- src/services/utilities.ts | 10 +- src/testRunner/tsconfig.json | 1 + src/tsc/tsc.ts | 9 +- src/tsserverlibrary/tsconfig.json | 3 +- src/typescriptServices/tsconfig.json | 3 +- ...ts.parsesCorrectly.Nested @param tags.json | 19 +- ...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 | 13 +- 80 files changed, 2810 insertions(+), 1911 deletions(-) rename src/{services/factoryCompat.ts => compat/factory.ts} (76%) create mode 100644 src/compat/tsconfig.json diff --git a/Gulpfile.js b/Gulpfile.js index 91c5912e5b7..faedadb7bb8 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -124,7 +124,7 @@ const buildApi = (() => { .pipe(newer("built/local/api.d.ts")) .pipe(sourcemaps.init({ loadMaps: true })) .pipe(transform(content => content.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, "$1$2enum $3 {$4"))) - .pipe(transform(content => `${content}\nexport = typeof ts;\n`)) + .pipe(transform(content => `${content}\nexport = ts;\n`)) .pipe(prependFile(copyright)) .pipe(rename("api.d.ts")) .pipe(dest("built/local")); diff --git a/src/services/factoryCompat.ts b/src/compat/factory.ts similarity index 76% rename from src/services/factoryCompat.ts rename to src/compat/factory.ts index 2b501b369e3..66fa2c5a33e 100644 --- a/src/services/factoryCompat.ts +++ b/src/compat/factory.ts @@ -1,19 +1,15 @@ namespace ts { - // NOTE: These exports are deprecated in favor of using a `NodeFactory` instance, and have been moved to services for backwards compatibility reasons. + // NOTE: These exports are deprecated in favor of using a `NodeFactory` instance and exist here purely for backwards compatibility reasons. export const { createNumericLiteral, createBigIntLiteral, createStringLiteral, createStringLiteralFromNode, createRegularExpressionLiteral, - createIdentifier, - /** @internal */ updateIdentifier, - createTempVariable, createLoopVariable, createUniqueName, createOptimisticUniqueName, createFileLevelUniqueName, - getGeneratedNameForNode, createToken, createSuper, createThis, @@ -46,9 +42,7 @@ namespace ts { updateCallSignature, createConstructSignature, updateConstructSignature, - createIndexSignature, updateIndexSignature, - /*@internal*/ createSignatureDeclaration, createKeywordTypeNode, createTypePredicateNode, updateTypePredicateNode, @@ -74,7 +68,6 @@ namespace ts { updateUnionTypeNode, createIntersectionTypeNode, updateIntersectionTypeNode, - createUnionOrIntersectionTypeNode, createConditionalTypeNode, updateConditionalTypeNode, createInferTypeNode, @@ -303,17 +296,31 @@ namespace ts { createLogicalNot, createVoidZero, createExportDefault, - createExternalModuleExport, - /*@internal*/ recreateOuterExpressions - } = syntheticNodeFactory; + createExternalModuleExport + } = factory; + + export function createIdentifier(text: string) { + return factory.createIdentifier(text, /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined); + } + + export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier { + return factory.createTempVariable(recordTempVariable, /*reserveInNestedScopes*/ undefined); + } + + export function getGeneratedNameForNode(node: Node | undefined): Identifier { + return factory.getGeneratedNameForNode(node, /*flags*/ undefined); + } + + export function createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration { + return factory.createIndexSignature(decorators, modifiers, parameters, type); + } - /* @internal */ export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote: boolean): StringLiteral; // tslint:disable-line unified-signatures /** 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 { + export function createLiteral(value: string | number | PseudoBigInt | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): PrimaryExpression { if (typeof value === "number") { return createNumericLiteral(value + ""); } @@ -324,9 +331,7 @@ namespace ts { return value ? createTrue() : createFalse(); } if (isString(value)) { - const res = createStringLiteral(value); - if (isSingleQuote) res.singleQuote = true; - return res; + return createStringLiteral(value, /*isSingleQuote*/ undefined); } return createStringLiteralFromNode(value); } @@ -338,7 +343,7 @@ namespace ts { name: string | PropertyName, questionToken: QuestionToken | undefined ) { - return syntheticNodeFactory.createMethodSignature(/*modifiers*/ undefined, name, questionToken, typeParameters, parameters, type); + return factory.createMethodSignature(/*modifiers*/ undefined, name, questionToken, typeParameters, parameters, type); } export function updateMethodSignature( @@ -349,7 +354,7 @@ namespace ts { name: PropertyName, questionToken: QuestionToken | undefined ) { - return syntheticNodeFactory.updateMethodSignature(node, node.modifiers, name, questionToken, typeParameters, parameters, type); + return factory.updateMethodSignature(node, node.modifiers, name, questionToken, typeParameters, parameters, type); } export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode; @@ -363,14 +368,12 @@ namespace ts { type = operatorOrType as TypeNode; operator = SyntaxKind.KeyOfKeyword; } - return syntheticNodeFactory.createTypeOperatorNode(operator, type); + return factory.createTypeOperatorNode(operator, type); } /** @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) { let typeArguments: readonly TypeNode[] | undefined; if (template) { @@ -379,7 +382,7 @@ namespace ts { else { template = typeArgumentsOrTemplate as TemplateLiteral; } - return syntheticNodeFactory.createTaggedTemplate(tag, typeArguments, template); + return factory.createTaggedTemplate(tag, typeArguments, template); } /** @deprecated */ @@ -393,7 +396,7 @@ namespace ts { else { template = typeArgumentsOrTemplate as TemplateLiteral; } - return syntheticNodeFactory.updateTaggedTemplate(node, tag, typeArguments, template); + return factory.updateTaggedTemplate(node, tag, typeArguments, template); } export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; @@ -411,7 +414,7 @@ namespace ts { questionToken = questionTokenOrWhenTrue as QuestionToken; whenTrue = whenTrueOrWhenFalse; } - return syntheticNodeFactory.createConditional(condition, questionToken, whenTrue, colonToken!, whenFalse); + return factory.createConditional(condition, questionToken, whenTrue, colonToken!, whenFalse); } export function createYield(expression?: Expression): YieldExpression; @@ -424,7 +427,7 @@ namespace ts { else { expression = asteriskTokenOrExpression as Expression; } - return syntheticNodeFactory.createYield(asteriskToken, expression); + return factory.createYield(asteriskToken, expression); } export function createClassExpression( @@ -434,7 +437,7 @@ namespace ts { heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - return syntheticNodeFactory.createClassExpression(/*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); + return factory.createClassExpression(/*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); } export function updateClassExpression( @@ -445,7 +448,7 @@ namespace ts { heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - return syntheticNodeFactory.updateClassExpression(node, /*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); + return factory.updateClassExpression(node, /*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); } export function createPropertySignature( @@ -455,7 +458,7 @@ namespace ts { type: TypeNode | undefined, initializer?: Expression ): PropertySignature { - const node = syntheticNodeFactory.createPropertySignature(modifiers, name, questionToken, type); + const node = factory.createPropertySignature(modifiers, name, questionToken, type); node.initializer = initializer; return node; } @@ -478,48 +481,10 @@ namespace ts { } export function createExpressionWithTypeArguments(typeArguments: readonly TypeNode[] | undefined, expression: Expression) { - return syntheticNodeFactory.createExpressionWithTypeArguments(expression, typeArguments); + return factory.createExpressionWithTypeArguments(expression, typeArguments); } export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression) { - return syntheticNodeFactory.updateExpressionWithTypeArguments(node, expression, typeArguments); - } -} - -/* @internal */ -namespace ts { - const syntheticParenthesizerRules = syntheticNodeFactory.getParenthesizerRules(); - - export const { - parenthesizeConditionOfConditionalExpression: parenthesizeForConditionalHead, - parenthesizeBranchOfConditionalExpression: parenthesizeSubexpressionOfConditionalExpression, - parenthesizeExpressionOfExportDefault: parenthesizeDefaultExpression, - parenthesizeExpressionOfNew: parenthesizeForNew, - parenthesizeLeftSideOfAccess: parenthesizeForAccess, - parenthesizeOperandOfPrefixUnary: parenthesizePrefixOperand, - parenthesizeOperandOfPostfixUnary: parenthesizePostfixOperand, - parenthesizeExpressionsOfCommaDelimitedList: parenthesizeListElements, - parenthesizeExpressionForDisallowedComma: parenthesizeExpressionForList, - parenthesizeExpressionOfExpressionStatement: parenthesizeExpressionForExpressionStatement, - parenthesizeConciseBodyOfArrowFunction: parenthesizeConciseBody, - parenthesizeMemberOfConditionalType: parenthesizeConditionalTypeMember, - parenthesizeMemberOfElementType: parenthesizeElementTypeMember, - parenthesizeElementTypeOfArrayType: parenthesizeArrayTypeMember, - parenthesizeConstituentTypesOfUnionOrIntersectionType: parenthesizeElementTypeMembers, - parenthesizeTypeArguments: parenthesizeTypeParameters, - } = syntheticParenthesizerRules; - - /** - * 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) { - return isLeftSideOfBinary ? syntheticParenthesizerRules.parenthesizeLeftSideOfBinary(binaryOperator, operand) : - syntheticParenthesizerRules.parenthesizeRightSideOfBinary(binaryOperator, leftOperand, operand); + return factory.updateExpressionWithTypeArguments(node, expression, typeArguments); } } \ No newline at end of file diff --git a/src/compat/tsconfig.json b/src/compat/tsconfig.json new file mode 100644 index 00000000000..6a4a20f900f --- /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/checker.ts b/src/compiler/checker.ts index 1d86e205e69..4e62d48b0b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -293,7 +293,6 @@ namespace ts { const Signature = objectAllocator.getSignatureConstructor(); // tslint:enable variable-name - const factory = syntheticNodeFactory; let typeCount = 0; let symbolCount = 0; let enumCount = 0; @@ -356,8 +355,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) => { @@ -392,16 +391,16 @@ namespace ts { symbolToTypeParameterDeclarations: nodeBuilder.symbolToTypeParameterDeclarations, symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration as (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => ParameterDeclaration, // TODO: GH#18217 typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration as (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => TypeParameterDeclaration, // TODO: GH#18217 - 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 => { @@ -411,8 +410,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 => { @@ -489,9 +488,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, @@ -562,15 +561,16 @@ namespace ts { getAccessibleSymbolChain, getTypePredicateOfSignature: getTypePredicateOfSignature as (signature: Signature) => TypePredicate, // TODO: GH#18217 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)) { return emptyArray; } @@ -3739,7 +3739,7 @@ namespace ts { } const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true); if (typeNodes && typeNodes.length > 0) { - const unionOrIntersectionTypeNode = factory.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 { @@ -4247,7 +4247,11 @@ namespace ts { returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum - return factory.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); + const node = factory.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); + if (typeArguments) { + node.typeArguments = createNodeArray(typeArguments); + } + return node; } function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration { @@ -4473,7 +4477,7 @@ namespace ts { } return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full } - const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration)); + const contextFile = getSourceFileOfNode(getParseTreeNode(context.enclosingDeclaration)) || Debug.fail("Could not determine parsed source file."); const links = getSymbolLinks(symbol); let specifier = links.specifierCache && links.specifierCache.get(contextFile.path); if (!specifier) { @@ -31920,19 +31924,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 bacbda3f625..44f320aec41 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2082,4 +2082,73 @@ namespace ts { throw e; } } + + export type Overload = ((this: This, ...args: A) => R) & OverloadOptions; + export type OverloadOptions = { minLength?: A["length"], maxLength?: A["length"] }; + export type OverloadLengthOptions = { length: A["length"] }; + export type OverloadParameters> = O extends unknown ? Parameters : never; + export type OverloadList[], R> = (this: This, ...args: OverloadParameters) => R; + + export function makeOverload(fn: (this: This, ...args: A) => R, options?: OverloadOptions | OverloadLengthOptions) { + const overload = fn as Overload; + if (options) { + if ("length" in options) { + overload.minLength = overload.maxLength = options.length; + } + else { + if ("minLength" in options) { + overload.minLength = options.minLength; + } + if ("maxLength" in options) { + overload.maxLength = options.maxLength; + } + } + } + return overload; + } + + /** + * Create a function from a set of overloads differentiated by argument count. + */ + export function overloadList[], R>(...overloads: O) { + type F = O[number]; + const overloadCache: F[] = []; + + // sort by minLength descending + const sortedOverloads = stableSort(overloads, (a, b) => -compareValues(minLength(a), minLength(b))); + + let lastLength = -1; + for (const overload of sortedOverloads) { + const overloadLength = minLength(overload); + Debug.assert(overloadLength !== lastLength, "Overloads must differ in minimum length"); + lastLength = overloadLength; + } + Debug.assert(lastLength !== -1, "Overload list must not be empty"); + + return function () { return chooseOverload(arguments.length).apply(this, arguments); } as OverloadList; + + function chooseOverload(length: number) { + const cached = overloadCache[length]; + if (cached) return cached; + for (const overload of sortedOverloads) { + if (length >= minLength(overload)) { + overloadCache[length] = overload; + return length <= maxLength(overload) ? overload : argumentCountMismatch; + } + } + return overloadCache[length] = argumentCountMismatch; + } + + function minLength(overload: F) { + return typeof overload.minLength === "number" ? overload.minLength : overload.length; + } + + function maxLength(overload: F) { + return typeof overload.maxLength === "number" ? overload.maxLength : overload.length; + } + } + + function argumentCountMismatch() { + return Debug.fail("Argument count mismatch"); + } } diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index c90f4d1fb01..70ae9558082 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -248,7 +248,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) : ""; } } }); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4b575ee8d89..9c47c9df0b4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3200,6 +3200,10 @@ "category": "Error", "code": 5080 }, + "Plugins are not supported in the current host environment.": { + "category": "Error", + "code": 5081 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6cbed61fcde..262b6e65d50 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 = syntheticNodeFactory.createBundle(sourceFiles, prepends); + const bundle = factory.createBundle(sourceFiles, prepends); const result = action(getOutputPathsFor(bundle, host, emitOnlyDtsFiles), bundle); if (result) { return result; @@ -312,7 +312,7 @@ namespace ts { return; } // Transform the source files - const transform = transformNodes(resolver, host, syntheticNodeFactory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); const printerOptions: PrinterOptions = { removeComments: compilerOptions.removeComments, @@ -357,13 +357,13 @@ namespace ts { const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; // Setup and perform the transformation to retrieve declarations from the input files const nonJsFiles = filter(sourceFiles, isSourceFileNotJS); - const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [syntheticNodeFactory.createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; + const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [factory.createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; 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 nonJsFiles.forEach(collectLinkedAliases); } - const declarationTransform = transformNodes(resolver, host, syntheticNodeFactory, 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); @@ -2183,7 +2183,7 @@ namespace ts { const dotRangeStart = skipTrivia(currentSourceFile!.text, dotRangeFirstCommentStart); const dotRangeEnd = dotRangeStart + 1; if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { - const dotToken = syntheticNodeFactory.createToken(SyntaxKind.DotToken); + const dotToken = factory.createToken(SyntaxKind.DotToken); dotToken.pos = node.expression.end; dotToken.end = dotRangeEnd; indentBeforeDot = needsIndentation(node, node.expression, dotToken); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 121e8840fbc..9f0b19d9b85 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -5,16 +5,30 @@ namespace ts { export function createNodeFactory( createNode: (kind: SyntaxKind) => Node, createParenthesizerRules: (factory: NodeFactory) => ParenthesizerRules, - createNodeConverters: (factory: NodeFactory) => NodeConverters + createNodeConverters: (factory: NodeFactory) => NodeConverters, + treeStateObserver: TreeStateObserver ): NodeFactory { - let actualCreatePropertyAccess = createPropertyAccessUnspecific; + let needsNoIndentationOnPropertyAccess: boolean | undefined; const parenthesizer = memoize(() => createParenthesizerRules(factory)); const getConverters = memoize(() => createNodeConverters(factory)); + const setChild = treeStateObserver === nullTreeStateObserver + || treeStateObserver.onSetChild === noop2 + || treeStateObserver.onSetChild === noop ? setChildWithoutTreeState : setChildWithTreeState; + const setChildren = treeStateObserver === nullTreeStateObserver + || treeStateObserver.onSetChildren === noop2 + || treeStateObserver.onSetChildren === noop ? setChildrenWithoutTreeState : setChildrenWithTreeState; + const finishNode = treeStateObserver === nullTreeStateObserver + || treeStateObserver.onFinishNode === noop ? finishNodeWithoutTreeState : finishNodeWithTreeState; + const updateNode = treeStateObserver === nullTreeStateObserver + || treeStateObserver.onUpdateNode === noop2 + || treeStateObserver.onUpdateNode === noop ? ts.updateNode : updateNodeWithTreeState; // tslint:disable-line no-unnecessary-qualifier + const reuseNode = treeStateObserver === nullTreeStateObserver + || treeStateObserver.onReuseNode === noop ? identity : reuseNodeWithTreeState; + const factory: NodeFactory = { getParenthesizerRules: parenthesizer, getConverters, - createNode, createNodeArray, createNumericLiteral, createBigIntLiteral, @@ -31,8 +45,8 @@ namespace ts { createFileLevelUniqueName, getGeneratedNameForNode, createToken, - createSuper, - createThis, + createSuper: createSuperExpression, + createThis: createThisExpression, createNull, createTrue, createFalse, @@ -94,7 +108,6 @@ namespace ts { updateUnionTypeNode, createIntersectionTypeNode, updateIntersectionTypeNode, - createUnionOrIntersectionTypeNode, createConditionalTypeNode, updateConditionalTypeNode, createInferTypeNode, @@ -118,44 +131,69 @@ namespace ts { updateArrayBindingPattern, createBindingElement, updateBindingElement, - createArrayLiteral, - updateArrayLiteral, - createObjectLiteral, - updateObjectLiteral, - createPropertyAccess: (expression, name) => actualCreatePropertyAccess(expression, name), - updatePropertyAccess, - createElementAccess, - updateElementAccess, - createCall, - updateCall, - createNew, - updateNew, - createTaggedTemplate, - updateTaggedTemplate, + createArrayLiteral: createArrayLiteralExpression, + updateArrayLiteral: updateArrayLiteralExpression, + createObjectLiteral: createObjectLiteralExpression, + updateObjectLiteral: updateObjectLiteralExpression, + createPropertyAccess: (expression, name) => { + const node = createPropertyAccessExpression(expression, name); + if (needsNoIndentationOnPropertyAccess === undefined) { + needsNoIndentationOnPropertyAccess = !!(node.flags & NodeFlags.Synthesized); + } + if (needsNoIndentationOnPropertyAccess) { + setEmitFlags(node, EmitFlags.NoIndentation); + } + return node; + }, + updatePropertyAccess: updatePropertyAccessExpression, + createElementAccess: createElementAccessExpression, + updateElementAccess: updateElementAccessExpression, + createCall: createCallExpression, + updateCall: updateCallExpression, + createNew: createNewExpression, + updateNew: updateNewExpression, + createTaggedTemplate: createTaggedTemplateExpression, + updateTaggedTemplate: updateTaggedTemplateExpression, createTypeAssertion, updateTypeAssertion, - createParen, - updateParen, + createParen: createParenthesizedExpression, + updateParen: updateParenthesizedExpression, createFunctionExpression, updateFunctionExpression, - createArrowFunction, - updateArrowFunction, - createDelete, - updateDelete, - createTypeOf, - updateTypeOf, - createVoid, - updateVoid, - createAwait, - updateAwait, - createPrefix, - updatePrefix, - createPostfix, - updatePostfix, - createBinary, - updateBinary, - createConditional, - updateConditional, + // createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction, + // createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction, + createArrowFunction: overloadList( + makeOverload(createArrowFunction, { minLength: 6 }), + makeOverload(createArrowFunctionWithoutTokens, { length: 5 }) + ), + // updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction, + // updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody): ArrowFunction, + updateArrowFunction: overloadList( + makeOverload(updateArrowFunction, { length: 7 }), + makeOverload(updateArrowFunctionWithoutTokens, { length: 6 }) + ), + 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: overloadList( + makeOverload(createConditionalExpression, { length: 5 }), + makeOverload(createConditionalExpressionWithoutTokens, { length: 3 }) + ), + updateConditional: overloadList( + makeOverload(updateConditionalExpression, { length: 6 }), + makeOverload(updateConditionalExpressionWithoutTokens, { length: 4 }) + ), createTemplateExpression, updateTemplateExpression, createTemplateHead, @@ -163,10 +201,10 @@ namespace ts { createTemplateTail, createNoSubstitutionTemplateLiteral, createTemplateLiteralLikeNode, - createYield, - updateYield, - createSpread, - updateSpread, + createYield: createYieldExpression, + updateYield: updateYieldExpression, + createSpread: createSpreadElement, + updateSpread: updateSpreadElement, createClassExpression, updateClassExpression, createOmittedExpression, @@ -188,37 +226,47 @@ namespace ts { 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, + 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, + // createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration, + // createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration, + createVariableDeclaration: overloadList( + makeOverload(createVariableDeclaration, { length: 4 }), + makeOverload(createVariableDeclarationWithoutTokens, { minLength: 1, maxLength: 3 }) + ), + // updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration, + // updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration, + updateVariableDeclaration: overloadList( + makeOverload(updateVariableDeclaration, { length: 5 }), + makeOverload(updateVariableDeclarationWithoutTokens, { length: 4 }) + ), createVariableDeclarationList, updateVariableDeclarationList, createFunctionDeclaration, @@ -259,6 +307,7 @@ namespace ts { updateNamedExports, createExportSpecifier, updateExportSpecifier, + createMissingDeclaration, createExternalModuleReference, updateExternalModuleReference, createJSDocAllType, @@ -330,8 +379,8 @@ namespace ts { createMergeDeclarationMarker, createPartiallyEmittedExpression, updatePartiallyEmittedExpression, - createCommaList, - updateCommaList, + createCommaList: createCommaListExpression, + updateCommaList: updateCommaListExpression, createBundle, updateBundle, createImmediatelyInvokedFunctionExpression, @@ -380,14 +429,18 @@ namespace ts { return factory; + function createBaseNode(kind: T["kind"]): T { + return createNode(kind) as T; + } + function createBaseDeclaration( kind: T["kind"], decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined - ): T { - const node = createNode(kind) as T; - node.decorators = asNodeArray(decorators); - node.modifiers = asNodeArray(modifiers); + ) { + const node = createBaseNode(kind); + setChildren(node, node.decorators = asNodeArray(decorators)); + setChildren(node, node.modifiers = asNodeArray(modifiers)); return node; } @@ -396,35 +449,57 @@ namespace ts { decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: DeclarationName | string | undefined - ): T { - const node = createBaseDeclaration(kind, decorators, modifiers); - node.name = asName(name); + ) { + const node = createBaseDeclaration( + kind, + decorators, + modifiers + ); + setChild(node, node.name = asName(name)); return node; } - function createBaseSignatureLikeDeclaration( + function createBaseGenericNamedDeclaration }>( + kind: T["kind"], + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: DeclarationName | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined + ) { + const node = createBaseNamedDeclaration( + kind, + decorators, + modifiers, + name + ); + setChildren(node, node.typeParameters = asNodeArray(typeParameters)); + return node; + } + + function createBaseSignatureDeclaration( kind: T["kind"], decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: DeclarationName | string | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], + parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined - ): T { - const node = createBaseNamedDeclaration(kind, decorators, modifiers, name); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; + ) { + const node = createBaseGenericNamedDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters + ); + setChildren(node, node.parameters = createNodeArray(parameters)); + setChild(node, node.type = type); return node; } - function createBaseSignatureDeclaration( - kind: T["kind"], - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined - ): T { - return createBaseSignatureLikeDeclaration(kind, /*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined, typeParameters, parameters, type); + function updateBaseSignatureDeclaration(updated: T, original: T) { + if (original.typeArguments) updated.typeArguments = original.typeArguments; + return updateNode(updated, original); } function createBaseFunctionLikeDeclaration( @@ -433,12 +508,102 @@ namespace ts { modifiers: readonly Modifier[] | undefined, name: DeclarationName | string | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], + parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: T["body"] - ): T { - const node = createBaseSignatureLikeDeclaration(kind, decorators, modifiers, name, typeParameters, parameters, type); - node.body = body; + ) { + const node = createBaseSignatureDeclaration( + kind, + decorators, + modifiers, + name, + typeParameters, + parameters, + type + ); + setChild(node, node.body = body); + 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); return node; } @@ -450,39 +615,52 @@ namespace ts { kind: T["kind"], text: string ) { - const node = createNode(kind) as T; + const node = createBaseNode(kind); 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; - return node; + return finishNode(node); } + // @api function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { - return createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); + const node = createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); + return finishNode(node); } - function createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral { + function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { const node = createBaseLiteral(SyntaxKind.StringLiteral, text); node.singleQuote = isSingleQuote; return node; } + // @api + function createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral { + const node = createBaseStringLiteral(text, isSingleQuote); + return finishNode(node); + } + + // @api function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { - const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); + const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); node.textSourceNode = sourceNode; - return node; + return finishNode(node); } + // @api function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { - return createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); + const node = createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); + return finishNode(node); } + // @api function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken { switch (kind) { case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); @@ -499,40 +677,48 @@ namespace ts { // Identifiers // - function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier { + function createBaseIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier { if (originalKeywordKind === undefined && text) { originalKeywordKind = stringToToken(text); } if (originalKeywordKind === SyntaxKind.Identifier) { originalKeywordKind = undefined; } - const node = createNode(SyntaxKind.Identifier) as Identifier; + const node = createBaseNode(SyntaxKind.Identifier); node.originalKeywordKind = originalKeywordKind; node.escapedText = escapeLeadingUnderscores(text); - node.typeArguments = asNodeArray(typeArguments); - node.autoGenerateFlags = undefined; - node.autoGenerateId = undefined; + if (typeArguments) { + node.typeArguments = createNodeArray(typeArguments); + } return node; } + function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags) { + const node = createBaseIdentifier(text) 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, typeArguments, originalKeywordKind); + return finishNode(node); + } + + // @api function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments ? updateNode(createIdentifier(idText(node), typeArguments), node) - : node; - } - - function createGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags) { - const name = createIdentifier(text) as GeneratedIdentifier; - name.autoGenerateFlags = autoGenerateFlags; - name.autoGenerateId = nextAutoGenerateId; - nextAutoGenerateId++; - return name; + : reuseNode(node); } + // @api function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { let flags = GeneratedIdentifierFlags.Auto; if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; - const name = createGeneratedIdentifier("", flags); + const name = finishNode(createBaseGeneratedIdentifier("", flags)); if (recordTempVariable) { recordTempVariable(name); } @@ -540,79 +726,88 @@ namespace ts { } /** Create a unique temporary variable for use in a loop. */ + // @api function createLoopVariable(): Identifier { - return createGeneratedIdentifier("", GeneratedIdentifierFlags.Loop); + return finishNode(createBaseGeneratedIdentifier("", GeneratedIdentifierFlags.Loop)); } /** Create a unique name based on the supplied text. */ + // @api function createUniqueName(text: string): Identifier { - return createGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique); + return finishNode(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique)); } + // @api function createOptimisticUniqueName(text: string): Identifier { - return createGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic); + return finishNode(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 createGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + return finishNode(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 = createGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags); + const name = createBaseGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags); name.original = node; - return name; + return finishNode(name); } // // Punctuation // + function createBaseToken(token: TKind) { + return createBaseNode>(token); + } + + // @api function createToken(token: TKind) { - return createNode(token) as Token; - } - - function createQuestionToken() { - return createToken(SyntaxKind.QuestionToken); - } - - function createColonToken() { - return createToken(SyntaxKind.ColonToken); + return finishNode(createBaseToken(token)); } // // Reserved words // - function createSuper() { - return createToken(SyntaxKind.SuperKeyword) as SuperExpression; + // @api + function createSuperExpression() { + return finishNode(createBaseToken(SyntaxKind.SuperKeyword)) as SuperExpression; } - function createThis() { - return createToken(SyntaxKind.ThisKeyword) as ThisExpression; + // @api + function createThisExpression() { + return finishNode(createBaseToken(SyntaxKind.ThisKeyword)) as ThisExpression; } + // @api function createNull() { - return createToken(SyntaxKind.NullKeyword) as NullLiteral; + return finishNode(createBaseToken(SyntaxKind.NullKeyword)) as NullLiteral; } + // @api function createTrue() { - return createToken(SyntaxKind.TrueKeyword) as TrueLiteral; + return finishNode(createBaseToken(SyntaxKind.TrueKeyword)) as TrueLiteral; } + // @api function createFalse() { - return createToken(SyntaxKind.FalseKeyword) as FalseLiteral; + return finishNode(createBaseToken(SyntaxKind.FalseKeyword)) as FalseLiteral; } // // Modifiers // + // @api function createModifier(kind: T): Token { - return createToken(kind); + return finishNode(createBaseToken(kind)); } + // @api function createModifiersFromModifierFlags(flags: ModifierFlags) { const result: Modifier[] = []; if (flags & ModifierFlags.Export) { result.push(createModifier(SyntaxKind.ExportKeyword)); } @@ -633,36 +828,41 @@ namespace ts { // Names // + // @api function createQualifiedName(left: EntityName, right: string | Identifier) { - const node = createNode(SyntaxKind.QualifiedName) as QualifiedName; - node.left = left; - node.right = asName(right); - return node; + const node = createBaseNode(SyntaxKind.QualifiedName); + setChild(node, node.left = left); + setChild(node, node.right = asName(right)); + return finishNode(node); } + // @api function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { return node.left !== left || node.right !== right ? updateNode(createQualifiedName(left, right), node) - : node; + : reuseNode(node); } + // @api function createComputedPropertyName(expression: Expression) { - const node = createNode(SyntaxKind.ComputedPropertyName) as ComputedPropertyName; - node.expression = parenthesizer().parenthesizeExpressionOfComputedPropertyName(expression); - return node; + const node = createBaseNode(SyntaxKind.ComputedPropertyName); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfComputedPropertyName(expression)); + return finishNode(node); } + // @api function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { return node.expression !== expression ? updateNode(createComputedPropertyName(expression), node) - : node; + : reuseNode(node); } // // Signature elements // + // @api function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) { const node = createBaseNamedDeclaration( SyntaxKind.TypeParameter, @@ -670,19 +870,21 @@ namespace ts { /*modifiers*/ undefined, name ); - node.constraint = constraint; - node.default = defaultType; - return node; + setChild(node, node.constraint = constraint); + setChild(node, node.default = defaultType); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api function createParameterDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -692,19 +894,20 @@ namespace ts { type?: TypeNode, initializer?: Expression ) { - const node = createBaseNamedDeclaration( + const node = createBaseVariableLikeDeclaration( SyntaxKind.Parameter, decorators, modifiers, - name + name, + type, + initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) ); - node.type = type; - node.initializer = initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer); - node.dotDotDotToken = dotDotDotToken; - node.questionToken = questionToken; - return node; + setChild(node, node.dotDotDotToken = dotDotDotToken); + setChild(node, node.questionToken = questionToken); + return finishNode(node); } + // @api function updateParameterDeclaration( node: ParameterDeclaration, decorators: readonly Decorator[] | undefined, @@ -723,25 +926,28 @@ namespace ts { || node.type !== type || node.initializer !== initializer ? updateNode(createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node) - : node; + : reuseNode(node); } + // @api function createDecorator(expression: Expression) { - const node = createNode(SyntaxKind.Decorator) as Decorator; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - return node; + const node = createBaseNode(SyntaxKind.Decorator); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + return finishNode(node); } + // @api function updateDecorator(node: Decorator, expression: Expression) { return node.expression !== expression ? updateNode(createDecorator(expression), node) - : node; + : reuseNode(node); } // // Type Elements // + // @api function createPropertySignature( modifiers: readonly Modifier[] | undefined, name: PropertyName | string, @@ -754,11 +960,12 @@ namespace ts { modifiers, name ); - node.type = type; - node.questionToken = questionToken; - return node; + setChild(node, node.type = type); + setChild(node, node.questionToken = questionToken); + return finishNode(node); } + // @api function updatePropertySignature( node: PropertySignature, modifiers: readonly Modifier[] | undefined, @@ -771,9 +978,10 @@ namespace ts { || node.questionToken !== questionToken || node.type !== type ? updateNode(createPropertySignature(modifiers, name, questionToken, type), node) - : node; + : reuseNode(node); } + // @api function createPropertyDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -782,19 +990,20 @@ namespace ts { type: TypeNode | undefined, initializer: Expression | undefined ) { - const node = createBaseNamedDeclaration( + const node = createBaseVariableLikeDeclaration( SyntaxKind.PropertyDeclaration, decorators, modifiers, - name + name, + type, + initializer ); - node.type = type; - node.initializer = initializer; - node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined; - return node; + setChild(node, node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.QuestionToken ? questionOrExclamationToken : undefined); + setChild(node, node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined); + return finishNode(node); } + // @api function updatePropertyDeclaration( node: PropertyDeclaration, decorators: readonly Decorator[] | undefined, @@ -812,9 +1021,10 @@ namespace ts { || node.type !== type || node.initializer !== initializer ? updateNode(createPropertyDeclaration(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) - : node; + : reuseNode(node); } + // @api function createMethodSignature( modifiers: readonly Modifier[] | undefined, name: string | PropertyName, @@ -823,7 +1033,7 @@ namespace ts { parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ) { - const node = createBaseSignatureLikeDeclaration( + const node = createBaseSignatureDeclaration( SyntaxKind.MethodSignature, /*decorators*/ undefined, modifiers, @@ -832,10 +1042,11 @@ namespace ts { parameters, type ); - node.questionToken = questionToken; - return node; + setChild(node, node.questionToken = questionToken); + return finishNode(node); } + // @api function updateMethodSignature( node: MethodSignature, modifiers: readonly Modifier[] | undefined, @@ -851,10 +1062,11 @@ namespace ts { || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type - ? updateNode(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node) - : node; + ? updateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node) + : reuseNode(node); } + // @api function createMethodDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -876,11 +1088,12 @@ namespace ts { type, body ); - node.asteriskToken = asteriskToken; - node.questionToken = questionToken; - return node; + setChild(node, node.asteriskToken = asteriskToken); + setChild(node, node.questionToken = questionToken); + return finishNode(node); } + // @api function updateMethodDeclaration( node: MethodDeclaration, decorators: readonly Decorator[] | undefined, @@ -902,10 +1115,11 @@ namespace ts { || node.parameters !== parameters || node.type !== type || node.body !== body - ? updateNode(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) + : reuseNode(node); } + // @api function createConstructorDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -922,9 +1136,10 @@ namespace ts { /*type*/ undefined, body ); - return node; + return finishNode(node); } + // @api function updateConstructorDeclaration( node: ConstructorDeclaration, decorators: readonly Decorator[] | undefined, @@ -936,10 +1151,11 @@ namespace ts { || node.modifiers !== modifiers || node.parameters !== parameters || node.body !== body - ? updateNode(createConstructorDeclaration(decorators, modifiers, parameters, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createConstructorDeclaration(decorators, modifiers, parameters, body), node) + : reuseNode(node); } + // @api function createGetAccessorDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -958,9 +1174,10 @@ namespace ts { type, body ); - return node; + return finishNode(node); } + // @api function updateGetAccessorDeclaration( node: GetAccessorDeclaration, decorators: readonly Decorator[] | undefined, @@ -976,10 +1193,11 @@ namespace ts { || node.parameters !== parameters || node.type !== type || node.body !== body - ? updateNode(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node) + : reuseNode(node); } + // @api function createSetAccessorDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -997,9 +1215,10 @@ namespace ts { /*type*/ undefined, body ); - return node; + return finishNode(node); } + // @api function updateSetAccessorDeclaration( node: SetAccessorDeclaration, decorators: readonly Decorator[] | undefined, @@ -1013,78 +1232,126 @@ namespace ts { || node.name !== name || node.parameters !== parameters || node.body !== body - ? updateNode(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node) + : reuseNode(node); } + // @api function createCallSignature( typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): CallSignatureDeclaration { - return createBaseSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type); + const node = createBaseSignatureDeclaration( + SyntaxKind.CallSignature, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + return finishNode(node); } + // @api function updateCallSignature( node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined ) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateBaseSignatureDeclaration(createCallSignature(typeParameters, parameters, type), node) + : reuseNode(node); } + // @api function createConstructSignature( typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): ConstructSignatureDeclaration { - return createBaseSignatureDeclaration(SyntaxKind.ConstructSignature, typeParameters, parameters, type); + const node = createBaseSignatureDeclaration( + SyntaxKind.ConstructSignature, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + typeParameters, + parameters, + type + ); + return finishNode(node); } + // @api function updateConstructSignature( node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined ) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - function createSignatureDeclaration( - kind: T["kind"], - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - typeArguments?: readonly TypeNode[] | undefined - ): T { - const node = createBaseSignatureDeclaration(kind, typeParameters, parameters, type); - if (typeArguments) { - node.typeArguments = createNodeArray(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; + ? updateBaseSignatureDeclaration(createConstructSignature(typeParameters, parameters, type), node) + : reuseNode(node); } + // Route signature creation to the appropriate factory method. Used by the NodeBuilder in the checker. + // @api + 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 createCallSignature(typeParameters, parameters, type); + case SyntaxKind.ConstructSignature: + return 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 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 createMethodDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type, /*body*/ undefined); + case SyntaxKind.Constructor: + return 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 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 createSetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, /*body*/ undefined); + case SyntaxKind.IndexSignature: + return createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, type); + case SyntaxKind.JSDocFunctionType: + return createJSDocFunctionType(parameters, type); + case SyntaxKind.FunctionType: + return createFunctionTypeNode(typeParameters, parameters, type); + case SyntaxKind.ConstructorType: + return createConstructorTypeNode(typeParameters, parameters, type); + case SyntaxKind.FunctionDeclaration: + return 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 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 createArrowFunction(/*modifiers*/ undefined, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, /*body*/ undefined!); + default: + return Debug.assertNever(kind); + } + } + + // @api function createIndexSignature( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): IndexSignatureDeclaration { - return createBaseSignatureLikeDeclaration( + const node = createBaseSignatureDeclaration( SyntaxKind.IndexSignature, decorators, modifiers, @@ -1093,8 +1360,10 @@ namespace ts { parameters, type ); + return finishNode(node); } + // @api function updateIndexSignature( node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, @@ -1106,311 +1375,402 @@ namespace ts { || node.type !== type || node.decorators !== decorators || node.modifiers !== modifiers - ? updateNode(createIndexSignature(decorators, modifiers, parameters, type), node) - : node; + ? updateBaseSignatureDeclaration(createIndexSignature(decorators, modifiers, parameters, type), node) + : reuseNode(node); } // // Types // + // @api function createKeywordTypeNode(kind: KeywordTypeNode["kind"]) { - return createNode(kind) as KeywordTypeNode; + return finishNode(createBaseToken(kind)) as KeywordTypeNode; } + // @api function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode) { - const node = createNode(SyntaxKind.TypePredicate) as TypePredicateNode; - node.parameterName = asName(parameterName); - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.TypePredicate); + setChild(node, node.parameterName = asName(parameterName)); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) { return node.parameterName !== parameterName || node.type !== type ? updateNode(createTypePredicateNode(parameterName, type), node) - : node; + : reuseNode(node); } + // @api function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { - const node = createNode(SyntaxKind.TypeReference) as TypeReferenceNode; - node.typeName = asName(typeName); - node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments)); - return node; + const node = createBaseNode(SyntaxKind.TypeReference); + setChild(node, node.typeName = asName(typeName)); + setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); + return finishNode(node); } + // @api function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { return node.typeName !== typeName || node.typeArguments !== typeArguments ? updateNode(createTypeReferenceNode(typeName, typeArguments), node) - : node; + : reuseNode(node); } - function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode { - return createSignatureDeclaration(SyntaxKind.FunctionType, typeParameters, parameters, type); + // @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 + ); + return finishNode(node); } - function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); + // @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) + : reuseNode(node); } - function createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode { - return createSignatureDeclaration(SyntaxKind.ConstructorType, typeParameters, parameters, type); + // @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 + ); + return finishNode(node); } - function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return updateSignatureDeclaration(node, typeParameters, parameters, type); + // @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) + : reuseNode(node); } + // @api function createTypeQueryNode(exprName: EntityName) { - const node = createNode(SyntaxKind.TypeQuery) as TypeQueryNode; - node.exprName = exprName; - return node; + const node = createBaseNode(SyntaxKind.TypeQuery); + setChild(node, node.exprName = exprName); + return finishNode(node); } + // @api function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { return node.exprName !== exprName ? updateNode(createTypeQueryNode(exprName), node) - : node; + : reuseNode(node); } + // @api function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { - const node = createNode(SyntaxKind.TypeLiteral) as TypeLiteralNode; - node.members = createNodeArray(members); - return node; + const node = createBaseNode(SyntaxKind.TypeLiteral); + setChildren(node, node.members = createNodeArray(members)); + return finishNode(node); } + // @api function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray) { return node.members !== members ? updateNode(createTypeLiteralNode(members), node) - : node; + : reuseNode(node); } + // @api function createArrayTypeNode(elementType: TypeNode) { - const node = createNode(SyntaxKind.ArrayType) as ArrayTypeNode; - node.elementType = parenthesizer().parenthesizeElementTypeOfArrayType(elementType); - return node; + const node = createBaseNode(SyntaxKind.ArrayType); + setChild(node, node.elementType = parenthesizer().parenthesizeElementTypeOfArrayType(elementType)); + return finishNode(node); } + // @api function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { return node.elementType !== elementType ? updateNode(createArrayTypeNode(elementType), node) - : node; + : reuseNode(node); } + // @api function createTupleTypeNode(elementTypes: readonly TypeNode[]) { - const node = createNode(SyntaxKind.TupleType) as TupleTypeNode; - node.elementTypes = createNodeArray(elementTypes); - return node; + const node = createBaseNode(SyntaxKind.TupleType); + setChildren(node, node.elementTypes = createNodeArray(elementTypes)); + return finishNode(node); } + // @api function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]) { return node.elementTypes !== elementTypes ? updateNode(createTupleTypeNode(elementTypes), node) - : node; + : reuseNode(node); } + // @api function createOptionalTypeNode(type: TypeNode) { - const node = createNode(SyntaxKind.OptionalType) as OptionalTypeNode; - node.type = parenthesizer().parenthesizeElementTypeOfArrayType(type); - return node; + const node = createBaseNode(SyntaxKind.OptionalType); + setChild(node, node.type = parenthesizer().parenthesizeElementTypeOfArrayType(type)); + return finishNode(node); } + // @api function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode { return node.type !== type ? updateNode(createOptionalTypeNode(type), node) - : node; + : reuseNode(node); } + // @api function createRestTypeNode(type: TypeNode) { - const node = createNode(SyntaxKind.RestType) as RestTypeNode; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.RestType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode { return node.type !== type ? updateNode(createRestTypeNode(type), node) - : node; - } - - function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types); - } - - function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types); - } - - function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types); - } - - function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types); + : reuseNode(node); } function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) { - const node = createNode(kind) as UnionTypeNode | IntersectionTypeNode; - node.types = parenthesizer().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types)); - return node; + const node = createBaseNode(kind); + setChildren(node, node.types = parenthesizer().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types))); + return finishNode(node); } function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray): T { return node.types !== types ? updateNode(createUnionOrIntersectionTypeNode(node.kind, types), node) - : node; + : reuseNode(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 = createNode(SyntaxKind.ConditionalType) as ConditionalTypeNode; - node.checkType = parenthesizer().parenthesizeMemberOfConditionalType(checkType); - node.extendsType = parenthesizer().parenthesizeMemberOfConditionalType(extendsType); - node.trueType = trueType; - node.falseType = falseType; - return node; + const node = createBaseNode(SyntaxKind.ConditionalType); + setChild(node, node.checkType = parenthesizer().parenthesizeMemberOfConditionalType(checkType)); + setChild(node, node.extendsType = parenthesizer().parenthesizeMemberOfConditionalType(extendsType)); + setChild(node, node.trueType = trueType); + setChild(node, node.falseType = falseType); + return finishNode(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 ? updateNode(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node) - : node; + : reuseNode(node); } + // @api function createInferTypeNode(typeParameter: TypeParameterDeclaration) { - const node = createNode(SyntaxKind.InferType) as InferTypeNode; - node.typeParameter = typeParameter; - return node; + const node = createBaseNode(SyntaxKind.InferType); + setChild(node, node.typeParameter = typeParameter); + return finishNode(node); } + // @api function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) { return node.typeParameter !== typeParameter ? updateNode(createInferTypeNode(typeParameter), node) - : node; + : reuseNode(node); } + // @api function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean) { - const node = createNode(SyntaxKind.ImportType) as ImportTypeNode; - node.argument = argument; - node.qualifier = qualifier; - node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments)); + const node = createBaseNode(SyntaxKind.ImportType); + setChild(node, node.argument = argument); + setChild(node, node.qualifier = qualifier); + setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); node.isTypeOf = isTypeOf; - return node; + return finishNode(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 ? updateNode(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node) - : node; + : reuseNode(node); } + // @api function createParenthesizedType(type: TypeNode) { - const node = createNode(SyntaxKind.ParenthesizedType) as ParenthesizedTypeNode; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.ParenthesizedType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) { return node.type !== type ? updateNode(createParenthesizedType(type), node) - : node; + : reuseNode(node); } + // @api function createThisTypeNode() { - return createNode(SyntaxKind.ThisType) as ThisTypeNode; + return finishNode(createBaseNode(SyntaxKind.ThisType)); } + // @api function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode { - const node = createNode(SyntaxKind.TypeOperator) as TypeOperatorNode; + const node = createBaseNode(SyntaxKind.TypeOperator); node.operator = operator; - node.type = parenthesizer().parenthesizeMemberOfElementType(type); - return node; + setChild(node, node.type = parenthesizer().parenthesizeMemberOfElementType(type)); + return finishNode(node); } + // @api function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) { return node.type !== type ? updateNode(createTypeOperatorNode(node.operator, type), node) - : node; + : reuseNode(node); } + // @api function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { - const node = createNode(SyntaxKind.IndexedAccessType) as IndexedAccessTypeNode; - node.objectType = parenthesizer().parenthesizeMemberOfElementType(objectType); - node.indexType = indexType; - return node; + const node = createBaseNode(SyntaxKind.IndexedAccessType); + setChild(node, node.objectType = parenthesizer().parenthesizeMemberOfElementType(objectType)); + setChild(node, node.indexType = indexType); + return finishNode(node); } + // @api function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { return node.objectType !== objectType || node.indexType !== indexType ? updateNode(createIndexedAccessTypeNode(objectType, indexType), node) - : node; + : reuseNode(node); } + // @api function createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { - const node = createNode(SyntaxKind.MappedType) as MappedTypeNode; - node.readonlyToken = readonlyToken; - node.typeParameter = typeParameter; - node.questionToken = questionToken; - node.type = type; - return node; + 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); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { - const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode; - node.literal = literal; - return node; + const node = createBaseNode(SyntaxKind.LiteralType); + setChild(node, node.literal = literal); + return finishNode(node); } + // @api function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) { return node.literal !== literal ? updateNode(createLiteralTypeNode(literal), node) - : node; + : reuseNode(node); } // // Binding Patterns // + // @api function createObjectBindingPattern(elements: readonly BindingElement[]) { - const node = createNode(SyntaxKind.ObjectBindingPattern) as ObjectBindingPattern; - node.elements = createNodeArray(elements); - return node; + const node = createBaseNode(SyntaxKind.ObjectBindingPattern); + setChildren(node, node.elements = createNodeArray(elements)); + return finishNode(node); } + // @api function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { return node.elements !== elements ? updateNode(createObjectBindingPattern(elements), node) - : node; + : reuseNode(node); } + // @api function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { - const node = createNode(SyntaxKind.ArrayBindingPattern) as ArrayBindingPattern; - node.elements = createNodeArray(elements); - return node; + const node = createBaseNode(SyntaxKind.ArrayBindingPattern); + setChildren(node, node.elements = createNodeArray(elements)); + return finishNode(node); } + // @api function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { return node.elements !== elements ? updateNode(createArrayBindingPattern(elements), node) - : node; + : reuseNode(node); } + // @api function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { const node = createBaseNamedDeclaration( SyntaxKind.BindingElement, @@ -1418,171 +1778,173 @@ namespace ts { /*modifiers*/ undefined, name ); - node.propertyName = asName(propertyName); - node.initializer = initializer; - node.dotDotDotToken = dotDotDotToken; - return node; + setChild(node, node.propertyName = asName(propertyName)); + setChild(node, node.initializer = initializer); + setChild(node, node.dotDotDotToken = dotDotDotToken); + return finishNode(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 ? updateNode(createBindingElement(dotDotDotToken, propertyName, name, initializer), node) - : node; + : reuseNode(node); } // // Expression // - function createArrayLiteral(elements?: readonly Expression[], multiLine?: boolean) { - const node = createNode(SyntaxKind.ArrayLiteralExpression) as ArrayLiteralExpression; - node.elements = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements)); + // @api + function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) { + const node = createBaseNode(SyntaxKind.ArrayLiteralExpression); + setChildren(node, node.elements = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements))); if (multiLine) node.multiLine = true; - return node; + return finishNode(node); } - function updateArrayLiteral(node: ArrayLiteralExpression, elements: readonly Expression[]) { + // @api + function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) { return node.elements !== elements - ? updateNode(createArrayLiteral(elements, node.multiLine), node) - : node; + ? updateNode(createArrayLiteralExpression(elements, node.multiLine), node) + : reuseNode(node); } - function createObjectLiteral(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { - const node = createNode(SyntaxKind.ObjectLiteralExpression) as ObjectLiteralExpression; - node.properties = createNodeArray(properties); + // @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 node; + return finishNode(node); } - function updateObjectLiteral(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { + // @api + function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { return node.properties !== properties - ? updateNode(createObjectLiteral(properties, node.multiLine), node) - : node; + ? updateNode(createObjectLiteralExpression(properties, node.multiLine), node) + : reuseNode(node); } - function createPropertyAccess(expression: Expression, name: string | Identifier) { - const node = createNode(SyntaxKind.PropertyAccessExpression) as PropertyAccessExpression; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - node.name = asName(name); - return node; + // @api + function createPropertyAccessExpression(expression: Expression, name: string | Identifier) { + const node = createBaseNode(SyntaxKind.PropertyAccessExpression); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.name = asName(name)); + return finishNode(node); } - function createPropertyAccessSynthesized(expression: Expression, name: string | Identifier) { - return setEmitFlags(createPropertyAccess(expression, name), EmitFlags.NoIndentation); - } - - // This function lazily chooses which `createPropertyAccess` implementation to use for future calls. This helps to avoid - // the overhead of the `if` check when its not needed. - function createPropertyAccessUnspecific(expression: Expression, name: string | Identifier) { - const node = createPropertyAccess(expression, name); - if (node.flags & NodeFlags.Synthesized) { - setEmitFlags(node, EmitFlags.NoIndentation); - actualCreatePropertyAccess = createPropertyAccessSynthesized; - } - else { - actualCreatePropertyAccess = createPropertyAccess; - } - return node; - } - - function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) { + // @api + function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier) { return node.expression !== expression || node.name !== name - ? updateNode(createPropertyAccess(expression, name), node) - : node; + ? updateNode(createPropertyAccessExpression(expression, name), node) + : reuseNode(node); } - function createElementAccess(expression: Expression, index: number | Expression) { - const node = createNode(SyntaxKind.ElementAccessExpression) as ElementAccessExpression; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - node.argumentExpression = asExpression(index); - return node; + // @api + function createElementAccessExpression(expression: Expression, index: number | Expression) { + const node = createBaseNode(SyntaxKind.ElementAccessExpression); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.argumentExpression = asExpression(index)); + return finishNode(node); } - function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { + // @api + function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { return node.expression !== expression || node.argumentExpression !== argumentExpression - ? updateNode(createElementAccess(expression, argumentExpression), node) - : node; + ? updateNode(createElementAccessExpression(expression, argumentExpression), node) + : reuseNode(node); } - function createCall(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createNode(SyntaxKind.CallExpression) as CallExpression; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - node.typeArguments = asNodeArray(typeArguments); - node.arguments = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); - return node; + // @api + function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseNode(SyntaxKind.CallExpression); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChildren(node, node.arguments = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); + return finishNode(node); } - function updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + // @api + function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { return node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray - ? updateNode(createCall(expression, typeArguments, argumentsArray), node) - : node; + ? updateNode(createCallExpression(expression, typeArguments, argumentsArray), node) + : reuseNode(node); } - function createNew(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createNode(SyntaxKind.NewExpression) as NewExpression; - node.expression = parenthesizer().parenthesizeExpressionOfNew(expression); - node.typeArguments = asNodeArray(typeArguments); - node.arguments = argumentsArray ? parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) : undefined; - return node; + // @api + function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseNode(SyntaxKind.NewExpression); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfNew(expression)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChildren(node, node.arguments = argumentsArray ? parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) : undefined); + return finishNode(node); } - function updateNew(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + // @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 - ? updateNode(createNew(expression, typeArguments, argumentsArray), node) - : node; + ? updateNode(createNewExpression(expression, typeArguments, argumentsArray), node) + : reuseNode(node); } - function createTaggedTemplate(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { - const node = createNode(SyntaxKind.TaggedTemplateExpression) as TaggedTemplateExpression; - node.tag = parenthesizer().parenthesizeLeftSideOfAccess(tag); - node.typeArguments = asNodeArray(typeArguments); - node.template = template; - return node; + // @api + function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + const node = createBaseNode(SyntaxKind.TaggedTemplateExpression); + setChild(node, node.tag = parenthesizer().parenthesizeLeftSideOfAccess(tag)); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.template = template); + return finishNode(node); } - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + // @api + function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { return node.tag !== tag || node.typeArguments !== typeArguments || node.template !== template - ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) - : node; + ? updateNode(createTaggedTemplateExpression(tag, typeArguments, template), node) + : reuseNode(node); } + // @api function createTypeAssertion(type: TypeNode, expression: Expression) { - const node = createNode(SyntaxKind.TypeAssertionExpression) as TypeAssertion; - node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression); - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.TypeAssertionExpression); + setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { return node.type !== type || node.expression !== expression ? updateNode(createTypeAssertion(type, expression), node) - : node; + : reuseNode(node); } - function createParen(expression: Expression) { - const node = createNode(SyntaxKind.ParenthesizedExpression) as ParenthesizedExpression; - node.expression = expression; - return node; + // @api + function createParenthesizedExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.ParenthesizedExpression); + setChild(node, node.expression = expression); + return finishNode(node); } - function updateParen(node: ParenthesizedExpression, expression: Expression) { + // @api + function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createParen(expression), node) - : node; + ? updateNode(createParenthesizedExpression(expression), node) + : reuseNode(node); } + // @api function createFunctionExpression( modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, @@ -1592,17 +1954,20 @@ namespace ts { type: TypeNode | undefined, body: Block ) { - const node = createNode(SyntaxKind.FunctionExpression) as 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; + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionExpression, + /*decorators*/ undefined, + modifiers, + name, + typeParameters, + parameters, + type, + body); + setChild(node, node.asteriskToken = asteriskToken); + return finishNode(node); } + // @api function updateFunctionExpression( node: FunctionExpression, modifiers: readonly Modifier[] | undefined, @@ -1620,8 +1985,31 @@ namespace ts { || node.parameters !== parameters || node.type !== type || node.body !== body - ? updateNode(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + : reuseNode(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, + parenthesizer().parenthesizeConciseBodyOfArrowFunction(body) + ); + setChild(node, node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken)); + return finishNode(node); } function createArrowFunctionWithoutTokens( @@ -1631,53 +2019,7 @@ namespace ts { type: TypeNode | undefined, body: ConciseBody ) { - return createArrowFunctionWithTokens(modifiers, typeParameters, parameters, type, createToken(SyntaxKind.EqualsGreaterThanToken), body); - } - - function createArrowFunctionWithTokens( - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken | undefined, - body: ConciseBody - ) { - const node = createNode(SyntaxKind.ArrowFunction) as ArrowFunction; - node.modifiers = asNodeArray(modifiers); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken); - node.body = parenthesizer().parenthesizeConciseBodyOfArrowFunction(body); - return node; - } - - function createArrowFunction( - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: ConciseBody - ): ArrowFunction; - function createArrowFunction( - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken, - body: ConciseBody - ): ArrowFunction; - function createArrowFunction( - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken | ConciseBody, - body?: ConciseBody - ) { - return arguments.length === 6 ? createArrowFunctionWithTokens(modifiers, typeParameters, parameters, type, equalsGreaterThanToken as EqualsGreaterThanToken, body!) : - arguments.length === 5 ? createArrowFunctionWithoutTokens(modifiers, typeParameters, parameters, type, body!) : - Debug.fail("Incorrect argument count"); + return createArrowFunction(modifiers, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, body); } function updateArrowFunctionWithoutTokens( @@ -1688,10 +2030,11 @@ namespace ts { type: TypeNode | undefined, body: ConciseBody ): ArrowFunction { - return updateArrowFunctionWithTokens(node, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body); + return updateArrowFunction(node, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body); } - function updateArrowFunctionWithTokens( + // @api + function updateArrowFunction( node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, @@ -1706,164 +2049,132 @@ namespace ts { || node.type !== type || node.equalsGreaterThanToken !== equalsGreaterThanToken || node.body !== body - ? updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) + : reuseNode(node); } - function updateArrowFunction( - node: ArrowFunction, - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - body: ConciseBody - ): ArrowFunction; - function updateArrowFunction( - node: ArrowFunction, - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken, - body: ConciseBody - ): ArrowFunction; - function updateArrowFunction( - node: ArrowFunction, - modifiers: readonly Modifier[] | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined, - equalsGreaterThanToken: EqualsGreaterThanToken | ConciseBody, - body?: ConciseBody - ): ArrowFunction { - return arguments.length === 7 ? updateArrowFunctionWithTokens(node, modifiers, typeParameters, parameters, type, equalsGreaterThanToken as EqualsGreaterThanToken, body!) : - arguments.length === 6 ? updateArrowFunctionWithoutTokens(node, modifiers, typeParameters, parameters, type, body!) : - Debug.fail("Incorrect argument count"); + // @api + function createDeleteExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.DeleteExpression); + setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + return finishNode(node); } - function createDelete(expression: Expression) { - const node = createNode(SyntaxKind.DeleteExpression) as DeleteExpression; - node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression); - return node; - } - - function updateDelete(node: DeleteExpression, expression: Expression) { + // @api + function updateDeleteExpression(node: DeleteExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createDelete(expression), node) - : node; + ? updateNode(createDeleteExpression(expression), node) + : reuseNode(node); } - function createTypeOf(expression: Expression) { - const node = createNode(SyntaxKind.TypeOfExpression) as TypeOfExpression; - node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression); - return node; + // @api + function createTypeOfExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.TypeOfExpression); + setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + return finishNode(node); } - function updateTypeOf(node: TypeOfExpression, expression: Expression) { + // @api + function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createTypeOf(expression), node) - : node; + ? updateNode(createTypeOfExpression(expression), node) + : reuseNode(node); } - function createVoid(expression: Expression) { - const node = createNode(SyntaxKind.VoidExpression) as VoidExpression; - node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression); - return node; + // @api + function createVoidExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.VoidExpression); + setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + return finishNode(node); } - function updateVoid(node: VoidExpression, expression: Expression) { + // @api + function updateVoidExpression(node: VoidExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createVoid(expression), node) - : node; + ? updateNode(createVoidExpression(expression), node) + : reuseNode(node); } - function createAwait(expression: Expression) { - const node = createNode(SyntaxKind.AwaitExpression) as AwaitExpression; - node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression); - return node; + // @api + function createAwaitExpression(expression: Expression) { + const node = createBaseNode(SyntaxKind.AwaitExpression); + setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + return finishNode(node); } - function updateAwait(node: AwaitExpression, expression: Expression) { + // @api + function updateAwaitExpression(node: AwaitExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createAwait(expression), node) - : node; + ? updateNode(createAwaitExpression(expression), node) + : reuseNode(node); } - function createPrefix(operator: PrefixUnaryOperator, operand: Expression) { - const node = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression; + // @api + function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { + const node = createBaseNode(SyntaxKind.PrefixUnaryExpression); node.operator = operator; - node.operand = parenthesizer().parenthesizeOperandOfPrefixUnary(operand); - return node; + setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPrefixUnary(operand)); + return finishNode(node); } - function updatePrefix(node: PrefixUnaryExpression, operand: Expression) { + // @api + function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) { return node.operand !== operand - ? updateNode(createPrefix(node.operator, operand), node) - : node; + ? updateNode(createPrefixUnaryExpression(node.operator, operand), node) + : reuseNode(node); } - function createPostfix(operand: Expression, operator: PostfixUnaryOperator) { - const node = createNode(SyntaxKind.PostfixUnaryExpression) as PostfixUnaryExpression; - node.operand = parenthesizer().parenthesizeOperandOfPostfixUnary(operand); + // @api + function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { + const node = createBaseNode(SyntaxKind.PostfixUnaryExpression); node.operator = operator; - return node; + setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPostfixUnary(operand)); + return finishNode(node); } - function updatePostfix(node: PostfixUnaryExpression, operand: Expression) { + // @api + function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) { return node.operand !== operand - ? updateNode(createPostfix(operand, node.operator), node) - : node; + ? updateNode(createPostfixUnaryExpression(operand, node.operator), node) + : reuseNode(node); } - function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { - const node = createNode(SyntaxKind.BinaryExpression) as BinaryExpression; + // @api + function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { + const node = createBaseNode(SyntaxKind.BinaryExpression); const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; - node.left = parenthesizer().parenthesizeLeftSideOfBinary(operatorKind, left); - node.operatorToken = operatorToken; - node.right = parenthesizer().parenthesizeRightSideOfBinary(operatorKind, node.left, right); - return node; + setChild(node, node.left = parenthesizer().parenthesizeLeftSideOfBinary(operatorKind, left)); + setChild(node, node.operatorToken = operatorToken); + setChild(node, node.right = parenthesizer().parenthesizeRightSideOfBinary(operatorKind, node.left, right)); + return finishNode(node); } - function updateBinary(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken) { + // @api + function updateBinaryExpression(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; + ? updateNode(createBinaryExpression(left, operator || node.operatorToken, right), node) + : reuseNode(node); } - function createConditionalWithoutTokens(condition: Expression, whenTrue: Expression, whenFalse: Expression) { - return createConditionalWithTokens(condition, createQuestionToken(), whenTrue, createColonToken(), whenFalse); + // @api + function createConditionalExpression(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression) { + const node = createBaseNode(SyntaxKind.ConditionalExpression); + setChild(node, node.condition = parenthesizer().parenthesizeConditionOfConditionalExpression(condition)); + setChild(node, node.questionToken = questionToken); + setChild(node, node.whenTrue = parenthesizer().parenthesizeBranchOfConditionalExpression(whenTrue)); + setChild(node, node.colonToken = colonToken); + setChild(node, node.whenFalse = parenthesizer().parenthesizeBranchOfConditionalExpression(whenFalse)); + return finishNode(node); } - function createConditionalWithTokens(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression) { - const node = createNode(SyntaxKind.ConditionalExpression) as ConditionalExpression; - node.condition = parenthesizer().parenthesizeConditionOfConditionalExpression(condition); - node.questionToken = questionToken; - node.whenTrue = parenthesizer().parenthesizeBranchOfConditionalExpression(whenTrue); - node.colonToken = colonToken; - node.whenFalse = parenthesizer().parenthesizeBranchOfConditionalExpression(whenFalse); - return node; + function createConditionalExpressionWithoutTokens(condition: Expression, whenTrue: Expression, whenFalse: Expression) { + return createConditionalExpression(condition, createToken(SyntaxKind.QuestionToken), whenTrue, createToken(SyntaxKind.ColonToken), whenFalse); } - function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; - function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; - function createConditional(condition: Expression, questionToken: QuestionToken | Expression, whenTrue: Expression, colonToken?: ColonToken, whenFalse?: Expression) { - return arguments.length === 3 ? createConditionalWithoutTokens(condition, questionToken as Expression, whenTrue) : - arguments.length === 5 ? createConditionalWithTokens(condition, questionToken as QuestionToken, whenTrue, colonToken!, whenFalse!) : - Debug.fail("Incorrect argument count"); - } - - function updateConditionalWithoutTokens( - node: ConditionalExpression, - condition: Expression, - whenTrue: Expression, - whenFalse: Expression - ): ConditionalExpression { - return updateConditionalWithTokens(node, condition, node.questionToken, whenTrue, node.colonToken, whenFalse); - } - - function updateConditionalWithTokens( + // @api + function updateConditionalExpression( node: ConditionalExpression, condition: Expression, questionToken: Token, @@ -1876,30 +2187,33 @@ namespace ts { || node.whenTrue !== whenTrue || node.colonToken !== colonToken || node.whenFalse !== whenFalse - ? updateNode(createConditionalWithTokens(condition, questionToken, whenTrue, colonToken, whenFalse), node) - : node; + ? updateNode(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node) + : reuseNode(node); } - function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; - function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; - function updateConditional(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken | Expression, whenTrue: Expression, colonToken?: ColonToken, whenFalse?: Expression) { - return arguments.length === 4 ? updateConditionalWithoutTokens(node, condition, questionToken as Expression, whenTrue) : - arguments.length === 6 ? updateConditionalWithTokens(node, condition, questionToken as QuestionToken, whenTrue, colonToken!, whenFalse!) : - Debug.fail("Incorrect argument count"); + function updateConditionalExpressionWithoutTokens( + node: ConditionalExpression, + condition: Expression, + whenTrue: Expression, + whenFalse: Expression + ): ConditionalExpression { + return updateConditionalExpression(node, condition, node.questionToken, whenTrue, node.colonToken, whenFalse); } + // @api function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { - const node = createNode(SyntaxKind.TemplateExpression) as TemplateExpression; - node.head = head; - node.templateSpans = createNodeArray(templateSpans); - return node; + const node = createBaseNode(SyntaxKind.TemplateExpression); + setChild(node, node.head = head); + setChildren(node, node.templateSpans = createNodeArray(templateSpans)); + return finishNode(node); } + // @api function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { return node.head !== head || node.templateSpans !== templateSpans ? updateNode(createTemplateExpression(head, templateSpans), node) - : node; + : reuseNode(node); } function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined) { @@ -1923,56 +2237,66 @@ namespace ts { return createTemplateLiteralLikeNode(kind, text, rawText); } + // @api function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined) { - const node = createNode(kind) as TemplateLiteralLikeNode; + const node = createBaseNode(kind); node.text = text; node.rawText = rawText; - return node; + return finishNode(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); } - function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { + // @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 = createNode(SyntaxKind.YieldExpression) as YieldExpression; - node.expression = expression; - node.asteriskToken = asteriskToken; - return node; + const node = createBaseNode(SyntaxKind.YieldExpression); + setChild(node, node.expression = expression); + setChild(node, node.asteriskToken = asteriskToken); + return finishNode(node); } - function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { + // @api + function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { return node.expression !== expression || node.asteriskToken !== asteriskToken - ? updateNode(createYield(asteriskToken, expression), node) - : node; + ? updateNode(createYieldExpression(asteriskToken, expression), node) + : reuseNode(node); } - function createSpread(expression: Expression) { - const node = createNode(SyntaxKind.SpreadElement) as SpreadElement; - node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression); - return node; + // @api + function createSpreadElement(expression: Expression) { + const node = createBaseNode(SyntaxKind.SpreadElement); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + return finishNode(node); } - function updateSpread(node: SpreadElement, expression: Expression) { + // @api + function updateSpreadElement(node: SpreadElement, expression: Expression) { return node.expression !== expression - ? updateNode(createSpread(expression), node) - : node; + ? updateNode(createSpreadElement(expression), node) + : reuseNode(node); } + // @api function createClassExpression( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -1981,14 +2305,19 @@ namespace ts { heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - const node: ClassExpression = createBaseDeclaration(SyntaxKind.ClassExpression, asNodeArray(decorators), asNodeArray(modifiers)); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassExpression, + decorators, + modifiers, + name, + typeParameters, + heritageClauses, + members + ); + return finishNode(node); } + // @api function updateClassExpression( node: ClassExpression, decorators: readonly Decorator[] | undefined, @@ -2005,369 +2334,436 @@ namespace ts { || node.heritageClauses !== heritageClauses || node.members !== members ? updateNode(createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : node; + : reuseNode(node); } + // @api function createOmittedExpression() { - return createNode(SyntaxKind.OmittedExpression) as OmittedExpression; + return finishNode(createBaseNode(SyntaxKind.OmittedExpression)); } + // @api function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) { - const node = createNode(SyntaxKind.ExpressionWithTypeArguments) as ExpressionWithTypeArguments; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(typeArguments); - return node; + const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(typeArguments)); + return finishNode(node); } + // @api function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) { return node.expression !== expression || node.typeArguments !== typeArguments ? updateNode(createExpressionWithTypeArguments(expression, typeArguments), node) - : node; + : reuseNode(node); } + // @api function createAsExpression(expression: Expression, type: TypeNode) { - const node = createNode(SyntaxKind.AsExpression) as AsExpression; - node.expression = expression; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.AsExpression); + setChild(node, node.expression = expression); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { return node.expression !== expression || node.type !== type ? updateNode(createAsExpression(expression, type), node) - : node; + : reuseNode(node); } + // @api function createNonNullExpression(expression: Expression) { - const node = createNode(SyntaxKind.NonNullExpression) as NonNullExpression; - node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression); - return node; + const node = createBaseNode(SyntaxKind.NonNullExpression); + setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + return finishNode(node); } + // @api function updateNonNullExpression(node: NonNullExpression, expression: Expression) { return node.expression !== expression ? updateNode(createNonNullExpression(expression), node) - : node; + : reuseNode(node); } + // @api function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { - const node = createNode(SyntaxKind.MetaProperty) as MetaProperty; + const node = createBaseNode(SyntaxKind.MetaProperty); node.keywordToken = keywordToken; - node.name = name; - return node; + setChild(node, node.name = name); + return finishNode(node); } + // @api function updateMetaProperty(node: MetaProperty, name: Identifier) { return node.name !== name ? updateNode(createMetaProperty(node.keywordToken, name), node) - : node; + : reuseNode(node); } // // Misc // + // @api function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { - const node = createNode(SyntaxKind.TemplateSpan) as TemplateSpan; - node.expression = expression; - node.literal = literal; - return node; + const node = createBaseNode(SyntaxKind.TemplateSpan); + setChild(node, node.expression = expression); + setChild(node, node.literal = literal); + return finishNode(node); } + // @api function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { return node.expression !== expression || node.literal !== literal ? updateNode(createTemplateSpan(expression, literal), node) - : node; + : reuseNode(node); } + // @api function createSemicolonClassElement() { - return createNode(SyntaxKind.SemicolonClassElement) as SemicolonClassElement; + return finishNode(createBaseNode(SyntaxKind.SemicolonClassElement)); } // // Element // + // @api function createBlock(statements: readonly Statement[], multiLine?: boolean): Block { - const node = createNode(SyntaxKind.Block) as Block; - node.statements = createNodeArray(statements); + const node = createBaseNode(SyntaxKind.Block); + setChildren(node, node.statements = createNodeArray(statements)); if (multiLine) node.multiLine = multiLine; - return node; + return finishNode(node); } + // @api function updateBlock(node: Block, statements: readonly Statement[]) { return node.statements !== statements ? updateNode(createBlock(statements, node.multiLine), node) - : node; + : reuseNode(node); } + // @api function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { - const node: VariableStatement = createBaseDeclaration(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers); - node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; - return node; + const node = createBaseDeclaration(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers); + setChild(node, node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList); + return finishNode(node); } + // @api function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) { return node.modifiers !== modifiers || node.declarationList !== declarationList ? updateNode(createVariableStatement(modifiers, declarationList), node) - : node; + : reuseNode(node); } + // @api function createEmptyStatement() { - return createNode(SyntaxKind.EmptyStatement) as EmptyStatement; + return finishNode(createBaseNode(SyntaxKind.EmptyStatement)); } + // @api function createExpressionStatement(expression: Expression): ExpressionStatement { - const node = createNode(SyntaxKind.ExpressionStatement) as ExpressionStatement; - node.expression = parenthesizer().parenthesizeExpressionOfExpressionStatement(expression); - return node; + const node = createBaseNode(SyntaxKind.ExpressionStatement); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfExpressionStatement(expression)); + return finishNode(node); } + // @api function updateExpressionStatement(node: ExpressionStatement, expression: Expression) { return node.expression !== expression ? updateNode(createExpressionStatement(expression), node) - : node; + : reuseNode(node); } - function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { - const node = createNode(SyntaxKind.IfStatement) as IfStatement; - node.expression = expression; - node.thenStatement = asEmbeddedStatement(thenStatement); - node.elseStatement = asEmbeddedStatement(elseStatement); - return 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 finishNode(node); } - function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) { + // @api + function updateIfStatement(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; + ? updateNode(createIfStatement(expression, thenStatement, elseStatement), node) + : reuseNode(node); } - function createDo(statement: Statement, expression: Expression) { - const node = createNode(SyntaxKind.DoStatement) as DoStatement; - node.statement = asEmbeddedStatement(statement); - node.expression = expression; - return 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 finishNode(node); } - function updateDo(node: DoStatement, statement: Statement, expression: Expression) { + // @api + function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) { return node.statement !== statement || node.expression !== expression - ? updateNode(createDo(statement, expression), node) - : node; + ? updateNode(createDoStatement(statement, expression), node) + : reuseNode(node); } - function createWhile(expression: Expression, statement: Statement) { - const node = createNode(SyntaxKind.WhileStatement) as WhileStatement; - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return 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 finishNode(node); } - function updateWhile(node: WhileStatement, expression: Expression, statement: Statement) { + // @api + function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement - ? updateNode(createWhile(expression, statement), node) - : node; + ? updateNode(createWhileStatement(expression, statement), node) + : reuseNode(node); } - function createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { - const node = createNode(SyntaxKind.ForStatement) as ForStatement; - node.initializer = initializer; - node.condition = condition; - node.incrementor = incrementor; - node.statement = asEmbeddedStatement(statement); - return 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 finishNode(node); } - function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + // @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 - ? updateNode(createFor(initializer, condition, incrementor, statement), node) - : node; + ? updateNode(createForStatement(initializer, condition, incrementor, statement), node) + : reuseNode(node); } - function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement) { - const node = createNode(SyntaxKind.ForInStatement) as ForInStatement; - node.initializer = initializer; - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return 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 finishNode(node); } - function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { + // @api + function updateForInStatement(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; + ? updateNode(createForInStatement(initializer, expression, statement), node) + : reuseNode(node); } - function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { - const node = createNode(SyntaxKind.ForOfStatement) as ForOfStatement; - node.awaitModifier = awaitModifier; - node.initializer = initializer; - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return node; + // @api + function createForOfStatement(awaitModifier: AwaitKeywordToken | 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 = expression); + setChild(node, node.statement = asEmbeddedStatement(statement)); + return finishNode(node); } - function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + // @api + function updateForOfStatement(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; + ? updateNode(createForOfStatement(awaitModifier, initializer, expression, statement), node) + : reuseNode(node); } - function createContinue(label?: string | Identifier): ContinueStatement { - const node = createNode(SyntaxKind.ContinueStatement) as ContinueStatement; - node.label = asName(label); - return node; + // @api + function createContinueStatement(label?: string | Identifier): ContinueStatement { + const node = createBaseNode(SyntaxKind.ContinueStatement); + setChild(node, node.label = asName(label)); + return finishNode(node); } - function updateContinue(node: ContinueStatement, label: Identifier | undefined) { + // @api + function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) { return node.label !== label - ? updateNode(createContinue(label), node) - : node; + ? updateNode(createContinueStatement(label), node) + : reuseNode(node); } - function createBreak(label?: string | Identifier): BreakStatement { - const node = createNode(SyntaxKind.BreakStatement) as BreakStatement; - node.label = asName(label); - return node; + // @api + function createBreakStatement(label?: string | Identifier): BreakStatement { + const node = createBaseNode(SyntaxKind.BreakStatement); + setChild(node, node.label = asName(label)); + return finishNode(node); } - function updateBreak(node: BreakStatement, label: Identifier | undefined) { + // @api + function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) { return node.label !== label - ? updateNode(createBreak(label), node) - : node; + ? updateNode(createBreakStatement(label), node) + : reuseNode(node); } - function createReturn(expression?: Expression): ReturnStatement { - const node = createNode(SyntaxKind.ReturnStatement) as ReturnStatement; - node.expression = expression; - return node; + // @api + function createReturnStatement(expression?: Expression): ReturnStatement { + const node = createBaseNode(SyntaxKind.ReturnStatement); + setChild(node, node.expression = expression); + return finishNode(node); } - function updateReturn(node: ReturnStatement, expression: Expression | undefined) { + // @api + function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) { return node.expression !== expression - ? updateNode(createReturn(expression), node) - : node; + ? updateNode(createReturnStatement(expression), node) + : reuseNode(node); } - function createWith(expression: Expression, statement: Statement) { - const node = createNode(SyntaxKind.WithStatement) as WithStatement; - node.expression = expression; - node.statement = asEmbeddedStatement(statement); - return 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 finishNode(node); } - function updateWith(node: WithStatement, expression: Expression, statement: Statement) { + // @api + function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement - ? updateNode(createWith(expression, statement), node) - : node; + ? updateNode(createWithStatement(expression, statement), node) + : reuseNode(node); } - function createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement { - const node = createNode(SyntaxKind.SwitchStatement) as SwitchStatement; - node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression); - node.caseBlock = caseBlock; - return node; + // @api + function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement { + const node = createBaseNode(SyntaxKind.SwitchStatement); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.caseBlock = caseBlock); + return finishNode(node); } - function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { + // @api + function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { return node.expression !== expression || node.caseBlock !== caseBlock - ? updateNode(createSwitch(expression, caseBlock), node) - : node; + ? updateNode(createSwitchStatement(expression, caseBlock), node) + : reuseNode(node); } - function createLabel(label: string | Identifier, statement: Statement) { - const node = createNode(SyntaxKind.LabeledStatement) as LabeledStatement; - node.label = asName(label); - node.statement = asEmbeddedStatement(statement); - return 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 finishNode(node); } - function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement) { + // @api + function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) { return node.label !== label || node.statement !== statement - ? updateNode(createLabel(label, statement), node) - : node; + ? updateNode(createLabeledStatement(label, statement), node) + : reuseNode(node); } - function createThrow(expression: Expression) { - const node = createNode(SyntaxKind.ThrowStatement) as ThrowStatement; - node.expression = expression; - return node; + // @api + function createThrowStatement(expression: Expression) { + const node = createBaseNode(SyntaxKind.ThrowStatement); + setChild(node, node.expression = expression); + return finishNode(node); } - function updateThrow(node: ThrowStatement, expression: Expression) { + // @api + function updateThrowStatement(node: ThrowStatement, expression: Expression) { return node.expression !== expression - ? updateNode(createThrow(expression), node) - : node; + ? updateNode(createThrowStatement(expression), node) + : reuseNode(node); } - function createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { - const node = createNode(SyntaxKind.TryStatement) as TryStatement; - node.tryBlock = tryBlock; - node.catchClause = catchClause; - node.finallyBlock = finallyBlock; - return 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 finishNode(node); } - function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + // @api + function updateTryStatement(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; + ? updateNode(createTryStatement(tryBlock, catchClause, finallyBlock), node) + : reuseNode(node); } + // @api function createDebuggerStatement() { - return createNode(SyntaxKind.DebuggerStatement) as DebuggerStatement; + return finishNode(createBaseNode(SyntaxKind.DebuggerStatement)); } - function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression) { - const node = createNode(SyntaxKind.VariableDeclaration) as VariableDeclaration; - node.name = asName(name); - node.type = type; - node.initializer = initializer !== undefined ? parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) : undefined; - return node; + // @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 && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) + ); + setChild(node, node.exclamationToken = exclamationToken); + return finishNode(node); } - function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) { + function createVariableDeclarationWithoutTokens(name: string | BindingName, type?: TypeNode, initializer?: Expression) { + return createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer); + } + + // @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 - ? updateNode(createVariableDeclaration(name, type, initializer), node) - : node; + ? updateNode(createVariableDeclaration(name, exclamationToken, type, initializer), node) + : reuseNode(node); } + function updateVariableDeclarationWithoutTokens(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) { + return updateVariableDeclaration(node, name, node.exclamationToken, type, initializer); + } + + // @api function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) { - const node = createNode(SyntaxKind.VariableDeclarationList) as VariableDeclarationList; + const node = createBaseNode(SyntaxKind.VariableDeclarationList); node.flags |= flags & NodeFlags.BlockScoped; - node.declarations = createNodeArray(declarations); - return node; + setChildren(node, node.declarations = createNodeArray(declarations)); + return finishNode(node); } + // @api function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { return node.declarations !== declarations ? updateNode(createVariableDeclarationList(declarations, node.flags), node) - : node; + : reuseNode(node); } + // @api function createFunctionDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -2378,16 +2774,21 @@ namespace ts { type: TypeNode | undefined, body: Block | undefined ) { - const node: FunctionDeclaration = createBaseDeclaration(SyntaxKind.FunctionDeclaration, decorators, modifiers); - node.asteriskToken = asteriskToken; - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - node.body = body; - return node; + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionDeclaration, + decorators, + modifiers, + name, + typeParameters, + parameters, + type, + body + ); + setChild(node, node.asteriskToken = asteriskToken); + return finishNode(node); } + // @api function updateFunctionDeclaration( node: FunctionDeclaration, decorators: readonly Decorator[] | undefined, @@ -2407,10 +2808,11 @@ namespace ts { || node.parameters !== parameters || node.type !== type || node.body !== body - ? updateNode(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : node; + ? updateBaseFunctionLikeDeclaration(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + : reuseNode(node); } + // @api function createClassDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -2419,14 +2821,19 @@ namespace ts { heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - const node: ClassDeclaration = createBaseDeclaration(SyntaxKind.ClassDeclaration, decorators, modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassDeclaration, + decorators, + modifiers, + name, + typeParameters, + heritageClauses, + members + ); + return finishNode(node); } + // @api function updateClassDeclaration( node: ClassDeclaration, decorators: readonly Decorator[] | undefined, @@ -2443,9 +2850,10 @@ namespace ts { || node.heritageClauses !== heritageClauses || node.members !== members ? updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : node; + : reuseNode(node); } + // @api function createInterfaceDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -2454,14 +2862,19 @@ namespace ts { heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[] ) { - const node: InterfaceDeclaration = createBaseDeclaration(SyntaxKind.InterfaceDeclaration, decorators, modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.heritageClauses = asNodeArray(heritageClauses); - node.members = createNodeArray(members); - return node; + const node = createBaseInterfaceOrClassLikeDeclaration( + SyntaxKind.InterfaceDeclaration, + decorators, + modifiers, + name, + typeParameters, + heritageClauses + ); + setChildren(node, node.members = createNodeArray(members)); + return finishNode(node); } + // @api function updateInterfaceDeclaration( node: InterfaceDeclaration, decorators: readonly Decorator[] | undefined, @@ -2478,9 +2891,10 @@ namespace ts { || node.heritageClauses !== heritageClauses || node.members !== members ? updateNode(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : node; + : reuseNode(node); } + // @api function createTypeAliasDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, @@ -2488,13 +2902,18 @@ namespace ts { typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode ) { - const node: TypeAliasDeclaration = createBaseDeclaration(SyntaxKind.TypeAliasDeclaration, decorators, modifiers); - node.name = asName(name); - node.typeParameters = asNodeArray(typeParameters); - node.type = type; - return node; + const node = createBaseGenericNamedDeclaration( + SyntaxKind.TypeAliasDeclaration, + decorators, + modifiers, + name, + typeParameters + ); + setChild(node, node.type = type); + return finishNode(node); } + // @api function updateTypeAliasDeclaration( node: TypeAliasDeclaration, decorators: readonly Decorator[] | undefined, @@ -2509,21 +2928,27 @@ namespace ts { || node.typeParameters !== typeParameters || node.type !== type ? updateNode(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node) - : node; + : reuseNode(node); } + // @api function createEnumDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, members: readonly EnumMember[] ) { - const node: EnumDeclaration = createBaseDeclaration(SyntaxKind.EnumDeclaration, decorators, modifiers); - node.name = asName(name); - node.members = createNodeArray(members); - return node; + const node = createBaseNamedDeclaration( + SyntaxKind.EnumDeclaration, + decorators, + modifiers, + name + ); + setChildren(node, node.members = createNodeArray(members)); + return finishNode(node); } + // @api function updateEnumDeclaration( node: EnumDeclaration, decorators: readonly Decorator[] | undefined, @@ -2535,90 +2960,137 @@ namespace ts { || node.name !== name || node.members !== members ? updateNode(createEnumDeclaration(decorators, modifiers, name, members), node) - : node; + : reuseNode(node); } - function createModuleDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags = NodeFlags.None) { - const node: ModuleDeclaration = createBaseDeclaration(SyntaxKind.ModuleDeclaration, decorators, modifiers); + // @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); - node.name = name; - node.body = body; - return node; + setChild(node, node.name = name); + setChild(node, node.body = body); + return finishNode(node); } - function updateModuleDeclaration(node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined) { + // @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 ? updateNode(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) - : node; + : reuseNode(node); } + // @api function createModuleBlock(statements: readonly Statement[]) { - const node = createNode(SyntaxKind.ModuleBlock) as ModuleBlock; - node.statements = createNodeArray(statements); - return node; + const node = createBaseNode(SyntaxKind.ModuleBlock); + setChildren(node, node.statements = createNodeArray(statements)); + return finishNode(node); } + // @api function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) { return node.statements !== statements ? updateNode(createModuleBlock(statements), node) - : node; + : reuseNode(node); } + // @api function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { - const node = createNode(SyntaxKind.CaseBlock) as CaseBlock; - node.clauses = createNodeArray(clauses); - return node; + const node = createBaseNode(SyntaxKind.CaseBlock); + setChildren(node, node.clauses = createNodeArray(clauses)); + return finishNode(node); } + // @api function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) { return node.clauses !== clauses ? updateNode(createCaseBlock(clauses), node) - : node; + : reuseNode(node); } + // @api function createNamespaceExportDeclaration(name: string | Identifier) { - const node = createNode(SyntaxKind.NamespaceExportDeclaration) as NamespaceExportDeclaration; - node.name = asName(name); - return node; + const node = createBaseNode(SyntaxKind.NamespaceExportDeclaration); + setChild(node, node.name = asName(name)); + return finishNode(node); } + // @api function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { return node.name !== name ? updateNode(createNamespaceExportDeclaration(name), node) - : node; + : reuseNode(node); } - function createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) { - const node: ImportEqualsDeclaration = createBaseDeclaration(SyntaxKind.ImportEqualsDeclaration, decorators, modifiers); - node.name = asName(name); - node.moduleReference = moduleReference; - return 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); + return finishNode(node); } - function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) { + // @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 ? updateNode(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) - : node; + : reuseNode(node); } + // @api function createImportDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression ): ImportDeclaration { - const node: ImportDeclaration = createBaseDeclaration(SyntaxKind.ImportDeclaration, decorators, modifiers); - node.importClause = importClause; - node.moduleSpecifier = moduleSpecifier; - return node; + const node = createBaseDeclaration( + SyntaxKind.ImportDeclaration, + decorators, + modifiers + ); + setChild(node, node.importClause = importClause); + setChild(node, node.moduleSpecifier = moduleSpecifier); + return finishNode(node); } + // @api function updateImportDeclaration( node: ImportDeclaration, decorators: readonly Decorator[] | undefined, @@ -2631,87 +3103,120 @@ namespace ts { || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier ? updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) - : node; + : reuseNode(node); } + // @api function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { - const node = createNode(SyntaxKind.ImportClause) as ImportClause; - node.name = name; - node.namedBindings = namedBindings; - return node; + const node = createBaseNode(SyntaxKind.ImportClause); + setChild(node, node.name = name); + setChild(node, node.namedBindings = namedBindings); + return finishNode(node); } + // @api function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { return node.name !== name || node.namedBindings !== namedBindings ? updateNode(createImportClause(name, namedBindings), node) - : node; + : reuseNode(node); } + // @api function createNamespaceImport(name: Identifier): NamespaceImport { - const node = createNode(SyntaxKind.NamespaceImport) as NamespaceImport; - node.name = name; - return node; + const node = createBaseNode(SyntaxKind.NamespaceImport); + setChild(node, node.name = name); + return finishNode(node); } + // @api function updateNamespaceImport(node: NamespaceImport, name: Identifier) { return node.name !== name ? updateNode(createNamespaceImport(name), node) - : node; + : reuseNode(node); } + // @api function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { - const node = createNode(SyntaxKind.NamedImports) as NamedImports; - node.elements = createNodeArray(elements); - return node; + const node = createBaseNode(SyntaxKind.NamedImports); + setChildren(node, node.elements = createNodeArray(elements)); + return finishNode(node); } + // @api function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) { return node.elements !== elements ? updateNode(createNamedImports(elements), node) - : node; + : reuseNode(node); } + // @api function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier) { - const node = createNode(SyntaxKind.ImportSpecifier) as ImportSpecifier; - node.propertyName = propertyName; - node.name = name; - return node; + const node = createBaseNode(SyntaxKind.ImportSpecifier); + setChild(node, node.propertyName = propertyName); + setChild(node, node.name = name); + return finishNode(node); } + // @api function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) { return node.propertyName !== propertyName || node.name !== name ? updateNode(createImportSpecifier(propertyName, name), node) - : node; + : reuseNode(node); } - function createExportAssignment(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, expression: Expression) { + // @api + function createExportAssignment( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + isExportEquals: boolean | undefined, + expression: Expression + ) { const node = createBaseDeclaration( - SyntaxKind.ExportAssignment, asNodeArray(decorators), asNodeArray(modifiers)); + SyntaxKind.ExportAssignment, + decorators, + modifiers + ); node.isExportEquals = isExportEquals; - node.expression = isExportEquals + setChild(node, node.expression = isExportEquals ? parenthesizer().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) - : parenthesizer().parenthesizeExpressionOfExportDefault(expression); - return node; + : parenthesizer().parenthesizeExpressionOfExportDefault(expression)); + return finishNode(node); } - function updateExportAssignment(node: ExportAssignment, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, expression: Expression) { + // @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 ? updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) - : node; + : reuseNode(node); } - function createExportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression) { + // @api + function createExportDeclaration( + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + exportClause: NamedExports | undefined, + moduleSpecifier?: Expression + ) { const node = createBaseDeclaration( - SyntaxKind.ExportDeclaration, asNodeArray(decorators), asNodeArray(modifiers)); - node.exportClause = exportClause; - node.moduleSpecifier = moduleSpecifier; - return node; + SyntaxKind.ExportDeclaration, + decorators, + modifiers + ); + setChild(node, node.exportClause = exportClause); + setChild(node, node.moduleSpecifier = moduleSpecifier); + return finishNode(node); } + // @api function updateExportDeclaration( node: ExportDeclaration, decorators: readonly Decorator[] | undefined, @@ -2724,480 +3229,586 @@ namespace ts { || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier ? updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) - : node; + : reuseNode(node); } + // @api function createNamedExports(elements: readonly ExportSpecifier[]) { - const node = createNode(SyntaxKind.NamedExports) as NamedExports; - node.elements = createNodeArray(elements); - return node; + const node = createBaseNode(SyntaxKind.NamedExports); + setChildren(node, node.elements = createNodeArray(elements)); + return finishNode(node); } + // @api function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) { return node.elements !== elements ? updateNode(createNamedExports(elements), node) - : node; + : reuseNode(node); } + // @api function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier) { - const node = createNode(SyntaxKind.ExportSpecifier) as ExportSpecifier; - node.propertyName = asName(propertyName); - node.name = asName(name); - return node; + const node = createBaseNode(SyntaxKind.ExportSpecifier); + setChild(node, node.propertyName = asName(propertyName)); + setChild(node, node.name = asName(name)); + return finishNode(node); } + // @api function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) { return node.propertyName !== propertyName || node.name !== name ? updateNode(createExportSpecifier(propertyName, name), node) - : node; + : reuseNode(node); + } + + // @api + function createMissingDeclaration() { + const node = createBaseDeclaration( + SyntaxKind.MissingDeclaration, + /*decorators*/ undefined, + /*modifiers*/ undefined + ); + return finishNode(node); } // // Module references // + // @api function createExternalModuleReference(expression: Expression) { - const node = createNode(SyntaxKind.ExternalModuleReference) as ExternalModuleReference; - node.expression = expression; - return node; + const node = createBaseNode(SyntaxKind.ExternalModuleReference); + setChild(node, node.expression = expression); + return finishNode(node); } + // @api function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { return node.expression !== expression ? updateNode(createExternalModuleReference(expression), node) - : node; + : reuseNode(node); } // // JSDoc // + // @api function createJSDocAllType() { - const node = createNode(SyntaxKind.JSDocAllType) as JSDocAllType; - return node; + return finishNode(createBaseNode(SyntaxKind.JSDocAllType)); } + // @api function createJSDocUnknownType() { - const node = createNode(SyntaxKind.JSDocUnknownType) as JSDocUnknownType; - return node; + return finishNode(createBaseNode(SyntaxKind.JSDocUnknownType)); } + // @api function createJSDocNonNullableType(type: TypeNode) { - const node = createNode(SyntaxKind.JSDocNonNullableType) as JSDocNonNullableType; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocNonNullableType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocNullableType(type: TypeNode) { - const node = createNode(SyntaxKind.JSDocNullableType) as JSDocNullableType; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocNullableType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocOptionalType(type: TypeNode) { - const node = createNode(SyntaxKind.JSDocOptionalType) as JSDocOptionalType; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocOptionalType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { - return createBaseSignatureDeclaration(SyntaxKind.JSDocFunctionType, /*typeParameters*/ undefined, parameters, type); + const node = createBaseSignatureDeclaration( + SyntaxKind.JSDocFunctionType, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + parameters, + type + ); + return finishNode(node); } + // @api function createJSDocVariadicType(type: TypeNode) { - const node = createNode(SyntaxKind.JSDocVariadicType) as JSDocVariadicType; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocVariadicType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocNamepathType(type: TypeNode) { - const node = createNode(SyntaxKind.JSDocNamepathType) as JSDocNamepathType; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocNamepathType); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral { - const node = createNode(SyntaxKind.JSDocTypeLiteral) as JSDocTypeLiteral; - node.jsDocPropertyTags = propertyTags; + const node = createBaseNode(SyntaxKind.JSDocTypeLiteral); + setChildren(node, node.jsDocPropertyTags = asNodeArray(propertyTags)); node.isArrayType = isArrayType; - return node; + return finishNode(node); } + // @api function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { - const node = createNode(SyntaxKind.JSDocTypeExpression) as JSDocTypeExpression; - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocTypeExpression); + setChild(node, node.type = type); + return finishNode(node); } + // @api function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { - const node = createNode(SyntaxKind.JSDocSignature) as JSDocSignature; - node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); - node.type = type; - return node; + const node = createBaseNode(SyntaxKind.JSDocSignature); + setChildren(node, node.typeParameters = asNodeArray(typeParameters)); + setChildren(node, node.parameters = createNodeArray(parameters)); + setChild(node, node.type = type); + return finishNode(node); } - function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[]): JSDocTemplateTag { - const tag = createJSDocTag(SyntaxKind.JSDocTemplateTag, tagName || createIdentifier("template")); - tag.constraint = constraint; - tag.typeParameters = createNodeArray(typeParameters); - return tag; - } - - function createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag { - const tag = createJSDocTag(SyntaxKind.JSDocTypeTag, tagName || createIdentifier("type")); - tag.typeExpression = typeExpression; - tag.comment = comment; - return tag; - } - - function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocTypedefTag { - const tag = createJSDocTag(SyntaxKind.JSDocTypedefTag, tagName || createIdentifier("typedef")); - tag.typeExpression = typeExpression; - tag.fullName = fullName; - tag.name = getJSDocTypeAliasName(fullName); - tag.comment = comment; - return tag; - } - - function createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag { - const tag = createJSDocTag(SyntaxKind.JSDocReturnTag, tagName || createIdentifier("returns")); - tag.typeExpression = typeExpression; - tag.comment = comment; - return tag; - } - - function createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocThisTag { - const tag = createJSDocTag(SyntaxKind.JSDocThisTag, tagName || createIdentifier("this")); - tag.typeExpression = typeExpression; - return tag; - } - - function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag { - const tag = createJSDocTag(SyntaxKind.JSDocParameterTag, tagName || createIdentifier("param")); - tag.typeExpression = typeExpression; - tag.name = name; - tag.isNameFirst = !!isNameFirst; - tag.isBracketed = isBracketed; - tag.comment = comment; - return tag; - } - - function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag { - const tag = createJSDocTag(SyntaxKind.JSDocPropertyTag, tagName || createIdentifier("prop")); - tag.typeExpression = typeExpression; - tag.name = name; - tag.isNameFirst = !!isNameFirst; - tag.isBracketed = isBracketed; - tag.comment = comment; - return tag; - } - - function createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag { - const tag = createJSDocTag(SyntaxKind.JSDocAuthorTag, tagName || createIdentifier("author")); - tag.comment = comment; - return tag; - } - - function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"]): JSDocAugmentsTag { - const tag = createJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName || createIdentifier("augments")); - tag.class = className; - return tag; - } - - function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag { - const tag = createJSDocTag(SyntaxKind.JSDocCallbackTag, tagName || createIdentifier("callback")); - tag.typeExpression = typeExpression; - tag.fullName = fullName; - tag.name = getJSDocTypeAliasName(fullName); - tag.comment = comment; - return tag; - } - - function createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag { - const tag = createJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class")); - return tag; - } - - function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag { - const tag = createJSDocTag(SyntaxKind.JSDocEnumTag, tagName || createIdentifier("enum")); - tag.typeExpression = typeExpression; - return tag; - } - - function createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined) { - const node = createNode(SyntaxKind.JSDocComment) as JSDoc; + // @api + function createBaseJSDocTag(kind: T["kind"], tagName: Identifier, comment: string | undefined) { + const node = createBaseNode(kind); + setChild(node, node.tagName = tagName); node.comment = comment; - node.tags = tags; 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 finishNode(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 finishNode(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 finishNode(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 finishNode(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 finishNode(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 finishNode(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 finishNode(node); + } + + // @api + function createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocAuthorTag, tagName || createIdentifier("author"), comment); + return finishNode(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 finishNode(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 finishNode(node); + } + + // @api + function createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class"), /*comment*/ undefined); + return finishNode(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 finishNode(node); + } + + // @api function createJSDocTag(kind: T["kind"], tagName: Identifier): T { - const node = createNode(kind) as T; - node.tagName = tagName; - return node; + const node = createBaseJSDocTag(kind, tagName, /*comment*/ undefined); + return finishNode(node); + } + + // @api + function createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined) { + const node = createBaseNode(SyntaxKind.JSDocComment); + node.comment = comment; + setChildren(node, node.tags = tags); + return finishNode(node); } // // JSX // + // @api function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { - const node = createNode(SyntaxKind.JsxElement) as JsxElement; - node.openingElement = openingElement; - node.children = createNodeArray(children); - node.closingElement = closingElement; - return node; + const node = createBaseNode(SyntaxKind.JsxElement); + setChild(node, node.openingElement = openingElement); + setChildren(node, node.children = createNodeArray(children)); + setChild(node, node.closingElement = closingElement); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - const node = createNode(SyntaxKind.JsxSelfClosingElement) as JsxSelfClosingElement; - node.tagName = tagName; - node.typeArguments = asNodeArray(typeArguments); - node.attributes = attributes; - return node; + const node = createBaseNode(SyntaxKind.JsxSelfClosingElement); + setChild(node, node.tagName = tagName); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.attributes = attributes); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { - const node = createNode(SyntaxKind.JsxOpeningElement) as JsxOpeningElement; - node.tagName = tagName; - node.typeArguments = asNodeArray(typeArguments); - node.attributes = attributes; - return node; + const node = createBaseNode(SyntaxKind.JsxOpeningElement); + setChild(node, node.tagName = tagName); + setChildren(node, node.typeArguments = asNodeArray(typeArguments)); + setChild(node, node.attributes = attributes); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api function createJsxClosingElement(tagName: JsxTagNameExpression) { - const node = createNode(SyntaxKind.JsxClosingElement) as JsxClosingElement; - node.tagName = tagName; - return node; + const node = createBaseNode(SyntaxKind.JsxClosingElement); + setChild(node, node.tagName = tagName); + return finishNode(node); } + // @api function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { return node.tagName !== tagName ? updateNode(createJsxClosingElement(tagName), node) - : node; + : reuseNode(node); } + // @api function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { - const node = createNode(SyntaxKind.JsxFragment) as JsxFragment; - node.openingFragment = openingFragment; - node.children = createNodeArray(children); - node.closingFragment = closingFragment; - return node; - } - - function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { - const node = createNode(SyntaxKind.JsxText) as JsxText; - node.text = text; - node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; - return node; - } - - function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { - return node.text !== text - || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces - ? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) - : node; - } - - function createJsxOpeningFragment() { - return createNode(SyntaxKind.JsxOpeningFragment) as JsxOpeningFragment; - } - - function createJsxJsxClosingFragment() { - return createNode(SyntaxKind.JsxClosingFragment) as JsxClosingFragment; + const node = createBaseNode(SyntaxKind.JsxFragment); + setChild(node, node.openingFragment = openingFragment); + setChildren(node, node.children = createNodeArray(children)); + setChild(node, node.closingFragment = closingFragment); + return finishNode(node); } + // @api 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; + : reuseNode(node); } + // @api + function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + const node = createBaseNode(SyntaxKind.JsxText); + node.text = text; + node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; + return finishNode(node); + } + + // @api + function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + return node.text !== text + || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces + ? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) + : reuseNode(node); + } + + // @api + function createJsxOpeningFragment() { + return finishNode(createBaseNode(SyntaxKind.JsxOpeningFragment)); + } + + // @api + function createJsxJsxClosingFragment() { + return finishNode(createBaseNode(SyntaxKind.JsxClosingFragment)); + } + + // @api function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined) { - const node = createNode(SyntaxKind.JsxAttribute) as JsxAttribute; - node.name = name; - node.initializer = initializer; - return node; + const node = createBaseNode(SyntaxKind.JsxAttribute); + setChild(node, node.name = name); + setChild(node, node.initializer = initializer); + return finishNode(node); } + // @api function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) { return node.name !== name || node.initializer !== initializer ? updateNode(createJsxAttribute(name, initializer), node) - : node; + : reuseNode(node); } + // @api function createJsxAttributes(properties: readonly JsxAttributeLike[]) { - const node = createNode(SyntaxKind.JsxAttributes) as JsxAttributes; - node.properties = createNodeArray(properties); - return node; + const node = createBaseNode(SyntaxKind.JsxAttributes); + setChildren(node, node.properties = createNodeArray(properties)); + return finishNode(node); } + // @api function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { return node.properties !== properties ? updateNode(createJsxAttributes(properties), node) - : node; + : reuseNode(node); } + // @api function createJsxSpreadAttribute(expression: Expression) { - const node = createNode(SyntaxKind.JsxSpreadAttribute) as JsxSpreadAttribute; - node.expression = expression; - return node; + const node = createBaseNode(SyntaxKind.JsxSpreadAttribute); + setChild(node, node.expression = expression); + return finishNode(node); } + // @api function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { return node.expression !== expression ? updateNode(createJsxSpreadAttribute(expression), node) - : node; + : reuseNode(node); } + // @api function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) { - const node = createNode(SyntaxKind.JsxExpression) as JsxExpression; - node.dotDotDotToken = dotDotDotToken; - node.expression = expression; - return node; + const node = createBaseNode(SyntaxKind.JsxExpression); + setChild(node, node.dotDotDotToken = dotDotDotToken); + setChild(node, node.expression = expression); + return finishNode(node); } + // @api function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { return node.expression !== expression ? updateNode(createJsxExpression(node.dotDotDotToken, expression), node) - : node; + : reuseNode(node); } // // Clauses // + // @api function createCaseClause(expression: Expression, statements: readonly Statement[]) { - const node = createNode(SyntaxKind.CaseClause) as CaseClause; - node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression); - node.statements = createNodeArray(statements); - return node; + const node = createBaseNode(SyntaxKind.CaseClause); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChildren(node, node.statements = createNodeArray(statements)); + return finishNode(node); } + // @api function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) { return node.expression !== expression || node.statements !== statements ? updateNode(createCaseClause(expression, statements), node) - : node; + : reuseNode(node); } + // @api function createDefaultClause(statements: readonly Statement[]) { - const node = createNode(SyntaxKind.DefaultClause) as DefaultClause; - node.statements = createNodeArray(statements); - return node; + const node = createBaseNode(SyntaxKind.DefaultClause); + setChildren(node, node.statements = createNodeArray(statements)); + return finishNode(node); } + // @api function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) { return node.statements !== statements ? updateNode(createDefaultClause(statements), node) - : node; + : reuseNode(node); } + // @api function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) { - const node = createNode(SyntaxKind.HeritageClause) as HeritageClause; + const node = createBaseNode(SyntaxKind.HeritageClause); node.token = token; - node.types = createNodeArray(types); - return node; + setChildren(node, node.types = createNodeArray(types)); + return finishNode(node); } + // @api function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) { return node.types !== types ? updateNode(createHeritageClause(node.token, types), node) - : node; + : reuseNode(node); } + // @api function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) { - const node = createNode(SyntaxKind.CatchClause) as CatchClause; - node.variableDeclaration = isString(variableDeclaration) ? createVariableDeclaration(variableDeclaration) : variableDeclaration; - node.block = block; - return node; + const node = createBaseNode(SyntaxKind.CatchClause); + setChild(node, node.variableDeclaration = !isString(variableDeclaration) ? variableDeclaration : createVariableDeclaration( + variableDeclaration, + /*exclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + )); + setChild(node, node.block = block); + return finishNode(node); } + // @api function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { return node.variableDeclaration !== variableDeclaration || node.block !== block ? updateNode(createCatchClause(variableDeclaration, block), node) - : node; + : reuseNode(node); } - // // Property assignments // + // @api function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { - const node = createNode(SyntaxKind.PropertyAssignment) as PropertyAssignment; - node.name = asName(name); - node.questionToken = undefined; - node.initializer = parenthesizer().parenthesizeExpressionForDisallowedComma(initializer); - return node; + const node = createBaseNode(SyntaxKind.PropertyAssignment); + setChild(node, node.name = asName(name)); + setChild(node, node.questionToken = undefined); + setChild(node, node.initializer = parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); + return finishNode(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 updateNode(updated, original); + } + + // @api function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) { return node.name !== name || node.initializer !== initializer - ? updateNode(createPropertyAssignment(name, initializer), node) - : node; + ? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node) + : reuseNode(node); } + // @api function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { - return createShorthandPropertyAssignmentInternal(/*decorators*/ undefined, /*modifiers*/ undefined, name, /*equalsToken*/ undefined, objectAssignmentInitializer); + const node = createBaseNamedDeclaration( + SyntaxKind.ShorthandPropertyAssignment, + /*decorators*/ undefined, + /*modifiers*/ undefined, + name + ); + setChild(node, node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined + ? parenthesizer().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) + : undefined); + return finishNode(node); } - function createShorthandPropertyAssignmentInternal(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, equalsToken: EqualsToken | undefined, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment { - const node: ShorthandPropertyAssignment = createBaseDeclaration(SyntaxKind.ShorthandPropertyAssignment, decorators, modifiers); - node.name = asName(name); - node.equalsToken = equalsToken; - node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizer().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) : undefined; - return 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 updateNode(updated, original); } + // @api function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) { return node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer - ? updateNode(createShorthandPropertyAssignmentInternal(node.decorators, node.modifiers, name, node.equalsToken, objectAssignmentInitializer), node) - : node; + ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) + : reuseNode(node); } + // @api function createSpreadAssignment(expression: Expression) { - const node = createNode(SyntaxKind.SpreadAssignment) as SpreadAssignment; - node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression); - return node; + const node = createBaseNode(SyntaxKind.SpreadAssignment); + setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + return finishNode(node); } + // @api function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { return node.expression !== expression ? updateNode(createSpreadAssignment(expression), node) - : node; + : reuseNode(node); } @@ -3205,18 +3816,20 @@ namespace ts { // Enum // + // @api function createEnumMember(name: string | PropertyName, initializer?: Expression) { - const node = createNode(SyntaxKind.EnumMember) as EnumMember; - node.name = asName(name); - node.initializer = initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer); - return node; + const node = createBaseNode(SyntaxKind.EnumMember); + setChild(node, node.name = asName(name)); + setChild(node, node.initializer = initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); + return finishNode(node); } + // @api function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { return node.name !== name || node.initializer !== initializer ? updateNode(createEnumMember(name, initializer), node) - : node; + : reuseNode(node); } // @@ -3232,45 +3845,23 @@ namespace ts { hasNoDefaultLib: boolean, libReferences: readonly FileReference[] ) { - const node = createNode(SyntaxKind.SourceFile) as SourceFile; + 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; - node.statements = createNodeArray(statements); - node.endOfFileToken = source.endOfFileToken; - node.fileName = source.fileName; - node.path = source.path; - node.text = source.text; + 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; - if (source.amdDependencies !== undefined) node.amdDependencies = source.amdDependencies; - if (source.moduleName !== undefined) node.moduleName = source.moduleName; - if (source.languageVariant !== undefined) node.languageVariant = source.languageVariant; - if (source.renamedDependencies !== undefined) node.renamedDependencies = source.renamedDependencies; - if (source.languageVersion !== undefined) node.languageVersion = source.languageVersion; - if (source.scriptKind !== undefined) node.scriptKind = source.scriptKind; - if (source.externalModuleIndicator !== undefined) node.externalModuleIndicator = source.externalModuleIndicator; - if (source.commonJsModuleIndicator !== undefined) node.commonJsModuleIndicator = source.commonJsModuleIndicator; - if (source.identifiers !== undefined) node.identifiers = source.identifiers; - if (source.nodeCount !== undefined) node.nodeCount = source.nodeCount; - if (source.identifierCount !== undefined) node.identifierCount = source.identifierCount; - if (source.symbolCount !== undefined) node.symbolCount = source.symbolCount; - if (source.parseDiagnostics !== undefined) node.parseDiagnostics = source.parseDiagnostics; - if (source.bindDiagnostics !== undefined) node.bindDiagnostics = source.bindDiagnostics; - if (source.bindSuggestionDiagnostics !== undefined) node.bindSuggestionDiagnostics = source.bindSuggestionDiagnostics; - if (source.lineMap !== undefined) node.lineMap = source.lineMap; - if (source.classifiableNames !== undefined) node.classifiableNames = source.classifiableNames; - if (source.resolvedModules !== undefined) node.resolvedModules = source.resolvedModules; - if (source.resolvedTypeReferenceDirectiveNames !== undefined) node.resolvedTypeReferenceDirectiveNames = source.resolvedTypeReferenceDirectiveNames; - if (source.imports !== undefined) node.imports = source.imports; - if (source.moduleAugmentations !== undefined) node.moduleAugmentations = source.moduleAugmentations; - if (source.pragmas !== undefined) node.pragmas = source.pragmas; - if (source.localJsxFactory !== undefined) node.localJsxFactory = source.localJsxFactory; - if (source.localJsxNamespace !== undefined) node.localJsxNamespace = source.localJsxNamespace; - return node; + return finishNode(node); } + // @api function updateSourceFile( node: SourceFile, statements: readonly Statement[], @@ -3287,7 +3878,7 @@ namespace ts { || node.hasNoDefaultLib !== hasNoDefaultLib || node.libReferenceDirectives !== libReferenceDirectives ? updateNode(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node) - : node; + : reuseNode(node); } // @@ -3300,35 +3891,36 @@ namespace ts { * * @param original The original statement. */ + // @api function createNotEmittedStatement(original: Node) { - const node = createNode(SyntaxKind.NotEmittedStatement) as NotEmittedStatement; + const node = createBaseNode(SyntaxKind.NotEmittedStatement); node.original = original; setTextRange(node, original); - return node; + return finishNode(node); } /** * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in * order to properly emit exports. */ - /* @internal */ + // @api function createEndOfDeclarationMarker(original: Node) { - const node = createNode(SyntaxKind.EndOfDeclarationMarker) as EndOfDeclarationMarker; + const node = createBaseNode(SyntaxKind.EndOfDeclarationMarker); node.emitNode = {} as EmitNode; node.original = original; - return node; + return finishNode(node); } /** * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in * order to properly emit exports. */ - /* @internal */ + // @api function createMergeDeclarationMarker(original: Node) { - const node = createNode(SyntaxKind.MergeDeclarationMarker) as MergeDeclarationMarker; + const node = createBaseNode(SyntaxKind.MergeDeclarationMarker); node.emitNode = {} as EmitNode; node.original = original; - return node; + return finishNode(node); } /** @@ -3338,19 +3930,20 @@ namespace ts { * @param expression The inner expression to emit. * @param original The original outer expression. */ + // @api function createPartiallyEmittedExpression(expression: Expression, original?: Node) { - const node = createNode(SyntaxKind.PartiallyEmittedExpression) as PartiallyEmittedExpression; - node.expression = expression; + const node = createBaseNode(SyntaxKind.PartiallyEmittedExpression); + setChild(node, node.expression = expression); node.original = original; setTextRange(node, original); - return node; + return finishNode(node); } + // @api function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createPartiallyEmittedExpression(expression, node.original), node); - } - return node; + return node.expression !== expression + ? updateNode(createPartiallyEmittedExpression(expression, node.original), node) + : reuseNode(node); } function flattenCommaElements(node: Expression): Expression | readonly Expression[] { @@ -3365,48 +3958,54 @@ namespace ts { return node; } - function createCommaList(elements: readonly Expression[]) { - const node = createNode(SyntaxKind.CommaListExpression) as CommaListExpression; - node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); - return node; + // @api + function createCommaListExpression(elements: readonly Expression[]) { + const node = createBaseNode(SyntaxKind.CommaListExpression); + setChildren(node, node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements))); + return finishNode(node); } - function updateCommaList(node: CommaListExpression, elements: readonly Expression[]) { + // @api + function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) { return node.elements !== elements - ? updateNode(createCommaList(elements), node) - : node; + ? updateNode(createCommaListExpression(elements), node) + : reuseNode(node); } + // @api function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { - const node = createNode(SyntaxKind.Bundle) as Bundle; + const node = createBaseNode(SyntaxKind.Bundle); node.prepends = prepends; node.sourceFiles = sourceFiles; - return node; + return finishNode(node); } + // @api 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; + return node.sourceFiles !== sourceFiles + || node.prepends !== prepends + ? updateNode(createBundle(sourceFiles, prepends), node) + : reuseNode(node); } // // Compound Nodes // + // TODO(rbuckton): Consider removing these from NodeFactory and putting them somewhere else. + 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( + return createCallExpression( + createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ param ? [param] : [], /*type*/ undefined, - factory.createBlock(statements, /*multiLine*/ true) + createBlock(statements, /*multiLine*/ true) ), /*typeArguments*/ undefined, /*argumentsArray*/ paramValue ? [paramValue] : [] @@ -3416,14 +4015,14 @@ namespace ts { 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( + return createCallExpression( + createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, /*parameters*/ param ? [param] : [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, - factory.createBlock(statements, /*multiLine*/ true) + createBlock(statements, /*multiLine*/ true) ), /*typeArguments*/ undefined, /*argumentsArray*/ paramValue ? [paramValue] : [] @@ -3432,57 +4031,57 @@ namespace ts { function createComma(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.CommaToken, right); + return createBinaryExpression(left, SyntaxKind.CommaToken, right); } function createLessThan(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.LessThanToken, right); + return createBinaryExpression(left, SyntaxKind.LessThanToken, right); } function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; function createAssignment(left: Expression, right: Expression): BinaryExpression; function createAssignment(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.EqualsToken, right); + return createBinaryExpression(left, SyntaxKind.EqualsToken, right); } function createStrictEquality(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.EqualsEqualsEqualsToken, right); + return createBinaryExpression(left, SyntaxKind.EqualsEqualsEqualsToken, right); } function createStrictInequality(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.ExclamationEqualsEqualsToken, right); + return createBinaryExpression(left, SyntaxKind.ExclamationEqualsEqualsToken, right); } function createAdd(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.PlusToken, right); + return createBinaryExpression(left, SyntaxKind.PlusToken, right); } function createSubtract(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.MinusToken, right); + return createBinaryExpression(left, SyntaxKind.MinusToken, right); } function createPostfixIncrement(operand: Expression) { - return factory.createPostfix(operand, SyntaxKind.PlusPlusToken); + return createPostfixUnaryExpression(operand, SyntaxKind.PlusPlusToken); } function createLogicalAnd(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.AmpersandAmpersandToken, right); + return createBinaryExpression(left, SyntaxKind.AmpersandAmpersandToken, right); } function createLogicalOr(left: Expression, right: Expression) { - return factory.createBinary(left, SyntaxKind.BarBarToken, right); + return createBinaryExpression(left, SyntaxKind.BarBarToken, right); } function createLogicalNot(operand: Expression) { - return factory.createPrefix(SyntaxKind.ExclamationToken, operand); + return createPrefixUnaryExpression(SyntaxKind.ExclamationToken, operand); } function createVoidZero() { - return factory.createVoid(factory.createNumericLiteral("0")); + return createVoidExpression(createNumericLiteral("0")); } function createExportDefault(expression: Expression) { - return factory.createExportAssignment( + return createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, @@ -3490,11 +4089,11 @@ namespace ts { } function createExternalModuleExport(exportName: Identifier) { - return factory.createExportDeclaration( + return createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - factory.createNamedExports([ - factory.createExportSpecifier(/*propertyName*/ undefined, exportName) + createNamedExports([ + createExportSpecifier(/*propertyName*/ undefined, exportName) ]) ); } @@ -3506,12 +4105,12 @@ namespace ts { function createTypeCheck(value: Expression, tag: TypeOfTag) { return tag === "undefined" ? createStrictEquality(value, createVoidZero()) - : createStrictEquality(createTypeOf(value), createStringLiteral(tag)); + : createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); } function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { - return createCall( - createPropertyAccess(object, asName(methodName)), + return createCallExpression( + createPropertyAccessExpression(object, asName(methodName)), /*typeArguments*/ undefined, argumentsList ); @@ -3565,12 +4164,12 @@ namespace ts { 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); + return createObjectLiteralExpression(properties, !singleLine); } function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) { switch (outerExpression.kind) { - case SyntaxKind.ParenthesizedExpression: return updateParen(outerExpression, expression); + case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(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); @@ -3615,7 +4214,7 @@ namespace ts { if (!outermostLabeledStatement) { return node; } - const updated = updateLabel( + const updated = updateLabeledStatement( outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === SyntaxKind.LabeledStatement @@ -3656,11 +4255,11 @@ namespace ts { let thisArg: Expression; let target: LeftHandSideExpression; if (isSuperProperty(callee)) { - thisArg = createThis(); + thisArg = createThisExpression(); target = callee; } else if (callee.kind === SyntaxKind.SuperKeyword) { - thisArg = createThis(); + thisArg = createThisExpression(); target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015 ? setTextRange(createIdentifier("_super"), callee) : callee; @@ -3673,7 +4272,7 @@ namespace ts { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a.b()` target is `(_a = a).b` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); - target = createPropertyAccess( + target = createPropertyAccessExpression( setTextRange( createAssignment( thisArg, @@ -3694,7 +4293,7 @@ namespace ts { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); - target = createElementAccess( + target = createElementAccessExpression( setTextRange( createAssignment( thisArg, @@ -3724,7 +4323,7 @@ namespace ts { // 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) + ? createCommaListExpression(expressions) : reduceLeft(expressions, createComma)!; } @@ -3804,7 +4403,7 @@ namespace ts { * @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 = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); + const qualifiedName = createPropertyAccessExpression(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); setTextRange(qualifiedName, name); let emitFlags: EmitFlags = 0; if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; @@ -3957,8 +4556,61 @@ namespace ts { function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; } + + // tslint:disable-next-line no-empty + function setChildWithoutTreeState(_parent: Node, _child: Node | undefined): void { + } + + function setChildWithTreeState(parent: Node, child: Node | undefined): void { + if (child) { + treeStateObserver.onSetChild(parent, child); + setChildWithoutTreeState(parent, child); + } + } + + // tslint:disable-next-line no-empty + function setChildrenWithoutTreeState(_parent: Node, _children: NodeArray | undefined): void { + } + + function setChildrenWithTreeState(parent: Node, children: NodeArray | undefined): void { + if (children) { + treeStateObserver.onSetChildren(parent, children); + setChildrenWithoutTreeState(parent, children); + } + } + + function finishNodeWithoutTreeState(node: T) { + return node; + } + + function finishNodeWithTreeState(node: T) { + treeStateObserver.onFinishNode(node); + return finishNodeWithoutTreeState(node); + } + + function updateNodeWithTreeState(updated: T, original: T) { + treeStateObserver.onUpdateNode(updated, original); + return ts.updateNode(updated, original); // tslint:disable-line no-unnecessary-qualifier + } + + function reuseNodeWithTreeState(node: T) { + treeStateObserver.onReuseNode(node); + return node; + } } + // similar to `ts.noop`, but used to avoid deoptimizations in v8 due to argument length mismatches + function noop2(_a: unknown, _b: unknown) { } // tslint:disable-line no-empty + + /* @internal */ + export const nullTreeStateObserver: TreeStateObserver = { + onSetChild: noop2, + onSetChildren: noop2, + onFinishNode: noop, + onUpdateNode: noop2, + onReuseNode: noop + }; + /* @internal */ export function createSynthesizedNode(kind: SyntaxKind): Node { const node = createNode(kind, -1, -1); @@ -4375,11 +5027,35 @@ namespace ts { // Utilities + export function isUnprocessedSourceFile(node: SourceFile) { + return !node.preprocessInfo || node === node.preprocessInfo.unprocessed; + } + + export function isProcessedSourceFile(node: SourceFile) { + return !!node.preprocessInfo && node !== node.preprocessInfo.unprocessed; + } + + /** + * If the source file has been preprocessed due to a plugin, gets the unprocessed + * source file. Otherwise, returns the source file. + */ + export function getUnprocessedSourceFile(node: SourceFile) { + return node.preprocessInfo ? node.preprocessInfo.unprocessed : node; + } + + /** + * If the source file has been preprocessed due to a plugin, gets the processed + * source file. Otherwise, returns the source file. + */ + export function getProcessedSourceFile(node: SourceFile) { + return node.preprocessInfo ? node.preprocessInfo.processed : node; + } + /** * Clears any EmitNode entries from parse-tree nodes. * @param sourceFile A source file. */ - export function disposeEmitNodes(sourceFile: SourceFile) { + 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 @@ -4411,7 +5087,7 @@ namespace ts { return node.emitNode = { annotatedNodes: [node] } as EmitNode; } - const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))); + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) || Debug.fail("Could not determine parsed source file."); getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } @@ -4691,7 +5367,11 @@ namespace ts { 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 (helpers) { + for (const helper of helpers) { + destEmitNode.helpers = appendIfUnique(destEmitNode.helpers, helper); + } + } if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; return destEmitNode; } @@ -4707,8 +5387,9 @@ namespace ts { /* @internal */ namespace ts { - export const syntheticNodeFactory = createNodeFactory(createSynthesizedNode, createParenthesizerRules, createNodeConverters); - export const syntheticNodeConverters = syntheticNodeFactory.getConverters(); + + export const factory = createNodeFactory(createSynthesizedNode, createParenthesizerRules, createNodeConverters, nullTreeStateObserver); + export const nodeConverters = factory.getConverters(); export function createNodeConverters(factory: NodeFactory): NodeConverters { return { @@ -4876,7 +5557,7 @@ namespace ts { 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); + react.parent = getParseTreeNode(parent)!; return react; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e7a1be18a4e..d91ec1a3b09 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -31,7 +31,7 @@ namespace ts { } /* @internal */ - export const parseNodeFactory = createNodeFactory(createNode, createParenthesizerRules, createNodeConverters); + export const parseNodeFactory = createNodeFactory(createNode, createParenthesizerRules, createNodeConverters, nullTreeStateObserver); function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); @@ -590,7 +590,7 @@ 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 factory = createNodeFactory(createNode, getNullParenthesizerRules, getNullNodeConverters); + const factory = createNodeFactory(createNode, getNullParenthesizerRules, getNullNodeConverters, nullTreeStateObserver); const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; // capture constructors in 'initializeState' to avoid null checks @@ -736,6 +736,7 @@ namespace ts { nextToken(); const pos = getNodePos(); if (token() === SyntaxKind.EndOfFileToken) { + // TODO(rbuckton): this does not create the tree correctly and transform flags won't be properly set sourceFile.statements = createNodeArray([], pos, pos); sourceFile.endOfFileToken = parseTokenNode(); } @@ -770,6 +771,7 @@ namespace ts { break; } + // 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); sourceFile.statements = createNodeArray([statement], pos); @@ -786,11 +788,6 @@ namespace ts { 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) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); @@ -856,6 +853,7 @@ namespace ts { processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic); + // TODO(rbuckton): this does not create the tree correctly and transform flags won't be properly set sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement); Debug.assert(token() === SyntaxKind.EndOfFileToken); sourceFile.endOfFileToken = addJSDocComment(parseTokenNode()); @@ -1375,7 +1373,8 @@ namespace ts { isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "") : kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) : kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) : - factory.createNode(kind); + kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : + factory.createToken(kind); return finishNode(result, pos) as T; } @@ -3238,7 +3237,11 @@ namespace ts { return parsePostfixTypeOrHigher(); } - function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { + function parseUnionOrIntersectionType( + operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken, + parseConstituentType: () => TypeNode, + createTypeNode: (types: NodeArray) => UnionOrIntersectionTypeNode + ): TypeNode { const pos = getNodePos(); const hasLeadingOperator = parseOptional(operator); let type = parseConstituentType(); @@ -3247,17 +3250,17 @@ namespace ts { while (parseOptional(operator)) { types.push(parseConstituentType()); } - type = finishNode(factory.createUnionOrIntersectionTypeNode(kind, createNodeArray(types, pos)), pos); + 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 { @@ -4888,7 +4891,7 @@ namespace ts { 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 its otherwise not useful. + // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful. if (equalsToken) node.equalsToken = equalsToken; } else { @@ -5654,8 +5657,7 @@ namespace ts { } const type = parseTypeAnnotation(); const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer(); - const node = factory.createVariableDeclaration(name, type, initializer); - node.exclamationToken = exclamationToken; + const node = factory.createVariableDeclaration(name, exclamationToken, type, initializer); return finishNode(node, pos); } diff --git a/src/compiler/plugin.ts b/src/compiler/plugin.ts index c7ddc7d3cd3..91963df3936 100644 --- a/src/compiler/plugin.ts +++ b/src/compiler/plugin.ts @@ -21,7 +21,6 @@ namespace ts { | { error: Diagnostic, result: undefined } | { error: undefined, result: T | undefined }; - /*@internal*/ export interface GetPluginsResult { plugins: CompilerPlugin[]; diagnostics?: Diagnostic[]; @@ -39,7 +38,6 @@ namespace ts { /** * Resolves the supplied plugins (and their dependencies) relative to an initial directory. */ - /*@internal*/ export function getPlugins(host: ModuleLoaderHost, initialDir: string, plugins: ReadonlyArray) { interface ResolvedModule { getModule(): RequireResult; @@ -185,6 +183,17 @@ namespace ts { } } + export function registerPluginApiModules(host: ModuleLoaderHost) { + host.registerModule(createPluginApiModuleFactory()); + } + + function createPluginApiModuleFactory(): ModuleFactory { + return { + id: ["typescript"], + load: () => ts + }; + } + function findPackageJsonPath(host: ModuleResolutionHost, modulePath: string) { while (true) { const candidate = combinePaths(modulePath, "package.json"); @@ -402,10 +411,12 @@ namespace ts { } function createLoadDiagnostic(compilerPlugin: CompilerPlugin, error: { message?: string, stack?: string }) { + debugger; return createCompilerDiagnostic(Diagnostics.Plugin_0_could_not_be_loaded, compilerPlugin.name, error.stack || error.message || error.toString()); } function createUserCodeDiagnostic(compilerPlugin: CompilerPlugin, hook: Hook, error: { message?: string, stack?: string }) { + debugger; return createCompilerDiagnostic(Diagnostics.Plugin_0_failed_while_executing_the_1_hook_Colon_2, compilerPlugin.name, hook, error.stack || error.message || error.toString()); } } \ No newline at end of file diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bce37c2c4b4..ef5f9a87cf3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -749,7 +749,36 @@ namespace ts { dropTypeCheckers: () => void; } - function createBaseProgram(createProgramOptions: CreateProgramOptions, preprocess?: Transformer): CreateBaseProgramResult { + function changeCompilerHostToUsePreprocessor(host: CompilerHost, preprocess: Transformer) { + const oldGetSourceFile = host.getSourceFile; + host.getSourceFile = function(fileName, languageVersion, onError, shouldCreateNewSourceFile) { + return getPreprocessedSourceFile(oldGetSourceFile.call(this, fileName, languageVersion, onError, shouldCreateNewSourceFile)); + }; + if (host.getSourceFileByPath) { + const oldGetSourceFileByPath = host.getSourceFileByPath; + // tslint:disable-next-line only-arrow-functions + host.getSourceFileByPath = function (fileName, path, languageVersion, onError, shouldCreateNewSourceFile) { + return getPreprocessedSourceFile(oldGetSourceFileByPath.call(this, fileName, path, languageVersion, onError, shouldCreateNewSourceFile)); + }; + } + if (host.onReleaseOldSourceFile) { + const oldOnReleaseOldSourceFile = host.onReleaseOldSourceFile; + // tslint:disable-next-line only-arrow-functions + host.onReleaseOldSourceFile = function (oldSourceFile, oldOptions, hasSourceFileByPath) { + return oldOnReleaseOldSourceFile.call(getUnprocessedSourceFile(oldSourceFile), oldOptions, hasSourceFileByPath); + }; + } + function getPreprocessedSourceFile(file: SourceFile | undefined) { + if (!file) return; + if (file.preprocessInfo) return file.preprocessInfo.processed; + const processed = preprocess(file); + const preprocessInfo: PreprocessInfo = { unprocessed: file, processed }; + file.preprocessInfo = processed.preprocessInfo = preprocessInfo; + return processed; + } + } + + function createBaseProgram(createProgramOptions: CreateProgramOptions, host: CompilerHost): CreateBaseProgramResult { const { options, configFileParsingDiagnostics } = createProgramOptions; const { rootNames, projectReferences } = createProgramOptions; let { oldProgram } = createProgramOptions; @@ -772,8 +801,6 @@ namespace ts { let resolvedTypeReferenceDirectives = createMap(); - const host = createProgramOptions.host || createCompilerHost(options); - // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. // This works as imported modules are discovered recursively in a depth first manner, specifically: // - For each root file, findSourceFile is called. @@ -2028,8 +2055,8 @@ namespace ts { && (options.isolatedModules || isExternalModuleFile) && !file.isDeclarationFile) { // synthesize 'import "tslib"' declaration - const externalHelpersModuleReference = syntheticNodeFactory.createStringLiteral(externalHelpersModuleNameText); - const importDecl = syntheticNodeFactory.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; @@ -2093,19 +2120,43 @@ namespace ts { } function collectDynamicImportOrRequireCalls(file: SourceFile) { + if (isProcessedSourceFile(file)) { + // If the file has gone through a preprocessor, we need to walk the tree to find dynamic imports and require calls + collectDynamicImportOrRequireCallsInSubtree(getUnprocessedSourceFile(file), file); + } + else { + collectDynamicImportOrRequireCallsInRange(file, 0, file.text.length); + } + } + + function collectDynamicImportOrRequireCallsInSubtree(unprocessedFile: SourceFile, node: Node) { + if (node.flags & NodeFlags.Preprocessed) { + collectDynamicImportOrRequireCallsOfNode(node); + forEachChild(node, child => collectDynamicImportOrRequireCallsInSubtree(unprocessedFile, child)); + } + else { + collectDynamicImportOrRequireCallsInRange(unprocessedFile, node.pos, node.end); + } + } + + function collectDynamicImportOrRequireCallsInRange(file: SourceFile, start: number, end: number) { const r = /import|require/g; - while (r.exec(file.text) !== null) { - const node = getNodeAtPosition(file, r.lastIndex); - if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { - imports = append(imports, node.arguments[0]); - } - // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. - else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) { - imports = append(imports, node.arguments[0] as StringLiteralLike); - } - else if (isLiteralImportTypeNode(node)) { - imports = append(imports, node.argument.literal); - } + const text = file.text.slice(start, end); + while (r.exec(text) !== null) { + collectDynamicImportOrRequireCallsOfNode(getNodeAtPosition(file, r.lastIndex + start)); + } + } + + function collectDynamicImportOrRequireCallsOfNode(node: Node) { + if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { + imports = append(imports, node.arguments[0]); + } + // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. + else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) { + imports = append(imports, node.arguments[0] as StringLiteralLike); + } + else if (isLiteralImportTypeNode(node)) { + imports = append(imports, node.argument.literal); } } @@ -2295,7 +2346,7 @@ namespace ts { } // We haven't looked for this file, do so now and cache result - let file = host.getSourceFile( + const file = host.getSourceFile( fileName, options.target!, hostErrorMessage => fileProcessingDiagnostics.add(createRefFileDiagnostic( @@ -2307,15 +2358,6 @@ namespace ts { shouldCreateNewSourceFile ); - // Pass the file through a user-defined preprocessor (provided by plugins) - if (file && preprocess) { - const processed = preprocess(file); - if (processed !== file) { - processed.preprocessInfo = { unprocessed: file }; - } - file = processed; - } - if (packageId) { const packageIdKey = packageIdToString(packageId); const fileFromPackageId = packageIdToSourceFile.get(packageIdKey); @@ -3325,7 +3367,8 @@ namespace ts { performance.mark("beforeProgram"); - const { baseProgram, emitWorker, dropTypeCheckers } = createBaseProgram(createProgramOptions); + const host = createProgramOptions.host || createCompilerHost(createProgramOptions.options); + const { baseProgram, emitWorker, dropTypeCheckers } = createBaseProgram(createProgramOptions, host); const program = baseProgram as Program; program.emit = emit; @@ -3339,6 +3382,14 @@ namespace ts { } } + function createPreprocessedNode(kind: SyntaxKind) { + const node = createNode(kind, -1, -1); + node.flags |= NodeFlags.Preprocessed; + return node; + } + + const preprocessorNodeFactory = createNodeFactory(createPreprocessedNode, createParenthesizerRules, createNodeConverters, nullTreeStateObserver); + /** * Create a new 'AsyncProgram' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -3369,7 +3420,6 @@ namespace ts { projectReferences: createProgramOptions.projectReferences }); - let preprocess: Transformer | undefined; let preprocessDiagnostics: DiagnosticWithLocation[] | undefined; let preprocessTransformer: NodeTransformer | undefined; let preprocessedNodes: Node[] | undefined; @@ -3385,24 +3435,22 @@ namespace ts { preprocessTransformer = createNodeTransformer( /*resolver*/ undefined, /*host*/ undefined, - parseNodeFactory, + preprocessorNodeFactory, options, preParseResult.preprocessors, /*allowDtsFiles*/ true ); preprocessDiagnostics = preprocessTransformer.diagnostics; preprocessedNodes = []; - preprocess = node => { + changeCompilerHostToUsePreprocessor(host, node => { disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node))); preprocessedNodes!.push(node); return preprocessTransformer!.transformNode(node); - }; + }); } } - // !!!! - // TODO(rbuckton): pass `parseTransform` to `createBaseProgram` - const { baseProgram, emitWorker, dropTypeCheckers } = createBaseProgram(createProgramOptions, preprocess); + const { baseProgram, emitWorker, dropTypeCheckers } = createBaseProgram(createProgramOptions, host); if (preprocessDiagnostics) { for (const diagnostic of preprocessDiagnostics) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index cdb3ecb7181..0193825a0c6 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -651,6 +651,7 @@ namespace ts { base64decode?(input: string): string; base64encode?(input: string): string; /*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer; + /*@internal*/ registerModule?(factory: ModuleFactory): void; /*@internal*/ require?(baseDir: string, moduleName: string): RequireResult; } @@ -718,6 +719,7 @@ namespace ts { const _fs = require("fs"); const _path = require("path"); const _os = require("os"); + const _module = require("module"); // crypto can be absent on reduced node installations let _crypto: typeof import("crypto") | undefined; try { @@ -749,6 +751,7 @@ namespace ts { const tscWatchDirectory = process.env.TSC_WATCHDIRECTORY; const fsWatchFile = memoize(() => createSingleFileWatcherPerName(fsWatchFileWorker, useCaseSensitiveFileNames)); let dynamicPollingWatchFile: HostWatchFile | undefined; + let factories: Map | undefined; const nodeSystem: System = { args: process.argv.slice(2), newLine: _os.EOL, @@ -839,6 +842,7 @@ namespace ts { bufferFrom, base64decode: input => bufferFrom(input, "base64").toString("utf8"), base64encode: input => bufferFrom(input).toString("base64"), + registerModule, require: (baseDir, moduleName) => { try { // NOTE: 'require' may be called before `resolveJSModule` is available (i.e. when loading shims). If that is the case then @@ -1337,6 +1341,29 @@ namespace ts { hash.update(data); return hash.digest("hex"); } + + // based on: + // - https://github.com/microsoft/vscode/blob/master/src/vs/workbench/api/common/extHostRequireInterceptor.ts + // - https://github.com/microsoft/vscode/blob/master/src/vs/workbench/api/node/extHostExtensionService.ts + function registerModule(factory: ModuleFactory) { + if (!factories) { + factories = createMap(); + const load = _module._load as ModuleLoadFunction; + _module._load = function(request: string, parent: { filename: string }, isMain: boolean) { + const factory = factories!.get(request); + return factory ? factory.load(request, parent, isMain, (...args) => load.apply(this, args)) : + load.apply(this, arguments); + }; + } + if (isArray(factory.id)) { + for (const id of factory.id) { + factories.set(id, factory); + } + } + else { + factories.set(factory.id, factory); + } + } } function getChakraSystem(): System { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 328001509c6..3c2da4b5fb4 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -450,7 +450,7 @@ namespace ts { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); - emitHelpers = append(emitHelpers, helper); + emitHelpers = appendIfUnique(emitHelpers, helper); } function readEmitHelpers(): EmitHelper[] | undefined { @@ -528,7 +528,7 @@ namespace ts { /* @internal */ export const nullTransformationContext: TransformationContext = { - factory: syntheticNodeFactory, + factory, getEmitHelperFactory: notImplemented, enableEmitNotification: noop, enableSubstitution: noop, diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index f41c3a990ba..039e2bfd854 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -5,7 +5,7 @@ namespace ts { return []; // No declaration diagnostics for js for now } const compilerOptions = host.getCompilerOptions(); - const result = transformNodes(resolver, host, syntheticNodeFactory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJS), [transformDeclarations], /*allowDtsFiles*/ false); + const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJS), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } @@ -839,24 +839,25 @@ namespace ts { case SyntaxKind.Constructor: { const isPrivate = hasModifier(input, ModifierFlags.Private); // A constructor declaration may not have a type annotation - const ctor = factory.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, + factory.createNodeArray(ensureModifiers(input)), + isPrivate ? factory.createNodeArray() : updateParamsList(input, input.parameters, ModifierFlags.None), + /*body*/ undefined ); - ctor.modifiers = factory.createNodeArray(ensureModifiers(input)); return cleanup(ctor); } case SyntaxKind.MethodDeclaration: { - const sig = factory.createMethodSignature( + 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) + ensureType(input, input.type), + /*body*/ undefined ); return cleanup(sig); } @@ -1054,16 +1055,24 @@ namespace ts { return input; } - function stripExportModifiers(statement: Statement): Statement { - if (isImportEqualsDeclaration(statement) || hasModifier(statement, ModifierFlags.Default)) { + function stripExportModifiers(node: Statement): Statement { + if (isImportEqualsDeclaration(node) || hasModifier(node, ModifierFlags.Default)) { // `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace // Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too - return statement; + return node; } - const clone = getMutableClone(statement); - const modifiers = factory.createModifiersFromModifierFlags(getModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export)); - clone.modifiers = modifiers.length ? factory.createNodeArray(modifiers) : undefined; - return clone; + return isClassDeclaration(node) ? factory.updateClassDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.name, node.typeParameters, node.heritageClauses, node.members) : + isFunctionDeclaration(node) ? factory.updateFunctionDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : + isModuleDeclaration(node) ? factory.updateModuleDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.name, node.body) : + isEnumDeclaration(node) ? factory.updateEnumDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.name, node.members) : + isInterfaceDeclaration(node) ? factory.updateInterfaceDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.name, node.typeParameters, node.heritageClauses, node.members) : + isTypeAliasDeclaration(node) ? factory.updateTypeAliasDeclaration(node, node.decorators, visitNodes(node.modifiers, modifierVisitor), node.name, node.typeParameters, node.type) : + isVariableStatement(node) ? factory.updateVariableStatement(node, visitNodes(node.modifiers, modifierVisitor), node.declarationList) : + node; + } + + function modifierVisitor(node: Modifier) { + return node.kind === SyntaxKind.ExportKeyword ? undefined : node; } function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index f04b8faede8..bd74f997f0a 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2161,9 +2161,7 @@ namespace ts { } if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) { - const clone = getMutableClone(node); - clone.initializer = factory.createVoidZero(); - return clone; + return factory.updateVariableDeclaration(node, node.name, /*type*/ undefined, factory.createVoidZero()); } return visitEachChild(node, visitor, context); diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index fa9aadc6fd3..d195555d434 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -785,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); @@ -1102,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); diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 0ef182e8617..e29e6d72903 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -172,8 +172,8 @@ namespace ts { 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 = factory.createStringLiteral(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) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 0fc35ec10a5..71a4b9b4276 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -278,9 +278,8 @@ namespace ts { factory.createBlock(executeStatements, /*multiLine*/ true) ) ) - ]); + ], /*multiLine*/ true); - moduleObject.multiLine = true; statements.push(factory.createReturn(moduleObject)); return factory.createBlock(statements, /*multiLine*/ true); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 2421089b657..251c6a0b74c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1740,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; diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 8a642c032ea..11e01dec6dd 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -60,6 +60,6 @@ "resolutionCache.ts", "moduleSpecifiers.ts", "watch.ts", - "tsbuild.ts", + "tsbuild.ts" ] } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ebfc85b9631..93fd34b50d4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -529,6 +529,7 @@ namespace ts { Let = 1 << 0, // Variable declaration Const = 1 << 1, // Variable declaration NestedNamespace = 1 << 2, // Namespace declaration + Preprocessed = 1 << 25, // Node was synthesized during preprocessing Synthesized = 1 << 3, // Node was synthesized during transformation Namespace = 1 << 4, // Namespace declaration ExportContext = 1 << 5, // Export context (initialized by binding) @@ -1289,6 +1290,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 @@ -2695,7 +2697,6 @@ namespace ts { name?: string; } - /* @internal */ /** * Subset of properties from SourceFile that are used in multiple utility functions */ @@ -2724,6 +2725,10 @@ namespace ts { * The source file prior to being passed to the preprocessor. */ readonly unprocessed: SourceFile; + /** + * The source file resulting from the preprocessor. + */ + readonly processed: SourceFile; } // Source files are declarations when they are external modules. @@ -4992,7 +4997,7 @@ namespace ts { /** Plugin dependencies that should be loaded before this plugin. */ pluginDependencies?: string[]; /** Loads the compiler plugin. */ - loadPlugin(): RequireResult; + /* @internal */ loadPlugin(): RequireResult; } /** @@ -5092,8 +5097,18 @@ namespace ts { export interface CompilerPluginDeactivationResult extends CompilerPluginResult { } + /*@internal*/ + export type ModuleLoadFunction = (request: string, parent: { filename: string }, isMain: boolean) => unknown; + + /*@internal*/ + export interface ModuleFactory { + readonly id: string | readonly string[]; + load(request: string, parent: { filename: string }, isMain: boolean, load: ModuleLoadFunction): unknown; + } + /* @internal */ export interface ModuleLoaderHost extends ModuleResolutionHost { + registerModule(factory: ModuleFactory): void; require(initialDir: string, moduleName: string): RequireResult; } @@ -5723,7 +5738,6 @@ namespace ts { export interface NodeFactory { /* @internal */ getParenthesizerRules(): ParenthesizerRules; /* @internal */ getConverters(): NodeConverters; - /* @internal */ createNode(kind: SyntaxKind): Node; createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; // @@ -5733,7 +5747,7 @@ namespace ts { createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; - createStringLiteralFromNode(node: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; + createStringLiteralFromNode(sourceNode: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; createRegularExpressionLiteral(text: string): RegularExpressionLiteral; // @@ -5829,7 +5843,7 @@ namespace ts { 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; - /* @internal */ createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, typeArguments?: readonly TypeNode[] | undefined): T; + /* @internal */ createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; 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; // tslint:disable-line unified-signatures updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; @@ -5863,7 +5877,6 @@ namespace ts { updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - /* @internal */ createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]): UnionOrIntersectionTypeNode; 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; @@ -5886,7 +5899,6 @@ namespace ts { // Binding Patterns // - createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; @@ -6019,8 +6031,8 @@ namespace ts { createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; createDebuggerStatement(): DebuggerStatement; - // TODO(rbuckton): Add `exclamationToken`: createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration; + createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; @@ -6062,6 +6074,7 @@ namespace ts { 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 @@ -6281,7 +6294,7 @@ namespace ts { // Utilities // - // TODO(rbuckton): Rename to `restoreOuterExpression`. + // TODO(rbuckton): Rename to `restoreOuterExpressions`. recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; /* @internal */ restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement; /* @internal */ createUseStrictPrologue(): PrologueDirective; @@ -6325,6 +6338,15 @@ namespace ts { convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression; } + /* @internal */ + export interface TreeStateObserver { + onSetChild(parent: Node, child: Node): void; + onSetChildren(parent: Node, children: NodeArray): void; + onFinishNode(node: Node): void; + onUpdateNode(updated: Node, original: Node): void; + onReuseNode(node: Node): void; + } + export interface CoreTransformationContext { readonly factory: NodeFactory; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 404f791a45f..2d31b02675c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -938,6 +938,9 @@ namespace ts { } export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan { + while (nodeIsSynthesized(node) && node.parent) { + node = node.parent; + } let errorNode: Node | undefined = node; switch (node.kind) { case SyntaxKind.SourceFile: @@ -2819,7 +2822,6 @@ namespace ts { } } - export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral; export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral { switch (node.kind) { case SyntaxKind.Identifier: @@ -5169,8 +5171,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. * @@ -5178,18 +5179,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; } @@ -7403,6 +7405,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/harness/fakes.ts b/src/harness/fakes.ts index 374b64d77ca..4f887df3211 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -21,6 +21,7 @@ namespace fakes { public readonly newLine: string; public readonly useCaseSensitiveFileNames: boolean; public exitCode: number | undefined; + public registerModule?: ts.System["registerModule"]; public require?: ts.System["require"]; private readonly _executingFilePath: string | undefined; @@ -34,6 +35,7 @@ namespace fakes { this._env = env; if (useFakeLoader) { const loader = new ModuleLoader(this.vfs); + this.registerModule = factory => loader.registerModule(factory); this.require = (baseDir: string, moduleName: string): ts.RequireResult => { try { const modulePath = ts.resolveJSModule(moduleName, baseDir, this); @@ -392,47 +394,73 @@ namespace fakes { type ModuleWrapper = (require: Function, module: any, exports: any, dirname: string, filename: string) => void; interface ModuleObject { + filename: string; exports: any; } class ModuleLoader { readonly vfs: vfs.FileSystem; private _modules = ts.createMap(); + private _factories = ts.createMap(); + private _linker?: (modulePath: string, moduleContent: string) => ModuleWrapper; constructor(vfs: vfs.FileSystem) { this.vfs = vfs; } + registerModule(factory: ts.ModuleFactory) { + if (ts.isArray(factory.id)) { + for (const id of factory.id) { + this._factories.set(id, factory); + } + } + else { + this._factories.set(factory.id, factory); + } + } + require(modulePath: string) { // this is a very basic loader that is only intended to load a single file for now. let module = this._modules.get(modulePath); if (!module) { - module = { exports: {} }; + module = { filename: modulePath, exports: {} }; this._modules.set(modulePath, module); const moduleContent = this.vfs.readFileSync(modulePath, "utf8"); const linkedModule = this.link(modulePath, moduleContent); - linkedModule(ts.notImplemented, module, module.exports, ts.getDirectoryPath(modulePath), modulePath); + const require = (request: string) => this.load(request, module!, /*isMain*/ false); + linkedModule(require, module, module.exports, ts.getDirectoryPath(modulePath), modulePath); } return module.exports; } + private load(request: string, parent: { filename: string }, isMain: boolean) { + const factory = this._factories.get(request); + if (factory) { + return factory.load(request, parent, isMain, ts.notImplemented); + } + return ts.notImplemented(); + } + private link(modulePath: string, moduleContent: string) { - let vm: typeof import("vm") | undefined; - try { - vm = require("vm"); + if (!this._linker) { + let vm: typeof import("vm") | undefined; + try { + vm = require("vm"); + } + catch { + // ignore + } + this._linker = vm ? (modulePath, moduleContent) => this.linkUsingNodeVM(vm!, modulePath, moduleContent) : + (modulePath, moduleContent) => this.linkUsingIndirectEval(modulePath, moduleContent); } - catch { - // ignore - } - return vm ? this.linkUsingNodeVM(vm, modulePath, moduleContent) : - this.linkUsingFunction(modulePath, moduleContent); + return this._linker(modulePath, moduleContent); } private linkUsingNodeVM(vm: typeof import("vm"), modulePath: string, moduleContent: string): ModuleWrapper { return vm.runInThisContext(`(function (require, module, exports, __dirname, __filename) {${moduleContent}\n})`, { filename: modulePath }); } - private linkUsingFunction(modulePath: string, moduleContent: string): ModuleWrapper { + private linkUsingIndirectEval(modulePath: string, moduleContent: string): ModuleWrapper { const indirectEval = eval; return indirectEval(`(function (require, module, exports, __dirname, __filename) {${moduleContent}\n//# sourceURL=${modulePath}\n})`); } diff --git a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts index e6e8d759c60..407a2eec9c0 100644 --- a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts +++ b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts @@ -16,8 +16,8 @@ namespace ts.codefix { const token = getTokenAtPosition(sourceFile, pos); const assertion = Debug.assertDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertion(n))); 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 3545c65faf9..1dffe0631e1 100644 --- a/src/services/codefixes/addMissingAwait.ts +++ b/src/services/codefixes/addMissingAwait.ts @@ -152,8 +152,8 @@ namespace ts.codefix { const { left, right } = insertionSite; const leftType = checker.getTypeAtLocation(left); const rightType = checker.getTypeAtLocation(right); - const newLeft = checker.getPromisedTypeOfPromise(leftType) ? createAwait(left) : left; - const newRight = checker.getPromisedTypeOfPromise(rightType) ? createAwait(right) : right; + const newLeft = checker.getPromisedTypeOfPromise(leftType) ? factory.createAwait(left) : left; + const newRight = checker.getPromisedTypeOfPromise(rightType) ? factory.createAwait(right) : right; changeTracker.replaceNode(sourceFile, left, newLeft); changeTracker.replaceNode(sourceFile, right, newRight); } @@ -161,13 +161,13 @@ namespace ts.codefix { changeTracker.replaceNode( sourceFile, insertionSite.parent.expression, - createParen(createAwait(insertionSite.parent.expression))); + factory.createParen(factory.createAwait(insertionSite.parent.expression))); } else if (contains(callableConstructableErrorCodes, errorCode) && isCallOrNewExpression(insertionSite.parent)) { - changeTracker.replaceNode(sourceFile, insertionSite, createParen(createAwait(insertionSite))); + changeTracker.replaceNode(sourceFile, insertionSite, factory.createParen(factory.createAwait(insertionSite))); } else { - 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 25100870623..4e5190ba571 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 3339f719008..07bc1bea7e3 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 ef701fe4a8c..0c556566e3a 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: @@ -98,27 +98,27 @@ namespace ts.codefix { } 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 = 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 b87a78106ad..5f1444bc05f 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 3842c30d6aa..79d5f9ea89e 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, 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), /* 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): ReadonlyArray { 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)), /*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), /*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), /*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 9572b4b1c17..0d44288dd06 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: @@ -236,7 +236,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); } @@ -260,7 +260,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); } @@ -285,14 +285,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); @@ -302,14 +302,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 } } @@ -368,8 +368,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: @@ -405,7 +405,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; @@ -413,7 +413,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; @@ -475,7 +475,7 @@ namespace ts.codefix { // Node helpers function functionExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray, 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), @@ -483,11 +483,11 @@ namespace ts.codefix { getSynthesizedDeepClones(fn.typeParameters), getSynthesizedDeepClones(fn.parameters), getSynthesizedDeepClone(fn.type), - syntheticNodeConverters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); + nodeConverters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); } function classExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray, 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, @@ -498,27 +498,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: ReadonlyArray | undefined, name: string | BindingName, init: Expression): VariableStatement { - return createVariableStatement( + return factory.createVariableStatement( modifiers, - createVariableDeclarationList( - [createVariableDeclaration(name, /*type*/ undefined, init)], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(name, /*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 0d79d6363c0..d6effb0603e 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 02ccbfd1d64..d2462546c62 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 843d22554ed..ea0e9ff18b5 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 5acaf6eb82e..f4dd8215007 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 b382b9a2f05..60cfce3b67e 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 e5b3a24dbea..4fcce8c5cde 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -70,7 +70,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", createNodeArray([returnType]))); } } changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore); diff --git a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts index 7d021d5e260..d170e431cba 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 8ab1c276910..1cafb7d1200 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/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 78dc6b1ae19..5c17a418057 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: ReadonlyArray): 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 e5f58885e1c..d488fa2314a 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 dc37aeff12b..a26f00748c2 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 5dd57b6c454..97ada1ba833 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 15c57c604dd..1b5884e9da9 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, @@ -110,10 +110,16 @@ namespace ts.codefix { 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 2d1c2f0fc38..b2b5c9b1b88 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 de071ded24c..3262234d042 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 e4c56e3ea51..885dc0129df 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -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); 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; } @@ -189,14 +189,14 @@ namespace ts.codefix { 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); @@ -205,13 +205,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); } @@ -247,13 +247,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); @@ -278,12 +278,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, @@ -291,22 +291,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; } @@ -324,7 +324,7 @@ namespace ts.codefix { if (compilerOptionsProperty === undefined) { changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment( "compilerOptions", - createObjectLiteral([ + factory.createObjectLiteral([ createJsonPropertyAssignment(optionName, optionValue), ]))); return; @@ -346,7 +346,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 267415f6cc0..bba583a007a 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -528,11 +528,11 @@ namespace ts.codefix { function doAddExistingFix(changes: textChanges.ChangeTracker, sourceFile: SourceFile, clause: ImportClause, defaultImport: string | undefined, namedImports: ReadonlyArray): void { if (defaultImport) { Debug.assert(!clause.name); - 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); @@ -540,7 +540,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); } @@ -578,25 +578,25 @@ 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), /*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 78278002371..31a4b79bcd3 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(/*tagName*/ undefined, createJSDocTypeExpression(typeNode), /*comment*/ ""); + const typeTag = factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode), /*comment*/ ""); addJSDocTags(changes, sourceFile, cast(parent.parent.parent, isExpressionStatement), [typeTag]); } return parent; @@ -218,13 +218,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); } } - if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), createToken(SyntaxKind.CloseParenToken)); + if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), factory.createToken(SyntaxKind.CloseParenToken)); } } @@ -254,7 +254,7 @@ namespace ts.codefix { function annotateJSDocThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: FunctionLike, typeNode: TypeNode) { addJSDocTags(changes, sourceFile, containingFunction, [ - createJSDocThisTag(/*tagName*/ undefined, createJSDocTypeExpression(typeNode)), + factory.createJSDocThisTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode)), ]); } @@ -282,8 +282,8 @@ namespace ts.codefix { if (!parent) { return; } - const typeExpression = createJSDocTypeExpression(typeNode); - const typeTag = isGetAccessorDeclaration(declaration) ? createJSDocReturnTag(/*tagName*/ undefined, typeExpression, "") : createJSDocTypeTag(/*tagName*/ undefined, 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 { @@ -305,7 +305,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 && syntheticNodeFactory.createJSDocParameterTag(/*tagName*/ undefined, name, !!inference.isOptional, createJSDocTypeExpression(typeNode), /*isNameFirst*/ undefined, ""); + return typeNode && factory.createJSDocParameterTag(/*tagName*/ undefined, name, !!inference.isOptional, factory.createJSDocTypeExpression(typeNode), /*isNameFirst*/ undefined, ""); }); addJSDocTags(changes, sourceFile, signature, paramTags); } @@ -318,7 +318,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"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent; jsDocNode.jsDoc = parent.jsDoc; jsDocNode.jsDocCache = parent.jsDocCache; @@ -341,11 +341,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 - ? syntheticNodeFactory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, newParam.isBracketed, newParam.typeExpression, /*isNameFirst*/ undefined, oldParam.comment) + ? factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, newParam.isBracketed, newParam.typeExpression, /*isNameFirst*/ undefined, oldParam.comment) : undefined; } case SyntaxKind.JSDocReturnTag: - return createJSDocReturnTag(/*tagName*/ undefined, (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 ee2a898147d..1528b6910a7 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/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index 66cc88c2677..a5a244c719b 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/organizeImports.ts b/src/services/organizeImports.ts index 81c9108749f..0e4a6b89abf 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 97d6f4d6667..dc763c52ea1 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 64c7e7567b8..a1f7f8c74e3 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))); + changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDefault(Debug.assertDefined(first(exportNode.declarationList.declarations).initializer))); 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); @@ -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 862717e728a..277da9b296d 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: ReadonlyArray | 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 fa795f20a8f..f9edb65fea0 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -363,9 +363,9 @@ namespace ts.refactor.convertParamsToDestructuredObject { 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, @@ -436,11 +436,11 @@ namespace ts.refactor.convertParamsToDestructuredObject { return 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 823bd640a59..9602b287b31 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -719,7 +719,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[] = []; @@ -734,7 +734,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, @@ -746,7 +746,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) })); @@ -759,7 +759,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: ReadonlyArray | 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 @@ -776,17 +776,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.createToken(SyntaxKind.PrivateKeyword)]; if (range.facts & RangeFacts.InStaticRegion) { - modifiers.push(createToken(SyntaxKind.StaticKeyword)); + modifiers.push(factory.createToken(SyntaxKind.StaticKeyword)); } if (range.facts & RangeFacts.IsAsyncFunction) { - modifiers.push(createToken(SyntaxKind.AsyncKeyword)); + modifiers.push(factory.createToken(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, @@ -796,10 +796,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, @@ -822,15 +822,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) { @@ -843,10 +843,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), /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns variableDeclaration.parent.flags))); } else { @@ -857,7 +857,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))); @@ -868,26 +868,25 @@ 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), /*type*/ typeLiteral, /*initializer*/call)], commonNodeFlags))); @@ -902,26 +901,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, 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, getTypeDeepCloneUnionUndefined(returnType))], NodeFlags.Let))); } const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { - assignments.unshift(createShorthandPropertyAssignment(returnValueProperty)); + assignments.unshift(factory.createShorthandPropertyAssignment(returnValueProperty)); } // propagate writes back @@ -930,28 +929,28 @@ namespace ts.refactor.extractSymbol { // other assignments to make. Debug.assert(!returnValueProperty); - 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); @@ -984,7 +983,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)]); } } @@ -1018,13 +1017,13 @@ namespace ts.refactor.extractSymbol { if (isClassLike(scope)) { Debug.assert(!isJS); // See CannotExtractToJSClass const modifiers: Modifier[] = []; - modifiers.push(createToken(SyntaxKind.PrivateKeyword)); + modifiers.push(factory.createToken(SyntaxKind.PrivateKeyword)); if (rangeFacts & RangeFacts.InStaticRegion) { - modifiers.push(createToken(SyntaxKind.StaticKeyword)); + modifiers.push(factory.createToken(SyntaxKind.StaticKeyword)); } - modifiers.push(createToken(SyntaxKind.ReadonlyKeyword)); + modifiers.push(factory.createToken(SyntaxKind.ReadonlyKeyword)); - const newVariable = createProperty( + const newVariable = factory.createPropertyDeclaration( /*decorators*/ undefined, modifiers, localNameText, @@ -1032,11 +1031,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; @@ -1047,7 +1046,7 @@ namespace ts.refactor.extractSymbol { changeTracker.replaceNode(context.file, node, localReference); } else { - const newVariableDeclaration = createVariableDeclaration(localNameText, variableType, initializer); + const newVariableDeclaration = factory.createVariableDeclaration(localNameText, 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). @@ -1060,21 +1059,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); @@ -1091,7 +1090,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); } } @@ -1147,10 +1146,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; @@ -1161,11 +1160,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 = 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(); @@ -1174,16 +1173,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 { @@ -1193,13 +1192,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 { @@ -1317,8 +1316,8 @@ namespace ts.refactor.extractSymbol { exposedVariableDeclarations: ReadonlyArray, writes: ReadonlyArray | 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 @@ -1433,7 +1432,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); @@ -1730,15 +1729,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 02f6cd39a18..b57f41d75ea 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -108,30 +108,30 @@ namespace ts.refactor { } function doTypeAliasChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, firstStatement: Statement, selection: TypeNode, typeParameters: ReadonlyArray) { - 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 doTypedefChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, firstStatement: Statement, selection: TypeNode, typeParameters: ReadonlyArray) { 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); @@ -141,7 +141,7 @@ namespace ts.refactor { 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, 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 dbc73781871..09ab795096b 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)) + : createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined; @@ -96,18 +96,18 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function createPropertyName (name: string, originalName: AcceptedNameType) { - return isIdentifier(originalName) ? createIdentifier(name) : createLiteral(name); + 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.createToken(accessModifier) as Token | Token] : undefined, + isStatic ? factory.createToken(SyntaxKind.StaticKeyword) : undefined ); return modifiers && createNodeArray(modifiers); } @@ -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)); } } @@ -229,10 +229,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 8da05ee55e1..2dc8d28aaed 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, /*type*/ undefined, createRequireCall(newModuleString)); default: return Debug.assertNever(node); } @@ -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: ReadonlyArray, 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); // 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, 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: ReadonlyArray, needExport: ReadonlySymbolSet, useEs6Exports: boolean): ReadonlyArray { @@ -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/textChanges.ts b/src/services/textChanges.ts index f3e5bf9bfb5..15b222d77a2 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -331,7 +331,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 { @@ -341,7 +341,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 { @@ -449,7 +449,7 @@ namespace ts.textChanges { } private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: ReadonlyArray): 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 { @@ -515,7 +515,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, {}); @@ -562,25 +562,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: " " }); } } @@ -688,7 +688,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 @@ -705,7 +705,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 { @@ -1250,7 +1250,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 29a7e495346..c0d87f67b6f 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, syntheticNodeFactory, 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/tsconfig.json b/src/services/tsconfig.json index 67baab22fee..6328c5c4628 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -94,7 +94,6 @@ "services.ts", "breakpoints.ts", "transform.ts", - "shims.ts", - "factoryCompat.ts", + "shims.ts" ] } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 2e6e6875a81..c4f9de4ea4c 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1301,17 +1301,17 @@ namespace ts { } export function makeImport(defaultImport: Identifier | undefined, namedImports: ReadonlyArray | 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 } @@ -1711,7 +1711,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, @@ -1723,7 +1723,7 @@ namespace ts { const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol))); if (renameInfo) { - clone = createIdentifier(renameInfo.text); + clone = factory.createIdentifier(renameInfo.text); } } diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index e10d5258d54..45bb6743cbc 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -18,6 +18,7 @@ { "path": "../promiseShim", "prepend": true }, { "path": "../compiler", "prepend": true }, { "path": "../services", "prepend": true }, + { "path": "../compat", "prepend": true }, { "path": "../jsTyping", "prepend": true }, { "path": "../server", "prepend": true }, { "path": "../typingsInstallerCore", "prepend": true }, diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 58ffcc38e14..d65b1b35e4b 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -144,15 +144,18 @@ namespace ts { } let plugins: ReadonlyArray | undefined; if (configParseResult.plugins) { - if (sys.require) { + if (sys.require && sys.registerModule) { const result = getPlugins(sys as ModuleLoaderHost, getDirectoryPath(configFileName), configParseResult.plugins); plugins = result.plugins; if (some(result.diagnostics)) { - // TODO(rbuckton): report diagnostics + forEach(result.diagnostics, reportDiagnostic); + } + if (some(plugins)) { + registerPluginApiModules(sys as ModuleLoaderHost); } } else { - // TODO(rbuckton): report diagnostic + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Plugins_are_not_supported_in_the_current_host_environment)); } } updateReportDiagnostic(configParseResult.options); diff --git a/src/tsserverlibrary/tsconfig.json b/src/tsserverlibrary/tsconfig.json index fcd4597dc6d..61ca62593a2 100644 --- a/src/tsserverlibrary/tsconfig.json +++ b/src/tsserverlibrary/tsconfig.json @@ -10,6 +10,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 1845d69a473..ec571d72c9b 100644 --- a/src/typescriptServices/tsconfig.json +++ b/src/typescriptServices/tsconfig.json @@ -9,6 +9,7 @@ "references": [ { "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.Nested @param tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json index 21ca6702ed7..d9b8e284652 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,12 @@ } }, "isNameFirst": false, - "isBracketed": false, - "comment": "Doc for f" - } - ], + "isBracketed": false + }, + "length": 1, + "pos": -1, + "end": -1 + }, "isArrayType": false } }, @@ -101,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 3a6ee3365dc..3e253bc7357 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 2fa5734c1a3..3f4cba67e1d 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 e0a57b72e93..16c0da9d8bf 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 712ac49a36f..05bf95a8c4f 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 3eebbc73ba9..7e6a7f86ee1 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 d864cbeafd2..03ecb9d4e85 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 4c29e477e10..e8e72f69a0f 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 5fe9854187d..42f6bd6512f 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 c3e885082a6..c02a2652988 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 cfb1f56fd1f..1f96a67a0d9 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -26,8 +26,8 @@ "end": 100, "modifierFlagsCache": 0, "transformFlags": 0, - "jsDocPropertyTags": [ - { + "jsDocPropertyTags": { + "0": { "kind": "JSDocPropertyTag", "pos": 47, "end": 74, @@ -66,7 +66,7 @@ "isNameFirst": false, "isBracketed": false }, - { + "1": { "kind": "JSDocPropertyTag", "pos": 74, "end": 100, @@ -104,8 +104,11 @@ }, "isNameFirst": false, "isBracketed": false - } - ] + }, + "length": 2, + "pos": -1, + "end": -1 + } }, "fullName": { "kind": "Identifier",