Skip to content

Commit 578ce1e

Browse files
authored
Merge pull request github#5683 from asgerf/js/typescript-template-literal-type-crash
Approved by erik-krogh
2 parents fa36ba9 + f8570bb commit 578ce1e

File tree

7 files changed

+273
-33
lines changed

7 files changed

+273
-33
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
lgtm,codescanning
2+
* Fixed a bug that could cause extraction to fail when extracting a TypeScript
3+
code base containing a template literal type without substitutions.

javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.util.List;
66
import java.util.regex.Matcher;
77
import java.util.regex.Pattern;
8-
import java.util.stream.Collectors;
98

109
import com.google.gson.JsonArray;
1110
import com.google.gson.JsonElement;
@@ -1001,10 +1000,10 @@ private Node convertConditionalExpression(JsonObject node, SourceLocation loc) t
10011000
private Node convertConditionalType(JsonObject node, SourceLocation loc) throws ParseError {
10021001
return new ConditionalTypeExpr(
10031002
loc,
1004-
convertChild(node, "checkType"),
1005-
convertChild(node, "extendsType"),
1006-
convertChild(node, "trueType"),
1007-
convertChild(node, "falseType"));
1003+
convertChildAsType(node, "checkType"),
1004+
convertChildAsType(node, "extendsType"),
1005+
convertChildAsType(node, "trueType"),
1006+
convertChildAsType(node, "falseType"));
10081007
}
10091008

10101009
private SourceLocation getSourceRange(Position from, Position to) {
@@ -1613,6 +1612,10 @@ private Node convertLiteralType(JsonObject node, SourceLocation loc) throws Pars
16131612
literal = new Literal(loc, arg.getTokenType(), "-" + arg.getValue());
16141613
}
16151614
}
1615+
if (literal instanceof TemplateLiteral) {
1616+
// A LiteralType containing a NoSubstitutionTemplateLiteral must produce a TemplateLiteralTypeExpr
1617+
return new TemplateLiteralTypeExpr(literal.getLoc(), new ArrayList<>(), ((TemplateLiteral)literal).getQuasis());
1618+
}
16161619
return literal;
16171620
}
16181621

@@ -1842,7 +1845,7 @@ private Node convertOmittedExpression() {
18421845
}
18431846

18441847
private Node convertOptionalType(JsonObject node, SourceLocation loc) throws ParseError {
1845-
return new OptionalTypeExpr(loc, convertChild(node, "type"));
1848+
return new OptionalTypeExpr(loc, convertChildAsType(node, "type"));
18461849
}
18471850

