@@ -964,7 +964,7 @@ import {
964
964
ScriptKind,
965
965
ScriptTarget,
966
966
SetAccessorDeclaration,
967
- setCommentRange,
967
+ setCommentRange as setCommentRangeWorker ,
968
968
setEmitFlags,
969
969
setIdentifierTypeArguments,
970
970
setNodeFlags,
@@ -1091,7 +1091,7 @@ import {
1091
1091
VariableLikeDeclaration,
1092
1092
VariableStatement,
1093
1093
VarianceFlags,
1094
- visitEachChild,
1094
+ visitEachChild as visitEachChildWorker ,
1095
1095
visitNode,
1096
1096
visitNodes,
1097
1097
Visitor,
@@ -2422,7 +2422,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2422
2422
2423
2423
function markAsSynthetic<T extends Node>(node: T): VisitResult<T> {
2424
2424
setTextRangePosEnd(node, -1, -1);
2425
- return visitEachChild (node, markAsSynthetic, /*context*/ undefined);
2425
+ return visitEachChildWorker (node, markAsSynthetic, /*context*/ undefined);
2426
2426
}
2427
2427
2428
2428
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken, skipDiagnostics?: boolean) {
@@ -6021,13 +6021,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6021
6021
* Unlike the utilities `setTextRange`, this checks if the `location` we're trying to set on `range` is within the
6022
6022
* same file as the active context. If not, the range is not applied. This prevents us from copying ranges across files,
6023
6023
* which will confuse the node printer (as it assumes all node ranges are within the current file).
6024
- * Additionally, if `range` _isn't synthetic_, and isn't in the current file, it will _copy_ it to _remove_ its' position
6024
+ * Additionally, if `range` _isn't synthetic_, or isn't in the current file, it will _copy_ it to _remove_ its' position
6025
6025
* information.
6026
6026
*
6027
6027
* It also calls `setOriginalNode` to setup a `.original` pointer, since you basically *always* want these in the node builder.
6028
6028
*/
6029
6029
function setTextRange<T extends Node>(context: NodeBuilderContext, range: T, location: Node | undefined): T {
6030
- if (!nodeIsSynthesized(range) && !(range.flags & NodeFlags.Synthesized) && ( !context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(range) )) {
6030
+ if (!nodeIsSynthesized(range) || !(range.flags & NodeFlags.Synthesized) || !context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(range)) {
6031
6031
range = factory.cloneNode(range);
6032
6032
}
6033
6033
if (range === location) return range;
@@ -6709,7 +6709,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6709
6709
if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) {
6710
6710
return node;
6711
6711
}
6712
- return setTextRange(context, factory.cloneNode(visitEachChild (node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes, deepCloneOrReuseNode)), node);
6712
+ return setTextRange(context, factory.cloneNode(visitEachChildWorker (node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes, deepCloneOrReuseNode)), node);
6713
6713
}
6714
6714
6715
6715
function deepCloneOrReuseNodes(
@@ -7056,6 +7056,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7056
7056
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
7057
7057
typeElements.push(
7058
7058
setCommentRange(
7059
+ context,
7059
7060
signatureToSignatureDeclarationHelper(getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7060
7061
getterDeclaration,
7061
7062
),
@@ -7064,6 +7065,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7064
7065
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
7065
7066
typeElements.push(
7066
7067
setCommentRange(
7068
+ context,
7067
7069
signatureToSignatureDeclarationHelper(setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7068
7070
setterDeclaration,
7069
7071
),
@@ -7121,12 +7123,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7121
7123
}
7122
7124
else if (propertySymbol.valueDeclaration) {
7123
7125
// Copy comments to node for declaration emit
7124
- setCommentRange(node, propertySymbol.valueDeclaration);
7126
+ setCommentRange(context, node, propertySymbol.valueDeclaration);
7125
7127
}
7126
7128
return node;
7127
7129
}
7128
7130
}
7129
7131
7132
+ function setCommentRange<T extends Node>(context: NodeBuilderContext, node: T, range: Node): T {
7133
+ if (context.enclosingFile && context.enclosingFile === getSourceFileOfNode(range)) {
7134
+ // Copy comments to node for declaration emit
7135
+ return setCommentRangeWorker(node, range);
7136
+ }
7137
+ return node;
7138
+ }
7139
+
7130
7140
function mapToTypeNodes(types: readonly Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): TypeNode[] | undefined {
7131
7141
if (some(types)) {
7132
7142
if (checkTruncationLength(context)) {
@@ -7568,7 +7578,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7568
7578
if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
7569
7579
trackComputedName(node.expression, context.enclosingDeclaration, context);
7570
7580
}
7571
- let visited = visitEachChild (node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags);
7581
+ let visited = visitEachChildWorker (node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags);
7572
7582
if (isBindingElement(visited)) {
7573
7583
visited = factory.updateBindingElement(
7574
7584
visited,
@@ -8382,7 +8392,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
8382
8392
name.symbol = sym!; // for quickinfo, which uses identifier symbol information
8383
8393
return setTextRange(context, setEmitFlags(name, EmitFlags.NoAsciiEscaping), node);
8384
8394
}
8385
- const updated = visitEachChild (node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined);
8395
+ const updated = visitEachChildWorker (node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined);
8386
8396
if (updated !== node) {
8387
8397
setTextRange(context, updated, node);
8388
8398
}
@@ -8480,7 +8490,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
8480
8490
// is set to build for (even though we are reusing the node structure, the position information
8481
8491
// would make the printer print invalid spans for literals and identifiers, and the formatter would
8482
8492
// choke on the mismatched positonal spans between a parent and an injected child from another file).
8483
- return result === node ? setTextRange(context, factory.cloneNode( result) , node) : result ;
8493
+ return result ? setTextRange(context, result, node) : undefined ;
8484
8494
}
8485
8495
8486
8496
function onEnterNewScope(node: IntroducesNewScopeNode | ConditionalTypeNode) {
@@ -8646,7 +8656,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
8646
8656
|| (isPropertySignature(node) && !node.type && !node.initializer)
8647
8657
|| (isParameter(node) && !node.type && !node.initializer)
8648
8658
) {
8649
- let visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined );
8659
+ let visited = visitEachChild(node, visitExistingNodeTreeSymbols);
8650
8660
if (visited === node) {
8651
8661
visited = setTextRange(context, factory.cloneNode(node), node);
8652
8662
}
@@ -8707,7 +8717,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
8707
8717
}
8708
8718
8709
8719
if (isTupleTypeNode(node) || isTypeLiteralNode(node) || isMappedTypeNode(node)) {
8710
- const visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined );
8720
+ const visited = visitEachChild(node, visitExistingNodeTreeSymbols);
8711
8721
const clone = setTextRange(context, visited === node ? factory.cloneNode(node) : visited, node);
8712
8722
const flags = getEmitFlags(clone);
8713
8723
setEmitFlags(clone, flags | (context.flags & NodeBuilderFlags.MultilineObjectLiterals && isTypeLiteralNode(node) ? 0 : EmitFlags.SingleLine));
@@ -8741,7 +8751,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
8741
8751
}
8742
8752
}
8743
8753
8744
- return visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
8754
+ return visitEachChild(node, visitExistingNodeTreeSymbols);
8755
+
8756
+ function visitEachChild<T extends Node>(node: T, visitor: Visitor): T;
8757
+ function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor): T | undefined;
8758
+ function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor): T | undefined {
8759
+ const nonlocalNode = !context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(node);
8760
+ return visitEachChildWorker(node, visitor, /*context*/ undefined, nonlocalNode ? visitNodesWithoutCopyingPositions : undefined);
8761
+ }
8762
+
8763
+ function visitNodesWithoutCopyingPositions(
8764
+ nodes: NodeArray<Node> | undefined,
8765
+ visitor: Visitor,
8766
+ test?: (node: Node) => boolean,
8767
+ start?: number,
8768
+ count?: number,
8769
+ ): NodeArray<Node> | undefined {
8770
+ let result = visitNodes(nodes, visitor, test, start, count);
8771
+ if (result) {
8772
+ if (result.pos !== -1 || result.end !== -1) {
8773
+ if (result === nodes) {
8774
+ result = factory.createNodeArray(nodes, nodes.hasTrailingComma);
8775
+ }
8776
+ setTextRangePosEnd(result, -1, -1);
8777
+ }
8778
+ }
8779
+ return result;
8780
+ }
8745
8781
8746
8782
function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) {
8747
8783
return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined);
0 commit comments