Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d4976c0

Browse files
authored
Clone node to remove location even when it has been modified if needed (#58706)
1 parent 6c058d4 commit d4976c0

File tree

668 files changed

+4621
-4428
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

668 files changed

+4621
-4428
lines changed

src/compiler/checker.ts

+55-15
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ import {
967967
ScriptKind,
968968
ScriptTarget,
969969
SetAccessorDeclaration,
970-
setCommentRange,
970+
setCommentRange as setCommentRangeWorker,
971971
setEmitFlags,
972972
setIdentifierTypeArguments,
973973
setNodeFlags,
@@ -1094,7 +1094,7 @@ import {
10941094
VariableLikeDeclaration,
10951095
VariableStatement,
10961096
VarianceFlags,
1097-
visitEachChild,
1097+
visitEachChild as visitEachChildWorker,
10981098
visitNode,
10991099
visitNodes,
11001100
Visitor,
@@ -2426,7 +2426,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
24262426

24272427
function markAsSynthetic<T extends Node>(node: T): VisitResult<T> {
24282428
setTextRangePosEnd(node, -1, -1);
2429-
return visitEachChild(node, markAsSynthetic, /*context*/ undefined);
2429+
return visitEachChildWorker(node, markAsSynthetic, /*context*/ undefined);
24302430
}
24312431

24322432
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken, skipDiagnostics?: boolean) {
@@ -6032,21 +6032,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
60326032
* Unlike the utilities `setTextRange`, this checks if the `location` we're trying to set on `range` is within the
60336033
* same file as the active context. If not, the range is not applied. This prevents us from copying ranges across files,
60346034
* which will confuse the node printer (as it assumes all node ranges are within the current file).
6035-
* Additionally, if `range` _isn't synthetic_, and isn't in the current file, it will _copy_ it to _remove_ its' position
6035+
* Additionally, if `range` _isn't synthetic_, or isn't in the current file, it will _copy_ it to _remove_ its' position
60366036
* information.
60376037
*
60386038
* It also calls `setOriginalNode` to setup a `.original` pointer, since you basically *always* want these in the node builder.
60396039
*/
60406040
function setTextRange<T extends Node>(context: NodeBuilderContext, range: T, location: Node | undefined): T {
6041-
if (!nodeIsSynthesized(range) && !(range.flags & NodeFlags.Synthesized) && (!context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(range))) {
6042-
range = factory.cloneNode(range);
6041+
if (!nodeIsSynthesized(range) || !(range.flags & NodeFlags.Synthesized) || !context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(getOriginalNode(range))) {
6042+
range = factory.cloneNode(range); // if `range` is synthesized or originates in another file, copy it so it definitely has synthetic positions
60436043
}
60446044
if (range === location) return range;
60456045
if (!location) {
60466046
return range;
60476047
}
60486048
if (!context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(getOriginalNode(location))) {
6049-
return setOriginalNode(range, location);
6049+
return setOriginalNode(range, location); // if `location` is from another file, only set/update original pointer, and not positions, since copying text across files isn't supported by the emitter
60506050
}
60516051
return setTextRangeWorker(setOriginalNode(range, location), location);
60526052
}
@@ -6720,7 +6720,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
67206720
if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) {
67216721
return node;
67226722
}
6723-
return setTextRange(context, factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes, deepCloneOrReuseNode)), node);
6723+
return setTextRange(context, factory.cloneNode(visitEachChildWorker(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes, deepCloneOrReuseNode)), node);
67246724
}
67256725