18481851
private ITypeExpression asType(Node node) {

javascript/extractor/tests/ts/output/trap/importNonStrings.ts.trap

Lines changed: 242 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,249 @@ hasLocation(#10000,#10002)
99
#20000=@"global_scope"
1010
scopes(#20000,0)
1111
#20001=@"script;{#10000},1,1"
12-
toplevels(#20001,0)
13-
#20002=@"loc,{#10000},1,1,1,1"
14-
locations_default(#20002,#10000,1,1,1,1)
15-
hasLocation(#20001,#20002)
16-
#20003=*
17-
js_parse_errors(#20003,#20001,"Error: Unsupported syntax in import","type Y = import(`Foo`);
18-
")
19-
#20004=@"loc,{#10000},2,10,2,10"
20-
locations_default(#20004,#10000,2,10,2,10)
21-
hasLocation(#20003,#20004)
22-
#20005=*
23-
lines(#20005,#20001,"type X = import(3);","
12+
#20002=*
13+
lines(#20002,#20001,"type X = import(3);","
2414
")
25-
#20006=@"loc,{#10000},1,1,1,19"
26-
locations_default(#20006,#10000,1,1,1,19)
27-
hasLocation(#20005,#20006)
28-
#20007=*
29-
lines(#20007,#20001,"type Y = import(`Foo`);","
15+
#20003=@"loc,{#10000},1,1,1,19"
16+
locations_default(#20003,#10000,1,1,1,19)
17+
hasLocation(#20002,#20003)
18+
#20004=*
19+
lines(#20004,#20001,"type Y = import(`Foo`);","
3020
")
31-
#20008=@"loc,{#10000},2,1,2,23"
32-
locations_default(#20008,#10000,2,1,2,23)
33-
hasLocation(#20007,#20008)
34-
#20009=*
35-
lines(#20009,#20001,"type Z = import(Y);","
21+
#20005=@"loc,{#10000},2,1,2,23"
22+
locations_default(#20005,#10000,2,1,2,23)
23+
hasLocation(#20004,#20005)
24+
#20006=*
25+
lines(#20006,#20001,"type Z = import(Y);","
3626
")
37-
#20010=@"loc,{#10000},3,1,3,19"
38-
locations_default(#20010,#10000,3,1,3,19)
39-
hasLocation(#20009,#20010)
40-
numlines(#20001,3,0,0)
41-
numlines(#10000,3,0,0)
27+
#20007=@"loc,{#10000},3,1,3,19"
28+
locations_default(#20007,#10000,3,1,3,19)
29+
hasLocation(#20006,#20007)
30+
numlines(#20001,3,3,0)
31+
#20008=*
32+
tokeninfo(#20008,7,#20001,0,"type")
33+
#20009=@"loc,{#10000},1,1,1,4"
34+
locations_default(#20009,#10000,1,1,1,4)
35+
hasLocation(#20008,#20009)
36+
#20010=*
37+
tokeninfo(#20010,6,#20001,1,"X")
38+
#20011=@"loc,{#10000},1,6,1,6"
39+
locations_default(#20011,#10000,1,6,1,6)
40+
hasLocation(#20010,#20011)
41+
#20012=*
42+
tokeninfo(#20012,8,#20001,2,"=")
43+
#20013=@"loc,{#10000},1,8,1,8"
44+
locations_default(#20013,#10000,1,8,1,8)
45+
hasLocation(#20012,#20013)
46+
#20014=*
47+
tokeninfo(#20014,7,#20001,3,"import")
48+
#20015=@"loc,{#10000},1,10,1,15"
49+
locations_default(#20015,#10000,1,10,1,15)
50+
hasLocation(#20014,#20015)
51+
#20016=*
52+
tokeninfo(#20016,8,#20001,4,"(")
53+
#20017=@"loc,{#10000},1,16,1,16"
54+
locations_default(#20017,#10000,1,16,1,16)
55+
hasLocation(#20016,#20017)
56+
#20018=*
57+
tokeninfo(#20018,3,#20001,5,"3")
58+
#20019=@"loc,{#10000},1,17,1,17"
59+
locations_default(#20019,#10000,1,17,1,17)
60+
hasLocation(#20018,#20019)
61+
#20020=*
62+
tokeninfo(#20020,8,#20001,6,")")
63+
#20021=@"loc,{#10000},1,18,1,18"
64+
locations_default(#20021,#10000,1,18,1,18)
65+
hasLocation(#20020,#20021)
66+
#20022=*
67+
tokeninfo(#20022,8,#20001,7,";")
68+
#20023=@"loc,{#10000},1,19,1,19"
69+
locations_default(#20023,#10000,1,19,1,19)
70+
hasLocation(#20022,#20023)
71+
#20024=*
72+
tokeninfo(#20024,7,#20001,8,"type")
73+
#20025=@"loc,{#10000},2,1,2,4"
74+
locations_default(#20025,#10000,2,1,2,4)
75+
hasLocation(#20024,#20025)
76+
#20026=*
77+
tokeninfo(#20026,6,#20001,9,"Y")
78+
#20027=@"loc,{#10000},2,6,2,6"
79+
locations_default(#20027,#10000,2,6,2,6)
80+
hasLocation(#20026,#20027)
81+
#20028=*
82+
tokeninfo(#20028,8,#20001,10,"=")
83+
#20029=@"loc,{#10000},2,8,2,8"
84+
locations_default(#20029,#10000,2,8,2,8)
85+
hasLocation(#20028,#20029)
86+
#20030=*
87+
tokeninfo(#20030,7,#20001,11,"import")
88+
#20031=@"loc,{#10000},2,10,2,15"
89+
locations_default(#20031,#10000,2,10,2,15)
90+
hasLocation(#20030,#20031)
91+
#20032=*
92+
tokeninfo(#20032,8,#20001,12,"(")
93+
#20033=@"loc,{#10000},2,16,2,16"
94+
locations_default(#20033,#10000,2,16,2,16)
95+
hasLocation(#20032,#20033)
96+
#20034=*
97+
tokeninfo(#20034,4,#20001,13,"`Foo`")
98+
#20035=@"loc,{#10000},2,17,2,21"
99+
locations_default(#20035,#10000,2,17,2,21)
100+
hasLocation(#20034,#20035)
101+
#20036=*
102+
tokeninfo(#20036,8,#20001,14,")")
103+
#20037=@"loc,{#10000},2,22,2,22"
104+
locations_default(#20037,#10000,2,22,2,22)
105+
hasLocation(#20036,#20037)
106+
#20038=*
107+
tokeninfo(#20038,8,#20001,15,";")
108+
#20039=@"loc,{#10000},2,23,2,23"
109+
locations_default(#20039,#10000,2,23,2,23)
110+
hasLocation(#20038,#20039)
111+
#20040=*
112+
tokeninfo(#20040,7,#20001,16,"type")
113+
#20041=@"loc,{#10000},3,1,3,4"
114+
locations_default(#20041,#10000,3,1,3,4)
115+
hasLocation(#20040,#20041)
116+
#20042=*
117+
tokeninfo(#20042,6,#20001,17,"Z")
118+
#20043=@"loc,{#10000},3,6,3,6"
119+
locations_default(#20043,#10000,3,6,3,6)
120+
hasLocation(#20042,#20043)
121+
#20044=*
122+
tokeninfo(#20044,8,#20001,18,"=")
123+
#20045=@"loc,{#10000},3,8,3,8"
124+
locations_default(#20045,#10000,3,8,3,8)
125+
hasLocation(#20044,#20045)
126+
#20046=*
127+
tokeninfo(#20046,7,#20001,19,"import")
128+
#20047=@"loc,{#10000},3,10,3,15"
129+
locations_default(#20047,#10000,3,10,3,15)
130+
hasLocation(#20046,#20047)
131+
#20048=*
132+
tokeninfo(#20048,8,#20001,20,"(")
133+
#20049=@"loc,{#10000},3,16,3,16"
134+
locations_default(#20049,#10000,3,16,3,16)
135+
hasLocation(#20048,#20049)
136+
#20050=*
137+
tokeninfo(#20050,6,#20001,21,"Y")
138+
#20051=@"loc,{#10000},3,17,3,17"
139+
locations_default(#20051,#10000,3,17,3,17)
140+
hasLocation(#20050,#20051)
141+
#20052=*
142+
tokeninfo(#20052,8,#20001,22,")")
143+
#20053=@"loc,{#10000},3,18,3,18"
144+
locations_default(#20053,#10000,3,18,3,18)
145+
hasLocation(#20052,#20053)
146+
#20054=*
147+
tokeninfo(#20054,8,#20001,23,";")
148+
#20055=@"loc,{#10000},3,19,3,19"
149+
locations_default(#20055,#10000,3,19,3,19)
150+
hasLocation(#20054,#20055)
151+
#20056=*
152+
tokeninfo(#20056,0,#20001,24,"")
153+
#20057=@"loc,{#10000},4,1,4,0"
154+
locations_default(#20057,#10000,4,1,4,0)
155+
hasLocation(#20056,#20057)
156+
toplevels(#20001,0)
157+
#20058=@"loc,{#10000},1,1,4,0"
158+
locations_default(#20058,#10000,1,1,4,0)
159+
hasLocation(#20001,#20058)
160+
#20059=@"local_type_name;{X};{#20000}"
161+
local_type_names(#20059,"X",#20000)
162+
#20060=@"local_type_name;{Y};{#20000}"
163+
local_type_names(#20060,"Y",#20000)
164+
#20061=@"local_type_name;{Z};{#20000}"
165+
local_type_names(#20061,"Z",#20000)
166+
#20062=*
167+
stmts(#20062,35,#20001,0,"type X = import(3);")
168+
hasLocation(#20062,#20003)
169+
stmt_containers(#20062,#20001)
170+
#20063=*
171+
typeexprs(#20063,1,#20062,0,"X")
172+
hasLocation(#20063,#20011)
173+
enclosing_stmt(#20063,#20062)
174+
expr_containers(#20063,#20001)
175+
literals("X","X",#20063)
176+
typedecl(#20063,#20059)
177+
#20064=*
178+
typeexprs(#20064,30,#20062,1,"import(3)")
179+
#20065=@"loc,{#10000},1,10,1,18"
180+
locations_default(#20065,#10000,1,10,1,18)
181+
hasLocation(#20064,#20065)
182+
enclosing_stmt(#20064,#20062)
183+
expr_containers(#20064,#20001)
184+
#20066=*
185+
typeexprs(#20066,4,#20064,0,"3")
186+
hasLocation(#20066,#20019)
187+
enclosing_stmt(#20066,#20062)
188+
expr_containers(#20066,#20001)
189+
literals("3","3",#20066)
190+
#20067=*
191+
stmts(#20067,35,#20001,1,"type Y ... `Foo`);")
192+
hasLocation(#20067,#20005)
193+
stmt_containers(#20067,#20001)
194+
#20068=*
195+
typeexprs(#20068,1,#20067,0,"Y")
196+
hasLocation(#20068,#20027)
197+
enclosing_stmt(#20068,#20067)
198+
expr_containers(#20068,#20001)
199+
literals("Y","Y",#20068)
200+
typedecl(#20068,#20060)
201+
#20069=*
202+
typeexprs(#20069,30,#20067,1,"import(`Foo`)")
203+
#20070=@"loc,{#10000},2,10,2,22"
204+
locations_default(#20070,#10000,2,10,2,22)
205+
hasLocation(#20069,#20070)
206+
enclosing_stmt(#20069,#20067)
207+
expr_containers(#20069,#20001)
208+
#20071=*
209+
typeexprs(#20071,37,#20069,0,"`Foo`")
210+
hasLocation(#20071,#20035)
211+
enclosing_stmt(#20071,#20067)
212+
expr_containers(#20071,#20001)
213+
#20072=*
214+
typeexprs(#20072,3,#20071,0,"`Foo`")
215+
hasLocation(#20072,#20035)
216+
enclosing_stmt(#20072,#20067)
217+
expr_containers(#20072,#20001)
218+
literals("Foo","Foo",#20072)
219+
#20073=*
220+
stmts(#20073,35,#20001,2,"type Z = import(Y);")
221+
hasLocation(#20073,#20007)
222+
stmt_containers(#20073,#20001)
223+
#20074=*
224+
typeexprs(#20074,1,#20073,0,"Z")
225+
hasLocation(#20074,#20043)
226+
enclosing_stmt(#20074,#20073)
227+
expr_containers(#20074,#20001)
228+
literals("Z","Z",#20074)
229+
typedecl(#20074,#20061)
230+
#20075=*
231+
typeexprs(#20075,30,#20073,1,"import(Y)")
232+
#20076=@"loc,{#10000},3,10,3,18"
233+
locations_default(#20076,#10000,3,10,3,18)
234+
hasLocation(#20075,#20076)
235+
enclosing_stmt(#20075,#20073)
236+
expr_containers(#20075,#20001)
237+
#20077=*
238+
typeexprs(#20077,0,#20075,0,"Y")
239+
hasLocation(#20077,#20051)
240+
enclosing_stmt(#20077,#20073)
241+
expr_containers(#20077,#20001)
242+
literals("Y","Y",#20077)
243+
typebind(#20077,#20060)
244+
#20078=*
245+
entry_cfg_node(#20078,#20001)
246+
#20079=@"loc,{#10000},1,1,1,0"
247+
locations_default(#20079,#10000,1,1,1,0)
248+
hasLocation(#20078,#20079)
249+
#20080=*
250+
exit_cfg_node(#20080,#20001)
251+
hasLocation(#20080,#20057)
252+
successor(#20073,#20080)
253+
successor(#20067,#20073)
254+
successor(#20062,#20067)
255+
successor(#20078,#20062)
256+
numlines(#10000,3,3,0)
42257
filetype(#10000,"typescript")
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
| tst.ts:2:11:2:21 | `foo ${T1}` |
2+
| tst.ts:4:45:4:49 | `foo` |
3+
| tst.ts:4:53:4:57 | `bar` |
4+
| tst.ts:5:46:5:50 | `foo` |
5+
| tst.ts:5:54:5:63 | `bar ${K}` |
6+
| tst.ts:7:15:7:19 | `foo` |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import javascript
2+
3+
query TemplateLiteralTypeExpr literalType() { any() }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"include": ["."]
3+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
type T1 = 'foo' | 'bar';
2+
type T2 = `foo ${T1}`;
3+
4+
type FooToBar<K extends string> = K extends `foo` ? `bar` : K;
5+
type FooToBar2<K extends string> = K extends `foo` ? `bar ${K}` : K;
6+
7+
type Tuple = [`foo`?];

0 commit comments

Comments
 (0)