From c1020ca59d0aa4f4820cccf5e99a0eb97923ac61 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 20 Sep 2019 18:15:33 -0700 Subject: [PATCH] Reorganize factory-related functionality, update parser to use createNodeArray --- src/compat/factory.ts | 1 + src/compiler/checker.ts | 14 +- src/compiler/core.ts | 9 +- src/compiler/emitter.ts | 10 +- src/compiler/factory/base.ts | 35 + src/compiler/factory/converters.ts | 139 + src/compiler/{ => factory}/emitHelpers.ts | 9 + src/compiler/factory/emitNode.ts | 270 ++ src/compiler/{ => factory}/factory.ts | 2379 ++++------------- src/compiler/factory/nodeTests.ts | 758 ++++++ .../{ => factory}/parenthesizerRules.ts | 18 +- src/compiler/factory/utilities.ts | 778 ++++++ src/compiler/parser.ts | 161 +- src/compiler/program.ts | 38 +- src/compiler/transformers/ts.ts | 8 +- src/compiler/tsconfig.json | 11 +- src/compiler/types.ts | 471 +++- src/compiler/utilities.ts | 1213 +++------ src/compiler/visitor.ts | 41 +- ...dConvertToUnknownForNonOverlappingTypes.ts | 2 +- .../codefixes/annotateWithTypeFromJSDoc.ts | 2 +- src/services/codefixes/convertToEs6Module.ts | 2 +- .../codefixes/fixAwaitInSyncFunction.ts | 2 +- src/services/codefixes/helpers.ts | 2 +- src/services/codefixes/inferFromUsage.ts | 2 +- .../convertParamsToDestructuredObject.ts | 6 +- src/services/refactors/extractSymbol.ts | 2 +- src/services/refactors/extractType.ts | 4 +- .../generateGetAccessorAndSetAccessor.ts | 4 +- src/services/signatureHelp.ts | 4 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 2 +- src/testRunner/unittests/asserts.ts | 6 +- src/testRunner/unittests/printer.ts | 2 +- src/testRunner/unittests/transform.ts | 4 +- 35 files changed, 3444 insertions(+), 2967 deletions(-) create mode 100644 src/compiler/factory/base.ts create mode 100644 src/compiler/factory/converters.ts rename src/compiler/{ => factory}/emitHelpers.ts (96%) create mode 100644 src/compiler/factory/emitNode.ts rename src/compiler/{ => factory}/factory.ts (70%) create mode 100644 src/compiler/factory/nodeTests.ts rename src/compiler/{ => factory}/parenthesizerRules.ts (95%) create mode 100644 src/compiler/factory/utilities.ts diff --git a/src/compat/factory.ts b/src/compat/factory.ts index 66fa2c5a33e..39e3d313541 100644 --- a/src/compat/factory.ts +++ b/src/compat/factory.ts @@ -1,6 +1,7 @@ namespace ts { // NOTE: These exports are deprecated in favor of using a `NodeFactory` instance and exist here purely for backwards compatibility reasons. export const { + createNodeArray, createNumericLiteral, createBigIntLiteral, createStringLiteral, diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4e62d48b0b4..f8a10320244 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3785,7 +3785,7 @@ namespace ts { function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); - const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) : undefined; + const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) : undefined; const questionToken = type.declaration.questionToken ? factory.createToken(type.declaration.questionToken.kind) : undefined; let appropriateConstraintTypeNode: TypeNode; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { @@ -4249,7 +4249,7 @@ namespace ts { context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum const node = factory.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); if (typeArguments) { - node.typeArguments = createNodeArray(typeArguments); + node.typeArguments = factory.createNodeArray(typeArguments); } return node; } @@ -4411,7 +4411,7 @@ namespace ts { let typeParameterNodes: NodeArray | undefined; const targetSymbol = getTargetSymbol(symbol); if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { - typeParameterNodes = createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); + typeParameterNodes = factory.createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); } return typeParameterNodes; } @@ -21819,14 +21819,14 @@ namespace ts { } if (hasRestParameter || hasSpreadArgument) { - spanArray = createNodeArray(args); + spanArray = factory.createNodeArray(args); if (hasSpreadArgument && argCount) { const nextArg = elementAt(args, getSpreadArgumentIndex(args) + 1) || undefined; - spanArray = createNodeArray(args.slice(max > argCount && nextArg ? args.indexOf(nextArg) : Math.min(max, args.length - 1))); + spanArray = factory.createNodeArray(args.slice(max > argCount && nextArg ? args.indexOf(nextArg) : Math.min(max, args.length - 1))); } } else { - spanArray = createNodeArray(args.slice(max)); + spanArray = factory.createNodeArray(args.slice(max)); } spanArray.pos = first(spanArray).pos; @@ -28058,7 +28058,7 @@ namespace ts { } } - function checkRightHandSideOfForOf(rhsExpression: Expression, awaitModifier: AwaitKeywordToken | undefined): Type { + function checkRightHandSideOfForOf(rhsExpression: Expression, awaitModifier: AwaitKeyword | undefined): Type { const expressionType = checkNonNullExpression(rhsExpression); const use = awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf; return checkIteratedTypeOrElementType(use, expressionType, undefinedType, rhsExpression); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 44f320aec41..264506e13a3 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2083,9 +2083,14 @@ namespace ts { } } + export interface OverloadOptions { + minLength?: A["length"]; + maxLength?: A["length"]; + } + export interface OverloadLengthOptions { + length: A["length"]; + } 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; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 262b6e65d50..26e0d3bfe86 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -642,7 +642,7 @@ namespace ts { !host.useCaseSensitiveFileNames() ); sourceFile.text = ""; - sourceFile.statements = createNodeArray(); + sourceFile.statements = factory.createNodeArray(); return sourceFile; }); const jsBundle = Debug.assertDefined(bundle.js); @@ -650,7 +650,7 @@ namespace ts { const sourceFile = sourceFiles[prologueInfo.file]; sourceFile.text = prologueInfo.text; sourceFile.end = prologueInfo.text.length; - sourceFile.statements = createNodeArray(prologueInfo.directives.map(directive => { + sourceFile.statements = factory.createNodeArray(prologueInfo.directives.map(directive => { const statement = createNode(SyntaxKind.ExpressionStatement, directive.pos, directive.end) as PrologueDirective; statement.expression = createNode(SyntaxKind.StringLiteral, directive.expression.pos, directive.expression.end) as StringLiteral; statement.expression.text = directive.expression.text; @@ -3357,15 +3357,15 @@ namespace ts { } function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) { - emitList(lit, createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment); + emitList(lit, factory.createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment); } function emitJSDocSignature(sig: JSDocSignature) { if (sig.typeParameters) { - emitList(sig, createNodeArray(sig.typeParameters), ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.typeParameters), ListFormat.JSDocComment); } if (sig.parameters) { - emitList(sig, createNodeArray(sig.parameters), ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.parameters), ListFormat.JSDocComment); } if (sig.type) { writeLine(); diff --git a/src/compiler/factory/base.ts b/src/compiler/factory/base.ts new file mode 100644 index 00000000000..03d607e7a20 --- /dev/null +++ b/src/compiler/factory/base.ts @@ -0,0 +1,35 @@ +/* @internal */ +namespace ts { + /* @internal */ + export function createBaseNodeFactory(): BaseNodeFactory { + // tslint:disable variable-name + let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + // tslint:enable variable-name + + return { + createBaseSourceFileNode, + createBaseIdentifierNode, + createBaseTokenNode, + createBaseNode + }; + + function createBaseSourceFileNode(kind: SyntaxKind): Node { + return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseIdentifierNode(kind: SyntaxKind): Node { + return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseTokenNode(kind: SyntaxKind): Node { + return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + + function createBaseNode(kind: SyntaxKind): Node { + return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + } + } +} \ No newline at end of file diff --git a/src/compiler/factory/converters.ts b/src/compiler/factory/converters.ts new file mode 100644 index 00000000000..110638e0bc4 --- /dev/null +++ b/src/compiler/factory/converters.ts @@ -0,0 +1,139 @@ +/* @internal */ +namespace ts { + export function createNodeConverters(factory: NodeFactory): NodeConverters { + return { + convertToFunctionBlock, + convertToFunctionExpression, + convertToArrayAssignmentElement, + convertToObjectAssignmentElement, + convertToAssignmentPattern, + convertToObjectAssignmentPattern, + convertToArrayAssignmentPattern, + convertToAssignmentElementTarget, + }; + + function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block { + if (isBlock(node)) return node; + const returnStatement = factory.createReturn(node); + setTextRange(returnStatement, node); + const body = factory.createBlock([returnStatement], multiLine); + setTextRange(body, node); + aggregateTransformFlags(body); + return body; + } + + function convertToFunctionExpression(node: FunctionDeclaration) { + if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`); + const updated = factory.createFunctionExpression( + node.modifiers, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + node.body + ); + setOriginalNode(updated, node); + setTextRange(updated, node); + if (getStartsOnNewLine(node)) { + setStartsOnNewLine(updated, /*newLine*/ true); + } + aggregateTransformFlags(updated); + return updated; + } + + function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) { + if (isBindingElement(element)) { + if (element.dotDotDotToken) { + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpread(element.name), element), element); + } + const expression = convertToAssignmentElementTarget(element.name); + return element.initializer + ? setOriginalNode( + setTextRange( + factory.createAssignment(expression, element.initializer), + element + ), + element + ) + : expression; + } + return cast(element, isExpression); + } + + function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) { + if (isBindingElement(element)) { + if (element.dotDotDotToken) { + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element); + } + if (element.propertyName) { + const expression = convertToAssignmentElementTarget(element.name); + return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); + } + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); + } + + return cast(element, isObjectLiteralElementLike); + } + + function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern { + switch (node.kind) { + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + return convertToArrayAssignmentPattern(node); + + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ObjectLiteralExpression: + return convertToObjectAssignmentPattern(node); + } + } + + function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { + if (isObjectBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createObjectLiteral(map(node.elements, convertToObjectAssignmentElement)), + node + ), + node + ); + } + return cast(node, isObjectLiteralExpression); + } + + function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { + if (isArrayBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createArrayLiteral(map(node.elements, convertToArrayAssignmentElement)), + node + ), + node + ); + } + return cast(node, isArrayLiteralExpression); + } + + function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression { + if (isBindingPattern(node)) { + return convertToAssignmentPattern(node); + } + + return cast(node, isExpression); + } + } + + export const nullNodeConverters: NodeConverters = { + convertToFunctionBlock: notImplemented, + convertToFunctionExpression: notImplemented, + convertToArrayAssignmentElement: notImplemented, + convertToObjectAssignmentElement: notImplemented, + convertToAssignmentPattern: notImplemented, + convertToObjectAssignmentPattern: notImplemented, + convertToArrayAssignmentPattern: notImplemented, + convertToAssignmentElementTarget: notImplemented, + }; +} \ No newline at end of file diff --git a/src/compiler/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts similarity index 96% rename from src/compiler/emitHelpers.ts rename to src/compiler/factory/emitHelpers.ts index de3246f3cbd..93fdb20c072 100644 --- a/src/compiler/emitHelpers.ts +++ b/src/compiler/factory/emitHelpers.ts @@ -343,6 +343,15 @@ namespace ts { } } + /* @internal */ + export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { + if (x === y) return Comparison.EqualTo; + if (x.priority === y.priority) return Comparison.EqualTo; + if (x.priority === undefined) return Comparison.GreaterThan; + if (y.priority === undefined) return Comparison.LessThan; + return compareValues(x.priority, y.priority); + } + /** * @param input Template string input strings * @param args Names which need to be made file-level unique diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts new file mode 100644 index 00000000000..d4b35d99aea --- /dev/null +++ b/src/compiler/factory/emitNode.ts @@ -0,0 +1,270 @@ +namespace ts { + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + export function disposeEmitNodes(sourceFile: SourceFile | undefined) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); + const emitNode = sourceFile && sourceFile.emitNode; + const annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (const node of annotatedNodes) { + node.emitNode = undefined; + } + } + } + + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + */ + /* @internal */ + export function getOrCreateEmitNode(node: Node): EmitNode { + if (!node.emitNode) { + if (isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === SyntaxKind.SourceFile) { + return node.emitNode = { annotatedNodes: [node] } as EmitNode; + } + + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) || Debug.fail("Could not determine parsed source file."); + getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); + } + + node.emitNode = {} as EmitNode; + } + + return node.emitNode; + } + + /** + * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. + * @internal + */ + export function removeAllComments(node: T): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags |= EmitFlags.NoComments; + emitNode.leadingComments = undefined; + emitNode.trailingComments = undefined; + return node; + } + + /** + * Sets flags that control emit behavior of a node. + */ + export function setEmitFlags(node: T, emitFlags: EmitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + + /** + * Sets flags that control emit behavior of a node. + */ + /* @internal */ + export function addEmitFlags(node: T, emitFlags: EmitFlags) { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags = emitNode.flags | emitFlags; + return node; + } + + /** + * Gets a custom text range to use when emitting source maps. + */ + export function getSourceMapRange(node: Node): SourceMapRange { + const emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + + /** + * Sets a custom text range to use when emitting source maps. + */ + export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + + /** + * Gets the TextRange to use for source maps for a token of a node. + */ + export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { + const emitNode = node.emitNode; + const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } + + /** + * Sets the TextRange to use for source maps for a token of a node. + */ + export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { + const emitNode = getOrCreateEmitNode(node); + const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); + tokenSourceMapRanges[token] = range; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function getStartsOnNewLine(node: Node) { + const emitNode = node.emitNode; + return emitNode && emitNode.startsOnNewLine; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function setStartsOnNewLine(node: T, newLine: boolean) { + getOrCreateEmitNode(node).startsOnNewLine = newLine; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + */ + export function getCommentRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + export function setCommentRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + + export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.leadingComments; + } + + export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { + getOrCreateEmitNode(node).leadingComments = comments; + return node; + } + + export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); + } + + export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.trailingComments; + } + + export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { + getOrCreateEmitNode(node).trailingComments = comments; + return node; + } + + export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); + } + + export function moveSyntheticComments(node: T, original: Node): T { + setSyntheticLeadingComments(node, getSyntheticLeadingComments(original)); + setSyntheticTrailingComments(node, getSyntheticTrailingComments(original)); + const emit = getOrCreateEmitNode(original); + emit.leadingComments = undefined; + emit.trailingComments = undefined; + return node; + } + + /** + * Gets the constant value to emit for an expression. + */ + export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.constantValue; + } + + /** + * Sets the constant value to emit for an expression. + */ + export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number) { + const emitNode = getOrCreateEmitNode(node); + emitNode.constantValue = value; + return node; + } + + /** + * Adds an EmitHelper to a node. + */ + export function addEmitHelper(node: T, helper: EmitHelper): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.helpers = append(emitNode.helpers, helper); + return node; + } + + /** + * Add EmitHelpers to a node. + */ + export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { + if (some(helpers)) { + const emitNode = getOrCreateEmitNode(node); + for (const helper of helpers) { + emitNode.helpers = appendIfUnique(emitNode.helpers, helper); + } + } + return node; + } + + /** + * Removes an EmitHelper from a node. + */ + export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { + const emitNode = node.emitNode; + if (emitNode) { + const helpers = emitNode.helpers; + if (helpers) { + return orderedRemoveItem(helpers, helper); + } + } + return false; + } + + /** + * Gets the EmitHelpers of a node. + */ + export function getEmitHelpers(node: Node): EmitHelper[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.helpers; + } + + /** + * Moves matching emit helpers from a source node to a target node. + */ + export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { + const sourceEmitNode = source.emitNode; + const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; + if (!some(sourceEmitHelpers)) return; + + const targetEmitNode = getOrCreateEmitNode(target); + let helpersRemoved = 0; + for (let i = 0; i < sourceEmitHelpers.length; i++) { + const helper = sourceEmitHelpers[i]; + if (predicate(helper)) { + helpersRemoved++; + targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); + } + else if (helpersRemoved > 0) { + sourceEmitHelpers[i - helpersRemoved] = helper; + } + } + + if (helpersRemoved > 0) { + sourceEmitHelpers.length -= helpersRemoved; + } + } +} \ No newline at end of file diff --git a/src/compiler/factory.ts b/src/compiler/factory/factory.ts similarity index 70% rename from src/compiler/factory.ts rename to src/compiler/factory/factory.ts index 9f0b19d9b85..9f0e79c7032 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory/factory.ts @@ -2,30 +2,18 @@ namespace ts { let nextAutoGenerateId = 0; /* @internal */ - export function createNodeFactory( - createNode: (kind: SyntaxKind) => Node, - createParenthesizerRules: (factory: NodeFactory) => ParenthesizerRules, - createNodeConverters: (factory: NodeFactory) => NodeConverters, - treeStateObserver: TreeStateObserver - ): NodeFactory { - 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; - + export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory, treeStateObserver?: TreeStateObserver): NodeFactory { + const parenthesizer = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); + const getConverters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); + const createNode = observeResult(baseFactory.createBaseNode, treeStateObserver && treeStateObserver.onCreateNode); + const createTokenNode = observeResult(baseFactory.createBaseTokenNode, treeStateObserver && treeStateObserver.onCreateNode); + const createIdentifierNode = observeResult(baseFactory.createBaseIdentifierNode, treeStateObserver && treeStateObserver.onCreateNode); + const createSourceFileNode = observeResult(baseFactory.createBaseSourceFileNode, treeStateObserver && treeStateObserver.onCreateNode); + const setChild = observeArguments(setChildWorker, treeStateObserver && treeStateObserver.onSetChild); + const setChildren = observeArguments(setChildrenWorker, treeStateObserver && treeStateObserver.onSetChildren); + const finish = observeResult(finishWorker, treeStateObserver && treeStateObserver.onFinishNode); + const update = observeArguments(updateWorker, treeStateObserver && treeStateObserver.onUpdateNode); + const reuse = observeResult(reuseWorker, treeStateObserver && treeStateObserver.onReuseNode); const factory: NodeFactory = { getParenthesizerRules: parenthesizer, getConverters, @@ -137,10 +125,7 @@ namespace ts { updateObjectLiteral: updateObjectLiteralExpression, createPropertyAccess: (expression, name) => { const node = createPropertyAccessExpression(expression, name); - if (needsNoIndentationOnPropertyAccess === undefined) { - needsNoIndentationOnPropertyAccess = !!(node.flags & NodeFlags.Synthesized); - } - if (needsNoIndentationOnPropertyAccess) { + if (flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess) { setEmitFlags(node, EmitFlags.NoIndentation); } return node; @@ -373,6 +358,7 @@ namespace ts { updateSpreadAssignment, createEnumMember, updateEnumMember, + createSourceFile, updateSourceFile, createNotEmittedStatement, createEndOfDeclarationMarker, @@ -429,6 +415,26 @@ namespace ts { return factory; + // @api + function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray { + if (!elements || elements === emptyArray) { + elements = []; + } + else if (isNodeArray(elements)) { + return elements; + } + + // Since the element list of a node array is typically created by starting with an empty array and + // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for + // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. + const length = elements.length; + const array = >(length >= 1 && length <= 4 ? elements.slice() : elements); + array.pos = -1; + array.end = -1; + array.hasTrailingComma = hasTrailingComma; + return array; + } + function createBaseNode(kind: T["kind"]): T { return createNode(kind) as T; } @@ -499,7 +505,7 @@ namespace ts { function updateBaseSignatureDeclaration(updated: T, original: T) { if (original.typeArguments) updated.typeArguments = original.typeArguments; - return updateNode(updated, original); + return update(updated, original); } function createBaseFunctionLikeDeclaration( @@ -615,7 +621,7 @@ namespace ts { kind: T["kind"], text: string ) { - const node = createBaseNode(kind); + const node = createTokenNode(kind) as T; node.text = text; node.hasExtendedUnicodeEscape = undefined; node.isUnterminated = undefined; @@ -626,13 +632,13 @@ namespace ts { function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { const node = createBaseLiteral(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value); node.numericLiteralFlags = numericLiteralFlags; - return finishNode(node); + return finish(node); } // @api function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { const node = createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); - return finishNode(node); + return finish(node); } function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { @@ -642,22 +648,23 @@ namespace ts { } // @api - function createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral { + function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral { const node = createBaseStringLiteral(text, isSingleQuote); - return finishNode(node); + node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + return finish(node); } // @api function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); node.textSourceNode = sourceNode; - return finishNode(node); + return finish(node); } // @api function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { const node = createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); - return finishNode(node); + return finish(node); } // @api @@ -684,7 +691,7 @@ namespace ts { if (originalKeywordKind === SyntaxKind.Identifier) { originalKeywordKind = undefined; } - const node = createBaseNode(SyntaxKind.Identifier); + const node = createIdentifierNode(SyntaxKind.Identifier) as Identifier; node.originalKeywordKind = originalKeywordKind; node.escapedText = escapeLeadingUnderscores(text); if (typeArguments) { @@ -704,21 +711,21 @@ namespace ts { // @api function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier { const node = createBaseIdentifier(text, typeArguments, originalKeywordKind); - return finishNode(node); + return finish(node); } // @api function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments - ? updateNode(createIdentifier(idText(node), typeArguments), node) - : reuseNode(node); + ? update(createIdentifier(idText(node), typeArguments), node) + : reuse(node); } // @api function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { let flags = GeneratedIdentifierFlags.Auto; if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; - const name = finishNode(createBaseGeneratedIdentifier("", flags)); + const name = finish(createBaseGeneratedIdentifier("", flags)); if (recordTempVariable) { recordTempVariable(name); } @@ -728,24 +735,24 @@ namespace ts { /** Create a unique temporary variable for use in a loop. */ // @api function createLoopVariable(): Identifier { - return finishNode(createBaseGeneratedIdentifier("", GeneratedIdentifierFlags.Loop)); + return finish(createBaseGeneratedIdentifier("", GeneratedIdentifierFlags.Loop)); } /** Create a unique name based on the supplied text. */ // @api function createUniqueName(text: string): Identifier { - return finishNode(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique)); + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique)); } // @api function createOptimisticUniqueName(text: string): Identifier { - return finishNode(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic)); + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic)); } /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ // @api function createFileLevelUniqueName(text: string): Identifier { - return finishNode(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)); + return finish(createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)); } /** Create a unique name generated for a node. */ @@ -753,20 +760,20 @@ namespace ts { function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0): Identifier { const name = createBaseGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags); name.original = node; - return finishNode(name); + return finish(name); } // // Punctuation // - function createBaseToken(token: TKind) { - return createBaseNode>(token); - } - // @api function createToken(token: TKind) { - return finishNode(createBaseToken(token)); + Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); + Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); + Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); + Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); + return finish(createTokenNode(token) as Token); } // @@ -775,27 +782,27 @@ namespace ts { // @api function createSuperExpression() { - return finishNode(createBaseToken(SyntaxKind.SuperKeyword)) as SuperExpression; + return createToken(SyntaxKind.SuperKeyword) as SuperExpression; } // @api function createThisExpression() { - return finishNode(createBaseToken(SyntaxKind.ThisKeyword)) as ThisExpression; + return createToken(SyntaxKind.ThisKeyword) as ThisExpression; } // @api function createNull() { - return finishNode(createBaseToken(SyntaxKind.NullKeyword)) as NullLiteral; + return createToken(SyntaxKind.NullKeyword) as NullLiteral; } // @api function createTrue() { - return finishNode(createBaseToken(SyntaxKind.TrueKeyword)) as TrueLiteral; + return createToken(SyntaxKind.TrueKeyword) as TrueLiteral; } // @api function createFalse() { - return finishNode(createBaseToken(SyntaxKind.FalseKeyword)) as FalseLiteral; + return createToken(SyntaxKind.FalseKeyword) as FalseLiteral; } // @@ -804,7 +811,7 @@ namespace ts { // @api function createModifier(kind: T): Token { - return finishNode(createBaseToken(kind)); + return createToken(kind); } // @api @@ -833,29 +840,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.QualifiedName); setChild(node, node.left = left); setChild(node, node.right = asName(right)); - return finishNode(node); + return finish(node); } // @api function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { return node.left !== left || node.right !== right - ? updateNode(createQualifiedName(left, right), node) - : reuseNode(node); + ? update(createQualifiedName(left, right), node) + : reuse(node); } // @api function createComputedPropertyName(expression: Expression) { const node = createBaseNode(SyntaxKind.ComputedPropertyName); setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfComputedPropertyName(expression)); - return finishNode(node); + return finish(node); } // @api function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { return node.expression !== expression - ? updateNode(createComputedPropertyName(expression), node) - : reuseNode(node); + ? update(createComputedPropertyName(expression), node) + : reuse(node); } // @@ -872,7 +879,7 @@ namespace ts { ); setChild(node, node.constraint = constraint); setChild(node, node.default = defaultType); - return finishNode(node); + return finish(node); } // @api @@ -880,8 +887,8 @@ namespace ts { return node.name !== name || node.constraint !== constraint || node.default !== defaultType - ? updateNode(createTypeParameterDeclaration(name, constraint, defaultType), node) - : reuseNode(node); + ? update(createTypeParameterDeclaration(name, constraint, defaultType), node) + : reuse(node); } // @api @@ -904,7 +911,7 @@ namespace ts { ); setChild(node, node.dotDotDotToken = dotDotDotToken); setChild(node, node.questionToken = questionToken); - return finishNode(node); + return finish(node); } // @api @@ -925,22 +932,22 @@ namespace ts { || node.questionToken !== questionToken || node.type !== type || node.initializer !== initializer - ? updateNode(createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node) - : reuseNode(node); + ? update(createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node) + : reuse(node); } // @api function createDecorator(expression: Expression) { const node = createBaseNode(SyntaxKind.Decorator); setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); - return finishNode(node); + return finish(node); } // @api function updateDecorator(node: Decorator, expression: Expression) { return node.expression !== expression - ? updateNode(createDecorator(expression), node) - : reuseNode(node); + ? update(createDecorator(expression), node) + : reuse(node); } // @@ -962,7 +969,7 @@ namespace ts { ); setChild(node, node.type = type); setChild(node, node.questionToken = questionToken); - return finishNode(node); + return finish(node); } // @api @@ -977,8 +984,8 @@ namespace ts { || node.name !== name || node.questionToken !== questionToken || node.type !== type - ? updateNode(createPropertySignature(modifiers, name, questionToken, type), node) - : reuseNode(node); + ? update(createPropertySignature(modifiers, name, questionToken, type), node) + : reuse(node); } // @api @@ -1000,7 +1007,7 @@ namespace ts { ); 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); + return finish(node); } // @api @@ -1020,8 +1027,8 @@ namespace ts { || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === SyntaxKind.ExclamationToken ? questionOrExclamationToken : undefined) || node.type !== type || node.initializer !== initializer - ? updateNode(createPropertyDeclaration(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) - : reuseNode(node); + ? update(createPropertyDeclaration(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) + : reuse(node); } // @api @@ -1043,7 +1050,7 @@ namespace ts { type ); setChild(node, node.questionToken = questionToken); - return finishNode(node); + return finish(node); } // @api @@ -1063,7 +1070,7 @@ namespace ts { || node.parameters !== parameters || node.type !== type ? updateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1090,7 +1097,7 @@ namespace ts { ); setChild(node, node.asteriskToken = asteriskToken); setChild(node, node.questionToken = questionToken); - return finishNode(node); + return finish(node); } // @api @@ -1116,7 +1123,7 @@ namespace ts { || node.type !== type || node.body !== body ? updateBaseFunctionLikeDeclaration(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1136,7 +1143,7 @@ namespace ts { /*type*/ undefined, body ); - return finishNode(node); + return finish(node); } // @api @@ -1152,7 +1159,7 @@ namespace ts { || node.parameters !== parameters || node.body !== body ? updateBaseFunctionLikeDeclaration(createConstructorDeclaration(decorators, modifiers, parameters, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1174,7 +1181,7 @@ namespace ts { type, body ); - return finishNode(node); + return finish(node); } // @api @@ -1194,7 +1201,7 @@ namespace ts { || node.type !== type || node.body !== body ? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1215,7 +1222,7 @@ namespace ts { /*type*/ undefined, body ); - return finishNode(node); + return finish(node); } // @api @@ -1233,7 +1240,7 @@ namespace ts { || node.parameters !== parameters || node.body !== body ? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1251,7 +1258,7 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api @@ -1265,7 +1272,7 @@ namespace ts { || node.parameters !== parameters || node.type !== type ? updateBaseSignatureDeclaration(createCallSignature(typeParameters, parameters, type), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1283,7 +1290,7 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api @@ -1297,7 +1304,7 @@ namespace ts { || node.parameters !== parameters || node.type !== type ? updateBaseSignatureDeclaration(createConstructSignature(typeParameters, parameters, type), node) - : reuseNode(node); + : reuse(node); } // Route signature creation to the appropriate factory method. Used by the NodeBuilder in the checker. @@ -1360,7 +1367,7 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api @@ -1376,7 +1383,7 @@ namespace ts { || node.decorators !== decorators || node.modifiers !== modifiers ? updateBaseSignatureDeclaration(createIndexSignature(decorators, modifiers, parameters, type), node) - : reuseNode(node); + : reuse(node); } // @@ -1385,7 +1392,7 @@ namespace ts { // @api function createKeywordTypeNode(kind: KeywordTypeNode["kind"]) { - return finishNode(createBaseToken(kind)) as KeywordTypeNode; + return createToken(kind) as KeywordTypeNode; } // @api @@ -1393,15 +1400,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.TypePredicate); setChild(node, node.parameterName = asName(parameterName)); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) { return node.parameterName !== parameterName || node.type !== type - ? updateNode(createTypePredicateNode(parameterName, type), node) - : reuseNode(node); + ? update(createTypePredicateNode(parameterName, type), node) + : reuse(node); } // @api @@ -1409,15 +1416,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.TypeReference); setChild(node, node.typeName = asName(typeName)); setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); - return finishNode(node); + return finish(node); } // @api function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { return node.typeName !== typeName || node.typeArguments !== typeArguments - ? updateNode(createTypeReferenceNode(typeName, typeArguments), node) - : reuseNode(node); + ? update(createTypeReferenceNode(typeName, typeArguments), node) + : reuse(node); } // @api @@ -1435,7 +1442,7 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api @@ -1449,7 +1456,7 @@ namespace ts { || node.parameters !== parameters || node.type !== type ? updateBaseSignatureDeclaration(createFunctionTypeNode(typeParameters, parameters, type), node) - : reuseNode(node); + : reuse(node); } // @api @@ -1467,7 +1474,7 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api @@ -1481,103 +1488,103 @@ namespace ts { || node.parameters !== parameters || node.type !== type ? updateBaseSignatureDeclaration(createConstructorTypeNode(typeParameters, parameters, type), node) - : reuseNode(node); + : reuse(node); } // @api function createTypeQueryNode(exprName: EntityName) { const node = createBaseNode(SyntaxKind.TypeQuery); setChild(node, node.exprName = exprName); - return finishNode(node); + return finish(node); } // @api function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { return node.exprName !== exprName - ? updateNode(createTypeQueryNode(exprName), node) - : reuseNode(node); + ? update(createTypeQueryNode(exprName), node) + : reuse(node); } // @api function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { const node = createBaseNode(SyntaxKind.TypeLiteral); setChildren(node, node.members = createNodeArray(members)); - return finishNode(node); + return finish(node); } // @api function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray) { return node.members !== members - ? updateNode(createTypeLiteralNode(members), node) - : reuseNode(node); + ? update(createTypeLiteralNode(members), node) + : reuse(node); } // @api function createArrayTypeNode(elementType: TypeNode) { const node = createBaseNode(SyntaxKind.ArrayType); setChild(node, node.elementType = parenthesizer().parenthesizeElementTypeOfArrayType(elementType)); - return finishNode(node); + return finish(node); } // @api function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { return node.elementType !== elementType - ? updateNode(createArrayTypeNode(elementType), node) - : reuseNode(node); + ? update(createArrayTypeNode(elementType), node) + : reuse(node); } // @api function createTupleTypeNode(elementTypes: readonly TypeNode[]) { const node = createBaseNode(SyntaxKind.TupleType); setChildren(node, node.elementTypes = createNodeArray(elementTypes)); - return finishNode(node); + return finish(node); } // @api function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]) { return node.elementTypes !== elementTypes - ? updateNode(createTupleTypeNode(elementTypes), node) - : reuseNode(node); + ? update(createTupleTypeNode(elementTypes), node) + : reuse(node); } // @api function createOptionalTypeNode(type: TypeNode) { const node = createBaseNode(SyntaxKind.OptionalType); setChild(node, node.type = parenthesizer().parenthesizeElementTypeOfArrayType(type)); - return finishNode(node); + return finish(node); } // @api function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode { return node.type !== type - ? updateNode(createOptionalTypeNode(type), node) - : reuseNode(node); + ? update(createOptionalTypeNode(type), node) + : reuse(node); } // @api function createRestTypeNode(type: TypeNode) { const node = createBaseNode(SyntaxKind.RestType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode { return node.type !== type - ? updateNode(createRestTypeNode(type), node) - : reuseNode(node); + ? update(createRestTypeNode(type), node) + : reuse(node); } function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) { const node = createBaseNode(kind); setChildren(node, node.types = parenthesizer().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types))); - return finishNode(node); + return finish(node); } function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray): T { return node.types !== types - ? updateNode(createUnionOrIntersectionTypeNode(node.kind, types), node) - : reuseNode(node); + ? update(createUnionOrIntersectionTypeNode(node.kind, types), node) + : reuse(node); } // @api @@ -1607,7 +1614,7 @@ namespace ts { setChild(node, node.extendsType = parenthesizer().parenthesizeMemberOfConditionalType(extendsType)); setChild(node, node.trueType = trueType); setChild(node, node.falseType = falseType); - return finishNode(node); + return finish(node); } // @api @@ -1616,22 +1623,22 @@ namespace ts { || node.extendsType !== extendsType || node.trueType !== trueType || node.falseType !== falseType - ? updateNode(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node) - : reuseNode(node); + ? update(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node) + : reuse(node); } // @api function createInferTypeNode(typeParameter: TypeParameterDeclaration) { const node = createBaseNode(SyntaxKind.InferType); setChild(node, node.typeParameter = typeParameter); - return finishNode(node); + return finish(node); } // @api function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) { return node.typeParameter !== typeParameter - ? updateNode(createInferTypeNode(typeParameter), node) - : reuseNode(node); + ? update(createInferTypeNode(typeParameter), node) + : reuse(node); } // @api @@ -1641,7 +1648,7 @@ namespace ts { setChild(node, node.qualifier = qualifier); setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); node.isTypeOf = isTypeOf; - return finishNode(node); + return finish(node); } // @api @@ -1650,27 +1657,27 @@ namespace ts { || node.qualifier !== qualifier || node.typeArguments !== typeArguments || node.isTypeOf !== isTypeOf - ? updateNode(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node) - : reuseNode(node); + ? update(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node) + : reuse(node); } // @api function createParenthesizedType(type: TypeNode) { const node = createBaseNode(SyntaxKind.ParenthesizedType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) { return node.type !== type - ? updateNode(createParenthesizedType(type), node) - : reuseNode(node); + ? update(createParenthesizedType(type), node) + : reuse(node); } // @api function createThisTypeNode() { - return finishNode(createBaseNode(SyntaxKind.ThisType)); + return finish(createBaseNode(SyntaxKind.ThisType)); } // @api @@ -1678,14 +1685,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.TypeOperator); node.operator = operator; setChild(node, node.type = parenthesizer().parenthesizeMemberOfElementType(type)); - return finishNode(node); + return finish(node); } // @api function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) { return node.type !== type - ? updateNode(createTypeOperatorNode(node.operator, type), node) - : reuseNode(node); + ? update(createTypeOperatorNode(node.operator, type), node) + : reuse(node); } // @api @@ -1693,49 +1700,49 @@ namespace ts { const node = createBaseNode(SyntaxKind.IndexedAccessType); setChild(node, node.objectType = parenthesizer().parenthesizeMemberOfElementType(objectType)); setChild(node, node.indexType = indexType); - return finishNode(node); + return finish(node); } // @api function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { return node.objectType !== objectType || node.indexType !== indexType - ? updateNode(createIndexedAccessTypeNode(objectType, indexType), node) - : reuseNode(node); + ? update(createIndexedAccessTypeNode(objectType, indexType), node) + : reuse(node); } // @api - function createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { const node = createBaseNode(SyntaxKind.MappedType); setChild(node, node.readonlyToken = readonlyToken); setChild(node, node.typeParameter = typeParameter); setChild(node, node.questionToken = questionToken); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api - function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { + function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode { return node.readonlyToken !== readonlyToken || node.typeParameter !== typeParameter || node.questionToken !== questionToken || node.type !== type - ? updateNode(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node) - : reuseNode(node); + ? update(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node) + : reuse(node); } // @api function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { const node = createBaseNode(SyntaxKind.LiteralType); setChild(node, node.literal = literal); - return finishNode(node); + return finish(node); } // @api function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) { return node.literal !== literal - ? updateNode(createLiteralTypeNode(literal), node) - : reuseNode(node); + ? update(createLiteralTypeNode(literal), node) + : reuse(node); } // @@ -1746,28 +1753,28 @@ namespace ts { function createObjectBindingPattern(elements: readonly BindingElement[]) { const node = createBaseNode(SyntaxKind.ObjectBindingPattern); setChildren(node, node.elements = createNodeArray(elements)); - return finishNode(node); + return finish(node); } // @api function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { return node.elements !== elements - ? updateNode(createObjectBindingPattern(elements), node) - : reuseNode(node); + ? update(createObjectBindingPattern(elements), node) + : reuse(node); } // @api function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { const node = createBaseNode(SyntaxKind.ArrayBindingPattern); setChildren(node, node.elements = createNodeArray(elements)); - return finishNode(node); + return finish(node); } // @api function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { return node.elements !== elements - ? updateNode(createArrayBindingPattern(elements), node) - : reuseNode(node); + ? update(createArrayBindingPattern(elements), node) + : reuse(node); } // @api @@ -1781,7 +1788,7 @@ namespace ts { setChild(node, node.propertyName = asName(propertyName)); setChild(node, node.initializer = initializer); setChild(node, node.dotDotDotToken = dotDotDotToken); - return finishNode(node); + return finish(node); } // @api @@ -1790,8 +1797,8 @@ namespace ts { || node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.initializer !== initializer - ? updateNode(createBindingElement(dotDotDotToken, propertyName, name, initializer), node) - : reuseNode(node); + ? update(createBindingElement(dotDotDotToken, propertyName, name, initializer), node) + : reuse(node); } // @@ -1803,14 +1810,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.ArrayLiteralExpression); setChildren(node, node.elements = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements))); if (multiLine) node.multiLine = true; - return finishNode(node); + return finish(node); } // @api function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) { return node.elements !== elements - ? updateNode(createArrayLiteralExpression(elements, node.multiLine), node) - : reuseNode(node); + ? update(createArrayLiteralExpression(elements, node.multiLine), node) + : reuse(node); } // @api @@ -1818,14 +1825,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.ObjectLiteralExpression); setChildren(node, node.properties = createNodeArray(properties)); if (multiLine) node.multiLine = true; - return finishNode(node); + return finish(node); } // @api function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { return node.properties !== properties - ? updateNode(createObjectLiteralExpression(properties, node.multiLine), node) - : reuseNode(node); + ? update(createObjectLiteralExpression(properties, node.multiLine), node) + : reuse(node); } // @api @@ -1833,15 +1840,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.PropertyAccessExpression); setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); setChild(node, node.name = asName(name)); - return finishNode(node); + return finish(node); } // @api function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier) { return node.expression !== expression || node.name !== name - ? updateNode(createPropertyAccessExpression(expression, name), node) - : reuseNode(node); + ? update(createPropertyAccessExpression(expression, name), node) + : reuse(node); } // @api @@ -1849,15 +1856,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.ElementAccessExpression); setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); setChild(node, node.argumentExpression = asExpression(index)); - return finishNode(node); + return finish(node); } // @api function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { return node.expression !== expression || node.argumentExpression !== argumentExpression - ? updateNode(createElementAccessExpression(expression, argumentExpression), node) - : reuseNode(node); + ? update(createElementAccessExpression(expression, argumentExpression), node) + : reuse(node); } // @api @@ -1866,7 +1873,7 @@ namespace ts { setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); setChildren(node, node.arguments = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); - return finishNode(node); + return finish(node); } // @api @@ -1874,8 +1881,8 @@ namespace ts { return node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray - ? updateNode(createCallExpression(expression, typeArguments, argumentsArray), node) - : reuseNode(node); + ? update(createCallExpression(expression, typeArguments, argumentsArray), node) + : reuse(node); } // @api @@ -1884,7 +1891,7 @@ namespace ts { 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); + return finish(node); } // @api @@ -1892,8 +1899,8 @@ namespace ts { return node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray - ? updateNode(createNewExpression(expression, typeArguments, argumentsArray), node) - : reuseNode(node); + ? update(createNewExpression(expression, typeArguments, argumentsArray), node) + : reuse(node); } // @api @@ -1902,7 +1909,7 @@ namespace ts { setChild(node, node.tag = parenthesizer().parenthesizeLeftSideOfAccess(tag)); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); setChild(node, node.template = template); - return finishNode(node); + return finish(node); } // @api @@ -1910,8 +1917,8 @@ namespace ts { return node.tag !== tag || node.typeArguments !== typeArguments || node.template !== template - ? updateNode(createTaggedTemplateExpression(tag, typeArguments, template), node) - : reuseNode(node); + ? update(createTaggedTemplateExpression(tag, typeArguments, template), node) + : reuse(node); } // @api @@ -1919,29 +1926,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.TypeAssertionExpression); setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { return node.type !== type || node.expression !== expression - ? updateNode(createTypeAssertion(type, expression), node) - : reuseNode(node); + ? update(createTypeAssertion(type, expression), node) + : reuse(node); } // @api function createParenthesizedExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.ParenthesizedExpression); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createParenthesizedExpression(expression), node) - : reuseNode(node); + ? update(createParenthesizedExpression(expression), node) + : reuse(node); } // @api @@ -1964,7 +1971,7 @@ namespace ts { type, body); setChild(node, node.asteriskToken = asteriskToken); - return finishNode(node); + return finish(node); } // @api @@ -1986,7 +1993,7 @@ namespace ts { || node.type !== type || node.body !== body ? updateBaseFunctionLikeDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -2009,7 +2016,7 @@ namespace ts { parenthesizer().parenthesizeConciseBodyOfArrowFunction(body) ); setChild(node, node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken)); - return finishNode(node); + return finish(node); } function createArrowFunctionWithoutTokens( @@ -2050,63 +2057,63 @@ namespace ts { || node.equalsGreaterThanToken !== equalsGreaterThanToken || node.body !== body ? updateBaseFunctionLikeDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) - : reuseNode(node); + : reuse(node); } // @api function createDeleteExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.DeleteExpression); setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); - return finishNode(node); + return finish(node); } // @api function updateDeleteExpression(node: DeleteExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createDeleteExpression(expression), node) - : reuseNode(node); + ? update(createDeleteExpression(expression), node) + : reuse(node); } // @api function createTypeOfExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.TypeOfExpression); setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); - return finishNode(node); + return finish(node); } // @api function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createTypeOfExpression(expression), node) - : reuseNode(node); + ? update(createTypeOfExpression(expression), node) + : reuse(node); } // @api function createVoidExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.VoidExpression); setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); - return finishNode(node); + return finish(node); } // @api function updateVoidExpression(node: VoidExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createVoidExpression(expression), node) - : reuseNode(node); + ? update(createVoidExpression(expression), node) + : reuse(node); } // @api function createAwaitExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.AwaitExpression); setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); - return finishNode(node); + return finish(node); } // @api function updateAwaitExpression(node: AwaitExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createAwaitExpression(expression), node) - : reuseNode(node); + ? update(createAwaitExpression(expression), node) + : reuse(node); } // @api @@ -2114,14 +2121,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.PrefixUnaryExpression); node.operator = operator; setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPrefixUnary(operand)); - return finishNode(node); + return finish(node); } // @api function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) { return node.operand !== operand - ? updateNode(createPrefixUnaryExpression(node.operator, operand), node) - : reuseNode(node); + ? update(createPrefixUnaryExpression(node.operator, operand), node) + : reuse(node); } // @api @@ -2129,14 +2136,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.PostfixUnaryExpression); node.operator = operator; setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPostfixUnary(operand)); - return finishNode(node); + return finish(node); } // @api function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) { return node.operand !== operand - ? updateNode(createPostfixUnaryExpression(operand, node.operator), node) - : reuseNode(node); + ? update(createPostfixUnaryExpression(operand, node.operator), node) + : reuse(node); } // @api @@ -2147,15 +2154,15 @@ namespace ts { 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); + return finish(node); } // @api function updateBinaryExpression(node: BinaryExpression, left: Expression, right: Expression, operator?: BinaryOperator | BinaryOperatorToken) { return node.left !== left || node.right !== right - ? updateNode(createBinaryExpression(left, operator || node.operatorToken, right), node) - : reuseNode(node); + ? update(createBinaryExpression(left, operator || node.operatorToken, right), node) + : reuse(node); } // @api @@ -2166,7 +2173,7 @@ namespace ts { setChild(node, node.whenTrue = parenthesizer().parenthesizeBranchOfConditionalExpression(whenTrue)); setChild(node, node.colonToken = colonToken); setChild(node, node.whenFalse = parenthesizer().parenthesizeBranchOfConditionalExpression(whenFalse)); - return finishNode(node); + return finish(node); } function createConditionalExpressionWithoutTokens(condition: Expression, whenTrue: Expression, whenFalse: Expression) { @@ -2187,8 +2194,8 @@ namespace ts { || node.whenTrue !== whenTrue || node.colonToken !== colonToken || node.whenFalse !== whenFalse - ? updateNode(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node) - : reuseNode(node); + ? update(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node) + : reuse(node); } function updateConditionalExpressionWithoutTokens( @@ -2205,15 +2212,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.TemplateExpression); setChild(node, node.head = head); setChildren(node, node.templateSpans = createNodeArray(templateSpans)); - return finishNode(node); + return finish(node); } // @api function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { return node.head !== head || node.templateSpans !== templateSpans - ? updateNode(createTemplateExpression(head, templateSpans), node) - : reuseNode(node); + ? update(createTemplateExpression(head, templateSpans), node) + : reuse(node); } function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined) { @@ -2239,10 +2246,10 @@ namespace ts { // @api function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined) { - const node = createBaseNode(kind); + const node = createTokenNode(kind) as TemplateLiteralLikeNode; node.text = text; node.rawText = rawText; - return finishNode(node); + return finish(node); } // @api @@ -2271,29 +2278,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.YieldExpression); setChild(node, node.expression = expression); setChild(node, node.asteriskToken = asteriskToken); - return finishNode(node); + return finish(node); } // @api function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { return node.expression !== expression || node.asteriskToken !== asteriskToken - ? updateNode(createYieldExpression(asteriskToken, expression), node) - : reuseNode(node); + ? update(createYieldExpression(asteriskToken, expression), node) + : reuse(node); } // @api function createSpreadElement(expression: Expression) { const node = createBaseNode(SyntaxKind.SpreadElement); setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); - return finishNode(node); + return finish(node); } // @api function updateSpreadElement(node: SpreadElement, expression: Expression) { return node.expression !== expression - ? updateNode(createSpreadElement(expression), node) - : reuseNode(node); + ? update(createSpreadElement(expression), node) + : reuse(node); } // @api @@ -2314,7 +2321,7 @@ namespace ts { heritageClauses, members ); - return finishNode(node); + return finish(node); } // @api @@ -2333,13 +2340,13 @@ namespace ts { || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members - ? updateNode(createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : reuseNode(node); + ? update(createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); } // @api function createOmittedExpression() { - return finishNode(createBaseNode(SyntaxKind.OmittedExpression)); + return finish(createBaseNode(SyntaxKind.OmittedExpression)); } // @api @@ -2347,15 +2354,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(typeArguments)); - return finishNode(node); + return finish(node); } // @api function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) { return node.expression !== expression || node.typeArguments !== typeArguments - ? updateNode(createExpressionWithTypeArguments(expression, typeArguments), node) - : reuseNode(node); + ? update(createExpressionWithTypeArguments(expression, typeArguments), node) + : reuse(node); } // @api @@ -2363,29 +2370,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.AsExpression); setChild(node, node.expression = expression); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { return node.expression !== expression || node.type !== type - ? updateNode(createAsExpression(expression, type), node) - : reuseNode(node); + ? update(createAsExpression(expression, type), node) + : reuse(node); } // @api function createNonNullExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.NonNullExpression); setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); - return finishNode(node); + return finish(node); } // @api function updateNonNullExpression(node: NonNullExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createNonNullExpression(expression), node) - : reuseNode(node); + ? update(createNonNullExpression(expression), node) + : reuse(node); } // @api @@ -2393,14 +2400,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.MetaProperty); node.keywordToken = keywordToken; setChild(node, node.name = name); - return finishNode(node); + return finish(node); } // @api function updateMetaProperty(node: MetaProperty, name: Identifier) { return node.name !== name - ? updateNode(createMetaProperty(node.keywordToken, name), node) - : reuseNode(node); + ? update(createMetaProperty(node.keywordToken, name), node) + : reuse(node); } // @@ -2412,20 +2419,20 @@ namespace ts { const node = createBaseNode(SyntaxKind.TemplateSpan); setChild(node, node.expression = expression); setChild(node, node.literal = literal); - return finishNode(node); + return finish(node); } // @api function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { return node.expression !== expression || node.literal !== literal - ? updateNode(createTemplateSpan(expression, literal), node) - : reuseNode(node); + ? update(createTemplateSpan(expression, literal), node) + : reuse(node); } // @api function createSemicolonClassElement() { - return finishNode(createBaseNode(SyntaxKind.SemicolonClassElement)); + return finish(createBaseNode(SyntaxKind.SemicolonClassElement)); } // @@ -2437,48 +2444,48 @@ namespace ts { const node = createBaseNode(SyntaxKind.Block); setChildren(node, node.statements = createNodeArray(statements)); if (multiLine) node.multiLine = multiLine; - return finishNode(node); + return finish(node); } // @api function updateBlock(node: Block, statements: readonly Statement[]) { return node.statements !== statements - ? updateNode(createBlock(statements, node.multiLine), node) - : reuseNode(node); + ? update(createBlock(statements, node.multiLine), node) + : reuse(node); } // @api function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { const node = createBaseDeclaration(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers); setChild(node, node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList); - return finishNode(node); + return finish(node); } // @api function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) { return node.modifiers !== modifiers || node.declarationList !== declarationList - ? updateNode(createVariableStatement(modifiers, declarationList), node) - : reuseNode(node); + ? update(createVariableStatement(modifiers, declarationList), node) + : reuse(node); } // @api function createEmptyStatement() { - return finishNode(createBaseNode(SyntaxKind.EmptyStatement)); + return finish(createBaseNode(SyntaxKind.EmptyStatement)); } // @api function createExpressionStatement(expression: Expression): ExpressionStatement { const node = createBaseNode(SyntaxKind.ExpressionStatement); setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfExpressionStatement(expression)); - return finishNode(node); + return finish(node); } // @api function updateExpressionStatement(node: ExpressionStatement, expression: Expression) { return node.expression !== expression - ? updateNode(createExpressionStatement(expression), node) - : reuseNode(node); + ? update(createExpressionStatement(expression), node) + : reuse(node); } // @api @@ -2487,7 +2494,7 @@ namespace ts { setChild(node, node.expression = expression); setChild(node, node.thenStatement = asEmbeddedStatement(thenStatement)); setChild(node, node.elseStatement = asEmbeddedStatement(elseStatement)); - return finishNode(node); + return finish(node); } // @api @@ -2495,8 +2502,8 @@ namespace ts { return node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement - ? updateNode(createIfStatement(expression, thenStatement, elseStatement), node) - : reuseNode(node); + ? update(createIfStatement(expression, thenStatement, elseStatement), node) + : reuse(node); } // @api @@ -2504,15 +2511,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.DoStatement); setChild(node, node.statement = asEmbeddedStatement(statement)); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) { return node.statement !== statement || node.expression !== expression - ? updateNode(createDoStatement(statement, expression), node) - : reuseNode(node); + ? update(createDoStatement(statement, expression), node) + : reuse(node); } // @api @@ -2520,15 +2527,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.WhileStatement); setChild(node, node.expression = expression); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement - ? updateNode(createWhileStatement(expression, statement), node) - : reuseNode(node); + ? update(createWhileStatement(expression, statement), node) + : reuse(node); } // @api @@ -2538,7 +2545,7 @@ namespace ts { setChild(node, node.condition = condition); setChild(node, node.incrementor = incrementor); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api @@ -2547,8 +2554,8 @@ namespace ts { || node.condition !== condition || node.incrementor !== incrementor || node.statement !== statement - ? updateNode(createForStatement(initializer, condition, incrementor, statement), node) - : reuseNode(node); + ? update(createForStatement(initializer, condition, incrementor, statement), node) + : reuse(node); } // @api @@ -2557,7 +2564,7 @@ namespace ts { setChild(node, node.initializer = initializer); setChild(node, node.expression = expression); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api @@ -2565,70 +2572,70 @@ namespace ts { return node.initializer !== initializer || node.expression !== expression || node.statement !== statement - ? updateNode(createForInStatement(initializer, expression, statement), node) - : reuseNode(node); + ? update(createForInStatement(initializer, expression, statement), node) + : reuse(node); } // @api - function createForOfStatement(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { const node = createBaseNode(SyntaxKind.ForOfStatement); setChild(node, node.awaitModifier = awaitModifier); setChild(node, node.initializer = initializer); setChild(node, node.expression = expression); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api - function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { return node.awaitModifier !== awaitModifier || node.initializer !== initializer || node.expression !== expression || node.statement !== statement - ? updateNode(createForOfStatement(awaitModifier, initializer, expression, statement), node) - : reuseNode(node); + ? update(createForOfStatement(awaitModifier, initializer, expression, statement), node) + : reuse(node); } // @api function createContinueStatement(label?: string | Identifier): ContinueStatement { const node = createBaseNode(SyntaxKind.ContinueStatement); setChild(node, node.label = asName(label)); - return finishNode(node); + return finish(node); } // @api function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) { return node.label !== label - ? updateNode(createContinueStatement(label), node) - : reuseNode(node); + ? update(createContinueStatement(label), node) + : reuse(node); } // @api function createBreakStatement(label?: string | Identifier): BreakStatement { const node = createBaseNode(SyntaxKind.BreakStatement); setChild(node, node.label = asName(label)); - return finishNode(node); + return finish(node); } // @api function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) { return node.label !== label - ? updateNode(createBreakStatement(label), node) - : reuseNode(node); + ? update(createBreakStatement(label), node) + : reuse(node); } // @api function createReturnStatement(expression?: Expression): ReturnStatement { const node = createBaseNode(SyntaxKind.ReturnStatement); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) { return node.expression !== expression - ? updateNode(createReturnStatement(expression), node) - : reuseNode(node); + ? update(createReturnStatement(expression), node) + : reuse(node); } // @api @@ -2636,15 +2643,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.WithStatement); setChild(node, node.expression = expression); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement - ? updateNode(createWithStatement(expression, statement), node) - : reuseNode(node); + ? update(createWithStatement(expression, statement), node) + : reuse(node); } // @api @@ -2652,15 +2659,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.SwitchStatement); setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); setChild(node, node.caseBlock = caseBlock); - return finishNode(node); + return finish(node); } // @api function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { return node.expression !== expression || node.caseBlock !== caseBlock - ? updateNode(createSwitchStatement(expression, caseBlock), node) - : reuseNode(node); + ? update(createSwitchStatement(expression, caseBlock), node) + : reuse(node); } // @api @@ -2668,29 +2675,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.LabeledStatement); setChild(node, node.label = asName(label)); setChild(node, node.statement = asEmbeddedStatement(statement)); - return finishNode(node); + return finish(node); } // @api function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) { return node.label !== label || node.statement !== statement - ? updateNode(createLabeledStatement(label, statement), node) - : reuseNode(node); + ? update(createLabeledStatement(label, statement), node) + : reuse(node); } // @api function createThrowStatement(expression: Expression) { const node = createBaseNode(SyntaxKind.ThrowStatement); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateThrowStatement(node: ThrowStatement, expression: Expression) { return node.expression !== expression - ? updateNode(createThrowStatement(expression), node) - : reuseNode(node); + ? update(createThrowStatement(expression), node) + : reuse(node); } // @api @@ -2699,7 +2706,7 @@ namespace ts { setChild(node, node.tryBlock = tryBlock); setChild(node, node.catchClause = catchClause); setChild(node, node.finallyBlock = finallyBlock); - return finishNode(node); + return finish(node); } // @api @@ -2707,13 +2714,13 @@ namespace ts { return node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock - ? updateNode(createTryStatement(tryBlock, catchClause, finallyBlock), node) - : reuseNode(node); + ? update(createTryStatement(tryBlock, catchClause, finallyBlock), node) + : reuse(node); } // @api function createDebuggerStatement() { - return finishNode(createBaseNode(SyntaxKind.DebuggerStatement)); + return finish(createBaseNode(SyntaxKind.DebuggerStatement)); } // @api @@ -2727,7 +2734,7 @@ namespace ts { initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) ); setChild(node, node.exclamationToken = exclamationToken); - return finishNode(node); + return finish(node); } function createVariableDeclarationWithoutTokens(name: string | BindingName, type?: TypeNode, initializer?: Expression) { @@ -2740,8 +2747,8 @@ namespace ts { || node.type !== type || node.exclamationToken !== exclamationToken || node.initializer !== initializer - ? updateNode(createVariableDeclaration(name, exclamationToken, type, initializer), node) - : reuseNode(node); + ? update(createVariableDeclaration(name, exclamationToken, type, initializer), node) + : reuse(node); } function updateVariableDeclarationWithoutTokens(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) { @@ -2753,14 +2760,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.VariableDeclarationList); node.flags |= flags & NodeFlags.BlockScoped; setChildren(node, node.declarations = createNodeArray(declarations)); - return finishNode(node); + return finish(node); } // @api function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { return node.declarations !== declarations - ? updateNode(createVariableDeclarationList(declarations, node.flags), node) - : reuseNode(node); + ? update(createVariableDeclarationList(declarations, node.flags), node) + : reuse(node); } // @api @@ -2785,7 +2792,7 @@ namespace ts { body ); setChild(node, node.asteriskToken = asteriskToken); - return finishNode(node); + return finish(node); } // @api @@ -2809,7 +2816,7 @@ namespace ts { || node.type !== type || node.body !== body ? updateBaseFunctionLikeDeclaration(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) - : reuseNode(node); + : reuse(node); } // @api @@ -2830,7 +2837,7 @@ namespace ts { heritageClauses, members ); - return finishNode(node); + return finish(node); } // @api @@ -2849,8 +2856,8 @@ namespace ts { || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members - ? updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : reuseNode(node); + ? update(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); } // @api @@ -2871,7 +2878,7 @@ namespace ts { heritageClauses ); setChildren(node, node.members = createNodeArray(members)); - return finishNode(node); + return finish(node); } // @api @@ -2890,8 +2897,8 @@ namespace ts { || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members - ? updateNode(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) - : reuseNode(node); + ? update(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : reuse(node); } // @api @@ -2910,7 +2917,7 @@ namespace ts { typeParameters ); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api @@ -2927,8 +2934,8 @@ namespace ts { || node.name !== name || node.typeParameters !== typeParameters || node.type !== type - ? updateNode(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node) - : reuseNode(node); + ? update(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node) + : reuse(node); } // @api @@ -2945,7 +2952,7 @@ namespace ts { name ); setChildren(node, node.members = createNodeArray(members)); - return finishNode(node); + return finish(node); } // @api @@ -2959,8 +2966,8 @@ namespace ts { || node.modifiers !== modifiers || node.name !== name || node.members !== members - ? updateNode(createEnumDeclaration(decorators, modifiers, name, members), node) - : reuseNode(node); + ? update(createEnumDeclaration(decorators, modifiers, name, members), node) + : reuse(node); } // @api @@ -2979,7 +2986,7 @@ namespace ts { node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); setChild(node, node.name = name); setChild(node, node.body = body); - return finishNode(node); + return finish(node); } // @api @@ -2994,50 +3001,50 @@ namespace ts { || node.modifiers !== modifiers || node.name !== name || node.body !== body - ? updateNode(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) - : reuseNode(node); + ? update(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) + : reuse(node); } // @api function createModuleBlock(statements: readonly Statement[]) { const node = createBaseNode(SyntaxKind.ModuleBlock); setChildren(node, node.statements = createNodeArray(statements)); - return finishNode(node); + return finish(node); } // @api function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) { return node.statements !== statements - ? updateNode(createModuleBlock(statements), node) - : reuseNode(node); + ? update(createModuleBlock(statements), node) + : reuse(node); } // @api function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { const node = createBaseNode(SyntaxKind.CaseBlock); setChildren(node, node.clauses = createNodeArray(clauses)); - return finishNode(node); + return finish(node); } // @api function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) { return node.clauses !== clauses - ? updateNode(createCaseBlock(clauses), node) - : reuseNode(node); + ? update(createCaseBlock(clauses), node) + : reuse(node); } // @api function createNamespaceExportDeclaration(name: string | Identifier) { const node = createBaseNode(SyntaxKind.NamespaceExportDeclaration); setChild(node, node.name = asName(name)); - return finishNode(node); + return finish(node); } // @api function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { return node.name !== name - ? updateNode(createNamespaceExportDeclaration(name), node) - : reuseNode(node); + ? update(createNamespaceExportDeclaration(name), node) + : reuse(node); } // @api @@ -3054,7 +3061,7 @@ namespace ts { name ); setChild(node, node.moduleReference = moduleReference); - return finishNode(node); + return finish(node); } // @api @@ -3069,8 +3076,8 @@ namespace ts { || node.modifiers !== modifiers || node.name !== name || node.moduleReference !== moduleReference - ? updateNode(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) - : reuseNode(node); + ? update(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) + : reuse(node); } // @api @@ -3087,7 +3094,7 @@ namespace ts { ); setChild(node, node.importClause = importClause); setChild(node, node.moduleSpecifier = moduleSpecifier); - return finishNode(node); + return finish(node); } // @api @@ -3102,8 +3109,8 @@ namespace ts { || node.modifiers !== modifiers || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier - ? updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) - : reuseNode(node); + ? update(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) + : reuse(node); } // @api @@ -3111,43 +3118,43 @@ namespace ts { const node = createBaseNode(SyntaxKind.ImportClause); setChild(node, node.name = name); setChild(node, node.namedBindings = namedBindings); - return finishNode(node); + return finish(node); } // @api function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { return node.name !== name || node.namedBindings !== namedBindings - ? updateNode(createImportClause(name, namedBindings), node) - : reuseNode(node); + ? update(createImportClause(name, namedBindings), node) + : reuse(node); } // @api function createNamespaceImport(name: Identifier): NamespaceImport { const node = createBaseNode(SyntaxKind.NamespaceImport); setChild(node, node.name = name); - return finishNode(node); + return finish(node); } // @api function updateNamespaceImport(node: NamespaceImport, name: Identifier) { return node.name !== name - ? updateNode(createNamespaceImport(name), node) - : reuseNode(node); + ? update(createNamespaceImport(name), node) + : reuse(node); } // @api function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { const node = createBaseNode(SyntaxKind.NamedImports); setChildren(node, node.elements = createNodeArray(elements)); - return finishNode(node); + return finish(node); } // @api function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) { return node.elements !== elements - ? updateNode(createNamedImports(elements), node) - : reuseNode(node); + ? update(createNamedImports(elements), node) + : reuse(node); } // @api @@ -3155,15 +3162,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.ImportSpecifier); setChild(node, node.propertyName = propertyName); setChild(node, node.name = name); - return finishNode(node); + return finish(node); } // @api function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) { return node.propertyName !== propertyName || node.name !== name - ? updateNode(createImportSpecifier(propertyName, name), node) - : reuseNode(node); + ? update(createImportSpecifier(propertyName, name), node) + : reuse(node); } // @api @@ -3182,7 +3189,7 @@ namespace ts { setChild(node, node.expression = isExportEquals ? parenthesizer().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) : parenthesizer().parenthesizeExpressionOfExportDefault(expression)); - return finishNode(node); + return finish(node); } // @api @@ -3195,8 +3202,8 @@ namespace ts { return node.decorators !== decorators || node.modifiers !== modifiers || node.expression !== expression - ? updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) - : reuseNode(node); + ? update(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) + : reuse(node); } // @api @@ -3213,7 +3220,7 @@ namespace ts { ); setChild(node, node.exportClause = exportClause); setChild(node, node.moduleSpecifier = moduleSpecifier); - return finishNode(node); + return finish(node); } // @api @@ -3228,22 +3235,22 @@ namespace ts { || node.modifiers !== modifiers || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier - ? updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) - : reuseNode(node); + ? update(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) + : reuse(node); } // @api function createNamedExports(elements: readonly ExportSpecifier[]) { const node = createBaseNode(SyntaxKind.NamedExports); setChildren(node, node.elements = createNodeArray(elements)); - return finishNode(node); + return finish(node); } // @api function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) { return node.elements !== elements - ? updateNode(createNamedExports(elements), node) - : reuseNode(node); + ? update(createNamedExports(elements), node) + : reuse(node); } // @api @@ -3251,15 +3258,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.ExportSpecifier); setChild(node, node.propertyName = asName(propertyName)); setChild(node, node.name = asName(name)); - return finishNode(node); + return finish(node); } // @api function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) { return node.propertyName !== propertyName || node.name !== name - ? updateNode(createExportSpecifier(propertyName, name), node) - : reuseNode(node); + ? update(createExportSpecifier(propertyName, name), node) + : reuse(node); } // @api @@ -3269,7 +3276,7 @@ namespace ts { /*decorators*/ undefined, /*modifiers*/ undefined ); - return finishNode(node); + return finish(node); } // @@ -3280,14 +3287,14 @@ namespace ts { function createExternalModuleReference(expression: Expression) { const node = createBaseNode(SyntaxKind.ExternalModuleReference); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { return node.expression !== expression - ? updateNode(createExternalModuleReference(expression), node) - : reuseNode(node); + ? update(createExternalModuleReference(expression), node) + : reuse(node); } // @@ -3296,33 +3303,33 @@ namespace ts { // @api function createJSDocAllType() { - return finishNode(createBaseNode(SyntaxKind.JSDocAllType)); + return finish(createBaseNode(SyntaxKind.JSDocAllType)); } // @api function createJSDocUnknownType() { - return finishNode(createBaseNode(SyntaxKind.JSDocUnknownType)); + return finish(createBaseNode(SyntaxKind.JSDocUnknownType)); } // @api function createJSDocNonNullableType(type: TypeNode) { const node = createBaseNode(SyntaxKind.JSDocNonNullableType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function createJSDocNullableType(type: TypeNode) { const node = createBaseNode(SyntaxKind.JSDocNullableType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function createJSDocOptionalType(type: TypeNode) { const node = createBaseNode(SyntaxKind.JSDocOptionalType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api @@ -3336,21 +3343,21 @@ namespace ts { parameters, type ); - return finishNode(node); + return finish(node); } // @api function createJSDocVariadicType(type: TypeNode) { const node = createBaseNode(SyntaxKind.JSDocVariadicType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api function createJSDocNamepathType(type: TypeNode) { const node = createBaseNode(SyntaxKind.JSDocNamepathType); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api @@ -3358,14 +3365,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.JSDocTypeLiteral); setChildren(node, node.jsDocPropertyTags = asNodeArray(propertyTags)); node.isArrayType = isArrayType; - return finishNode(node); + return finish(node); } // @api function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { const node = createBaseNode(SyntaxKind.JSDocTypeExpression); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api @@ -3374,7 +3381,7 @@ namespace ts { setChildren(node, node.typeParameters = asNodeArray(typeParameters)); setChildren(node, node.parameters = createNodeArray(parameters)); setChild(node, node.type = type); - return finishNode(node); + return finish(node); } // @api @@ -3390,14 +3397,14 @@ namespace ts { const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName || createIdentifier("template"), /*comment*/ undefined); setChild(node, node.constraint = constraint); setChildren(node, node.typeParameters = createNodeArray(typeParameters)); - return finishNode(node); + return finish(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); + return finish(node); } // @api @@ -3406,21 +3413,21 @@ namespace ts { setChild(node, node.typeExpression = typeExpression); setChild(node, node.fullName = fullName); setChild(node, node.name = getJSDocTypeAliasName(fullName)); - return finishNode(node); + return finish(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); + return finish(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); + return finish(node); } // @api @@ -3430,7 +3437,7 @@ namespace ts { setChild(node, node.name = name); node.isNameFirst = !!isNameFirst; node.isBracketed = isBracketed; - return finishNode(node); + return finish(node); } // @api @@ -3440,20 +3447,20 @@ namespace ts { setChild(node, node.name = name); node.isNameFirst = !!isNameFirst; node.isBracketed = isBracketed; - return finishNode(node); + return finish(node); } // @api function createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag { const node = createBaseJSDocTag(SyntaxKind.JSDocAuthorTag, tagName || createIdentifier("author"), comment); - return finishNode(node); + return finish(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); + return finish(node); } // @api @@ -3462,26 +3469,26 @@ namespace ts { setChild(node, node.typeExpression = typeExpression); setChild(node, node.fullName = fullName); node.name = getJSDocTypeAliasName(fullName); - return finishNode(node); + return finish(node); } // @api function createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag { const node = createBaseJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class"), /*comment*/ undefined); - return finishNode(node); + return finish(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); + return finish(node); } // @api function createJSDocTag(kind: T["kind"], tagName: Identifier): T { const node = createBaseJSDocTag(kind, tagName, /*comment*/ undefined); - return finishNode(node); + return finish(node); } // @api @@ -3489,7 +3496,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.JSDocComment); node.comment = comment; setChildren(node, node.tags = tags); - return finishNode(node); + return finish(node); } // @@ -3502,7 +3509,7 @@ namespace ts { setChild(node, node.openingElement = openingElement); setChildren(node, node.children = createNodeArray(children)); setChild(node, node.closingElement = closingElement); - return finishNode(node); + return finish(node); } // @api @@ -3510,8 +3517,8 @@ namespace ts { return node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement - ? updateNode(createJsxElement(openingElement, children, closingElement), node) - : reuseNode(node); + ? update(createJsxElement(openingElement, children, closingElement), node) + : reuse(node); } // @api @@ -3520,7 +3527,7 @@ namespace ts { setChild(node, node.tagName = tagName); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); setChild(node, node.attributes = attributes); - return finishNode(node); + return finish(node); } // @api @@ -3528,8 +3535,8 @@ namespace ts { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes - ? updateNode(createJsxSelfClosingElement(tagName, typeArguments, attributes), node) - : reuseNode(node); + ? update(createJsxSelfClosingElement(tagName, typeArguments, attributes), node) + : reuse(node); } // @api @@ -3538,7 +3545,7 @@ namespace ts { setChild(node, node.tagName = tagName); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); setChild(node, node.attributes = attributes); - return finishNode(node); + return finish(node); } // @api @@ -3546,22 +3553,22 @@ namespace ts { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes - ? updateNode(createJsxOpeningElement(tagName, typeArguments, attributes), node) - : reuseNode(node); + ? update(createJsxOpeningElement(tagName, typeArguments, attributes), node) + : reuse(node); } // @api function createJsxClosingElement(tagName: JsxTagNameExpression) { const node = createBaseNode(SyntaxKind.JsxClosingElement); setChild(node, node.tagName = tagName); - return finishNode(node); + return finish(node); } // @api function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { return node.tagName !== tagName - ? updateNode(createJsxClosingElement(tagName), node) - : reuseNode(node); + ? update(createJsxClosingElement(tagName), node) + : reuse(node); } // @api @@ -3570,7 +3577,7 @@ namespace ts { setChild(node, node.openingFragment = openingFragment); setChildren(node, node.children = createNodeArray(children)); setChild(node, node.closingFragment = closingFragment); - return finishNode(node); + return finish(node); } // @api @@ -3578,8 +3585,8 @@ namespace ts { return node.openingFragment !== openingFragment || node.children !== children || node.closingFragment !== closingFragment - ? updateNode(createJsxFragment(openingFragment, children, closingFragment), node) - : reuseNode(node); + ? update(createJsxFragment(openingFragment, children, closingFragment), node) + : reuse(node); } // @api @@ -3587,25 +3594,25 @@ namespace ts { const node = createBaseNode(SyntaxKind.JsxText); node.text = text; node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; - return finishNode(node); + return finish(node); } // @api function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { return node.text !== text || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces - ? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) - : reuseNode(node); + ? update(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) + : reuse(node); } // @api function createJsxOpeningFragment() { - return finishNode(createBaseNode(SyntaxKind.JsxOpeningFragment)); + return finish(createBaseNode(SyntaxKind.JsxOpeningFragment)); } // @api function createJsxJsxClosingFragment() { - return finishNode(createBaseNode(SyntaxKind.JsxClosingFragment)); + return finish(createBaseNode(SyntaxKind.JsxClosingFragment)); } // @api @@ -3613,43 +3620,43 @@ namespace ts { const node = createBaseNode(SyntaxKind.JsxAttribute); setChild(node, node.name = name); setChild(node, node.initializer = initializer); - return finishNode(node); + return finish(node); } // @api function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) { return node.name !== name || node.initializer !== initializer - ? updateNode(createJsxAttribute(name, initializer), node) - : reuseNode(node); + ? update(createJsxAttribute(name, initializer), node) + : reuse(node); } // @api function createJsxAttributes(properties: readonly JsxAttributeLike[]) { const node = createBaseNode(SyntaxKind.JsxAttributes); setChildren(node, node.properties = createNodeArray(properties)); - return finishNode(node); + return finish(node); } // @api function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { return node.properties !== properties - ? updateNode(createJsxAttributes(properties), node) - : reuseNode(node); + ? update(createJsxAttributes(properties), node) + : reuse(node); } // @api function createJsxSpreadAttribute(expression: Expression) { const node = createBaseNode(SyntaxKind.JsxSpreadAttribute); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { return node.expression !== expression - ? updateNode(createJsxSpreadAttribute(expression), node) - : reuseNode(node); + ? update(createJsxSpreadAttribute(expression), node) + : reuse(node); } // @api @@ -3657,14 +3664,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.JsxExpression); setChild(node, node.dotDotDotToken = dotDotDotToken); setChild(node, node.expression = expression); - return finishNode(node); + return finish(node); } // @api function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { return node.expression !== expression - ? updateNode(createJsxExpression(node.dotDotDotToken, expression), node) - : reuseNode(node); + ? update(createJsxExpression(node.dotDotDotToken, expression), node) + : reuse(node); } // @@ -3676,29 +3683,29 @@ namespace ts { const node = createBaseNode(SyntaxKind.CaseClause); setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); setChildren(node, node.statements = createNodeArray(statements)); - return finishNode(node); + return finish(node); } // @api function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) { return node.expression !== expression || node.statements !== statements - ? updateNode(createCaseClause(expression, statements), node) - : reuseNode(node); + ? update(createCaseClause(expression, statements), node) + : reuse(node); } // @api function createDefaultClause(statements: readonly Statement[]) { const node = createBaseNode(SyntaxKind.DefaultClause); setChildren(node, node.statements = createNodeArray(statements)); - return finishNode(node); + return finish(node); } // @api function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) { return node.statements !== statements - ? updateNode(createDefaultClause(statements), node) - : reuseNode(node); + ? update(createDefaultClause(statements), node) + : reuse(node); } // @api @@ -3706,14 +3713,14 @@ namespace ts { const node = createBaseNode(SyntaxKind.HeritageClause); node.token = token; setChildren(node, node.types = createNodeArray(types)); - return finishNode(node); + return finish(node); } // @api function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) { return node.types !== types - ? updateNode(createHeritageClause(node.token, types), node) - : reuseNode(node); + ? update(createHeritageClause(node.token, types), node) + : reuse(node); } // @api @@ -3726,15 +3733,15 @@ namespace ts { /*initializer*/ undefined )); setChild(node, node.block = block); - return finishNode(node); + return finish(node); } // @api function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { return node.variableDeclaration !== variableDeclaration || node.block !== block - ? updateNode(createCatchClause(variableDeclaration, block), node) - : reuseNode(node); + ? update(createCatchClause(variableDeclaration, block), node) + : reuse(node); } // @@ -3747,7 +3754,7 @@ namespace ts { setChild(node, node.name = asName(name)); setChild(node, node.questionToken = undefined); setChild(node, node.initializer = parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); - return finishNode(node); + return finish(node); } function finishUpdatePropertyAssignment(updated: PropertyAssignment, original: PropertyAssignment) { @@ -3755,7 +3762,7 @@ namespace ts { 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); + return update(updated, original); } // @api @@ -3763,7 +3770,7 @@ namespace ts { return node.name !== name || node.initializer !== initializer ? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node) - : reuseNode(node); + : reuse(node); } // @api @@ -3777,7 +3784,7 @@ namespace ts { setChild(node, node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizer().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) : undefined); - return finishNode(node); + return finish(node); } function finishUpdateShorthandPropertyAssignment(updated: ShorthandPropertyAssignment, original: ShorthandPropertyAssignment) { @@ -3786,7 +3793,7 @@ namespace ts { 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); + return update(updated, original); } // @api @@ -3794,24 +3801,23 @@ namespace ts { return node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) - : reuseNode(node); + : reuse(node); } // @api function createSpreadAssignment(expression: Expression) { const node = createBaseNode(SyntaxKind.SpreadAssignment); setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); - return finishNode(node); + return finish(node); } // @api function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { return node.expression !== expression - ? updateNode(createSpreadAssignment(expression), node) - : reuseNode(node); + ? update(createSpreadAssignment(expression), node) + : reuse(node); } - // // Enum // @@ -3821,21 +3827,39 @@ namespace ts { const node = createBaseNode(SyntaxKind.EnumMember); setChild(node, node.name = asName(name)); setChild(node, node.initializer = initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); - return finishNode(node); + return finish(node); } // @api function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { return node.name !== name || node.initializer !== initializer - ? updateNode(createEnumMember(name, initializer), node) - : reuseNode(node); + ? update(createEnumMember(name, initializer), node) + : reuse(node); } // // Top-level nodes // + // @api + function createSourceFile( + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + ) { + const node = createSourceFileNode(SyntaxKind.SourceFile) as SourceFile; + setChildren(node, node.statements = createNodeArray(statements)); + setChild(node, node.endOfFileToken = endOfFileToken); + node.fileName = ""; + node.text = ""; + node.languageVersion = 0; + node.languageVariant = 0; + node.scriptKind = 0; + node.isDeclarationFile = false; + node.hasNoDefaultLib = false; + return finish(node); + } + function cloneSourceFileWithChanges( source: SourceFile, statements: readonly Statement[], @@ -3858,7 +3882,7 @@ namespace ts { node.typeReferenceDirectives = typeReferences; node.hasNoDefaultLib = hasNoDefaultLib; node.libReferenceDirectives = libReferences; - return finishNode(node); + return finish(node); } // @api @@ -3877,8 +3901,8 @@ namespace ts { || node.typeReferenceDirectives !== typeReferenceDirectives || node.hasNoDefaultLib !== hasNoDefaultLib || node.libReferenceDirectives !== libReferenceDirectives - ? updateNode(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node) - : reuseNode(node); + ? update(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node) + : reuse(node); } // @@ -3896,7 +3920,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.NotEmittedStatement); node.original = original; setTextRange(node, original); - return finishNode(node); + return finish(node); } /** @@ -3908,7 +3932,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.EndOfDeclarationMarker); node.emitNode = {} as EmitNode; node.original = original; - return finishNode(node); + return finish(node); } /** @@ -3920,7 +3944,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.MergeDeclarationMarker); node.emitNode = {} as EmitNode; node.original = original; - return finishNode(node); + return finish(node); } /** @@ -3936,14 +3960,14 @@ namespace ts { setChild(node, node.expression = expression); node.original = original; setTextRange(node, original); - return finishNode(node); + return finish(node); } // @api function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { return node.expression !== expression - ? updateNode(createPartiallyEmittedExpression(expression, node.original), node) - : reuseNode(node); + ? update(createPartiallyEmittedExpression(expression, node.original), node) + : reuse(node); } function flattenCommaElements(node: Expression): Expression | readonly Expression[] { @@ -3962,14 +3986,14 @@ namespace ts { function createCommaListExpression(elements: readonly Expression[]) { const node = createBaseNode(SyntaxKind.CommaListExpression); setChildren(node, node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements))); - return finishNode(node); + return finish(node); } // @api function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) { return node.elements !== elements - ? updateNode(createCommaListExpression(elements), node) - : reuseNode(node); + ? update(createCommaListExpression(elements), node) + : reuse(node); } // @api @@ -3977,15 +4001,15 @@ namespace ts { const node = createBaseNode(SyntaxKind.Bundle); node.prepends = prepends; node.sourceFiles = sourceFiles; - return finishNode(node); + return finish(node); } // @api function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { return node.sourceFiles !== sourceFiles || node.prepends !== prepends - ? updateNode(createBundle(sourceFiles, prepends), node) - : reuseNode(node); + ? update(createBundle(sourceFiles, prepends), node) + : reuse(node); } // @@ -4558,124 +4582,45 @@ namespace ts { } // 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); - } + function setChildWorker(_parent: Node, _child: Node | undefined): void { } // tslint:disable-next-line no-empty - function setChildrenWithoutTreeState(_parent: Node, _children: NodeArray | undefined): void { + function setChildrenWorker(_parent: Node, _children: NodeArray | undefined): void { } - function setChildrenWithTreeState(parent: Node, children: NodeArray | undefined): void { - if (children) { - treeStateObserver.onSetChildren(parent, children); - setChildrenWithoutTreeState(parent, children); + function finishWorker(node: T) { + return node; + } + + function updateWorker(updated: T, original: T) { + return updateNode(updated, original); + } + + function reuseWorker(node: T) { + return node; + } + } + + function observeArguments(action: (arg1: U, arg2: U) => U, observer: ((arg1: T, arg2: T) => void) | undefined): (arg1: U, arg2: U) => U; + function observeArguments(action: (arg1: T, arg2: U) => R, observer: ((arg1: T, arg2: U) => void) | undefined): (arg1: T, arg2: U) => R; + function observeArguments(action: (arg1: T, arg2: U) => R, observer: ((arg1: T, arg2: U) => void) | undefined): (arg1: T, arg2: U) => R { + return !observer ? action : (arg1, arg2) => { + if (arg2 !== undefined) { + observer(arg1, arg2); } - } - - 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; - } + return action(arg1, arg2); + }; } - // 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); - node.flags |= NodeFlags.Synthesized; - return node; - } - - /** - * Creates a shallow, memberwise clone of a node with no source map location. - */ - /* @internal */ - export function getSynthesizedClone(node: T): T { - // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of - // the original node. We also need to exclude specific properties and only include own- - // properties (to skip members already defined on the shared prototype). - - if (node === undefined) { - return node; - } - - const clone = createSynthesizedNode(node.kind); - clone.flags |= node.flags; - setOriginalNode(clone, node); - - for (const key in node) { - if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { - continue; - } - - (clone)[key] = (node)[key]; - } - - return clone; - } - - /** - * Creates a shallow, memberwise clone of a node for mutation. - */ - export function getMutableClone(node: T): T { - const clone = getSynthesizedClone(node); - clone.pos = node.pos; - clone.end = node.end; - clone.parent = node.parent; - return clone; - } - - /* @internal */ - export function createNodeArray(elements?: T[], hasTrailingComma?: boolean): MutableNodeArray; - export function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; - /** - * Make `elements` into a `NodeArray`. If `elements` is `undefined`, returns an empty `NodeArray`. - */ - export function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray { - if (!elements || elements === emptyArray) { - elements = []; - } - else if (isNodeArray(elements)) { - return elements; - } - - const array = >elements; - array.pos = -1; - array.end = -1; - array.hasTrailingComma = hasTrailingComma; - return array; + function observeResult(action: (arg: U) => U, observer: ((result: T) => void) | undefined): (arg: U) => U; + function observeResult(action: (arg: T) => R, observer: ((result: R) => void) | undefined): (arg: T) => R; + function observeResult(action: (arg: T) => R, observer: ((result: R) => void) | undefined): (arg: T) => R { + return !observer ? action : arg => { + const result = action(arg); + observer(result); + return result; + }; } let rawTextScanner: Scanner | undefined; @@ -4731,6 +4676,56 @@ namespace ts { return tokenValue; } + export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, createBaseNodeFactory(), { + onCreateNode: node => node.flags |= NodeFlags.Synthesized + }); + + /* @internal */ + export function createSynthesizedNode(kind: SyntaxKind): Node { + const node = createNode(kind, -1, -1); + node.flags |= NodeFlags.Synthesized; + return node; + } + + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + /* @internal */ + export function getSynthesizedClone(node: T): T { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). + + if (node === undefined) { + return node; + } + + const clone = createSynthesizedNode(node.kind); + clone.flags |= node.flags; + setOriginalNode(clone, node); + + for (const key in node) { + if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { + continue; + } + + (clone)[key] = (node)[key]; + } + + return clone; + } + + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + export function getMutableClone(node: T): T { + const clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + clone.parent = node.parent; + return clone; + } + /* @internal */ export function updateNode(updated: T, original: T): T { if (updated !== original) { @@ -5027,316 +5022,6 @@ 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 | undefined) { - // During transformation we may need to annotate a parse tree node with transient - // transformation properties. As parse tree nodes live longer than transformation - // nodes, we need to make sure we reclaim any memory allocated for custom ranges - // from these nodes to ensure we do not hold onto entire subtrees just for position - // information. We also need to reset these nodes to a pre-transformation state - // for incremental parsing scenarios so that we do not impact later emit. - sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); - const emitNode = sourceFile && sourceFile.emitNode; - const annotatedNodes = emitNode && emitNode.annotatedNodes; - if (annotatedNodes) { - for (const node of annotatedNodes) { - node.emitNode = undefined; - } - } - } - - /** - * Associates a node with the current transformation, initializing - * various transient transformation properties. - */ - /* @internal */ - export function getOrCreateEmitNode(node: Node): EmitNode { - if (!node.emitNode) { - if (isParseTreeNode(node)) { - // To avoid holding onto transformation artifacts, we keep track of any - // parse tree node we are annotating. This allows us to clean them up after - // all transformations have completed. - if (node.kind === SyntaxKind.SourceFile) { - return node.emitNode = { annotatedNodes: [node] } as EmitNode; - } - - const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) || Debug.fail("Could not determine parsed source file."); - getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); - } - - node.emitNode = {} as EmitNode; - } - - return node.emitNode; - } - - /** - * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. - * @internal - */ - export function removeAllComments(node: T): T { - const emitNode = getOrCreateEmitNode(node); - emitNode.flags |= EmitFlags.NoComments; - emitNode.leadingComments = undefined; - emitNode.trailingComments = undefined; - return node; - } - - export function setTextRange(range: T, location: TextRange | undefined): T { - if (location) { - range.pos = location.pos; - range.end = location.end; - } - return range; - } - - /** - * Sets flags that control emit behavior of a node. - */ - export function setEmitFlags(node: T, emitFlags: EmitFlags) { - getOrCreateEmitNode(node).flags = emitFlags; - return node; - } - - /** - * Sets flags that control emit behavior of a node. - */ - /* @internal */ - export function addEmitFlags(node: T, emitFlags: EmitFlags) { - const emitNode = getOrCreateEmitNode(node); - emitNode.flags = emitNode.flags | emitFlags; - return node; - } - - /** - * Gets a custom text range to use when emitting source maps. - */ - export function getSourceMapRange(node: Node): SourceMapRange { - const emitNode = node.emitNode; - return (emitNode && emitNode.sourceMapRange) || node; - } - - /** - * Sets a custom text range to use when emitting source maps. - */ - export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { - getOrCreateEmitNode(node).sourceMapRange = range; - return node; - } - - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { - const emitNode = node.emitNode; - const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; - return tokenSourceMapRanges && tokenSourceMapRanges[token]; - } - - /** - * Sets the TextRange to use for source maps for a token of a node. - */ - export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { - const emitNode = getOrCreateEmitNode(node); - const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); - tokenSourceMapRanges[token] = range; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - */ - /*@internal*/ - export function getStartsOnNewLine(node: Node) { - const emitNode = node.emitNode; - return emitNode && emitNode.startsOnNewLine; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - /*@internal*/ - export function setStartsOnNewLine(node: T, newLine: boolean) { - getOrCreateEmitNode(node).startsOnNewLine = newLine; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - */ - export function getCommentRange(node: Node) { - const emitNode = node.emitNode; - return (emitNode && emitNode.commentRange) || node; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - export function setCommentRange(node: T, range: TextRange) { - getOrCreateEmitNode(node).commentRange = range; - return node; - } - - export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.leadingComments; - } - - export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { - getOrCreateEmitNode(node).leadingComments = comments; - return node; - } - - export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); - } - - export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.trailingComments; - } - - export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { - getOrCreateEmitNode(node).trailingComments = comments; - return node; - } - - export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); - } - - export function moveSyntheticComments(node: T, original: Node): T { - setSyntheticLeadingComments(node, getSyntheticLeadingComments(original)); - setSyntheticTrailingComments(node, getSyntheticTrailingComments(original)); - const emit = getOrCreateEmitNode(original); - emit.leadingComments = undefined; - emit.trailingComments = undefined; - return node; - } - - /** - * Gets the constant value to emit for an expression. - */ - export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.constantValue; - } - - /** - * Sets the constant value to emit for an expression. - */ - export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number) { - const emitNode = getOrCreateEmitNode(node); - emitNode.constantValue = value; - return node; - } - - /** - * Adds an EmitHelper to a node. - */ - export function addEmitHelper(node: T, helper: EmitHelper): T { - const emitNode = getOrCreateEmitNode(node); - emitNode.helpers = append(emitNode.helpers, helper); - return node; - } - - /** - * Add EmitHelpers to a node. - */ - export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { - if (some(helpers)) { - const emitNode = getOrCreateEmitNode(node); - for (const helper of helpers) { - emitNode.helpers = appendIfUnique(emitNode.helpers, helper); - } - } - return node; - } - - /** - * Removes an EmitHelper from a node. - */ - export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { - const emitNode = node.emitNode; - if (emitNode) { - const helpers = emitNode.helpers; - if (helpers) { - return orderedRemoveItem(helpers, helper); - } - } - return false; - } - - /** - * Gets the EmitHelpers of a node. - */ - export function getEmitHelpers(node: Node): EmitHelper[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.helpers; - } - - /** - * Moves matching emit helpers from a source node to a target node. - */ - export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { - const sourceEmitNode = source.emitNode; - const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; - if (!some(sourceEmitHelpers)) return; - - const targetEmitNode = getOrCreateEmitNode(target); - let helpersRemoved = 0; - for (let i = 0; i < sourceEmitHelpers.length; i++) { - const helper = sourceEmitHelpers[i]; - if (predicate(helper)) { - helpersRemoved++; - targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); - } - else if (helpersRemoved > 0) { - sourceEmitHelpers[i - helpersRemoved] = helper; - } - } - - if (helpersRemoved > 0) { - sourceEmitHelpers.length -= helpersRemoved; - } - } - - /* @internal */ - export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { - if (x === y) return Comparison.EqualTo; - if (x.priority === y.priority) return Comparison.EqualTo; - if (x.priority === undefined) return Comparison.GreaterThan; - if (y.priority === undefined) return Comparison.LessThan; - return compareValues(x.priority, y.priority); - } - export function setOriginalNode(node: T, original: Node | undefined): T { node.original = original; if (original) { @@ -5385,925 +5070,3 @@ namespace ts { } } -/* @internal */ -namespace ts { - - export const factory = createNodeFactory(createSynthesizedNode, createParenthesizerRules, createNodeConverters, nullTreeStateObserver); - export const nodeConverters = factory.getConverters(); - - export function createNodeConverters(factory: NodeFactory): NodeConverters { - return { - convertToFunctionBlock, - convertToFunctionExpression, - convertToArrayAssignmentElement, - convertToObjectAssignmentElement, - convertToAssignmentPattern, - convertToObjectAssignmentPattern, - convertToArrayAssignmentPattern, - convertToAssignmentElementTarget, - }; - - function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block { - if (isBlock(node)) return node; - const returnStatement = factory.createReturn(node); - setTextRange(returnStatement, node); - const body = factory.createBlock([returnStatement], multiLine); - setTextRange(body, node); - aggregateTransformFlags(body); - return body; - } - - function convertToFunctionExpression(node: FunctionDeclaration) { - if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`); - const updated = factory.createFunctionExpression( - node.modifiers, - node.asteriskToken, - node.name, - node.typeParameters, - node.parameters, - node.type, - node.body - ); - setOriginalNode(updated, node); - setTextRange(updated, node); - if (getStartsOnNewLine(node)) { - setStartsOnNewLine(updated, /*newLine*/ true); - } - aggregateTransformFlags(updated); - return updated; - } - - function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) { - if (isBindingElement(element)) { - if (element.dotDotDotToken) { - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(factory.createSpread(element.name), element), element); - } - const expression = convertToAssignmentElementTarget(element.name); - return element.initializer - ? setOriginalNode( - setTextRange( - factory.createAssignment(expression, element.initializer), - element - ), - element - ) - : expression; - } - return cast(element, isExpression); - } - - function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) { - if (isBindingElement(element)) { - if (element.dotDotDotToken) { - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element); - } - if (element.propertyName) { - const expression = convertToAssignmentElementTarget(element.name); - return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); - } - Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); - } - - return cast(element, isObjectLiteralElementLike); - } - - function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern { - switch (node.kind) { - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ArrayLiteralExpression: - return convertToArrayAssignmentPattern(node); - - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ObjectLiteralExpression: - return convertToObjectAssignmentPattern(node); - } - } - - function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { - if (isObjectBindingPattern(node)) { - return setOriginalNode( - setTextRange( - factory.createObjectLiteral(map(node.elements, convertToObjectAssignmentElement)), - node - ), - node - ); - } - return cast(node, isObjectLiteralExpression); - } - - function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { - if (isArrayBindingPattern(node)) { - return setOriginalNode( - setTextRange( - factory.createArrayLiteral(map(node.elements, convertToArrayAssignmentElement)), - node - ), - node - ); - } - return cast(node, isArrayLiteralExpression); - } - - function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression { - if (isBindingPattern(node)) { - return convertToAssignmentPattern(node); - } - - return cast(node, isExpression); - } - } - - const nullNodeConverters: NodeConverters = { - convertToFunctionBlock: notImplemented, - convertToFunctionExpression: notImplemented, - convertToArrayAssignmentElement: notImplemented, - convertToObjectAssignmentElement: notImplemented, - convertToAssignmentPattern: notImplemented, - convertToObjectAssignmentPattern: notImplemented, - convertToArrayAssignmentPattern: notImplemented, - convertToAssignmentElementTarget: notImplemented, - }; - - export function getNullNodeConverters(_factory: NodeFactory) { - return nullNodeConverters; - } - - // Compound nodes - - export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { - if (isComputedPropertyName(memberName)) { - return setTextRange(factory.createElementAccess(target, memberName.expression), location); - } - else { - const expression = setTextRange( - isIdentifier(memberName) - ? factory.createPropertyAccess(target, memberName) - : factory.createElementAccess(target, memberName), - memberName - ); - getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; - return expression; - } - } - - function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { - // To ensure the emit resolver can properly resolve the namespace, we need to - // treat this identifier as if it were a source tree node by clearing the `Synthesized` - // flag and setting a parent node. - const react = parseNodeFactory.createIdentifier(reactNamespace || "React"); - // Set the parent that is in parse tree - // this makes sure that parent chain is intact for checker to traverse complete scope tree - react.parent = getParseTreeNode(parent)!; - return react; - } - - function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - if (isQualifiedName(jsxFactory)) { - const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent); - const right = factory.createIdentifier(idText(jsxFactory.right)); - right.escapedText = jsxFactory.right.escapedText; - return factory.createPropertyAccess(left, right); - } - else { - return createReactNamespace(idText(jsxFactory), parent); - } - } - - function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - return jsxFactoryEntity ? - createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) : - factory.createPropertyAccess( - createReactNamespace(reactNamespace, parent), - "createElement" - ); - } - - export function createExpressionForJsxElement(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { - const argumentsList = [tagName]; - if (props) { - argumentsList.push(props); - } - - if (children && children.length > 0) { - if (!props) { - argumentsList.push(factory.createNull()); - } - - if (children.length > 1) { - for (const child of children) { - startOnNewLine(child); - argumentsList.push(child); - } - } - else { - argumentsList.push(children[0]); - } - } - - return setTextRange( - factory.createCall( - createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), - /*typeArguments*/ undefined, - argumentsList - ), - location - ); - } - - export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { - const tagName = factory.createPropertyAccess( - createReactNamespace(reactNamespace, parentElement), - "Fragment" - ); - - const argumentsList = [tagName]; - argumentsList.push(factory.createNull()); - - if (children && children.length > 0) { - if (children.length > 1) { - for (const child of children) { - startOnNewLine(child); - argumentsList.push(child); - } - } - else { - argumentsList.push(children[0]); - } - } - - return setTextRange( - factory.createCall( - createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), - /*typeArguments*/ undefined, - argumentsList - ), - location - ); - } - - // Utilities - - export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement { - if (isVariableDeclarationList(node)) { - const firstDeclaration = first(node.declarations); - const updatedDeclaration = factory.updateVariableDeclaration( - firstDeclaration, - firstDeclaration.name, - /*typeNode*/ undefined, - boundValue - ); - return setTextRange( - factory.createVariableStatement( - /*modifiers*/ undefined, - factory.updateVariableDeclarationList(node, [updatedDeclaration]) - ), - /*location*/ node - ); - } - else { - const updatedExpression = setTextRange(factory.createAssignment(node, boundValue), /*location*/ node); - return setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node); - } - } - - export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement) { - if (isBlock(dest)) { - return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); - } - else { - return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true); - } - } - - export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression { - if (isQualifiedName(node)) { - const left = createExpressionFromEntityName(factory, node.left); - const right = getMutableClone(node.right); - return setTextRange(factory.createPropertyAccess(left, right), node); - } - else { - return getMutableClone(node); - } - } - - export function createExpressionForPropertyName(factory: NodeFactory, memberName: PropertyName): Expression { - if (isIdentifier(memberName)) { - return factory.createStringLiteralFromNode(memberName); - } - else if (isComputedPropertyName(memberName)) { - return getMutableClone(memberName.expression); - } - else { - return getMutableClone(memberName); - } - } - - function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { - const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); - if (property === firstAccessor) { - return aggregateTransformFlags( - setTextRange( - factory.createObjectDefinePropertyCall( - receiver, - createExpressionForPropertyName(factory, property.name), - factory.createPropertyDescriptor({ - enumerable: true, - configurable: true, - get: getAccessor && setTextRange( - setOriginalNode( - factory.createFunctionExpression( - getAccessor.modifiers, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - getAccessor.parameters, - /*type*/ undefined, - getAccessor.body! // TODO: GH#18217 - ), - getAccessor - ), - getAccessor - ), - set: setAccessor && setTextRange( - setOriginalNode( - factory.createFunctionExpression( - setAccessor.modifiers, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - setAccessor.parameters, - /*type*/ undefined, - setAccessor.body! // TODO: GH#18217 - ), - setAccessor - ), - setAccessor - ) - }, !multiLine) - ), - firstAccessor - ) - ); - } - - return undefined; - } - - function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - factory.createAssignment( - createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), - property.initializer - ), - property - ), - property - ) - ); - } - - function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - factory.createAssignment( - createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), - getSynthesizedClone(property.name) - ), - /*location*/ property - ), - /*original*/ property - ) - ); - } - - function createExpressionForMethodDeclaration(factory: NodeFactory, method: MethodDeclaration, receiver: Expression) { - return aggregateTransformFlags( - setOriginalNode( - setTextRange( - factory.createAssignment( - createMemberAccessForPropertyName(factory, receiver, method.name, /*location*/ method.name), - setOriginalNode( - setTextRange( - factory.createFunctionExpression( - method.modifiers, - method.asteriskToken, - /*name*/ undefined, - /*typeParameters*/ undefined, - method.parameters, - /*type*/ undefined, - method.body! // TODO: GH#18217 - ), - /*location*/ method - ), - /*original*/ method - ) - ), - /*location*/ method - ), - /*original*/ method - ) - ); - } - - export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { - switch (property.kind) { - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(factory, node.properties, property, receiver, !!node.multiLine); - case SyntaxKind.PropertyAssignment: - return createExpressionForPropertyAssignment(factory, property, receiver); - case SyntaxKind.ShorthandPropertyAssignment: - return createExpressionForShorthandPropertyAssignment(factory, property, receiver); - case SyntaxKind.MethodDeclaration: - return createExpressionForMethodDeclaration(factory, property, receiver); - } - } - - /** - * Gets whether an identifier should only be referred to by its internal name. - */ - export function isInternalName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; - } - - /** - * Gets whether an identifier should only be referred to by its local name. - */ - export function isLocalName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; - } - - /** - * Gets whether an identifier should only be referred to by its export representation if the - * name points to an exported symbol. - */ - export function isExportName(node: Identifier) { - return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; - } - - function isUseStrictPrologue(node: ExpressionStatement): boolean { - return isStringLiteral(node.expression) && node.expression.text === "use strict"; - } - - export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined { - for (const statement of statements) { - if (isPrologueDirective(statement)) { - if (isUseStrictPrologue(statement)) { - return statement; - } - } - else { - break; - } - } - return undefined; - } - - export function startsWithUseStrict(statements: readonly Statement[]) { - const firstStatement = firstOrUndefined(statements); - return firstStatement !== undefined - && isPrologueDirective(firstStatement) - && isUseStrictPrologue(firstStatement); - } - - export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token} | CommaListExpression { - return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.CommaToken || - node.kind === SyntaxKind.CommaListExpression; - } - - export type OuterExpression = ParenthesizedExpression | TypeAssertion | AsExpression | NonNullExpression | PartiallyEmittedExpression; - - export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { - switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: - return (kinds & OuterExpressionKinds.Parentheses) !== 0; - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.NonNullExpression: - return (kinds & OuterExpressionKinds.Assertions) !== 0; - case SyntaxKind.PartiallyEmittedExpression: - return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; - } - return false; - } - - export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; - export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; - export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { - let previousNode: Node; - do { - previousNode = node; - if (kinds & OuterExpressionKinds.Parentheses) { - node = skipParentheses(node); - } - - if (kinds & OuterExpressionKinds.Assertions) { - node = skipAssertions(node); - } - - if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) { - node = skipPartiallyEmittedExpressions(node); - } - } - while (previousNode !== node); - - return node; - } - - export function skipAssertions(node: Expression): Expression; - export function skipAssertions(node: Node): Node; - export function skipAssertions(node: Node): Node { - while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) { - node = (node).expression; - } - - return node; - } - - export function startOnNewLine(node: T): T { - return setStartsOnNewLine(node, /*newLine*/ true); - } - - export function getExternalHelpersModuleName(node: SourceFile) { - const parseNode = getOriginalNode(node, isSourceFile); - const emitNode = parseNode && parseNode.emitNode; - return emitNode && emitNode.externalHelpersModuleName; - } - - export function hasRecordedExternalHelpers(sourceFile: SourceFile) { - const parseNode = getOriginalNode(sourceFile, isSourceFile); - const emitNode = parseNode && parseNode.emitNode; - return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); - } - - export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { - if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { - let namedBindings: NamedImportBindings | undefined; - const moduleKind = getEmitModuleKind(compilerOptions); - if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) { - // use named imports - const helpers = getEmitHelpers(sourceFile); - if (helpers) { - const helperNames: string[] = []; - for (const helper of helpers) { - if (!helper.scoped) { - const importName = (helper as UnscopedEmitHelper).importName; - if (importName) { - pushIfUnique(helperNames, importName); - } - } - } - if (some(helperNames)) { - helperNames.sort(compareStringsCaseSensitive); - // Alias the imports if the names are used somewhere in the file. - // NOTE: We don't need to care about global import collisions as this is a module. - namedBindings = nodeFactory.createNamedImports( - map(helperNames, name => isFileLevelUniqueName(sourceFile, name) - ? nodeFactory.createImportSpecifier(/*propertyName*/ undefined, nodeFactory.createIdentifier(name)) - : nodeFactory.createImportSpecifier(nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name)) - ) - ); - const parseNode = getOriginalNode(sourceFile, isSourceFile); - const emitNode = getOrCreateEmitNode(parseNode); - emitNode.externalHelpers = true; - } - } - } - else { - // use a namespace import - const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(nodeFactory, sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault); - if (externalHelpersModuleName) { - namedBindings = nodeFactory.createNamespaceImport(externalHelpersModuleName); - } - } - if (namedBindings) { - const externalHelpersImportDeclaration = nodeFactory.createImportDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, - nodeFactory.createImportClause(/*name*/ undefined, namedBindings), - nodeFactory.createStringLiteral(externalHelpersModuleNameText) - ); - addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper); - return externalHelpersImportDeclaration; - } - } - } - - export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { - if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { - const externalHelpersModuleName = getExternalHelpersModuleName(node); - if (externalHelpersModuleName) { - return externalHelpersModuleName; - } - - const moduleKind = getEmitModuleKind(compilerOptions); - let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault)) - && moduleKind !== ModuleKind.System - && moduleKind !== ModuleKind.ES2015 - && moduleKind !== ModuleKind.ESNext; - if (!create) { - const helpers = getEmitHelpers(node); - if (helpers) { - for (const helper of helpers) { - if (!helper.scoped) { - create = true; - break; - } - } - } - } - - if (create) { - const parseNode = getOriginalNode(node, isSourceFile); - const emitNode = getOrCreateEmitNode(parseNode); - return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); - } - } - } - - /** - * Get the name of that target module from an import or export declaration - */ - export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { - const namespaceDeclaration = getNamespaceDeclarationNode(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - const name = namespaceDeclaration.name; - return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); - } - if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { - return factory.getGeneratedNameForNode(node); - } - if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) { - return factory.getGeneratedNameForNode(node); - } - return undefined; - } - - /** - * Get the name of a target module from an import/export declaration as should be written in the emitted output. - * The emitted output name can be different from the input if: - * 1. The module has a /// - * 2. --out or --outFile is used, making the name relative to the rootDir - * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). - * Otherwise, a new StringLiteral node representing the module name will be returned. - */ - export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { - const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 - if (moduleName.kind === SyntaxKind.StringLiteral) { - return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) - || tryRenameExternalModule(factory, moduleName, sourceFile) - || getSynthesizedClone(moduleName); - } - - return undefined; - } - - /** - * Some bundlers (SystemJS builder) sometimes want to rename dependencies. - * Here we check if alternative name was provided for a given moduleName and return it if possible. - */ - function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) { - const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); - return rename && factory.createStringLiteral(rename); - } - - /** - * Get the name of a module as should be written in the emitted output. - * The emitted output name can be different from the input if: - * 1. The module has a /// - * 2. --out or --outFile is used, making the name relative to the rootDir - * Otherwise, a new StringLiteral node representing the module name will be returned. - */ - export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { - if (!file) { - return undefined; - } - if (file.moduleName) { - return factory.createStringLiteral(file.moduleName); - } - if (!file.isDeclarationFile && (options.out || options.outFile)) { - return factory.createStringLiteral(getExternalModuleNameFromPath(host, file.fileName)); - } - return undefined; - } - - function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { - return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); - } - - /** - * Gets the initializer of an BindingOrAssignmentElement. - */ - export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { - if (isDeclarationBindingElement(bindingElement)) { - // `1` in `let { a = 1 } = ...` - // `1` in `let { a: b = 1 } = ...` - // `1` in `let { a: {b} = 1 } = ...` - // `1` in `let { a: [b] = 1 } = ...` - // `1` in `let [a = 1] = ...` - // `1` in `let [{a} = 1] = ...` - // `1` in `let [[a] = 1] = ...` - return bindingElement.initializer; - } - - if (isPropertyAssignment(bindingElement)) { - // `1` in `({ a: b = 1 } = ...)` - // `1` in `({ a: {b} = 1 } = ...)` - // `1` in `({ a: [b] = 1 } = ...)` - const initializer = bindingElement.initializer; - return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) - ? initializer.right - : undefined; - } - - if (isShorthandPropertyAssignment(bindingElement)) { - // `1` in `({ a = 1 } = ...)` - return bindingElement.objectAssignmentInitializer; - } - - if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { - // `1` in `[a = 1] = ...` - // `1` in `[{a} = 1] = ...` - // `1` in `[[a] = 1] = ...` - return bindingElement.right; - } - - if (isSpreadElement(bindingElement)) { - // Recovery consistent with existing emit. - return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); - } - } - - /** - * Gets the name of an BindingOrAssignmentElement. - */ - export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { - if (isDeclarationBindingElement(bindingElement)) { - // `a` in `let { a } = ...` - // `a` in `let { a = 1 } = ...` - // `b` in `let { a: b } = ...` - // `b` in `let { a: b = 1 } = ...` - // `a` in `let { ...a } = ...` - // `{b}` in `let { a: {b} } = ...` - // `{b}` in `let { a: {b} = 1 } = ...` - // `[b]` in `let { a: [b] } = ...` - // `[b]` in `let { a: [b] = 1 } = ...` - // `a` in `let [a] = ...` - // `a` in `let [a = 1] = ...` - // `a` in `let [...a] = ...` - // `{a}` in `let [{a}] = ...` - // `{a}` in `let [{a} = 1] = ...` - // `[a]` in `let [[a]] = ...` - // `[a]` in `let [[a] = 1] = ...` - return bindingElement.name; - } - - if (isObjectLiteralElementLike(bindingElement)) { - switch (bindingElement.kind) { - case SyntaxKind.PropertyAssignment: - // `b` in `({ a: b } = ...)` - // `b` in `({ a: b = 1 } = ...)` - // `{b}` in `({ a: {b} } = ...)` - // `{b}` in `({ a: {b} = 1 } = ...)` - // `[b]` in `({ a: [b] } = ...)` - // `[b]` in `({ a: [b] = 1 } = ...)` - // `b.c` in `({ a: b.c } = ...)` - // `b.c` in `({ a: b.c = 1 } = ...)` - // `b[0]` in `({ a: b[0] } = ...)` - // `b[0]` in `({ a: b[0] = 1 } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); - - case SyntaxKind.ShorthandPropertyAssignment: - // `a` in `({ a } = ...)` - // `a` in `({ a = 1 } = ...)` - return bindingElement.name; - - case SyntaxKind.SpreadAssignment: - // `a` in `({ ...a } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression); - } - - // no target - return undefined; - } - - if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { - // `a` in `[a = 1] = ...` - // `{a}` in `[{a} = 1] = ...` - // `[a]` in `[[a] = 1] = ...` - // `a.b` in `[a.b = 1] = ...` - // `a[0]` in `[a[0] = 1] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.left); - } - - if (isSpreadElement(bindingElement)) { - // `a` in `[...a] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression); - } - - // `a` in `[a] = ...` - // `{a}` in `[{a}] = ...` - // `[a]` in `[[a]] = ...` - // `a.b` in `[a.b] = ...` - // `a[0]` in `[a[0]] = ...` - return bindingElement; - } - - /** - * Determines whether an BindingOrAssignmentElement is a rest element. - */ - export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { - switch (bindingElement.kind) { - case SyntaxKind.Parameter: - case SyntaxKind.BindingElement: - // `...` in `let [...a] = ...` - return bindingElement.dotDotDotToken; - - case SyntaxKind.SpreadElement: - case SyntaxKind.SpreadAssignment: - // `...` in `[...a] = ...` - return bindingElement; - } - - return undefined; - } - - /** - * Gets the property name of a BindingOrAssignmentElement - */ - export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { - switch (bindingElement.kind) { - case SyntaxKind.BindingElement: - // `a` in `let { a: b } = ...` - // `[a]` in `let { [a]: b } = ...` - // `"a"` in `let { "a": b } = ...` - // `1` in `let { 1: b } = ...` - if (bindingElement.propertyName) { - const propertyName = bindingElement.propertyName; - return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) - ? propertyName.expression - : propertyName; - } - - break; - - case SyntaxKind.PropertyAssignment: - // `a` in `({ a: b } = ...)` - // `[a]` in `({ [a]: b } = ...)` - // `"a"` in `({ "a": b } = ...)` - // `1` in `({ 1: b } = ...)` - if (bindingElement.name) { - const propertyName = bindingElement.name; - return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) - ? propertyName.expression - : propertyName; - } - - break; - - case SyntaxKind.SpreadAssignment: - // `a` in `({ ...a } = ...)` - return bindingElement.name; - } - - const target = getTargetOfBindingOrAssignmentElement(bindingElement); - if (target && isPropertyName(target)) { - return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression) - ? target.expression - : target; - } - - Debug.fail("Invalid property name for binding element."); - } - - function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral { - const kind = node.kind; - return kind === SyntaxKind.StringLiteral - || kind === SyntaxKind.NumericLiteral; - } - - /** - * Gets the elements of a BindingOrAssignmentPattern - */ - export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { - switch (name.kind) { - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.ArrayLiteralExpression: - // `a` in `{a}` - // `a` in `[a]` - return name.elements; - - case SyntaxKind.ObjectLiteralExpression: - // `a` in `{a}` - return name.properties; - } - } -} diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts new file mode 100644 index 00000000000..c22bf559b33 --- /dev/null +++ b/src/compiler/factory/nodeTests.ts @@ -0,0 +1,758 @@ +namespace ts { + // Literals + + export function isNumericLiteral(node: Node): node is NumericLiteral { + return node.kind === SyntaxKind.NumericLiteral; + } + + export function isBigIntLiteral(node: Node): node is BigIntLiteral { + return node.kind === SyntaxKind.BigIntLiteral; + } + + export function isStringLiteral(node: Node): node is StringLiteral { + return node.kind === SyntaxKind.StringLiteral; + } + + export function isJsxText(node: Node): node is JsxText { + return node.kind === SyntaxKind.JsxText; + } + + export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral { + return node.kind === SyntaxKind.RegularExpressionLiteral; + } + + export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral { + return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; + } + + // Pseudo-literals + + export function isTemplateHead(node: Node): node is TemplateHead { + return node.kind === SyntaxKind.TemplateHead; + } + + export function isTemplateMiddle(node: Node): node is TemplateMiddle { + return node.kind === SyntaxKind.TemplateMiddle; + } + + export function isTemplateTail(node: Node): node is TemplateTail { + return node.kind === SyntaxKind.TemplateTail; + } + + // Identifiers + + export function isIdentifier(node: Node): node is Identifier { + return node.kind === SyntaxKind.Identifier; + } + + // Names + + export function isQualifiedName(node: Node): node is QualifiedName { + return node.kind === SyntaxKind.QualifiedName; + } + + export function isComputedPropertyName(node: Node): node is ComputedPropertyName { + return node.kind === SyntaxKind.ComputedPropertyName; + } + + // Signature elements + + export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { + return node.kind === SyntaxKind.TypeParameter; + } + + // TODO(rbuckton): Rename to 'isParameterDeclaration' + export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter; + } + + export function isDecorator(node: Node): node is Decorator { + return node.kind === SyntaxKind.Decorator; + } + + // TypeMember + + export function isPropertySignature(node: Node): node is PropertySignature { + return node.kind === SyntaxKind.PropertySignature; + } + + export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { + return node.kind === SyntaxKind.PropertyDeclaration; + } + + export function isMethodSignature(node: Node): node is MethodSignature { + return node.kind === SyntaxKind.MethodSignature; + } + + export function isMethodDeclaration(node: Node): node is MethodDeclaration { + return node.kind === SyntaxKind.MethodDeclaration; + } + + export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { + return node.kind === SyntaxKind.Constructor; + } + + export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { + return node.kind === SyntaxKind.GetAccessor; + } + + export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor; + } + + export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { + return node.kind === SyntaxKind.CallSignature; + } + + export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration { + return node.kind === SyntaxKind.ConstructSignature; + } + + export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration { + return node.kind === SyntaxKind.IndexSignature; + } + + // Type + + export function isTypePredicateNode(node: Node): node is TypePredicateNode { + return node.kind === SyntaxKind.TypePredicate; + } + + export function isTypeReferenceNode(node: Node): node is TypeReferenceNode { + return node.kind === SyntaxKind.TypeReference; + } + + export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { + return node.kind === SyntaxKind.FunctionType; + } + + export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode { + return node.kind === SyntaxKind.ConstructorType; + } + + export function isTypeQueryNode(node: Node): node is TypeQueryNode { + return node.kind === SyntaxKind.TypeQuery; + } + + export function isTypeLiteralNode(node: Node): node is TypeLiteralNode { + return node.kind === SyntaxKind.TypeLiteral; + } + + export function isArrayTypeNode(node: Node): node is ArrayTypeNode { + return node.kind === SyntaxKind.ArrayType; + } + + export function isTupleTypeNode(node: Node): node is TupleTypeNode { + return node.kind === SyntaxKind.TupleType; + } + + export function isOptionalTypeNode(node: Node): node is OptionalTypeNode { + return node.kind === SyntaxKind.OptionalType; + } + + export function isRestTypeNode(node: Node): node is RestTypeNode { + return node.kind === SyntaxKind.RestType; + } + + export function isUnionTypeNode(node: Node): node is UnionTypeNode { + return node.kind === SyntaxKind.UnionType; + } + + export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode { + return node.kind === SyntaxKind.IntersectionType; + } + + export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode { + return node.kind === SyntaxKind.ConditionalType; + } + + export function isInferTypeNode(node: Node): node is InferTypeNode { + return node.kind === SyntaxKind.InferType; + } + + export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode { + return node.kind === SyntaxKind.ParenthesizedType; + } + + export function isThisTypeNode(node: Node): node is ThisTypeNode { + return node.kind === SyntaxKind.ThisType; + } + + export function isTypeOperatorNode(node: Node): node is TypeOperatorNode { + return node.kind === SyntaxKind.TypeOperator; + } + + export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode { + return node.kind === SyntaxKind.IndexedAccessType; + } + + export function isMappedTypeNode(node: Node): node is MappedTypeNode { + return node.kind === SyntaxKind.MappedType; + } + + export function isLiteralTypeNode(node: Node): node is LiteralTypeNode { + return node.kind === SyntaxKind.LiteralType; + } + + export function isImportTypeNode(node: Node): node is ImportTypeNode { + return node.kind === SyntaxKind.ImportType; + } + + // Binding patterns + + export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { + return node.kind === SyntaxKind.ObjectBindingPattern; + } + + export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { + return node.kind === SyntaxKind.ArrayBindingPattern; + } + + export function isBindingElement(node: Node): node is BindingElement { + return node.kind === SyntaxKind.BindingElement; + } + + // Expression + + export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { + return node.kind === SyntaxKind.ArrayLiteralExpression; + } + + export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { + return node.kind === SyntaxKind.ObjectLiteralExpression; + } + + export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node.kind === SyntaxKind.PropertyAccessExpression; + } + + export function isElementAccessExpression(node: Node): node is ElementAccessExpression { + return node.kind === SyntaxKind.ElementAccessExpression; + } + + export function isCallExpression(node: Node): node is CallExpression { + return node.kind === SyntaxKind.CallExpression; + } + + export function isNewExpression(node: Node): node is NewExpression { + return node.kind === SyntaxKind.NewExpression; + } + + export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { + return node.kind === SyntaxKind.TaggedTemplateExpression; + } + + export function isTypeAssertionExpression(node: Node): node is TypeAssertion { + return node.kind === SyntaxKind.TypeAssertionExpression; + } + + export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { + return node.kind === SyntaxKind.ParenthesizedExpression; + } + + export function isFunctionExpression(node: Node): node is FunctionExpression { + return node.kind === SyntaxKind.FunctionExpression; + } + + export function isArrowFunction(node: Node): node is ArrowFunction { + return node.kind === SyntaxKind.ArrowFunction; + } + + export function isDeleteExpression(node: Node): node is DeleteExpression { + return node.kind === SyntaxKind.DeleteExpression; + } + + export function isTypeOfExpression(node: Node): node is TypeOfExpression { + return node.kind === SyntaxKind.TypeOfExpression; + } + + export function isVoidExpression(node: Node): node is VoidExpression { + return node.kind === SyntaxKind.VoidExpression; + } + + export function isAwaitExpression(node: Node): node is AwaitExpression { + return node.kind === SyntaxKind.AwaitExpression; + } + + export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { + return node.kind === SyntaxKind.PrefixUnaryExpression; + } + + export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { + return node.kind === SyntaxKind.PostfixUnaryExpression; + } + + export function isBinaryExpression(node: Node): node is BinaryExpression { + return node.kind === SyntaxKind.BinaryExpression; + } + + export function isConditionalExpression(node: Node): node is ConditionalExpression { + return node.kind === SyntaxKind.ConditionalExpression; + } + + export function isTemplateExpression(node: Node): node is TemplateExpression { + return node.kind === SyntaxKind.TemplateExpression; + } + + export function isYieldExpression(node: Node): node is YieldExpression { + return node.kind === SyntaxKind.YieldExpression; + } + + export function isSpreadElement(node: Node): node is SpreadElement { + return node.kind === SyntaxKind.SpreadElement; + } + + export function isClassExpression(node: Node): node is ClassExpression { + return node.kind === SyntaxKind.ClassExpression; + } + + export function isOmittedExpression(node: Node): node is OmittedExpression { + return node.kind === SyntaxKind.OmittedExpression; + } + + export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { + return node.kind === SyntaxKind.ExpressionWithTypeArguments; + } + + export function isAsExpression(node: Node): node is AsExpression { + return node.kind === SyntaxKind.AsExpression; + } + + export function isNonNullExpression(node: Node): node is NonNullExpression { + return node.kind === SyntaxKind.NonNullExpression; + } + + export function isMetaProperty(node: Node): node is MetaProperty { + return node.kind === SyntaxKind.MetaProperty; + } + + export function isSyntheticExpression(node: Node): node is SyntheticExpression { + return node.kind === SyntaxKind.SyntheticExpression; + } + + export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression { + return node.kind === SyntaxKind.PartiallyEmittedExpression; + } + + export function isCommaListExpression(node: Node): node is CommaListExpression { + return node.kind === SyntaxKind.CommaListExpression; + } + + // Misc + + export function isTemplateSpan(node: Node): node is TemplateSpan { + return node.kind === SyntaxKind.TemplateSpan; + } + + export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { + return node.kind === SyntaxKind.SemicolonClassElement; + } + + // Elements + + export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block; + } + + export function isVariableStatement(node: Node): node is VariableStatement { + return node.kind === SyntaxKind.VariableStatement; + } + + export function isEmptyStatement(node: Node): node is EmptyStatement { + return node.kind === SyntaxKind.EmptyStatement; + } + + export function isExpressionStatement(node: Node): node is ExpressionStatement { + return node.kind === SyntaxKind.ExpressionStatement; + } + + export function isIfStatement(node: Node): node is IfStatement { + return node.kind === SyntaxKind.IfStatement; + } + + export function isDoStatement(node: Node): node is DoStatement { + return node.kind === SyntaxKind.DoStatement; + } + + export function isWhileStatement(node: Node): node is WhileStatement { + return node.kind === SyntaxKind.WhileStatement; + } + + export function isForStatement(node: Node): node is ForStatement { + return node.kind === SyntaxKind.ForStatement; + } + + export function isForInStatement(node: Node): node is ForInStatement { + return node.kind === SyntaxKind.ForInStatement; + } + + export function isForOfStatement(node: Node): node is ForOfStatement { + return node.kind === SyntaxKind.ForOfStatement; + } + + export function isContinueStatement(node: Node): node is ContinueStatement { + return node.kind === SyntaxKind.ContinueStatement; + } + + export function isBreakStatement(node: Node): node is BreakStatement { + return node.kind === SyntaxKind.BreakStatement; + } + + export function isReturnStatement(node: Node): node is ReturnStatement { + return node.kind === SyntaxKind.ReturnStatement; + } + + export function isWithStatement(node: Node): node is WithStatement { + return node.kind === SyntaxKind.WithStatement; + } + + export function isSwitchStatement(node: Node): node is SwitchStatement { + return node.kind === SyntaxKind.SwitchStatement; + } + + export function isLabeledStatement(node: Node): node is LabeledStatement { + return node.kind === SyntaxKind.LabeledStatement; + } + + export function isThrowStatement(node: Node): node is ThrowStatement { + return node.kind === SyntaxKind.ThrowStatement; + } + + export function isTryStatement(node: Node): node is TryStatement { + return node.kind === SyntaxKind.TryStatement; + } + + export function isDebuggerStatement(node: Node): node is DebuggerStatement { + return node.kind === SyntaxKind.DebuggerStatement; + } + + export function isVariableDeclaration(node: Node): node is VariableDeclaration { + return node.kind === SyntaxKind.VariableDeclaration; + } + + export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { + return node.kind === SyntaxKind.VariableDeclarationList; + } + + export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { + return node.kind === SyntaxKind.FunctionDeclaration; + } + + export function isClassDeclaration(node: Node): node is ClassDeclaration { + return node.kind === SyntaxKind.ClassDeclaration; + } + + export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { + return node.kind === SyntaxKind.InterfaceDeclaration; + } + + export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { + return node.kind === SyntaxKind.TypeAliasDeclaration; + } + + export function isEnumDeclaration(node: Node): node is EnumDeclaration { + return node.kind === SyntaxKind.EnumDeclaration; + } + + export function isModuleDeclaration(node: Node): node is ModuleDeclaration { + return node.kind === SyntaxKind.ModuleDeclaration; + } + + export function isModuleBlock(node: Node): node is ModuleBlock { + return node.kind === SyntaxKind.ModuleBlock; + } + + export function isCaseBlock(node: Node): node is CaseBlock { + return node.kind === SyntaxKind.CaseBlock; + } + + export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration { + return node.kind === SyntaxKind.NamespaceExportDeclaration; + } + + export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { + return node.kind === SyntaxKind.ImportEqualsDeclaration; + } + + export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node.kind === SyntaxKind.ImportDeclaration; + } + + export function isImportClause(node: Node): node is ImportClause { + return node.kind === SyntaxKind.ImportClause; + } + + export function isNamespaceImport(node: Node): node is NamespaceImport { + return node.kind === SyntaxKind.NamespaceImport; + } + + export function isNamedImports(node: Node): node is NamedImports { + return node.kind === SyntaxKind.NamedImports; + } + + export function isImportSpecifier(node: Node): node is ImportSpecifier { + return node.kind === SyntaxKind.ImportSpecifier; + } + + export function isExportAssignment(node: Node): node is ExportAssignment { + return node.kind === SyntaxKind.ExportAssignment; + } + + export function isExportDeclaration(node: Node): node is ExportDeclaration { + return node.kind === SyntaxKind.ExportDeclaration; + } + + export function isNamedExports(node: Node): node is NamedExports { + return node.kind === SyntaxKind.NamedExports; + } + + export function isExportSpecifier(node: Node): node is ExportSpecifier { + return node.kind === SyntaxKind.ExportSpecifier; + } + + export function isMissingDeclaration(node: Node): node is MissingDeclaration { + return node.kind === SyntaxKind.MissingDeclaration; + } + + export function isNotEmittedStatement(node: Node): node is NotEmittedStatement { + return node.kind === SyntaxKind.NotEmittedStatement; + } + + /* @internal */ + export function isMergeDeclarationMarker(node: Node): node is MergeDeclarationMarker { + return node.kind === SyntaxKind.MergeDeclarationMarker; + } + + /* @internal */ + export function isEndOfDeclarationMarker(node: Node): node is EndOfDeclarationMarker { + return node.kind === SyntaxKind.EndOfDeclarationMarker; + } + + // Module References + + export function isExternalModuleReference(node: Node): node is ExternalModuleReference { + return node.kind === SyntaxKind.ExternalModuleReference; + } + + // JSX + + export function isJsxElement(node: Node): node is JsxElement { + return node.kind === SyntaxKind.JsxElement; + } + + export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { + return node.kind === SyntaxKind.JsxSelfClosingElement; + } + + export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { + return node.kind === SyntaxKind.JsxOpeningElement; + } + + export function isJsxClosingElement(node: Node): node is JsxClosingElement { + return node.kind === SyntaxKind.JsxClosingElement; + } + + export function isJsxFragment(node: Node): node is JsxFragment { + return node.kind === SyntaxKind.JsxFragment; + } + + export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { + return node.kind === SyntaxKind.JsxOpeningFragment; + } + + export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { + return node.kind === SyntaxKind.JsxClosingFragment; + } + + export function isJsxAttribute(node: Node): node is JsxAttribute { + return node.kind === SyntaxKind.JsxAttribute; + } + + export function isJsxAttributes(node: Node): node is JsxAttributes { + return node.kind === SyntaxKind.JsxAttributes; + } + + export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { + return node.kind === SyntaxKind.JsxSpreadAttribute; + } + + export function isJsxExpression(node: Node): node is JsxExpression { + return node.kind === SyntaxKind.JsxExpression; + } + + // Clauses + + export function isCaseClause(node: Node): node is CaseClause { + return node.kind === SyntaxKind.CaseClause; + } + + export function isDefaultClause(node: Node): node is DefaultClause { + return node.kind === SyntaxKind.DefaultClause; + } + + export function isHeritageClause(node: Node): node is HeritageClause { + return node.kind === SyntaxKind.HeritageClause; + } + + export function isCatchClause(node: Node): node is CatchClause { + return node.kind === SyntaxKind.CatchClause; + } + + // Property assignments + + export function isPropertyAssignment(node: Node): node is PropertyAssignment { + return node.kind === SyntaxKind.PropertyAssignment; + } + + export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { + return node.kind === SyntaxKind.ShorthandPropertyAssignment; + } + + export function isSpreadAssignment(node: Node): node is SpreadAssignment { + return node.kind === SyntaxKind.SpreadAssignment; + } + + // Enum + + export function isEnumMember(node: Node): node is EnumMember { + return node.kind === SyntaxKind.EnumMember; + } + + // Unparsed + + // TODO(rbuckton): isUnparsedPrologue + + export function isUnparsedPrepend(node: Node): node is UnparsedPrepend { + return node.kind === SyntaxKind.UnparsedPrepend; + } + + // TODO(rbuckton): isUnparsedText + // TODO(rbuckton): isUnparsedInternalText + // TODO(rbuckton): isUnparsedSyntheticReference + + // Top-level nodes + export function isSourceFile(node: Node): node is SourceFile { + return node.kind === SyntaxKind.SourceFile; + } + + export function isBundle(node: Node): node is Bundle { + return node.kind === SyntaxKind.Bundle; + } + + export function isUnparsedSource(node: Node): node is UnparsedSource { + return node.kind === SyntaxKind.UnparsedSource; + } + + // TODO(rbuckton): isInputFiles + + // JSDoc Elements + + export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { + return node.kind === SyntaxKind.JSDocTypeExpression; + } + + export function isJSDocAllType(node: JSDocAllType): node is JSDocAllType { + return node.kind === SyntaxKind.JSDocAllType; + } + + export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { + return node.kind === SyntaxKind.JSDocUnknownType; + } + + export function isJSDocNullableType(node: Node): node is JSDocNullableType { + return node.kind === SyntaxKind.JSDocNullableType; + } + + export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { + return node.kind === SyntaxKind.JSDocNonNullableType; + } + + export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { + return node.kind === SyntaxKind.JSDocOptionalType; + } + + export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { + return node.kind === SyntaxKind.JSDocFunctionType; + } + + export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { + return node.kind === SyntaxKind.JSDocVariadicType; + } + + export function isJSDocNamepathType(node: Node): node is JSDocNamepathType { + return node.kind === SyntaxKind.JSDocNamepathType; + } + + export function isJSDoc(node: Node): node is JSDoc { + return node.kind === SyntaxKind.JSDocComment; + } + + export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { + return node.kind === SyntaxKind.JSDocTypeLiteral; + } + + export function isJSDocSignature(node: Node): node is JSDocSignature { + return node.kind === SyntaxKind.JSDocSignature; + } + + // JSDoc Tags + + export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { + return node.kind === SyntaxKind.JSDocAugmentsTag; + } + + export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { + return node.kind === SyntaxKind.JSDocAuthorTag; + } + + export function isJSDocClassTag(node: Node): node is JSDocClassTag { + return node.kind === SyntaxKind.JSDocClassTag; + } + + export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag { + return node.kind === SyntaxKind.JSDocCallbackTag; + } + + export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { + return node.kind === SyntaxKind.JSDocEnumTag; + } + + export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { + return node.kind === SyntaxKind.JSDocParameterTag; + } + + export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { + return node.kind === SyntaxKind.JSDocReturnTag; + } + + export function isJSDocThisTag(node: Node): node is JSDocThisTag { + return node.kind === SyntaxKind.JSDocThisTag; + } + + export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { + return node.kind === SyntaxKind.JSDocTypeTag; + } + + export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { + return node.kind === SyntaxKind.JSDocTemplateTag; + } + + export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { + return node.kind === SyntaxKind.JSDocTypedefTag; + } + + export function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag { + return node.kind === SyntaxKind.JSDocTag; + } + + export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag { + return node.kind === SyntaxKind.JSDocPropertyTag; + } + + // Synthesized list + + /* @internal */ + export function isSyntaxList(n: Node): n is SyntaxList { + return n.kind === SyntaxKind.SyntaxList; + } +} diff --git a/src/compiler/parenthesizerRules.ts b/src/compiler/factory/parenthesizerRules.ts similarity index 95% rename from src/compiler/parenthesizerRules.ts rename to src/compiler/factory/parenthesizerRules.ts index ca5c295625d..9ae45f03c69 100644 --- a/src/compiler/parenthesizerRules.ts +++ b/src/compiler/factory/parenthesizerRules.ts @@ -315,7 +315,7 @@ namespace ts { function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray): NodeArray { const result = sameMap(elements, parenthesizeExpressionForDisallowedComma); - return setTextRange(createNodeArray(result, elements.hasTrailingComma), elements); + return setTextRange(factory.createNodeArray(result, elements.hasTrailingComma), elements); } function parenthesizeExpressionForDisallowedComma(expression: Expression): Expression { @@ -387,7 +387,7 @@ namespace ts { } function parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray { - return createNodeArray(sameMap(members, parenthesizeMemberOfElementType)); + return factory.createNodeArray(sameMap(members, parenthesizeMemberOfElementType)); } @@ -397,12 +397,12 @@ namespace ts { function parenthesizeTypeArguments(typeArguments: NodeArray | undefined): NodeArray | undefined { if (some(typeArguments)) { - return createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); + return factory.createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); } } } - const nullParenthesizerRules: ParenthesizerRules = { + export const nullParenthesizerRules: ParenthesizerRules = { parenthesizeLeftSideOfBinary: (_binaryOperator, leftSide) => leftSide, parenthesizeRightSideOfBinary: (_binaryOperator, _leftSide, rightSide) => rightSide, parenthesizeExpressionOfComputedPropertyName: identity, @@ -413,18 +413,14 @@ namespace ts { parenthesizeLeftSideOfAccess: expression => cast(expression, isLeftHandSideExpression), parenthesizeOperandOfPostfixUnary: operand => cast(operand, isLeftHandSideExpression), parenthesizeOperandOfPrefixUnary: operand => cast(operand, isUnaryExpression), - parenthesizeExpressionsOfCommaDelimitedList: nodes => createNodeArray(nodes), + parenthesizeExpressionsOfCommaDelimitedList: nodes => cast(nodes, isNodeArray), parenthesizeExpressionForDisallowedComma: identity, parenthesizeExpressionOfExpressionStatement: identity, parenthesizeConciseBodyOfArrowFunction: identity, parenthesizeMemberOfConditionalType: identity, parenthesizeMemberOfElementType: identity, parenthesizeElementTypeOfArrayType: identity, - parenthesizeConstituentTypesOfUnionOrIntersectionType: nodes => createNodeArray(nodes), - parenthesizeTypeArguments: nodes => nodes && createNodeArray(nodes), + parenthesizeConstituentTypesOfUnionOrIntersectionType: nodes => cast(nodes, isNodeArray), + parenthesizeTypeArguments: nodes => nodes && cast(nodes, isNodeArray), }; - - export function getNullParenthesizerRules(_factory: NodeFactory): ParenthesizerRules { - return nullParenthesizerRules; - } } \ No newline at end of file diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts new file mode 100644 index 00000000000..d6a83b30858 --- /dev/null +++ b/src/compiler/factory/utilities.ts @@ -0,0 +1,778 @@ +/* @internal */ +namespace ts { + + // Compound nodes + + export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { + if (isComputedPropertyName(memberName)) { + return setTextRange(factory.createElementAccess(target, memberName.expression), location); + } + else { + const expression = setTextRange( + isIdentifier(memberName) + ? factory.createPropertyAccess(target, memberName) + : factory.createElementAccess(target, memberName), + memberName + ); + getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; + return expression; + } + } + + function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. + const react = parseNodeFactory.createIdentifier(reactNamespace || "React"); + // Set the parent that is in parse tree + // this makes sure that parent chain is intact for checker to traverse complete scope tree + react.parent = getParseTreeNode(parent)!; + return react; + } + + function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + if (isQualifiedName(jsxFactory)) { + const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent); + const right = factory.createIdentifier(idText(jsxFactory.right)); + right.escapedText = jsxFactory.right.escapedText; + return factory.createPropertyAccess(left, right); + } + else { + return createReactNamespace(idText(jsxFactory), parent); + } + } + + function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + return jsxFactoryEntity ? + createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) : + factory.createPropertyAccess( + createReactNamespace(reactNamespace, parent), + "createElement" + ); + } + + export function createExpressionForJsxElement(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { + const argumentsList = [tagName]; + if (props) { + argumentsList.push(props); + } + + if (children && children.length > 0) { + if (!props) { + argumentsList.push(factory.createNull()); + } + + if (children.length > 1) { + for (const child of children) { + startOnNewLine(child); + argumentsList.push(child); + } + } + else { + argumentsList.push(children[0]); + } + } + + return setTextRange( + factory.createCall( + createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), + location + ); + } + + export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { + const tagName = factory.createPropertyAccess( + createReactNamespace(reactNamespace, parentElement), + "Fragment" + ); + + const argumentsList = [tagName]; + argumentsList.push(factory.createNull()); + + if (children && children.length > 0) { + if (children.length > 1) { + for (const child of children) { + startOnNewLine(child); + argumentsList.push(child); + } + } + else { + argumentsList.push(children[0]); + } + } + + return setTextRange( + factory.createCall( + createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), + location + ); + } + + // Utilities + + export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement { + if (isVariableDeclarationList(node)) { + const firstDeclaration = first(node.declarations); + const updatedDeclaration = factory.updateVariableDeclaration( + firstDeclaration, + firstDeclaration.name, + /*typeNode*/ undefined, + boundValue + ); + return setTextRange( + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.updateVariableDeclarationList(node, [updatedDeclaration]) + ), + /*location*/ node + ); + } + else { + const updatedExpression = setTextRange(factory.createAssignment(node, boundValue), /*location*/ node); + return setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node); + } + } + + export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement) { + if (isBlock(dest)) { + return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); + } + else { + return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true); + } + } + + export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression { + if (isQualifiedName(node)) { + const left = createExpressionFromEntityName(factory, node.left); + const right = getMutableClone(node.right); + return setTextRange(factory.createPropertyAccess(left, right), node); + } + else { + return getMutableClone(node); + } + } + + export function createExpressionForPropertyName(factory: NodeFactory, memberName: PropertyName): Expression { + if (isIdentifier(memberName)) { + return factory.createStringLiteralFromNode(memberName); + } + else if (isComputedPropertyName(memberName)) { + return getMutableClone(memberName.expression); + } + else { + return getMutableClone(memberName); + } + } + + function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray, property: AccessorDeclaration, receiver: Expression, multiLine: boolean) { + const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); + if (property === firstAccessor) { + return aggregateTransformFlags( + setTextRange( + factory.createObjectDefinePropertyCall( + receiver, + createExpressionForPropertyName(factory, property.name), + factory.createPropertyDescriptor({ + enumerable: true, + configurable: true, + get: getAccessor && setTextRange( + setOriginalNode( + factory.createFunctionExpression( + getAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + getAccessor.parameters, + /*type*/ undefined, + getAccessor.body! // TODO: GH#18217 + ), + getAccessor + ), + getAccessor + ), + set: setAccessor && setTextRange( + setOriginalNode( + factory.createFunctionExpression( + setAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + setAccessor.parameters, + /*type*/ undefined, + setAccessor.body! // TODO: GH#18217 + ), + setAccessor + ), + setAccessor + ) + }, !multiLine) + ), + firstAccessor + ) + ); + } + + return undefined; + } + + function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) { + return aggregateTransformFlags( + setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), + property.initializer + ), + property + ), + property + ) + ); + } + + function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) { + return aggregateTransformFlags( + setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), + getSynthesizedClone(property.name) + ), + /*location*/ property + ), + /*original*/ property + ) + ); + } + + function createExpressionForMethodDeclaration(factory: NodeFactory, method: MethodDeclaration, receiver: Expression) { + return aggregateTransformFlags( + setOriginalNode( + setTextRange( + factory.createAssignment( + createMemberAccessForPropertyName(factory, receiver, method.name, /*location*/ method.name), + setOriginalNode( + setTextRange( + factory.createFunctionExpression( + method.modifiers, + method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, + method.parameters, + /*type*/ undefined, + method.body! // TODO: GH#18217 + ), + /*location*/ method + ), + /*original*/ method + ) + ), + /*location*/ method + ), + /*original*/ method + ) + ); + } + + export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { + switch (property.kind) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return createExpressionForAccessorDeclaration(factory, node.properties, property, receiver, !!node.multiLine); + case SyntaxKind.PropertyAssignment: + return createExpressionForPropertyAssignment(factory, property, receiver); + case SyntaxKind.ShorthandPropertyAssignment: + return createExpressionForShorthandPropertyAssignment(factory, property, receiver); + case SyntaxKind.MethodDeclaration: + return createExpressionForMethodDeclaration(factory, property, receiver); + } + } + + /** + * Gets whether an identifier should only be referred to by its internal name. + */ + export function isInternalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; + } + + /** + * Gets whether an identifier should only be referred to by its local name. + */ + export function isLocalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; + } + + /** + * Gets whether an identifier should only be referred to by its export representation if the + * name points to an exported symbol. + */ + export function isExportName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; + } + + function isUseStrictPrologue(node: ExpressionStatement): boolean { + return isStringLiteral(node.expression) && node.expression.text === "use strict"; + } + + export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined { + for (const statement of statements) { + if (isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement)) { + return statement; + } + } + else { + break; + } + } + return undefined; + } + + export function startsWithUseStrict(statements: readonly Statement[]) { + const firstStatement = firstOrUndefined(statements); + return firstStatement !== undefined + && isPrologueDirective(firstStatement) + && isUseStrictPrologue(firstStatement); + } + + export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token} | CommaListExpression { + return node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.CommaToken || + node.kind === SyntaxKind.CommaListExpression; + } + + export type OuterExpression = ParenthesizedExpression | TypeAssertion | AsExpression | NonNullExpression | PartiallyEmittedExpression; + + export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { + switch (node.kind) { + case SyntaxKind.ParenthesizedExpression: + return (kinds & OuterExpressionKinds.Parentheses) !== 0; + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + return (kinds & OuterExpressionKinds.Assertions) !== 0; + case SyntaxKind.PartiallyEmittedExpression: + return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; + } + return false; + } + + export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; + export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; + export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { + let previousNode: Node; + do { + previousNode = node; + if (kinds & OuterExpressionKinds.Parentheses) { + node = skipParentheses(node); + } + + if (kinds & OuterExpressionKinds.Assertions) { + node = skipAssertions(node); + } + + if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) { + node = skipPartiallyEmittedExpressions(node); + } + } + while (previousNode !== node); + + return node; + } + + export function skipAssertions(node: Expression): Expression; + export function skipAssertions(node: Node): Node; + export function skipAssertions(node: Node): Node { + while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) { + node = (node).expression; + } + + return node; + } + + export function startOnNewLine(node: T): T { + return setStartsOnNewLine(node, /*newLine*/ true); + } + + export function getExternalHelpersModuleName(node: SourceFile) { + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = parseNode && parseNode.emitNode; + return emitNode && emitNode.externalHelpersModuleName; + } + + export function hasRecordedExternalHelpers(sourceFile: SourceFile) { + const parseNode = getOriginalNode(sourceFile, isSourceFile); + const emitNode = parseNode && parseNode.emitNode; + return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); + } + + export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { + let namedBindings: NamedImportBindings | undefined; + const moduleKind = getEmitModuleKind(compilerOptions); + if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) { + // use named imports + const helpers = getEmitHelpers(sourceFile); + if (helpers) { + const helperNames: string[] = []; + for (const helper of helpers) { + if (!helper.scoped) { + const importName = (helper as UnscopedEmitHelper).importName; + if (importName) { + pushIfUnique(helperNames, importName); + } + } + } + if (some(helperNames)) { + helperNames.sort(compareStringsCaseSensitive); + // Alias the imports if the names are used somewhere in the file. + // NOTE: We don't need to care about global import collisions as this is a module. + namedBindings = nodeFactory.createNamedImports( + map(helperNames, name => isFileLevelUniqueName(sourceFile, name) + ? nodeFactory.createImportSpecifier(/*propertyName*/ undefined, nodeFactory.createIdentifier(name)) + : nodeFactory.createImportSpecifier(nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name)) + ) + ); + const parseNode = getOriginalNode(sourceFile, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + emitNode.externalHelpers = true; + } + } + } + else { + // use a namespace import + const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(nodeFactory, sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault); + if (externalHelpersModuleName) { + namedBindings = nodeFactory.createNamespaceImport(externalHelpersModuleName); + } + } + if (namedBindings) { + const externalHelpersImportDeclaration = nodeFactory.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + nodeFactory.createImportClause(/*name*/ undefined, namedBindings), + nodeFactory.createStringLiteral(externalHelpersModuleNameText) + ); + addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper); + return externalHelpersImportDeclaration; + } + } + } + + export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { + const externalHelpersModuleName = getExternalHelpersModuleName(node); + if (externalHelpersModuleName) { + return externalHelpersModuleName; + } + + const moduleKind = getEmitModuleKind(compilerOptions); + let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault)) + && moduleKind !== ModuleKind.System + && moduleKind !== ModuleKind.ES2015 + && moduleKind !== ModuleKind.ESNext; + if (!create) { + const helpers = getEmitHelpers(node); + if (helpers) { + for (const helper of helpers) { + if (!helper.scoped) { + create = true; + break; + } + } + } + } + + if (create) { + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); + } + } + } + + /** + * Get the name of that target module from an import or export declaration + */ + export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { + const namespaceDeclaration = getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !isDefaultImport(node)) { + const name = namespaceDeclaration.name; + return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); + } + if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { + return factory.getGeneratedNameForNode(node); + } + if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) { + return factory.getGeneratedNameForNode(node); + } + return undefined; + } + + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { + const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 + if (moduleName.kind === SyntaxKind.StringLiteral) { + return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) + || tryRenameExternalModule(factory, moduleName, sourceFile) + || getSynthesizedClone(moduleName); + } + + return undefined; + } + + /** + * Some bundlers (SystemJS builder) sometimes want to rename dependencies. + * Here we check if alternative name was provided for a given moduleName and return it if possible. + */ + function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) { + const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); + return rename && factory.createStringLiteral(rename); + } + + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { + if (!file) { + return undefined; + } + if (file.moduleName) { + return factory.createStringLiteral(file.moduleName); + } + if (!file.isDeclarationFile && (options.out || options.outFile)) { + return factory.createStringLiteral(getExternalModuleNameFromPath(host, file.fileName)); + } + return undefined; + } + + function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { + return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); + } + + /** + * Gets the initializer of an BindingOrAssignmentElement. + */ + export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { + if (isDeclarationBindingElement(bindingElement)) { + // `1` in `let { a = 1 } = ...` + // `1` in `let { a: b = 1 } = ...` + // `1` in `let { a: {b} = 1 } = ...` + // `1` in `let { a: [b] = 1 } = ...` + // `1` in `let [a = 1] = ...` + // `1` in `let [{a} = 1] = ...` + // `1` in `let [[a] = 1] = ...` + return bindingElement.initializer; + } + + if (isPropertyAssignment(bindingElement)) { + // `1` in `({ a: b = 1 } = ...)` + // `1` in `({ a: {b} = 1 } = ...)` + // `1` in `({ a: [b] = 1 } = ...)` + const initializer = bindingElement.initializer; + return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) + ? initializer.right + : undefined; + } + + if (isShorthandPropertyAssignment(bindingElement)) { + // `1` in `({ a = 1 } = ...)` + return bindingElement.objectAssignmentInitializer; + } + + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `1` in `[a = 1] = ...` + // `1` in `[{a} = 1] = ...` + // `1` in `[[a] = 1] = ...` + return bindingElement.right; + } + + if (isSpreadElement(bindingElement)) { + // Recovery consistent with existing emit. + return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); + } + } + + /** + * Gets the name of an BindingOrAssignmentElement. + */ + export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { + if (isDeclarationBindingElement(bindingElement)) { + // `a` in `let { a } = ...` + // `a` in `let { a = 1 } = ...` + // `b` in `let { a: b } = ...` + // `b` in `let { a: b = 1 } = ...` + // `a` in `let { ...a } = ...` + // `{b}` in `let { a: {b} } = ...` + // `{b}` in `let { a: {b} = 1 } = ...` + // `[b]` in `let { a: [b] } = ...` + // `[b]` in `let { a: [b] = 1 } = ...` + // `a` in `let [a] = ...` + // `a` in `let [a = 1] = ...` + // `a` in `let [...a] = ...` + // `{a}` in `let [{a}] = ...` + // `{a}` in `let [{a} = 1] = ...` + // `[a]` in `let [[a]] = ...` + // `[a]` in `let [[a] = 1] = ...` + return bindingElement.name; + } + + if (isObjectLiteralElementLike(bindingElement)) { + switch (bindingElement.kind) { + case SyntaxKind.PropertyAssignment: + // `b` in `({ a: b } = ...)` + // `b` in `({ a: b = 1 } = ...)` + // `{b}` in `({ a: {b} } = ...)` + // `{b}` in `({ a: {b} = 1 } = ...)` + // `[b]` in `({ a: [b] } = ...)` + // `[b]` in `({ a: [b] = 1 } = ...)` + // `b.c` in `({ a: b.c } = ...)` + // `b.c` in `({ a: b.c = 1 } = ...)` + // `b[0]` in `({ a: b[0] } = ...)` + // `b[0]` in `({ a: b[0] = 1 } = ...)` + return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); + + case SyntaxKind.ShorthandPropertyAssignment: + // `a` in `({ a } = ...)` + // `a` in `({ a = 1 } = ...)` + return bindingElement.name; + + case SyntaxKind.SpreadAssignment: + // `a` in `({ ...a } = ...)` + return getTargetOfBindingOrAssignmentElement(bindingElement.expression); + } + + // no target + return undefined; + } + + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `a` in `[a = 1] = ...` + // `{a}` in `[{a} = 1] = ...` + // `[a]` in `[[a] = 1] = ...` + // `a.b` in `[a.b = 1] = ...` + // `a[0]` in `[a[0] = 1] = ...` + return getTargetOfBindingOrAssignmentElement(bindingElement.left); + } + + if (isSpreadElement(bindingElement)) { + // `a` in `[...a] = ...` + return getTargetOfBindingOrAssignmentElement(bindingElement.expression); + } + + // `a` in `[a] = ...` + // `{a}` in `[{a}] = ...` + // `[a]` in `[[a]] = ...` + // `a.b` in `[a.b] = ...` + // `a[0]` in `[a[0]] = ...` + return bindingElement; + } + + /** + * Determines whether an BindingOrAssignmentElement is a rest element. + */ + export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { + switch (bindingElement.kind) { + case SyntaxKind.Parameter: + case SyntaxKind.BindingElement: + // `...` in `let [...a] = ...` + return bindingElement.dotDotDotToken; + + case SyntaxKind.SpreadElement: + case SyntaxKind.SpreadAssignment: + // `...` in `[...a] = ...` + return bindingElement; + } + + return undefined; + } + + /** + * Gets the property name of a BindingOrAssignmentElement + */ + export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined { + switch (bindingElement.kind) { + case SyntaxKind.BindingElement: + // `a` in `let { a: b } = ...` + // `[a]` in `let { [a]: b } = ...` + // `"a"` in `let { "a": b } = ...` + // `1` in `let { 1: b } = ...` + if (bindingElement.propertyName) { + const propertyName = bindingElement.propertyName; + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + ? propertyName.expression + : propertyName; + } + + break; + + case SyntaxKind.PropertyAssignment: + // `a` in `({ a: b } = ...)` + // `[a]` in `({ [a]: b } = ...)` + // `"a"` in `({ "a": b } = ...)` + // `1` in `({ 1: b } = ...)` + if (bindingElement.name) { + const propertyName = bindingElement.name; + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + ? propertyName.expression + : propertyName; + } + + break; + + case SyntaxKind.SpreadAssignment: + // `a` in `({ ...a } = ...)` + return bindingElement.name; + } + + const target = getTargetOfBindingOrAssignmentElement(bindingElement); + if (target && isPropertyName(target)) { + return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression) + ? target.expression + : target; + } + + Debug.fail("Invalid property name for binding element."); + } + + function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral { + const kind = node.kind; + return kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral; + } + + /** + * Gets the elements of a BindingOrAssignmentPattern + */ + export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { + switch (name.kind) { + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + // `a` in `{a}` + // `a` in `[a]` + return name.elements; + + case SyntaxKind.ObjectLiteralExpression: + // `a` in `{a}` + return name.properties; + } + } +} \ No newline at end of file diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d91ec1a3b09..db8abef3f04 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -31,7 +31,12 @@ namespace ts { } /* @internal */ - export const parseNodeFactory = createNodeFactory(createNode, createParenthesizerRules, createNodeConverters, nullTreeStateObserver); + export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.None, { + createBaseSourceFileNode: createNode, + createBaseIdentifierNode: createNode, + createBaseTokenNode: createNode, + createBaseNode: createNode + }); function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); @@ -590,7 +595,16 @@ 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, nullTreeStateObserver); + + const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters, { + createBaseSourceFileNode: kind => new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseIdentifierNode: kind => new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseTokenNode: kind => new TokenConstructor(kind, /*pos*/ 0, /*end*/ 0), + createBaseNode: kind => new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0) + }, { + onCreateNode: _node => nodeCount++ + }); + const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; // capture constructors in 'initializeState' to avoid null checks @@ -601,12 +615,16 @@ namespace ts { let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; // tslint:enable variable-name - let sourceFile: SourceFile; - let parseDiagnostics: DiagnosticWithLocation[]; + let sourceFlags: NodeFlags; + let sourceText: string; + let languageVersion: ScriptTarget; + let scriptKind: ScriptKind; + let languageVariant: LanguageVariant; + let parseDiagnostics: DiagnosticWithDetachedLocation[]; + let jsDocDiagnostics: DiagnosticWithDetachedLocation[]; let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; let currentToken: SyntaxKind; - let sourceText: string; let nodeCount: number; let identifiers: Map; let identifierCount: number; @@ -728,17 +746,15 @@ namespace ts { export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): JsonSourceFile { initializeState(sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); - // Set source file so that errors will be reported with this file name - sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false); - sourceFile.flags = contextFlags; + sourceFlags = contextFlags; // Prime the scanner. nextToken(); const pos = getNodePos(); + let statements, endOfFileToken; 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(); + statements = createNodeArray([], pos, pos); + endOfFileToken = parseTokenNode(); } else { let expression; @@ -774,34 +790,46 @@ namespace ts { // 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); - sourceFile.endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); + statements = createNodeArray([statement], pos); + endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); } + // Set source file so that errors will be reported with this file name + const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken); + sourceFile.flags |= sourceFlags; + if (setParentNodes) { fixupParentReferences(sourceFile); } - sourceFile.parseDiagnostics = parseDiagnostics; + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } + const result = sourceFile as JsonSourceFile; clearState(); return result; } - function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, scriptKind: ScriptKind) { + function initializeState(_sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); SourceFileConstructor = objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; + languageVersion = _languageVersion; syntaxCursor = _syntaxCursor; + scriptKind = _scriptKind; + languageVariant = getLanguageVariant(_scriptKind); parseDiagnostics = []; parsingContext = 0; identifiers = createMap(); identifierCount = 0; nodeCount = 0; + sourceFlags = 0; switch (scriptKind) { case ScriptKind.JS: @@ -821,7 +849,7 @@ namespace ts { scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + scanner.setLanguageVariant(languageVariant); } function clearState() { @@ -830,11 +858,16 @@ namespace ts { scanner.setOnError(undefined); // Clear any data. We don't want to accidentally hold onto it for too long. - parseDiagnostics = undefined!; - sourceFile = undefined!; - identifiers = undefined!; - syntaxCursor = undefined; sourceText = undefined!; + languageVersion = undefined!; + syntaxCursor = undefined; + scriptKind = undefined!; + languageVariant = undefined!; + sourceFlags = 0; + parseDiagnostics = undefined!; + jsDocDiagnostics = undefined!; + parsingContext = 0; + identifiers = undefined!; notParenthesizedArrow = undefined!; } @@ -844,27 +877,31 @@ namespace ts { contextFlags |= NodeFlags.Ambient; } - sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); - sourceFile.flags = contextFlags; + sourceFlags = contextFlags; // Prime the scanner. nextToken(); + + const statements = parseList(ParsingContext.SourceElements, parseStatement); + Debug.assert(token() === SyntaxKind.EndOfFileToken); + const endOfFileToken = addJSDocComment(parseTokenNode()); + + const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken); + sourceFile.flags |= sourceFlags; + // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic); - // 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()); - - setExternalModuleIndicator(sourceFile); - sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = parseDiagnostics; + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } + setExternalModuleIndicator(sourceFile); if (setParentNodes) { fixupParentReferences(sourceFile); } @@ -872,7 +909,7 @@ namespace ts { return sourceFile; function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) { - parseDiagnostics.push(createFileDiagnostic(sourceFile, pos, end, diagnostic)); + parseDiagnostics.push(createDetachedDiagnostic(pos, end, diagnostic)); } } @@ -882,7 +919,7 @@ namespace ts { function addJSDocComment(node: T): T { Debug.assert(!node.jsDoc); // Should only be called once per node - const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceFile.text), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); + const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); if (jsDoc.length) node.jsDoc = jsDoc; return node; } @@ -919,12 +956,12 @@ namespace ts { } } - function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean): SourceFile { + function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean, statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible - const sourceFile = new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length); - nodeCount++; - + const sourceFile = factory.createSourceFile(statements, endOfFileToken); + sourceFile.pos = 0; + sourceFile.end = sourceText.length; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.bindSuggestionDiagnostics = undefined; @@ -1060,7 +1097,7 @@ namespace ts { // Don't report another error if it would just be at the same position as the last error. const lastError = lastOrUndefined(parseDiagnostics); if (!lastError || start !== lastError.start) { - parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0)); + parseDiagnostics.push(createDetachedDiagnostic(start, length, message, arg0)); } // Mark that we've encountered an error. We'll set an appropriate bit on the next @@ -1320,19 +1357,8 @@ namespace ts { } } - function createNode(kind: SyntaxKind): Node { - nodeCount++; - return isNodeKind(kind) || kind === SyntaxKind.Unknown ? new NodeConstructor(kind, 0, 0) : - kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, 0, 0) : - new TokenConstructor(kind, 0, 0); - } - function createNodeArray(elements: T[], pos: number, end?: number): NodeArray { - // Since the element list of a node array is typically created by starting with an empty array and - // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for - // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. - const length = elements.length; - const array = >(length >= 1 && length <= 4 ? elements.slice() : elements); + const array = factory.createNodeArray(elements, /*hasTrailingComma*/ undefined); array.pos = pos; array.end = end === undefined ? scanner.getStartPos() : end; return array; @@ -2335,6 +2361,7 @@ namespace ts { // We also do not need to check for negatives because any prefix operator would be part of a // parent unary expression. kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : + kind === SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) : Debug.fail(); @@ -2940,9 +2967,9 @@ namespace ts { function parseMappedType() { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); - let readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined; + let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - readonlyToken = parseTokenNode(); + readonlyToken = parseTokenNode(); if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { parseExpected(SyntaxKind.ReadonlyKeyword); } @@ -3033,7 +3060,7 @@ namespace ts { } function parseImportType(): ImportTypeNode { - sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; const pos = getNodePos(); const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword); parseExpected(SyntaxKind.ImportKeyword); @@ -3762,7 +3789,7 @@ namespace ts { } // JSX overrides - if (sourceFile.languageVariant === LanguageVariant.JSX) { + if (languageVariant === LanguageVariant.JSX) { const isArrowFunctionInJsx = lookAhead(() => { const third = nextToken(); if (third === SyntaxKind.ExtendsKeyword) { @@ -4182,7 +4209,7 @@ namespace ts { return false; case SyntaxKind.LessThanToken: // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression - if (sourceFile.languageVariant !== LanguageVariant.JSX) { + if (languageVariant !== LanguageVariant.JSX) { return false; } // We are in JSX context and the token is part of JSXElement. @@ -4208,7 +4235,7 @@ namespace ts { const pos = getNodePos(); return finishNode(factory.createPrefix(token(), nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); } - else if (sourceFile.languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { // JSXElement is part of primaryExpression return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } @@ -4266,7 +4293,7 @@ namespace ts { // var foo3 = require("subfolder // import * as foo1 from "module-from-node // We want this import to be a statement rather than import call expression - sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { @@ -4274,7 +4301,7 @@ namespace ts { nextToken(); // advance past the 'import' nextToken(); // advance past the dot expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos); - sourceFile.flags |= NodeFlags.PossiblyContainsImportMeta; + sourceFlags |= NodeFlags.PossiblyContainsImportMeta; } else { expression = parseMemberExpressionOrHigher(); @@ -6522,11 +6549,16 @@ namespace ts { export namespace JSDocParser { export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); - sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false); scanner.setText(content, start, length); currentToken = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); - const diagnostics = parseDiagnostics; + + const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(SyntaxKind.EndOfFileToken)); + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + if (jsDocDiagnostics) { + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + } + clearState(); return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined; @@ -6549,9 +6581,10 @@ namespace ts { export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); - sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); - const diagnostics = parseDiagnostics; + + const sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); clearState(); return jsDoc ? { jsDoc, diagnostics } : undefined; @@ -6568,10 +6601,10 @@ namespace ts { } if (contextFlags & NodeFlags.JavaScriptFile) { - if (!sourceFile.jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = []; + if (!jsDocDiagnostics) { + jsDocDiagnostics = []; } - sourceFile.jsDocDiagnostics.push(...parseDiagnostics); + jsDocDiagnostics.push(...parseDiagnostics); } currentToken = saveToken; parseDiagnostics.length = saveParseDiagnosticsLength; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ef5f9a87cf3..ecb52feb1f3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3382,13 +3382,13 @@ 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); + const preprocessorNodeFactory = createNodeFactory(NodeFactoryFlags.None, createBaseNodeFactory(), { + onCreateNode: node => { + node.flags |= NodeFlags.Preprocessed; + node.pos = -1; + node.end = -1; + } + }); /** * Create a new 'AsyncProgram' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' @@ -3658,4 +3658,28 @@ namespace ts { } return res; } + + 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; + } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 251c6a0b74c..763ef8b1197 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -919,7 +919,7 @@ namespace ts { } addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return setTextRange(createNodeArray(members), /*location*/ node.members); + return setTextRange(factory.createNodeArray(members), /*location*/ node.members); } @@ -1941,7 +1941,7 @@ namespace ts { // End the lexical environment. statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); - const block = factory.createBlock(setTextRange(createNodeArray(statements), body.statements), /*multiLine*/ true); + const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), body.statements), /*multiLine*/ true); setTextRange(block, /*location*/ body); setOriginalNode(block, body); return block; @@ -2386,7 +2386,7 @@ namespace ts { currentNamespaceContainerName = savedCurrentNamespaceLocalName; return factory.createBlock( - setTextRange(createNodeArray(statements), /*location*/ node.members), + setTextRange(factory.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true ); } @@ -2710,7 +2710,7 @@ namespace ts { const block = factory.createBlock( setTextRange( - createNodeArray(statements), + factory.createNodeArray(statements), /*location*/ statementsLocation ), /*multiLine*/ true diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 11e01dec6dd..3d1514e6c8e 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -20,8 +20,14 @@ "diagnosticInformationMap.generated.ts", "scanner.ts", "utilities.ts", - "parenthesizerRules.ts", - "factory.ts", + "factory/parenthesizerRules.ts", + "factory/converters.ts", + "factory/base.ts", + "factory/factory.ts", + "factory/emitNode.ts", + "factory/emitHelpers.ts", + "factory/nodeTests.ts", + "factory/utilities.ts", "parser.ts", "commandLineParser.ts", "moduleNameResolver.ts", @@ -30,7 +36,6 @@ "symbolWalker.ts", "checker.ts", "visitor.ts", - "emitHelpers.ts", "sourcemap.ts", "transformers/utilities.ts", "transformers/destructuring.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 93fd34b50d4..423e1153d31 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -11,112 +11,6 @@ namespace ts { end: number; } - export type JSDocSyntaxKind = - | SyntaxKind.EndOfFileToken - | SyntaxKind.WhitespaceTrivia - | SyntaxKind.AtToken - | SyntaxKind.NewLineTrivia - | SyntaxKind.AsteriskToken - | SyntaxKind.OpenBraceToken - | SyntaxKind.CloseBraceToken - | SyntaxKind.LessThanToken - | SyntaxKind.GreaterThanToken - | SyntaxKind.OpenBracketToken - | SyntaxKind.CloseBracketToken - | SyntaxKind.EqualsToken - | SyntaxKind.CommaToken - | SyntaxKind.DotToken - | SyntaxKind.Identifier - | SyntaxKind.BacktickToken - | SyntaxKind.Unknown - | KeywordSyntaxKind; - - export type KeywordSyntaxKind = - | SyntaxKind.AbstractKeyword - | SyntaxKind.AnyKeyword - | SyntaxKind.AsKeyword - | SyntaxKind.BigIntKeyword - | SyntaxKind.BooleanKeyword - | SyntaxKind.BreakKeyword - | SyntaxKind.CaseKeyword - | SyntaxKind.CatchKeyword - | SyntaxKind.ClassKeyword - | SyntaxKind.ContinueKeyword - | SyntaxKind.ConstKeyword - | SyntaxKind.ConstructorKeyword - | SyntaxKind.DebuggerKeyword - | SyntaxKind.DeclareKeyword - | SyntaxKind.DefaultKeyword - | SyntaxKind.DeleteKeyword - | SyntaxKind.DoKeyword - | SyntaxKind.ElseKeyword - | SyntaxKind.EnumKeyword - | SyntaxKind.ExportKeyword - | SyntaxKind.ExtendsKeyword - | SyntaxKind.FalseKeyword - | SyntaxKind.FinallyKeyword - | SyntaxKind.ForKeyword - | SyntaxKind.FromKeyword - | SyntaxKind.FunctionKeyword - | SyntaxKind.GetKeyword - | SyntaxKind.IfKeyword - | SyntaxKind.ImplementsKeyword - | SyntaxKind.ImportKeyword - | SyntaxKind.InKeyword - | SyntaxKind.InferKeyword - | SyntaxKind.InstanceOfKeyword - | SyntaxKind.InterfaceKeyword - | SyntaxKind.IsKeyword - | SyntaxKind.KeyOfKeyword - | SyntaxKind.LetKeyword - | SyntaxKind.ModuleKeyword - | SyntaxKind.NamespaceKeyword - | SyntaxKind.NeverKeyword - | SyntaxKind.NewKeyword - | SyntaxKind.NullKeyword - | SyntaxKind.NumberKeyword - | SyntaxKind.ObjectKeyword - | SyntaxKind.PackageKeyword - | SyntaxKind.PrivateKeyword - | SyntaxKind.ProtectedKeyword - | SyntaxKind.PublicKeyword - | SyntaxKind.ReadonlyKeyword - | SyntaxKind.RequireKeyword - | SyntaxKind.GlobalKeyword - | SyntaxKind.ReturnKeyword - | SyntaxKind.SetKeyword - | SyntaxKind.StaticKeyword - | SyntaxKind.StringKeyword - | SyntaxKind.SuperKeyword - | SyntaxKind.SwitchKeyword - | SyntaxKind.SymbolKeyword - | SyntaxKind.ThisKeyword - | SyntaxKind.ThrowKeyword - | SyntaxKind.TrueKeyword - | SyntaxKind.TryKeyword - | SyntaxKind.TypeKeyword - | SyntaxKind.TypeOfKeyword - | SyntaxKind.UndefinedKeyword - | SyntaxKind.UniqueKeyword - | SyntaxKind.UnknownKeyword - | SyntaxKind.VarKeyword - | SyntaxKind.VoidKeyword - | SyntaxKind.WhileKeyword - | SyntaxKind.WithKeyword - | SyntaxKind.YieldKeyword - | SyntaxKind.AsyncKeyword - | SyntaxKind.AwaitKeyword - | SyntaxKind.OfKeyword; - - export type JsxTokenSyntaxKind = - | SyntaxKind.LessThanSlashToken - | SyntaxKind.EndOfFileToken - | SyntaxKind.ConflictMarkerTrivia - | SyntaxKind.JsxText - | SyntaxKind.JsxTextAllWhiteSpaces - | SyntaxKind.OpenBraceToken - | SyntaxKind.LessThanToken; - // token > SyntaxKind.Identifier => token is a keyword // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync export const enum SyntaxKind { @@ -524,6 +418,209 @@ namespace ts { /* @internal */ LastContextualKeyword = OfKeyword, } + export type TriviaSyntaxKind = + | SyntaxKind.SingleLineCommentTrivia + | SyntaxKind.MultiLineCommentTrivia + | SyntaxKind.NewLineTrivia + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.ShebangTrivia + | SyntaxKind.ConflictMarkerTrivia + ; + + export type LiteralSyntaxKind = + | SyntaxKind.NumericLiteral + | SyntaxKind.BigIntLiteral + | SyntaxKind.StringLiteral + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.RegularExpressionLiteral + | SyntaxKind.NoSubstitutionTemplateLiteral + ; + + export type PseudoLiteralSyntaxKind = + | SyntaxKind.TemplateHead + | SyntaxKind.TemplateMiddle + | SyntaxKind.TemplateTail + ; + + export type PunctuationSyntaxKind = + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.OpenParenToken + | SyntaxKind.CloseParenToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.DotToken + | SyntaxKind.DotDotDotToken + | SyntaxKind.SemicolonToken + | SyntaxKind.CommaToken + | SyntaxKind.LessThanToken + | SyntaxKind.LessThanSlashToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.LessThanEqualsToken + | SyntaxKind.GreaterThanEqualsToken + | SyntaxKind.EqualsEqualsToken + | SyntaxKind.ExclamationEqualsToken + | SyntaxKind.EqualsEqualsEqualsToken + | SyntaxKind.ExclamationEqualsEqualsToken + | SyntaxKind.EqualsGreaterThanToken + | SyntaxKind.PlusToken + | SyntaxKind.MinusToken + | SyntaxKind.AsteriskToken + | SyntaxKind.AsteriskAsteriskToken + | SyntaxKind.SlashToken + | SyntaxKind.PercentToken + | SyntaxKind.PlusPlusToken + | SyntaxKind.MinusMinusToken + | SyntaxKind.LessThanLessThanToken + | SyntaxKind.GreaterThanGreaterThanToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanToken + | SyntaxKind.AmpersandToken + | SyntaxKind.BarToken + | SyntaxKind.CaretToken + | SyntaxKind.ExclamationToken + | SyntaxKind.TildeToken + | SyntaxKind.AmpersandAmpersandToken + | SyntaxKind.BarBarToken + | SyntaxKind.QuestionToken + | SyntaxKind.ColonToken + | SyntaxKind.AtToken + | SyntaxKind.BacktickToken + | SyntaxKind.EqualsToken + | SyntaxKind.PlusEqualsToken + | SyntaxKind.MinusEqualsToken + | SyntaxKind.AsteriskEqualsToken + | SyntaxKind.AsteriskAsteriskEqualsToken + | SyntaxKind.SlashEqualsToken + | SyntaxKind.PercentEqualsToken + | SyntaxKind.LessThanLessThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken + | SyntaxKind.AmpersandEqualsToken + | SyntaxKind.BarEqualsToken + | SyntaxKind.CaretEqualsToken + ; + + export type KeywordSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AnyKeyword + | SyntaxKind.AsKeyword + | SyntaxKind.BigIntKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.BreakKeyword + | SyntaxKind.CaseKeyword + | SyntaxKind.CatchKeyword + | SyntaxKind.ClassKeyword + | SyntaxKind.ContinueKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.ConstructorKeyword + | SyntaxKind.DebuggerKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.DeleteKeyword + | SyntaxKind.DoKeyword + | SyntaxKind.ElseKeyword + | SyntaxKind.EnumKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.ExtendsKeyword + | SyntaxKind.FalseKeyword + | SyntaxKind.FinallyKeyword + | SyntaxKind.ForKeyword + | SyntaxKind.FromKeyword + | SyntaxKind.FunctionKeyword + | SyntaxKind.GetKeyword + | SyntaxKind.IfKeyword + | SyntaxKind.ImplementsKeyword + | SyntaxKind.ImportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.InferKeyword + | SyntaxKind.InstanceOfKeyword + | SyntaxKind.InterfaceKeyword + | SyntaxKind.IsKeyword + | SyntaxKind.KeyOfKeyword + | SyntaxKind.LetKeyword + | SyntaxKind.ModuleKeyword + | SyntaxKind.NamespaceKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NewKeyword + | SyntaxKind.NullKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.PackageKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.RequireKeyword + | SyntaxKind.GlobalKeyword + | SyntaxKind.ReturnKeyword + | SyntaxKind.SetKeyword + | SyntaxKind.StaticKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SuperKeyword + | SyntaxKind.SwitchKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.ThisKeyword + | SyntaxKind.ThrowKeyword + | SyntaxKind.TrueKeyword + | SyntaxKind.TryKeyword + | SyntaxKind.TypeKeyword + | SyntaxKind.TypeOfKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UniqueKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VarKeyword + | SyntaxKind.VoidKeyword + | SyntaxKind.WhileKeyword + | SyntaxKind.WithKeyword + | SyntaxKind.YieldKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.AwaitKeyword + | SyntaxKind.OfKeyword + ; + + export type TokenSyntaxKind = + | SyntaxKind.Unknown + | SyntaxKind.EndOfFileToken + | TriviaSyntaxKind + | LiteralSyntaxKind + | PseudoLiteralSyntaxKind + | PunctuationSyntaxKind + | SyntaxKind.Identifier + | KeywordSyntaxKind + ; + + export type JsxTokenSyntaxKind = + | SyntaxKind.LessThanSlashToken + | SyntaxKind.EndOfFileToken + | SyntaxKind.ConflictMarkerTrivia + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.OpenBraceToken + | SyntaxKind.LessThanToken + ; + + export type JSDocSyntaxKind = + | SyntaxKind.EndOfFileToken + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.AtToken + | SyntaxKind.NewLineTrivia + | SyntaxKind.AsteriskToken + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.LessThanToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.EqualsToken + | SyntaxKind.CommaToken + | SyntaxKind.DotToken + | SyntaxKind.Identifier + | SyntaxKind.BacktickToken + | SyntaxKind.Unknown + | KeywordSyntaxKind + ; + export const enum NodeFlags { None = 0, Let = 1 << 0, // Variable declaration @@ -727,35 +824,78 @@ namespace ts { /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined } + // TODO(rbuckton): Constraint 'TKind' to 'TokenSyntaxKind' export interface Token extends Node { kind: TKind; } - export type DotDotDotToken = Token; - export type QuestionToken = Token; - export type ExclamationToken = Token; - export type ColonToken = Token; - export type EqualsToken = Token; - export type AsteriskToken = Token; - export type EqualsGreaterThanToken = Token; export type EndOfFileToken = Token & JSDocContainer; - export type ReadonlyToken = Token; - export type AwaitKeywordToken = Token; - export type PlusToken = Token; - export type MinusToken = Token; + + export interface PunctuationToken extends Token { + } + + // Punctuation + export type DotDotDotToken = PunctuationToken; + export type QuestionToken = PunctuationToken; + export type ExclamationToken = PunctuationToken; + export type ColonToken = PunctuationToken; + export type EqualsToken = PunctuationToken; + export type AsteriskToken = PunctuationToken; + export type EqualsGreaterThanToken = PunctuationToken; + export type PlusToken = PunctuationToken; + export type MinusToken = PunctuationToken; + + export interface KeywordToken extends Token { + } + + /** @deprecated Use `AwaitKeyword` instead. */ + export type AwaitKeywordToken = AwaitKeyword; + + /** @deprecated Use `ReadonlyKeyword` instead. */ + export type ReadonlyToken = ReadonlyKeyword; + + export type AwaitKeyword = Token; + export type AbstractKeyword = Token; + export type AsyncKeyword = Token; + export type ConstKeyword = Token; + export type DeclareKeyword = Token; + export type DefaultKeyword = Token; + export type ExportKeyword = Token; + export type PublicKeyword = Token; + export type PrivateKeyword = Token; + export type ProtectedKeyword = Token; + export type ReadonlyKeyword = Token; + export type StaticKeyword = Token; export type Modifier - = Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token - | Token + = AbstractKeyword + | AsyncKeyword + | ConstKeyword + | DeclareKeyword + | DefaultKeyword + | ExportKeyword + | PublicKeyword + | PrivateKeyword + | ProtectedKeyword + | ReadonlyKeyword + | StaticKeyword + ; + + export type AccessibilityModifier = + | PublicKeyword + | PrivateKeyword + | ProtectedKeyword + ; + + export type ParameterPropertyModifier = + | AccessibilityModifier + | ReadonlyKeyword + ; + + export type ClassMemberModifier = + | AccessibilityModifier + | ReadonlyKeyword + | StaticKeyword ; export type ModifiersArray = NodeArray; @@ -956,12 +1096,14 @@ namespace ts { initializer?: Expression; // Optional initializer } + // TODO(rbuckton): Rename to 'BaseObjectLiteralElement' export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrand: any; name?: PropertyName; } /** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */ + // TODO(rbuckton): Rename to 'ObjectLiteralElement' export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment @@ -1271,7 +1413,7 @@ namespace ts { export interface MappedTypeNode extends TypeNode, Declaration { kind: SyntaxKind.MappedType; - readonlyToken?: ReadonlyToken | PlusToken | MinusToken; + readonlyToken?: ReadonlyKeyword | PlusToken | MinusToken; typeParameter: TypeParameterDeclaration; questionToken?: QuestionToken | PlusToken | MinusToken; type?: TypeNode; @@ -2125,7 +2267,7 @@ namespace ts { export interface ForOfStatement extends IterationStatement { kind: SyntaxKind.ForOfStatement; - awaitModifier?: AwaitKeywordToken; + awaitModifier?: AwaitKeyword; initializer: ForInitializer; expression: Expression; } @@ -2231,17 +2373,41 @@ namespace ts { export type ClassLikeDeclaration = ClassDeclaration | ClassExpression; + // TODO(rbuckton): Rename to 'BaseClassElement' export interface ClassElement extends NamedDeclaration { _classElementBrand: any; name?: PropertyName; } + // TODO(rbuckton): Rename to 'ClassElement' and make public + /* @internal */ + export type ClassElementNode = + | ConstructorDeclaration + | PropertyDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | IndexSignatureDeclaration + | SemicolonClassElement + ; + + // TODO(rbuckton): Rename to 'BaseTypeElement' export interface TypeElement extends NamedDeclaration { _typeElementBrand: any; name?: PropertyName; questionToken?: QuestionToken; } + // TODO(rbuckton): Rename to 'TypeElement' and make public + /* @internal */ + export type TypeElementNode = + | PropertySignature + | MethodSignature + | ConstructSignatureDeclaration + | CallSignatureDeclaration + | IndexSignatureDeclaration + ; + export interface InterfaceDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.InterfaceDeclaration; name: Identifier; @@ -4721,6 +4887,13 @@ namespace ts { length: number; } + /* @internal*/ + export interface DiagnosticWithDetachedLocation extends Diagnostic { + file: undefined; + start: number; + length: number; + } + export enum DiagnosticCategory { Warning, Error, @@ -5735,6 +5908,22 @@ namespace ts { set?: Expression; } + /* @internal */ + export interface BaseNodeFactory { + createBaseSourceFileNode(kind: SyntaxKind): Node; + createBaseIdentifierNode(kind: SyntaxKind): Node; + createBaseTokenNode(kind: SyntaxKind): Node; + createBaseNode(kind: SyntaxKind): Node; + } + + /* @internal */ + export const enum NodeFactoryFlags { + None = 0, + NoParenthesizerRules = 1 << 0, + NoNodeConverters = 1 << 1, + NoIndentationOnFreshPropertyAccess = 1 << 2, + } + export interface NodeFactory { /* @internal */ getParenthesizerRules(): ParenthesizerRules; /* @internal */ getConverters(): NodeConverters; @@ -5747,6 +5936,7 @@ namespace ts { createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; + /* @internal*/ createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral; // tslint:disable-line unified-signatures createStringLiteralFromNode(sourceNode: PropertyNameLiteral, isSingleQuote?: boolean): StringLiteral; createRegularExpressionLiteral(text: string): RegularExpressionLiteral; @@ -5890,8 +6080,8 @@ namespace ts { updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; + updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; @@ -6012,8 +6202,8 @@ namespace ts { updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + createForOf(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForOf(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; createContinue(label?: string | Identifier): ContinueStatement; updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; createBreak(label?: string | Identifier): BreakStatement; @@ -6034,6 +6224,7 @@ namespace ts { 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; + updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; createFunctionDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; @@ -6175,6 +6366,7 @@ namespace ts { // Top-level nodes // + createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken): SourceFile; updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; // @@ -6340,11 +6532,12 @@ namespace ts { /* @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; + onCreateNode?(node: Node): void; + 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 { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2d31b02675c..8df6bba8f24 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5547,246 +5547,13 @@ namespace ts { } } -// Simple node tests of the form `node.kind === SyntaxKind.Foo`. namespace ts { - // Literals - export function isNumericLiteral(node: Node): node is NumericLiteral { - return node.kind === SyntaxKind.NumericLiteral; - } - - export function isBigIntLiteral(node: Node): node is BigIntLiteral { - return node.kind === SyntaxKind.BigIntLiteral; - } - - export function isStringLiteral(node: Node): node is StringLiteral { - return node.kind === SyntaxKind.StringLiteral; - } - - export function isJsxText(node: Node): node is JsxText { - return node.kind === SyntaxKind.JsxText; - } - - export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral { - return node.kind === SyntaxKind.RegularExpressionLiteral; - } - - export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral { - return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; - } - - // Pseudo-literals - - export function isTemplateHead(node: Node): node is TemplateHead { - return node.kind === SyntaxKind.TemplateHead; - } - - export function isTemplateMiddle(node: Node): node is TemplateMiddle { - return node.kind === SyntaxKind.TemplateMiddle; - } - - export function isTemplateTail(node: Node): node is TemplateTail { - return node.kind === SyntaxKind.TemplateTail; - } - - export function isIdentifier(node: Node): node is Identifier { - return node.kind === SyntaxKind.Identifier; - } - - // Names - - export function isQualifiedName(node: Node): node is QualifiedName { - return node.kind === SyntaxKind.QualifiedName; - } - - export function isComputedPropertyName(node: Node): node is ComputedPropertyName { - return node.kind === SyntaxKind.ComputedPropertyName; - } - - // Signature elements - - export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { - return node.kind === SyntaxKind.TypeParameter; - } - - export function isParameter(node: Node): node is ParameterDeclaration { - return node.kind === SyntaxKind.Parameter; - } - - export function isDecorator(node: Node): node is Decorator { - return node.kind === SyntaxKind.Decorator; - } - - // TypeMember - - export function isPropertySignature(node: Node): node is PropertySignature { - return node.kind === SyntaxKind.PropertySignature; - } - - export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { - return node.kind === SyntaxKind.PropertyDeclaration; - } - - export function isMethodSignature(node: Node): node is MethodSignature { - return node.kind === SyntaxKind.MethodSignature; - } - - export function isMethodDeclaration(node: Node): node is MethodDeclaration { - return node.kind === SyntaxKind.MethodDeclaration; - } - - export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { - return node.kind === SyntaxKind.Constructor; - } - - export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { - return node.kind === SyntaxKind.GetAccessor; - } - - export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor; - } - - export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { - return node.kind === SyntaxKind.CallSignature; - } - - export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration { - return node.kind === SyntaxKind.ConstructSignature; - } - - export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration { - return node.kind === SyntaxKind.IndexSignature; - } - - /* @internal */ - export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; - } - - // Type - - export function isTypePredicateNode(node: Node): node is TypePredicateNode { - return node.kind === SyntaxKind.TypePredicate; - } - - export function isTypeReferenceNode(node: Node): node is TypeReferenceNode { - return node.kind === SyntaxKind.TypeReference; - } - - export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { - return node.kind === SyntaxKind.FunctionType; - } - - export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode { - return node.kind === SyntaxKind.ConstructorType; - } - - export function isTypeQueryNode(node: Node): node is TypeQueryNode { - return node.kind === SyntaxKind.TypeQuery; - } - - export function isTypeLiteralNode(node: Node): node is TypeLiteralNode { - return node.kind === SyntaxKind.TypeLiteral; - } - - export function isArrayTypeNode(node: Node): node is ArrayTypeNode { - return node.kind === SyntaxKind.ArrayType; - } - - export function isTupleTypeNode(node: Node): node is TupleTypeNode { - return node.kind === SyntaxKind.TupleType; - } - - export function isUnionTypeNode(node: Node): node is UnionTypeNode { - return node.kind === SyntaxKind.UnionType; - } - - export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode { - return node.kind === SyntaxKind.IntersectionType; - } - - export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode { - return node.kind === SyntaxKind.ConditionalType; - } - - export function isInferTypeNode(node: Node): node is InferTypeNode { - return node.kind === SyntaxKind.InferType; - } - - export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode { - return node.kind === SyntaxKind.ParenthesizedType; - } - - export function isThisTypeNode(node: Node): node is ThisTypeNode { - return node.kind === SyntaxKind.ThisType; - } - - export function isTypeOperatorNode(node: Node): node is TypeOperatorNode { - return node.kind === SyntaxKind.TypeOperator; - } - - export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode { - return node.kind === SyntaxKind.IndexedAccessType; - } - - export function isMappedTypeNode(node: Node): node is MappedTypeNode { - return node.kind === SyntaxKind.MappedType; - } - - export function isLiteralTypeNode(node: Node): node is LiteralTypeNode { - return node.kind === SyntaxKind.LiteralType; - } - - export function isImportTypeNode(node: Node): node is ImportTypeNode { - return node.kind === SyntaxKind.ImportType; - } - - // Binding patterns - - export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { - return node.kind === SyntaxKind.ObjectBindingPattern; - } - - export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { - return node.kind === SyntaxKind.ArrayBindingPattern; - } - - export function isBindingElement(node: Node): node is BindingElement { - return node.kind === SyntaxKind.BindingElement; - } - - // Expression - - export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { - return node.kind === SyntaxKind.ArrayLiteralExpression; - } - - export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { - return node.kind === SyntaxKind.ObjectLiteralExpression; - } - - export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { - return node.kind === SyntaxKind.PropertyAccessExpression; - } - - export function isElementAccessExpression(node: Node): node is ElementAccessExpression { - return node.kind === SyntaxKind.ElementAccessExpression; - } - - export function isCallExpression(node: Node): node is CallExpression { - return node.kind === SyntaxKind.CallExpression; - } - - export function isNewExpression(node: Node): node is NewExpression { - return node.kind === SyntaxKind.NewExpression; - } - - export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { - return node.kind === SyntaxKind.TaggedTemplateExpression; - } - - export function isTypeAssertion(node: Node): node is TypeAssertion { - return node.kind === SyntaxKind.TypeAssertionExpression; + export function setTextRange(range: T, location: TextRange | undefined): T { + if (location) { + range.pos = location.pos; + range.end = location.end; + } + return range; } export function isConstTypeReference(node: Node) { @@ -5794,10 +5561,6 @@ namespace ts { node.typeName.escapedText === "const" && !node.typeArguments; } - export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { - return node.kind === SyntaxKind.ParenthesizedExpression; - } - export function skipPartiallyEmittedExpressions(node: Expression): Expression; export function skipPartiallyEmittedExpressions(node: Node): Node; export function skipPartiallyEmittedExpressions(node: Node) { @@ -5808,369 +5571,352 @@ namespace ts { return node; } - export function isFunctionExpression(node: Node): node is FunctionExpression { - return node.kind === SyntaxKind.FunctionExpression; + /* @internal */ + export function isAsyncModifier(node: Modifier): node is AsyncKeyword { + return node.kind === SyntaxKind.AsyncKeyword; } - export function isArrowFunction(node: Node): node is ArrowFunction { - return node.kind === SyntaxKind.ArrowFunction; + /* @internal */ + export function isStaticModifier(node: Modifier): node is StaticKeyword { + return node.kind === SyntaxKind.StaticKeyword; } - export function isDeleteExpression(node: Node): node is DeleteExpression { - return node.kind === SyntaxKind.DeleteExpression; + export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { + return node.kind === SyntaxKind.JSDocPropertyTag || node.kind === SyntaxKind.JSDocParameterTag; } - export function isTypeOfExpression(node: Node): node is TypeOfExpression { - return node.kind === SyntaxKind.TypeOfExpression; + // Groups + + // used in 'TemplateSpan' + export function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail { + const kind = node.kind; + return kind === SyntaxKind.TemplateMiddle + || kind === SyntaxKind.TemplateTail; } - export function isVoidExpression(node: Node): node is VoidExpression { - return node.kind === SyntaxKind.VoidExpression; + // used in 'ModifiersArray' + export function isModifier(node: Node): node is Modifier { + return isModifierKind(node.kind); } - export function isAwaitExpression(node: Node): node is AwaitExpression { - return node.kind === SyntaxKind.AwaitExpression; + // used in 'QualifiedName' + export function isEntityName(node: Node): node is EntityName { + const kind = node.kind; + return kind === SyntaxKind.QualifiedName + || kind === SyntaxKind.Identifier; } - export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { - return node.kind === SyntaxKind.PrefixUnaryExpression; + // used in 'ClassElement', 'TypeElement', and 'ObjectLiteralElement' + export function isPropertyName(node: Node): node is PropertyName { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral + || kind === SyntaxKind.ComputedPropertyName; } - export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { - return node.kind === SyntaxKind.PostfixUnaryExpression; + // used in 'VariableDeclaration', 'ParameterDeclaration', and 'BindingElement' + export function isBindingName(node: Node): node is BindingName { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.ObjectBindingPattern + || kind === SyntaxKind.ArrayBindingPattern; } - export function isBinaryExpression(node: Node): node is BinaryExpression { - return node.kind === SyntaxKind.BinaryExpression; + // TODO(rbuckton): Rename 'isDeclarationName' and add an 'isDeclarationName' node test + + // used in 'ClassDeclaration' and 'ClassExpression' + // TODO(rbuckton): Change return type to 'ClassElementNode' + export function isClassElement(node: Node): node is ClassElement { + const kind = node.kind; + return kind === SyntaxKind.Constructor + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.IndexSignature + || kind === SyntaxKind.SemicolonClassElement; } - export function isConditionalExpression(node: Node): node is ConditionalExpression { - return node.kind === SyntaxKind.ConditionalExpression; + // used in 'InterfaceDeclaration' and 'TypeLiteralNode' + // TODO(rbuckton): Change return type to 'TypeElementNode' + export function isTypeElement(node: Node): node is TypeElement { + const kind = node.kind; + return kind === SyntaxKind.ConstructSignature + || kind === SyntaxKind.CallSignature + || kind === SyntaxKind.PropertySignature + || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.IndexSignature; } - export function isTemplateExpression(node: Node): node is TemplateExpression { - return node.kind === SyntaxKind.TemplateExpression; + // used in 'ObjectLiteralExpression' and 'JsxAttributes' + // TODO(rbuckton): Rename to 'isObjectLiteralElement' + export function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike { + const kind = node.kind; + return kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.SpreadAssignment + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor; } - export function isYieldExpression(node: Node): node is YieldExpression { - return node.kind === SyntaxKind.YieldExpression; + // TODO(rbuckton): Rename to 'isJsxAttributesElement' + export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { + return node.kind === SyntaxKind.JsxAttribute + || node.kind === SyntaxKind.JsxSpreadAttribute + || isObjectLiteralElementLike(node); } - export function isSpreadElement(node: Node): node is SpreadElement { - return node.kind === SyntaxKind.SpreadElement; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + // used in type annotations, type arguments, and complex types + export function isTypeNode(node: Node): node is TypeNode { + return isTypeNodeKind(node.kind); } - export function isClassExpression(node: Node): node is ClassExpression { - return node.kind === SyntaxKind.ClassExpression; + // used in 'TaggedTemplateExpression' + export function isTemplateLiteral(node: Node): node is TemplateLiteral { + const kind = node.kind; + return kind === SyntaxKind.TemplateExpression + || kind === SyntaxKind.NoSubstitutionTemplateLiteral; } - export function isOmittedExpression(node: Node): node is OmittedExpression { - return node.kind === SyntaxKind.OmittedExpression; + function isPrimaryExpressionKind(kind: SyntaxKind): boolean { + // PrimaryExpression: + // `this` + // IdentifierReference + // Literal + // ArrayLiteral + // ObjectLiteral + // FunctionExpression + // ClassExpression + // GeneratorExpression + // AsyncFunctionExpression + // AsyncGeneratorExpression + // RegularExpressionLiteral + // TemplateLiteral + // CoverParenthesizedExpressionAndArrowParameterList (ParenthesizedExpression) + // + // Literal: + // NullLiteral + // BooleanLiteral + // NumericLiteral + // BigIntLiteral + // StringLiteral + // + // TemplateLiteral: + // NoSubstitutionTemplate + // SubstitutionTemplate (i.e. TemplateExpression) + + switch (kind) { + // ECMAScript + case SyntaxKind.ThisKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.SuperKeyword: // `super(...)` or `super.prop` + case SyntaxKind.ImportKeyword: // `import(...)` + // JSX + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: + return true; + default: + return false; + } } - export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { - return node.kind === SyntaxKind.ExpressionWithTypeArguments; + function isMemberExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.MetaProperty: + return true; + default: + return isPrimaryExpressionKind(kind); + } } - export function isAsExpression(node: Node): node is AsExpression { - return node.kind === SyntaxKind.AsExpression; + function isLeftHandSideExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.NewExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.TaggedTemplateExpression: + return true; + default: + return isMemberExpressionOrHigherKind(kind); + } } - export function isNonNullExpression(node: Node): node is NonNullExpression { - return node.kind === SyntaxKind.NonNullExpression; + function isUpdateExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + return true; + default: + return isLeftHandSideExpressionOrHigherKind(kind); + } } - export function isMetaProperty(node: Node): node is MetaProperty { - return node.kind === SyntaxKind.MetaProperty; + function isUnaryExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeAssertionExpression: + return true; + default: + return isUpdateExpressionOrHigherKind(kind); + } } - // Misc - - export function isTemplateSpan(node: Node): node is TemplateSpan { - return node.kind === SyntaxKind.TemplateSpan; + function isBinaryExpressionOrHigherKind(kind: SyntaxKind): boolean { + switch (kind) { + case SyntaxKind.BinaryExpression: + return true; + default: + return isUnaryExpressionOrHigherKind(kind); + } } - export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { - return node.kind === SyntaxKind.SemicolonClassElement; + function isAssignmentExpressionOrHigherKind(kind: SyntaxKind) { + switch (kind) { + // ECMAScript + case SyntaxKind.ConditionalExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.OmittedExpression: // when used in an array literal + case SyntaxKind.SpreadElement: // when used in an array literal or argument list + // TypeScript + case SyntaxKind.AsExpression: + return true; + default: + return isBinaryExpressionOrHigherKind(kind); + } } - // Block - - export function isBlock(node: Node): node is Block { - return node.kind === SyntaxKind.Block; + function isExpressionKind(kind: SyntaxKind): boolean { + switch (kind) { + // ECMAScript + case SyntaxKind.CommaListExpression: + // TypeScript + case SyntaxKind.PartiallyEmittedExpression: + return true; + default: + return isAssignmentExpressionOrHigherKind(kind); + } } - export function isVariableStatement(node: Node): node is VariableStatement { - return node.kind === SyntaxKind.VariableStatement; + /* @internal */ + export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { + return isLeftHandSideExpressionOrHigherKind(skipPartiallyEmittedExpressions(node).kind); } - export function isEmptyStatement(node: Node): node is EmptyStatement { - return node.kind === SyntaxKind.EmptyStatement; + /* @internal */ + export function isUnaryExpression(node: Node): node is UnaryExpression { + return isUnaryExpressionOrHigherKind(skipPartiallyEmittedExpressions(node).kind); } - export function isExpressionStatement(node: Node): node is ExpressionStatement { - return node.kind === SyntaxKind.ExpressionStatement; + // TODO(rbuckton): Make this public + /* @internal */ + /** + * Determines whether a node is an expression based only on its kind. + * Use `isExpressionNode` if not in transforms. + */ + export function isExpression(node: Node): node is Expression { + return isExpressionKind(skipPartiallyEmittedExpressions(node).kind); } - export function isIfStatement(node: Node): node is IfStatement { - return node.kind === SyntaxKind.IfStatement; + // used in 'ArrowFunction' + // TODO(rbuckton): Make this public + /* @internal */ + export function isConciseBody(node: Node): node is ConciseBody { + return isBlock(node) + || isExpression(node); } - export function isDoStatement(node: Node): node is DoStatement { - return node.kind === SyntaxKind.DoStatement; + // used in functions + // TODO(rbuckton): Make this public + /* @internal */ + export function isFunctionBody(node: Node): node is FunctionBody { + return isBlock(node); } - export function isWhileStatement(node: Node): node is WhileStatement { - return node.kind === SyntaxKind.WhileStatement; + // used in 'ForStatement', 'ForInStatement', 'ForOfStatement' + // TODO(rbuckton): Make this public + /* @internal */ + export function isForInitializer(node: Node): node is ForInitializer { + return isVariableDeclarationList(node) + || isExpression(node); } - export function isForStatement(node: Node): node is ForStatement { - return node.kind === SyntaxKind.ForStatement; + // used in 'ModuleDeclaration' + /* @internal */ + export function isModuleBody(node: Node): node is ModuleBody { + const kind = node.kind; + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.Identifier; } - export function isForInStatement(node: Node): node is ForInStatement { - return node.kind === SyntaxKind.ForInStatement; + // used in 'NamespaceDeclaration' + /* @internal */ + export function isNamespaceBody(node: Node): node is NamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration; } - export function isForOfStatement(node: Node): node is ForOfStatement { - return node.kind === SyntaxKind.ForOfStatement; + // used in 'JSDocNamespace' + /* @internal */ + export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.ModuleDeclaration; } - export function isContinueStatement(node: Node): node is ContinueStatement { - return node.kind === SyntaxKind.ContinueStatement; + // used in 'ImportClause' + /* @internal */ + export function isNamedImportBindings(node: Node): node is NamedImportBindings { + const kind = node.kind; + return kind === SyntaxKind.NamedImports + || kind === SyntaxKind.NamespaceImport; } - export function isBreakStatement(node: Node): node is BreakStatement { - return node.kind === SyntaxKind.BreakStatement; + // TODO(rbuckton): Move 'isStatement' here and remove dependence on 'parent' pointer. + + // used in 'CaseBlock' + export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { + const kind = node.kind; + return kind === SyntaxKind.CaseClause + || kind === SyntaxKind.DefaultClause; } export function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement { return node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement; } - export function isReturnStatement(node: Node): node is ReturnStatement { - return node.kind === SyntaxKind.ReturnStatement; - } - - export function isWithStatement(node: Node): node is WithStatement { - return node.kind === SyntaxKind.WithStatement; - } - - export function isSwitchStatement(node: Node): node is SwitchStatement { - return node.kind === SyntaxKind.SwitchStatement; - } - - export function isLabeledStatement(node: Node): node is LabeledStatement { - return node.kind === SyntaxKind.LabeledStatement; - } - - export function isThrowStatement(node: Node): node is ThrowStatement { - return node.kind === SyntaxKind.ThrowStatement; - } - - export function isTryStatement(node: Node): node is TryStatement { - return node.kind === SyntaxKind.TryStatement; - } - - export function isDebuggerStatement(node: Node): node is DebuggerStatement { - return node.kind === SyntaxKind.DebuggerStatement; - } - - export function isVariableDeclaration(node: Node): node is VariableDeclaration { - return node.kind === SyntaxKind.VariableDeclaration; - } - - export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { - return node.kind === SyntaxKind.VariableDeclarationList; - } - - export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { - return node.kind === SyntaxKind.FunctionDeclaration; - } - - export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node.kind === SyntaxKind.ClassDeclaration; - } - - export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { - return node.kind === SyntaxKind.InterfaceDeclaration; - } - - export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { - return node.kind === SyntaxKind.TypeAliasDeclaration; - } - - export function isEnumDeclaration(node: Node): node is EnumDeclaration { - return node.kind === SyntaxKind.EnumDeclaration; - } - - export function isModuleDeclaration(node: Node): node is ModuleDeclaration { - return node.kind === SyntaxKind.ModuleDeclaration; - } - - export function isModuleBlock(node: Node): node is ModuleBlock { - return node.kind === SyntaxKind.ModuleBlock; - } - - export function isCaseBlock(node: Node): node is CaseBlock { - return node.kind === SyntaxKind.CaseBlock; - } - - export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration { - return node.kind === SyntaxKind.NamespaceExportDeclaration; - } - - export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { - return node.kind === SyntaxKind.ImportEqualsDeclaration; - } - - export function isImportDeclaration(node: Node): node is ImportDeclaration { - return node.kind === SyntaxKind.ImportDeclaration; - } - - export function isImportClause(node: Node): node is ImportClause { - return node.kind === SyntaxKind.ImportClause; - } - - export function isNamespaceImport(node: Node): node is NamespaceImport { - return node.kind === SyntaxKind.NamespaceImport; - } - - export function isNamedImports(node: Node): node is NamedImports { - return node.kind === SyntaxKind.NamedImports; - } - - export function isImportSpecifier(node: Node): node is ImportSpecifier { - return node.kind === SyntaxKind.ImportSpecifier; - } - - export function isExportAssignment(node: Node): node is ExportAssignment { - return node.kind === SyntaxKind.ExportAssignment; - } - - export function isExportDeclaration(node: Node): node is ExportDeclaration { - return node.kind === SyntaxKind.ExportDeclaration; - } - - export function isNamedExports(node: Node): node is NamedExports { - return node.kind === SyntaxKind.NamedExports; - } - - export function isExportSpecifier(node: Node): node is ExportSpecifier { - return node.kind === SyntaxKind.ExportSpecifier; - } - - export function isMissingDeclaration(node: Node): node is MissingDeclaration { - return node.kind === SyntaxKind.MissingDeclaration; - } - - // Module References - - export function isExternalModuleReference(node: Node): node is ExternalModuleReference { - return node.kind === SyntaxKind.ExternalModuleReference; - } - - // JSX - - export function isJsxElement(node: Node): node is JsxElement { - return node.kind === SyntaxKind.JsxElement; - } - - export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { - return node.kind === SyntaxKind.JsxSelfClosingElement; - } - - export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { - return node.kind === SyntaxKind.JsxOpeningElement; - } - - export function isJsxClosingElement(node: Node): node is JsxClosingElement { - return node.kind === SyntaxKind.JsxClosingElement; - } - - export function isJsxFragment(node: Node): node is JsxFragment { - return node.kind === SyntaxKind.JsxFragment; - } - - export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { - return node.kind === SyntaxKind.JsxOpeningFragment; - } - - export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { - return node.kind === SyntaxKind.JsxClosingFragment; - } - - export function isJsxAttribute(node: Node): node is JsxAttribute { - return node.kind === SyntaxKind.JsxAttribute; - } - - export function isJsxAttributes(node: Node): node is JsxAttributes { - return node.kind === SyntaxKind.JsxAttributes; - } - - export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { - return node.kind === SyntaxKind.JsxSpreadAttribute; - } - - export function isJsxExpression(node: Node): node is JsxExpression { - return node.kind === SyntaxKind.JsxExpression; - } - - // Clauses - - export function isCaseClause(node: Node): node is CaseClause { - return node.kind === SyntaxKind.CaseClause; - } - - export function isDefaultClause(node: Node): node is DefaultClause { - return node.kind === SyntaxKind.DefaultClause; - } - - export function isHeritageClause(node: Node): node is HeritageClause { - return node.kind === SyntaxKind.HeritageClause; - } - - export function isCatchClause(node: Node): node is CatchClause { - return node.kind === SyntaxKind.CatchClause; - } - - // Property assignments - - export function isPropertyAssignment(node: Node): node is PropertyAssignment { - return node.kind === SyntaxKind.PropertyAssignment; - } - - export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { - return node.kind === SyntaxKind.ShorthandPropertyAssignment; - } - - export function isSpreadAssignment(node: Node): node is SpreadAssignment { - return node.kind === SyntaxKind.SpreadAssignment; - } - - // Enum - - export function isEnumMember(node: Node): node is EnumMember { - return node.kind === SyntaxKind.EnumMember; - } - - // Top-level nodes - export function isSourceFile(node: Node): node is SourceFile { - return node.kind === SyntaxKind.SourceFile; - } - - export function isBundle(node: Node): node is Bundle { - return node.kind === SyntaxKind.Bundle; - } - - export function isUnparsedSource(node: Node): node is UnparsedSource { - return node.kind === SyntaxKind.UnparsedSource; - } - - export function isUnparsedPrepend(node: Node): node is UnparsedPrepend { - return node.kind === SyntaxKind.UnparsedPrepend; - } - export function isUnparsedTextLike(node: Node): node is UnparsedTextLike { switch (node.kind) { case SyntaxKind.UnparsedText: @@ -6187,115 +5933,6 @@ namespace ts { node.kind === SyntaxKind.UnparsedSyntheticReference; } - // JSDoc - - export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { - return node.kind === SyntaxKind.JSDocTypeExpression; - } - - export function isJSDocAllType(node: JSDocAllType): node is JSDocAllType { - return node.kind === SyntaxKind.JSDocAllType; - } - - export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { - return node.kind === SyntaxKind.JSDocUnknownType; - } - - export function isJSDocNullableType(node: Node): node is JSDocNullableType { - return node.kind === SyntaxKind.JSDocNullableType; - } - - export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { - return node.kind === SyntaxKind.JSDocNonNullableType; - } - - export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { - return node.kind === SyntaxKind.JSDocOptionalType; - } - - export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { - return node.kind === SyntaxKind.JSDocFunctionType; - } - - export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { - return node.kind === SyntaxKind.JSDocVariadicType; - } - - export function isJSDoc(node: Node): node is JSDoc { - return node.kind === SyntaxKind.JSDocComment; - } - - export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { - return node.kind === SyntaxKind.JSDocAuthorTag; - } - - export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { - return node.kind === SyntaxKind.JSDocAugmentsTag; - } - - export function isJSDocClassTag(node: Node): node is JSDocClassTag { - return node.kind === SyntaxKind.JSDocClassTag; - } - - export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { - return node.kind === SyntaxKind.JSDocEnumTag; - } - - export function isJSDocThisTag(node: Node): node is JSDocThisTag { - return node.kind === SyntaxKind.JSDocThisTag; - } - - export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { - return node.kind === SyntaxKind.JSDocParameterTag; - } - - export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { - return node.kind === SyntaxKind.JSDocReturnTag; - } - - export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { - return node.kind === SyntaxKind.JSDocTypeTag; - } - - export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { - return node.kind === SyntaxKind.JSDocTemplateTag; - } - - export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { - return node.kind === SyntaxKind.JSDocTypedefTag; - } - - export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag { - return node.kind === SyntaxKind.JSDocPropertyTag; - } - - export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { - return node.kind === SyntaxKind.JSDocPropertyTag || node.kind === SyntaxKind.JSDocParameterTag; - } - - export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { - return node.kind === SyntaxKind.JSDocTypeLiteral; - } - - export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag { - return node.kind === SyntaxKind.JSDocCallbackTag; - } - - export function isJSDocSignature(node: Node): node is JSDocSignature { - return node.kind === SyntaxKind.JSDocSignature; - } -} - -// Node tests -// -// All node tests in the following list should *not* reference parent pointers so that -// they may be used with transformations. -namespace ts { - /* @internal */ - export function isSyntaxList(n: Node): n is SyntaxList { - return n.kind === SyntaxKind.SyntaxList; - } - /* @internal */ export function isNode(node: Node) { return isNodeKind(node.kind); @@ -6311,6 +5948,7 @@ namespace ts { * For example, this is true for an IfKeyword but not for an IfStatement. * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. */ + // TODO(rbuckton): Rename to 'isTokenKind' and change return type to 'n is TokenSyntaxKind' export function isToken(n: Node): boolean { return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken; } @@ -6344,16 +5982,11 @@ namespace ts { return isTemplateLiteralKind(node.kind); } - export function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail { - const kind = node.kind; - return kind === SyntaxKind.TemplateMiddle - || kind === SyntaxKind.TemplateTail; - } - export function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier { return isImportSpecifier(node) || isExportSpecifier(node); } + // TODO(rbuckton): Rename to 'isStringLiteralOrTemplateLiteralToken' export function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken { return node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind); } @@ -6387,50 +6020,17 @@ namespace ts { } /* @internal */ + // TODO(rbuckton): Rename to 'isParameterPropertyModifierKind' export function isParameterPropertyModifier(kind: SyntaxKind): boolean { return !!(modifierToFlag(kind) & ModifierFlags.ParameterPropertyModifier); } /* @internal */ + // TODO(rbuckton): Rename to 'isClassMemberModifierKind' export function isClassMemberModifier(idToken: SyntaxKind): boolean { return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.StaticKeyword; } - export function isModifier(node: Node): node is Modifier { - return isModifierKind(node.kind); - } - - /* @internal */ - export function isAsyncModifier(node: Modifier): node is Token { - return node.kind === SyntaxKind.AsyncKeyword; - } - - /* @internal */ - export function isStaticModifier(node: Modifier): node is Token { - return node.kind === SyntaxKind.StaticKeyword; - } - - export function isEntityName(node: Node): node is EntityName { - const kind = node.kind; - return kind === SyntaxKind.QualifiedName - || kind === SyntaxKind.Identifier; - } - - export function isPropertyName(node: Node): node is PropertyName { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.StringLiteral - || kind === SyntaxKind.NumericLiteral - || kind === SyntaxKind.ComputedPropertyName; - } - - export function isBindingName(node: Node): node is BindingName { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.ObjectBindingPattern - || kind === SyntaxKind.ArrayBindingPattern; - } - // Functions export function isFunctionLike(node: Node): node is SignatureDeclaration { @@ -6480,25 +6080,22 @@ namespace ts { } // Classes - export function isClassElement(node: Node): node is ClassElement { - const kind = node.kind; - return kind === SyntaxKind.Constructor - || kind === SyntaxKind.PropertyDeclaration - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.IndexSignature - || kind === SyntaxKind.SemicolonClassElement; - } export function isClassLike(node: Node): node is ClassLikeDeclaration { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } + // TODO(rbuckton): Rename to 'isAccessorDeclaration' + /* @internal */ + export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; + } + export function isAccessor(node: Node): node is AccessorDeclaration { return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor); } + // TODO(rbuckton): Rename to 'isMethodOrAccessorDeclaration' /* @internal */ export function isMethodOrAccessor(node: Node): node is MethodDeclaration | AccessorDeclaration { switch (node.kind) { @@ -6513,40 +6110,12 @@ namespace ts { // Type members - export function isTypeElement(node: Node): node is TypeElement { - const kind = node.kind; - return kind === SyntaxKind.ConstructSignature - || kind === SyntaxKind.CallSignature - || kind === SyntaxKind.PropertySignature - || kind === SyntaxKind.MethodSignature - || kind === SyntaxKind.IndexSignature; - } - export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement { return isTypeElement(node) || isClassElement(node); } - export function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike { - const kind = node.kind; - return kind === SyntaxKind.PropertyAssignment - || kind === SyntaxKind.ShorthandPropertyAssignment - || kind === SyntaxKind.SpreadAssignment - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor; - } - // Type - /** - * Node test that determines whether a node is a valid type node. - * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* - * of a TypeNode. - */ - export function isTypeNode(node: Node): node is TypeNode { - return isTypeNodeKind(node.kind); - } - export function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode { switch (node.kind) { case SyntaxKind.FunctionType: @@ -6559,6 +6128,7 @@ namespace ts { // Binding patterns + // TODO(rbuckton): Remove the '| undefined' and make this public /* @internal */ export function isBindingPattern(node: Node | undefined): node is BindingPattern { if (node) { @@ -6672,73 +6242,6 @@ namespace ts { return node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.NewExpression; } - export function isTemplateLiteral(node: Node): node is TemplateLiteral { - const kind = node.kind; - return kind === SyntaxKind.TemplateExpression - || kind === SyntaxKind.NoSubstitutionTemplateLiteral; - } - - /* @internal */ - export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { - return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxFragment: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ClassExpression: - case SyntaxKind.FunctionExpression: - case SyntaxKind.Identifier: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.BigIntLiteral: - case SyntaxKind.StringLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateExpression: - case SyntaxKind.FalseKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.ThisKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.SuperKeyword: - case SyntaxKind.NonNullExpression: - case SyntaxKind.MetaProperty: - case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression - return true; - default: - return false; - } - } - - /* @internal */ - export function isUnaryExpression(node: Node): node is UnaryExpression { - return isUnaryExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isUnaryExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: - case SyntaxKind.DeleteExpression: - case SyntaxKind.TypeOfExpression: - case SyntaxKind.VoidExpression: - case SyntaxKind.AwaitExpression: - case SyntaxKind.TypeAssertionExpression: - return true; - default: - return isLeftHandSideExpressionKind(kind); - } - } - /* @internal */ export function isUnaryExpressionWithWrite(expr: Node): expr is PrefixUnaryExpression | PostfixUnaryExpression { switch (expr.kind) { @@ -6752,48 +6255,12 @@ namespace ts { } } - /* @internal */ - /** - * Determines whether a node is an expression based only on its kind. - * Use `isExpressionNode` if not in transforms. - */ - export function isExpression(node: Node): node is Expression { - return isExpressionKind(skipPartiallyEmittedExpressions(node).kind); - } - - function isExpressionKind(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.ConditionalExpression: - case SyntaxKind.YieldExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.BinaryExpression: - case SyntaxKind.SpreadElement: - case SyntaxKind.AsExpression: - case SyntaxKind.OmittedExpression: - case SyntaxKind.CommaListExpression: - case SyntaxKind.PartiallyEmittedExpression: - return true; - default: - return isUnaryExpressionKind(kind); - } - } - export function isAssertionExpression(node: Node): node is AssertionExpression { const kind = node.kind; return kind === SyntaxKind.TypeAssertionExpression || kind === SyntaxKind.AsExpression; } - /* @internal */ - export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression { - return node.kind === SyntaxKind.PartiallyEmittedExpression; - } - - /* @internal */ - export function isNotEmittedStatement(node: Node): node is NotEmittedStatement { - return node.kind === SyntaxKind.NotEmittedStatement; - } - /* @internal */ export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression { return isNotEmittedStatement(node) @@ -6826,52 +6293,6 @@ namespace ts { // Element - /* @internal */ - export function isConciseBody(node: Node): node is ConciseBody { - return isBlock(node) - || isExpression(node); - } - - /* @internal */ - export function isFunctionBody(node: Node): node is FunctionBody { - return isBlock(node); - } - - /* @internal */ - export function isForInitializer(node: Node): node is ForInitializer { - return isVariableDeclarationList(node) - || isExpression(node); - } - - /* @internal */ - export function isModuleBody(node: Node): node is ModuleBody { - const kind = node.kind; - return kind === SyntaxKind.ModuleBlock - || kind === SyntaxKind.ModuleDeclaration - || kind === SyntaxKind.Identifier; - } - - /* @internal */ - export function isNamespaceBody(node: Node): node is NamespaceBody { - const kind = node.kind; - return kind === SyntaxKind.ModuleBlock - || kind === SyntaxKind.ModuleDeclaration; - } - - /* @internal */ - export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.ModuleDeclaration; - } - - /* @internal */ - export function isNamedImportBindings(node: Node): node is NamedImportBindings { - const kind = node.kind; - return kind === SyntaxKind.NamedImports - || kind === SyntaxKind.NamespaceImport; - } - /* @internal */ export function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration { return node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration; @@ -7050,14 +6471,6 @@ namespace ts { || kind === SyntaxKind.JsxSelfClosingElement; } - // Clauses - - export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { - const kind = node.kind; - return kind === SyntaxKind.CaseClause - || kind === SyntaxKind.DefaultClause; - } - // JSDoc /** True if node is of some JSDoc syntax kind. */ @@ -7077,10 +6490,12 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode; } + // TODO(rbuckton): Deprecate export function isSetAccessor(node: Node): node is SetAccessorDeclaration { return node.kind === SyntaxKind.SetAccessor; } + // TODO(rbuckton): Deprecate export function isGetAccessor(node: Node): node is GetAccessorDeclaration { return node.kind === SyntaxKind.GetAccessor; } @@ -7124,10 +6539,6 @@ namespace ts { return hasInitializer(node) && !isForStatement(node) && !isForInStatement(node) && !isForOfStatement(node) && !isJsxAttribute(node); } - export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { - return node.kind === SyntaxKind.JsxAttribute || node.kind === SyntaxKind.JsxSpreadAttribute || isObjectLiteralElementLike(node); - } - /* @internal */ export function isTypeReferenceType(node: Node): node is TypeReferenceType { return node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ExpressionWithTypeArguments; @@ -7237,6 +6648,38 @@ namespace ts { return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message; } + export function createDetachedDiagnostic(start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithDetachedLocation; + export function createDetachedDiagnostic(start: number, length: number, message: DiagnosticMessage): DiagnosticWithDetachedLocation { + Debug.assertGreaterThanOrEqual(start, 0); + Debug.assertGreaterThanOrEqual(length, 0); + + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 3) { + text = formatStringFromArgs(text, arguments, 3); + } + + return { + file: undefined, + start, + length, + + messageText: text, + category: message.category, + code: message.code, + reportsUnnecessary: message.reportsUnnecessary, + }; + } + + export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocation[], file: SourceFile): DiagnosticWithLocation[] { + for (const diagnostic of diagnostics) { + Debug.assertLessThanOrEqual(diagnostic.start, file.text.length); + Debug.assertLessThanOrEqual(diagnostic.start + diagnostic.length, file.text.length); + (diagnostic as Diagnostic).file = file; + } + return diagnostics as Diagnostic[] as DiagnosticWithLocation[]; + } + export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation { Debug.assertGreaterThanOrEqual(start, 0); diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 773853684f1..9d940d8e24a 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -84,7 +84,7 @@ namespace ts { return nodes; } - let updated: MutableNodeArray | undefined; + let updated: T[] | undefined; // Ensure start and count have valid values const length = nodes.length; @@ -96,11 +96,15 @@ namespace ts { count = length - start; } + let hasTrailingComma: boolean | undefined; + let pos = -1; + let end = -1; if (start > 0 || count < length) { // If we are not visiting all of the original nodes, we must always create a new array. // Since this is a fragment of a node array, we do not copy over the previous location // and will only copy over `hasTrailingComma` if we are including the last element. - updated = createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + updated = []; + hasTrailingComma = nodes.hasTrailingComma && start + count === length; } // Visit each original node. @@ -111,8 +115,10 @@ namespace ts { if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { // Ensure we have a copy of `nodes`, up to the current index. - updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); - setTextRange(updated, nodes); + updated = nodes.slice(0, i); + hasTrailingComma = nodes.hasTrailingComma; + pos = nodes.pos; + end = nodes.end; } if (visited) { if (isArray(visited)) { @@ -131,7 +137,15 @@ namespace ts { } } - return updated || nodes; + if (updated) { + // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. + const updatedArray = factory.createNodeArray(updated, hasTrailingComma); + updatedArray.pos = pos; + updatedArray.end = end; + return updatedArray; + } + + return nodes; } /** @@ -143,10 +157,12 @@ namespace ts { startLexicalEnvironment(); statements = visitNodes(statements, visitor, isStatementOrBlock, start); if (ensureUseStrict && !startsWithUseStrict(statements)) { + // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. statements = setTextRange(factory.createNodeArray([factory.createUseStrictPrologue(), ...statements]), statements); } const declarations = endLexicalEnvironment(); - return setTextRange(createNodeArray(concatenate(declarations, statements)), statements); + // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. + return setTextRange(factory.createNodeArray(concatenate(declarations, statements)), statements); } /** @@ -1483,8 +1499,9 @@ namespace ts { return statements; } + // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. return isNodeArray(statements) - ? setTextRange(createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements) + ? setTextRange(factory.createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements) : insertStatementsAfterStandardPrologue(statements, declarations); } @@ -1508,7 +1525,15 @@ namespace ts { return TransformFlags.None; } if (node.transformFlags & TransformFlags.HasComputedFlags) { - return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + const nodeFlags = node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + switch (node.kind) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return nodeFlags | ((node as NamedDeclaration).name!.transformFlags & TransformFlags.PropertyNamePropagatingFlags); + } + return nodeFlags; } const subtreeFlags = aggregateTransformFlagsForSubtree(node); return computeTransformFlagsForNode(node, subtreeFlags); diff --git a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts index 407a2eec9c0..ce72309d4cf 100644 --- a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts +++ b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts @@ -14,7 +14,7 @@ namespace ts.codefix { function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) { const token = getTokenAtPosition(sourceFile, pos); - const assertion = Debug.assertDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertion(n))); + const assertion = Debug.assertDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertionExpression(n))); const replacement = isAsExpression(assertion) ? factory.createAsExpression(assertion.expression, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)) : factory.createTypeAssertion(factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression); diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index 0c556566e3a..a680af23dfb 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -144,7 +144,7 @@ namespace ts.codefix { } name = factory.createIdentifier(text); if ((text === "Array" || text === "Promise") && !node.typeArguments) { - args = createNodeArray([factory.createTypeReferenceNode("any", emptyArray)]); + args = factory.createNodeArray([factory.createTypeReferenceNode("any", emptyArray)]); } else { args = visitNodes(node.typeArguments, transformJSDocType); diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 0d44288dd06..19746e48a1d 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -483,7 +483,7 @@ namespace ts.codefix { getSynthesizedDeepClones(fn.typeParameters), getSynthesizedDeepClones(fn.parameters), getSynthesizedDeepClone(fn.type), - nodeConverters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); + factory.getConverters().convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); } function classExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray, cls: ClassExpression): ClassDeclaration { diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 4fcce8c5cde..e78f99da873 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, factory.createTypeReferenceNode("Promise", createNodeArray([returnType]))); + changes.replaceNode(sourceFile, returnType, factory.createTypeReferenceNode("Promise", factory.createNodeArray([returnType]))); } } changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore); diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 885dc0129df..14144ca8e42 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -52,7 +52,7 @@ namespace ts.codefix { const declaration = declarations[0]; const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName; const visibilityModifier = createVisibilityModifier(getModifierFlags(declaration)); - const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined; + const modifiers = visibilityModifier ? factory.createNodeArray([visibilityModifier]) : undefined; const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); const optional = !!(symbol.flags & SymbolFlags.Optional); const ambient = !!(enclosingDeclaration.flags & NodeFlags.Ambient); diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 31a4b79bcd3..3eeb907f57c 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -318,7 +318,7 @@ namespace ts.codefix { if (merged) oldTags[i] = merged; return !!merged; })); - const tag = factory.createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); + const tag = factory.createJSDocComment(comments.join("\n"), factory.createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent; jsDocNode.jsDoc = parent.jsDoc; jsDocNode.jsDocCache = parent.jsDocCache; diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts index f9edb65fea0..13e69e218ee 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -356,7 +356,7 @@ namespace ts.refactor.convertParamsToDestructuredObject { function getRefactorableParameters(parameters: NodeArray): NodeArray { if (hasThisParameter(parameters)) { - parameters = createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + parameters = factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); } return parameters; } @@ -431,9 +431,9 @@ namespace ts.refactor.convertParamsToDestructuredObject { copyComments(thisParameter.type, newThisParameter.type!); } - return createNodeArray([newThisParameter, objectParameter]); + return factory.createNodeArray([newThisParameter, objectParameter]); } - return createNodeArray([objectParameter]); + return factory.createNodeArray([objectParameter]); function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement { const element = factory.createBindingElement( diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 9602b287b31..30113ab6b80 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1164,7 +1164,7 @@ namespace ts.refactor.extractSymbol { } let returnValueProperty: string | undefined; let ignoreReturns = false; - const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturn(body)]); + const statements = factory.createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { const rewrittenStatements = visitNodes(statements, visitor).slice(); diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index b57f41d75ea..316b7339ab9 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -136,12 +136,12 @@ namespace ts.refactor { const parameter = createNode(SyntaxKind.TypeParameter); parameter.name = typeParameter.name; - template.typeParameters = createNodeArray([parameter]); + template.typeParameters = factory.createNodeArray([parameter]); templates.push(template); }); - changes.insertNodeBefore(file, firstStatement, factory.createJSDocComment(/* comment */ undefined, createNodeArray(concatenate(templates, [node]))), /* blankLineBetween */ true); + changes.insertNodeBefore(file, firstStatement, factory.createJSDocComment(/* comment */ undefined, factory.createNodeArray(concatenate(templates, [node]))), /* blankLineBetween */ true); changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); } } diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 09ab795096b..09256c8d713 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(factory.createModifiersFromModifierFlags(modifierFlags)) + : factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined; @@ -109,7 +109,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { !isJS ? [factory.createToken(accessModifier) as Token | Token] : undefined, isStatic ? factory.createToken(SyntaxKind.StaticKeyword) : undefined ); - return modifiers && createNodeArray(modifiers); + return modifiers && factory.createNodeArray(modifiers); } function startsWithUnderscore(name: string): boolean { diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 998e45bd461..bcc90994d82 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -569,7 +569,7 @@ namespace ts.SignatureHelp { const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const parameterParts = mapToDisplayParts(writer => { const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : []; - const params = createNodeArray([...thisParameter, ...checker.getExpandedParameters(candidateSignature).map(param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); + const params = factory.createNodeArray([...thisParameter, ...checker.getExpandedParameters(candidateSignature).map(param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); printer.writeList(ListFormat.CallExpressionArguments, params, sourceFile, writer); }); return { isVariadic: false, parameters, prefix: [punctuationPart(SyntaxKind.LessThanToken)], suffix: [punctuationPart(SyntaxKind.GreaterThanToken), ...parameterParts] }; @@ -580,7 +580,7 @@ namespace ts.SignatureHelp { const printer = createPrinter({ removeComments: true }); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { - const args = createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration)!)); + const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration)!)); printer.writeList(ListFormat.TypeParameters, args, sourceFile, writer); } }); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 15b222d77a2..c3e20ccc521 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -886,7 +886,7 @@ namespace ts.textChanges { return visited; } // clone nodearray if necessary - const nodeArray = visited === nodes ? createNodeArray(visited.slice(0)) : visited; + const nodeArray = visited === nodes ? factory.createNodeArray(visited.slice(0)) : visited; nodeArray.pos = getPos(nodes); nodeArray.end = getEnd(nodes); return nodeArray; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index c4f9de4ea4c..e1112e19f77 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1769,7 +1769,7 @@ namespace ts { export function getSynthesizedDeepClones(nodes: NodeArray, includeTrivia?: boolean): NodeArray; export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia?: boolean): NodeArray | undefined; export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia = true): NodeArray | undefined { - return nodes && createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); + return nodes && factory.createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); } /** diff --git a/src/testRunner/unittests/asserts.ts b/src/testRunner/unittests/asserts.ts index 116a74cf179..d5ff7552f11 100644 --- a/src/testRunner/unittests/asserts.ts +++ b/src/testRunner/unittests/asserts.ts @@ -1,9 +1,9 @@ namespace ts { describe("unittests:: assert", () => { it("deepEqual", () => { - assert.throws(() => assert.deepEqual(createNodeArray([createIdentifier("A")]), createNodeArray([createIdentifier("B")]))); - assert.throws(() => assert.deepEqual(createNodeArray([], /*hasTrailingComma*/ true), createNodeArray([], /*hasTrailingComma*/ false))); - assert.deepEqual(createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true), createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true)); + assert.throws(() => assert.deepEqual(factory.createNodeArray([createIdentifier("A")]), factory.createNodeArray([createIdentifier("B")]))); + assert.throws(() => assert.deepEqual(factory.createNodeArray([], /*hasTrailingComma*/ true), factory.createNodeArray([], /*hasTrailingComma*/ false))); + assert.deepEqual(factory.createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true), factory.createNodeArray([createIdentifier("A")], /*hasTrailingComma*/ true)); }); it("assertNever on string has correct error", () => { assert.throws(() => Debug.assertNever("hi" as never), "Debug Failure. Illegal value: \"hi\""); diff --git a/src/testRunner/unittests/printer.ts b/src/testRunner/unittests/printer.ts index 8e217aa6a3a..88942d87bc0 100644 --- a/src/testRunner/unittests/printer.ts +++ b/src/testRunner/unittests/printer.ts @@ -104,7 +104,7 @@ namespace ts { /*heritageClauses*/ undefined, [createProperty( /*decorators*/ undefined, - createNodeArray([createToken(SyntaxKind.PublicKeyword)]), + factory.createNodeArray([createToken(SyntaxKind.PublicKeyword)]), createIdentifier("prop"), /*questionToken*/ undefined, /*type*/ undefined, diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index 35c3ab9a942..8e1d6a6ae64 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -175,7 +175,7 @@ namespace ts { function replaceWithClassAndNamespace() { return (sourceFile: SourceFile) => { const result = getMutableClone(sourceFile); - result.statements = createNodeArray([ + result.statements = factory.createNodeArray([ createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) ]); @@ -191,7 +191,7 @@ namespace ts { function visitNode(node: T): T { if (node.kind === SyntaxKind.ModuleBlock) { const block = node as T & ModuleBlock; - const statements = createNodeArray([...block.statements]); + const statements = factory.createNodeArray([...block.statements]); return updateModuleBlock(block, statements) as typeof block; } return visitEachChild(node, visitNode, context);