Skip to content

Commit 8e7cc78

Browse files
authored
Ensure deep cloned AST nodes have synthetic positions (#1174)
1 parent 0a2ea49 commit 8e7cc78

13 files changed

+283
-16
lines changed

internal/ast/deepclone.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package ast
22

3+
import "github.com/microsoft/typescript-go/internal/core"
4+
35
// Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory
46
func getDeepCloneVisitor(f *NodeFactory) *NodeVisitor {
57
var visitor *NodeVisitor
@@ -9,7 +11,12 @@ func getDeepCloneVisitor(f *NodeFactory) *NodeVisitor {
911
if visited != node {
1012
return visited
1113
}
12-
return node.Clone(f) // forcibly clone leaf nodes, which will then cascade new nodes/arrays upwards via `update` calls
14+
c := node.Clone(f) // forcibly clone leaf nodes, which will then cascade new nodes/arrays upwards via `update` calls
15+
// In strada, `factory.cloneNode` was dynamic and did _not_ clone positions for any "special cases", meanwhile
16+
// Node.Clone in corsa reliably uses `Update` calls for all nodes and so copies locations by default.
17+
// Deep clones are done to copy a node across files, so here, we explicitly make the location range synthetic on all cloned nodes
18+
c.Loc = core.NewTextRange(-1, -1)
19+
return c
1320
},
1421
f,
1522
NodeVisitorHooks{

testdata/baselines/reference/compiler/declarationEmitNoCrashOnCommentCopiedFromOtherFile.js

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testdata/baselines/reference/compiler/declarationEmitNoCrashOnCommentCopiedFromOtherFile.js.map

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
===================================================================
2+
JsFile: export.d.ts
3+
mapUrl: export.d.ts.map
4+
sourceRoot:
5+
sources: export.ts
6+
===================================================================
7+
-------------------------------------------------------------------
8+
emittedFile:export.d.ts
9+
sourceFile:export.ts
10+
-------------------------------------------------------------------
11+
>>>/**
12+
1 >
13+
2 >^^^^^^^^^^^^^^^^^^^^^^^->
14+
1 >
15+
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
16+
---
17+
>>> * blah blah blah blah
18+
>>> * blah blah blah blah
19+
>>> * blah blah blah blah
20+
>>> * blah blah blah blah
21+
>>> * blah blah blah blah
22+
>>> */
23+
1->^^^
24+
2 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
25+
1->/**
26+
> * blah blah blah blah
27+
> * blah blah blah blah
28+
> * blah blah blah blah
29+
> * blah blah blah blah
30+
> * blah blah blah blah
31+
> */
32+
1->Emitted(7, 4) Source(7, 4) + SourceIndex(0)
33+
---
34+
>>>export declare function foo(): (_item: unknown) => _item is boolean;
35+
1->
36+
2 >^^^^^^^^^^^^^^^^^^^^^^^^
37+
3 > ^^^
38+
4 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
1->
40+
>
41+
>
42+
2 >export function
43+
3 > foo
44+
4 > () {
45+
> return (_item: unknown): _item is boolean => {
46+
> return true;
47+
> };
48+
> }
49+
1->Emitted(8, 1) Source(9, 1) + SourceIndex(0)
50+
2 >Emitted(8, 25) Source(9, 17) + SourceIndex(0)
51+
3 >Emitted(8, 28) Source(9, 20) + SourceIndex(0)
52+
4 >Emitted(8, 69) Source(13, 2) + SourceIndex(0)
53+
---
54+
>>>//# sourceMappingURL=export.d.ts.map===================================================================
55+
JsFile: import.d.ts
56+
mapUrl: import.d.ts.map
57+
sourceRoot:
58+
sources: import.ts
59+
===================================================================
60+
-------------------------------------------------------------------
61+
emittedFile:import.d.ts
62+
sourceFile:import.ts
63+
-------------------------------------------------------------------
64+
>>>export declare const x: (_item: unknown) => _item is boolean;
65+
1 >
66+
2 >^^^^^^^^^^^^^^^
67+
3 > ^^^^^^
68+
4 > ^
69+
5 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
70+
6 > ^
71+
1 >import { foo } from './export';
72+
>
73+
2 >export
74+
3 > const
75+
4 > x
76+
5 > = foo()
77+
6 > ;
78+
1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0)
79+
2 >Emitted(1, 16) Source(2, 8) + SourceIndex(0)
80+
3 >Emitted(1, 22) Source(2, 14) + SourceIndex(0)
81+
4 >Emitted(1, 23) Source(2, 15) + SourceIndex(0)
82+
5 >Emitted(1, 61) Source(2, 23) + SourceIndex(0)
83+
6 >Emitted(1, 62) Source(2, 24) + SourceIndex(0)
84+
---
85+
>>>//# sourceMappingURL=import.d.ts.map
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/compiler/declarationEmitNoCrashOnCommentCopiedFromOtherFile.ts] ////
2+
3+
=== export.ts ===
4+
/**
5+
* blah blah blah blah
6+
* blah blah blah blah
7+
* blah blah blah blah
8+
* blah blah blah blah
9+
* blah blah blah blah
10+
*/
11+
12+
export function foo() {
13+
>foo : Symbol(foo, Decl(export.ts, 0, 0))
14+
15+
return (_item: unknown): _item is boolean => {
16+
>_item : Symbol(_item, Decl(export.ts, 9, 10))
17+
>_item : Symbol(_item, Decl(export.ts, 9, 10))
18+
19+
return true;
20+
};
21+
}
22+
=== import.ts ===
23+
import { foo } from './export';
24+
>foo : Symbol(foo, Decl(import.ts, 0, 8))
25+
26+
export const x = foo();
27+
>x : Symbol(x, Decl(import.ts, 1, 12))
28+
>foo : Symbol(foo, Decl(import.ts, 0, 8))
29+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [tests/cases/compiler/declarationEmitNoCrashOnCommentCopiedFromOtherFile.ts] ////
2+
3+
=== export.ts ===
4+
/**
5+
* blah blah blah blah
6+
* blah blah blah blah
7+
* blah blah blah blah
8+
* blah blah blah blah
9+
* blah blah blah blah
10+
*/
11+
12+
export function foo() {
13+
>foo : () => (_item: unknown) => _item is boolean
14+
15+
return (_item: unknown): _item is boolean => {
16+
>(_item: unknown): _item is boolean => { return true; } : (_item: unknown) => _item is boolean
17+
>_item : unknown
18+
19+
return true;
20+
>true : true
21+
22+
};
23+
}
24+
=== import.ts ===
25+
import { foo } from './export';
26+
>foo : () => (_item: unknown) => _item is boolean
27+
28+
export const x = foo();
29+
>x : (_item: unknown) => _item is boolean
30+
>foo() : (_item: unknown) => _item is boolean
31+
>foo : () => (_item: unknown) => _item is boolean
32+

testdata/baselines/reference/submodule/compiler/arrayBindingPatternOmittedExpressions.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var results: string[];
2424

2525

2626
function f([, a, , b, , , , s, , , ] = results) {
27-
>f : ([, a, , b, , , , s, , ,]?: string[]) => void
27+
>f : ([, a, , b, , , , s, , ]?: string[]) => void
2828
>a : string
2929
>b : string
3030
>s : string
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- old.arrayBindingPatternOmittedExpressions.types
2+
+++ new.arrayBindingPatternOmittedExpressions.types
3+
@@= skipped -23, +23 lines =@@
4+
5+
6+
function f([, a, , b, , , , s, , , ] = results) {
7+
->f : ([, a, , b, , , , s, , ,]?: string[]) => void
8+
+>f : ([, a, , b, , , , s, , ]?: string[]) => void
9+
>a : string
10+
>b : string
11+
>s : string

testdata/baselines/reference/submodule/compiler/declarationEmitDestructuring5.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
=== declarationEmitDestructuring5.ts ===
44
function baz([, z, , ]) { }
5-
>baz : ([, z, ,]: [any, any, any?]) => void
5+
>baz : ([, z, ]: [any, any, any?]) => void
66
>z : any
77

88
function foo([, b, ]: [any, any]): void { }
99
>foo : ([, b,]: [any, any]) => void
1010
>b : any
1111

1212
function bar([z, , , ]) { }
13-
>bar : ([z, , ,]: [any, any?, any?]) => void
13+
>bar : ([z, , ]: [any, any?, any?]) => void
1414
>z : any
1515

1616
function bar1([z, , , ] = [1, 3, 4, 6, 7]) { }
17-
>bar1 : ([z, , ,]?: [number, number, number, number, number]) => void
17+
>bar1 : ([z, , ]?: [number, number, number, number, number]) => void
1818
>z : number
1919
>[1, 3, 4, 6, 7] : [number, number, number, number, number]
2020
>1 : 1
@@ -24,6 +24,6 @@ function bar1([z, , , ] = [1, 3, 4, 6, 7]) { }
2424
>7 : 7
2525

2626
function bar2([,,z, , , ]) { }
27-
>bar2 : ([, , z, , ,]: [any, any, any, any?, any?]) => void
27+
>bar2 : ([, , z, , ]: [any, any, any, any?, any?]) => void
2828
>z : any
2929

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--- old.declarationEmitDestructuring5.types
2+
+++ new.declarationEmitDestructuring5.types
3+
@@= skipped -1, +1 lines =@@
4+
5+
=== declarationEmitDestructuring5.ts ===
6+
function baz([, z, , ]) { }
7+
->baz : ([, z, ,]: [any, any, any?]) => void
8+
+>baz : ([, z, ]: [any, any, any?]) => void
9+
>z : any
10+
11+
function foo([, b, ]: [any, any]): void { }
12+
@@= skipped -8, +8 lines =@@
13+
>b : any
14+
15+
function bar([z, , , ]) { }
16+
->bar : ([z, , ,]: [any, any?, any?]) => void
17+
+>bar : ([z, , ]: [any, any?, any?]) => void
18+
>z : any
19+
20+
function bar1([z, , , ] = [1, 3, 4, 6, 7]) { }
21+
->bar1 : ([z, , ,]?: [number, number, number, number, number]) => void
22+
+>bar1 : ([z, , ]?: [number, number, number, number, number]) => void
23+
>z : number
24+
>[1, 3, 4, 6, 7] : [number, number, number, number, number]
25+
>1 : 1
26+
@@= skipped -14, +14 lines =@@
27+
>7 : 7
28+
29+
function bar2([,,z, , , ]) { }
30+
->bar2 : ([, , z, , ,]: [any, any, any, any?, any?]) => void
31+
+>bar2 : ([, , z, , ]: [any, any, any, any?, any?]) => void
32+
>z : any

0 commit comments

Comments
 (0)