67266726
function deepCloneOrReuseNodes(
@@ -7067,6 +7067,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
70677067
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
70687068
typeElements.push(
70697069
setCommentRange(
7070+
context,
70707071
signatureToSignatureDeclarationHelper(getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
70717072
getterDeclaration,
70727073
),
@@ -7075,6 +7076,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
70757076
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
70767077
typeElements.push(
70777078
setCommentRange(
7079+
context,
70787080
signatureToSignatureDeclarationHelper(setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
70797081
setterDeclaration,
70807082
),
@@ -7132,12 +7134,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
71327134
}
71337135
else if (propertySymbol.valueDeclaration) {
71347136
// Copy comments to node for declaration emit
7135-
setCommentRange(node, propertySymbol.valueDeclaration);
7137+
setCommentRange(context, node, propertySymbol.valueDeclaration);
71367138
}
71377139
return node;
71387140
}
71397141
}
71407142

7143+
function setCommentRange<T extends Node>(context: NodeBuilderContext, node: T, range: Node): T {
7144+
if (context.enclosingFile && context.enclosingFile === getSourceFileOfNode(range)) {
7145+
// Copy comments to node for declaration emit
7146+
return setCommentRangeWorker(node, range);
7147+
}
7148+
return node;
7149+
}
7150+
71417151
function mapToTypeNodes(types: readonly Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): TypeNode[] | undefined {
71427152
if (some(types)) {
71437153
if (checkTruncationLength(context)) {
@@ -7579,7 +7589,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75797589
if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
75807590
trackComputedName(node.expression, context.enclosingDeclaration, context);
75817591
}
7582-
let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags);
7592+
let visited = visitEachChildWorker(node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags);
75837593
if (isBindingElement(visited)) {
75847594
visited = factory.updateBindingElement(
75857595
visited,
@@ -7992,6 +8002,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
79928002
if (!(result.kind & SyntaxKind.Identifier)) {
79938003
return factory.createIdentifier("(Missing type parameter)");
79948004
}
8005+
const decl = type.symbol?.declarations?.[0];
8006+
if (decl && isTypeParameterDeclaration(decl)) {
8007+
result = setTextRange(context, result, decl.name);
8008+
}
79958009
if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) {
79968010
const rawtext = result.escapedText as string;
79978011
let i = context.typeParameterNamesByTextNextNameCount?.get(rawtext) || 0;
@@ -8393,7 +8407,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
83938407
name.symbol = sym!; // for quickinfo, which uses identifier symbol information
83948408
return setTextRange(context, setEmitFlags(name, EmitFlags.NoAsciiEscaping), node);
83958409
}
8396-
const updated = visitEachChild(node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined);
8410+
const updated = visitEachChildWorker(node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined);
83978411
if (updated !== node) {
83988412
setTextRange(context, updated, node);
83998413
}
@@ -8504,7 +8518,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
85048518
// is set to build for (even though we are reusing the node structure, the position information
85058519
// would make the printer print invalid spans for literals and identifiers, and the formatter would
85068520
// choke on the mismatched positonal spans between a parent and an injected child from another file).
8507-
return result === node ? setTextRange(context, factory.cloneNode(result), node) : result;
8521+
return result ? setTextRange(context, result, node) : undefined;
85088522
}
85098523

85108524
function createRecoveryBoundary() {
@@ -8769,7 +8783,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
87698783
|| (isPropertySignature(node) && !node.type && !node.initializer)
87708784
|| (isParameter(node) && !node.type && !node.initializer)
87718785
) {
8772-
let visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
8786+
let visited = visitEachChild(node, visitExistingNodeTreeSymbols);
87738787
if (visited === node) {
87748788
visited = setTextRange(context, factory.cloneNode(node), node);
87758789
}
@@ -8831,7 +8845,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88318845
}
88328846

88338847
if (isTupleTypeNode(node) || isTypeLiteralNode(node) || isMappedTypeNode(node)) {
8834-
const visited = visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
8848+
const visited = visitEachChild(node, visitExistingNodeTreeSymbols);
88358849
const clone = setTextRange(context, visited === node ? factory.cloneNode(node) : visited, node);
88368850
const flags = getEmitFlags(clone);
88378851
setEmitFlags(clone, flags | (context.flags & NodeBuilderFlags.MultilineObjectLiterals && isTypeLiteralNode(node) ? 0 : EmitFlags.SingleLine));
@@ -8878,7 +8892,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88788892
}
88798893
}
88808894

8881-
return visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined);
8895+
return visitEachChild(node, visitExistingNodeTreeSymbols);
8896+
8897+
function visitEachChild<T extends Node>(node: T, visitor: Visitor): T;
8898+
function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor): T | undefined;
8899+
function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor): T | undefined {
8900+
const nonlocalNode = !context.enclosingFile || context.enclosingFile !== getSourceFileOfNode(node);
8901+
return visitEachChildWorker(node, visitor, /*context*/ undefined, nonlocalNode ? visitNodesWithoutCopyingPositions : undefined);
8902+
}
8903+
8904+
function visitNodesWithoutCopyingPositions(
8905+
nodes: NodeArray<Node> | undefined,
8906+
visitor: Visitor,
8907+
test?: (node: Node) => boolean,
8908+
start?: number,
8909+
count?: number,
8910+
): NodeArray<Node> | undefined {
8911+
let result = visitNodes(nodes, visitor, test, start, count);
8912+
if (result) {
8913+
if (result.pos !== -1 || result.end !== -1) {
8914+
if (result === nodes) {
8915+
result = factory.createNodeArray(nodes, nodes.hasTrailingComma);
8916+
}
8917+
setTextRangePosEnd(result, -1, -1);
8918+
}
8919+
}
8920+
return result;
8921+
}
88828922

88838923
function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) {
88848924
return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined);

tests/baselines/reference/2dArrays.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ class Board {
3535
>this.ships.every(function (val) { return val.isSunk; }) : boolean
3636
> : ^^^^^^^
3737
>this.ships.every : { <S extends Ship>(predicate: (value: Ship, index: number, array: Ship[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any): boolean; }
38-
> : ^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^ ^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^ ^^ ^^^ ^^^ ^^^
38+
> : ^^^ ^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^ ^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^ ^^ ^^^ ^^^ ^^^
3939
>this.ships : Ship[]
4040
> : ^^^^^^
4141
>this : this
4242
> : ^^^^
4343
>ships : Ship[]
4444
> : ^^^^^^
4545
>every : { <S extends Ship>(predicate: (value: Ship, index: number, array: Ship[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Ship, index: number, array: Ship[]) => unknown, thisArg?: any): boolean; }
46-
> : ^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^ ^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^ ^^ ^^^ ^^^ ^^^
46+
> : ^^^ ^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^ ^^^ ^^^ ^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^ ^^ ^^^ ^^^ ^^^
4747
>function (val) { return val.isSunk; } : (val: Ship) => boolean
4848
> : ^ ^^^^^^^^^^^^^^^^^^
4949
>val : Ship

tests/baselines/reference/FunctionPropertyAssignments6_es6.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
=== FunctionPropertyAssignments6_es6.ts ===
44
var v = { *<T>() { } }
55
>v : { ""<T>(): Generator<never, void, unknown>; }
6-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77
>{ *<T>() { } } : { ""<T>(): Generator<never, void, unknown>; }
8-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99
> : <T>() => Generator<never, void, unknown>
10-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1111

tests/baselines/reference/MemberFunctionDeclaration7_es6.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ class C {
77

88
*foo<T>() { }
99
>foo : <T>() => Generator<never, void, unknown>
10-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1111
}

0 commit comments

Comments
 (0)