Skip to content

Commit fc8c1e1

Browse files
authored
Merge pull request #2177 from asger-semmle/nodejs-detector-class-expression
Approved by max-schaefer
2 parents 30483db + 45667cc commit fc8c1e1

File tree

3 files changed

+123
-4
lines changed

3 files changed

+123
-4
lines changed

javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -942,9 +942,7 @@ private Node convertClass(JsonObject node, String kind, SourceLocation loc) thro
942942
SourceLocation bodyLoc = new SourceLocation(loc.getSource(), loc.getStart(), loc.getEnd());
943943
advance(bodyLoc, skip);
944944
ClassBody body = new ClassBody(bodyLoc, convertChildren(node, "members"));
945-
if ("ClassExpression".equals(kind) || id == null) {
946-
// Note that `export default class {}` is represented as a ClassDeclaration
947-
// in TypeScript but we treat this as a ClassExpression.
945+
if ("ClassExpression".equals(kind)) {
948946
ClassExpression classExpr =
949947
new ClassExpression(loc, id, typeParameters, superClass, superInterfaces, body);
950948
attachSymbolInformation(classExpr.getClassDef(), node);
@@ -967,7 +965,13 @@ private Node convertClass(JsonObject node, String kind, SourceLocation loc) thro
967965
classDecl.addDecorators(convertChildren(node, "decorators"));
968966
advanceUntilAfter(loc, classDecl.getDecorators());
969967
}
970-
return fixExports(loc, classDecl);
968+
Node exportedDecl = fixExports(loc, classDecl);
969+
// Convert default-exported anonymous class declarations to class expressions.
970+
if (exportedDecl instanceof ExportDefaultDeclaration && !classDecl.getClassDef().hasId()) {
971+
return new ExportDefaultDeclaration(
972+
exportedDecl.getLoc(), new ClassExpression(classDecl.getLoc(), classDecl.getClassDef()));
973+
}
974+
return exportedDecl;
971975
}
972976

973977
private Node convertCommaListExpression(JsonObject node, SourceLocation loc) throws ParseError {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export class {}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#10000=@"/exportclass.ts;sourcefile"
2+
files(#10000,"/exportclass.ts","exportclass","ts",0)
3+
#10001=@"/;folder"
4+
folders(#10001,"/","")
5+
containerparent(#10001,#10000)
6+
#10002=@"loc,{#10000},0,0,0,0"
7+
locations_default(#10002,#10000,0,0,0,0)
8+
hasLocation(#10000,#10002)
9+
#20000=@"global_scope"
10+
scopes(#20000,0)
11+
#20001=@"script;{#10000},1,1"
12+
#20002=*
13+
lines(#20002,#20001,"export class {}","
14+
")
15+
#20003=@"loc,{#10000},1,1,1,15"
16+
locations_default(#20003,#10000,1,1,1,15)
17+
hasLocation(#20002,#20003)
18+
numlines(#20001,1,1,0)
19+
#20004=*
20+
tokeninfo(#20004,7,#20001,0,"export")
21+
#20005=@"loc,{#10000},1,1,1,6"
22+
locations_default(#20005,#10000,1,1,1,6)
23+
hasLocation(#20004,#20005)
24+
#20006=*
25+
tokeninfo(#20006,7,#20001,1,"class")
26+
#20007=@"loc,{#10000},1,8,1,12"
27+
locations_default(#20007,#10000,1,8,1,12)
28+
hasLocation(#20006,#20007)
29+
#20008=*
30+
tokeninfo(#20008,8,#20001,2,"{")
31+
#20009=@"loc,{#10000},1,14,1,14"
32+
locations_default(#20009,#10000,1,14,1,14)
33+
hasLocation(#20008,#20009)
34+
#20010=*
35+
tokeninfo(#20010,8,#20001,3,"}")
36+
#20011=@"loc,{#10000},1,15,1,15"
37+
locations_default(#20011,#10000,1,15,1,15)
38+
hasLocation(#20010,#20011)
39+
#20012=*
40+
tokeninfo(#20012,0,#20001,4,"")
41+
#20013=@"loc,{#10000},2,1,2,0"
42+
locations_default(#20013,#10000,2,1,2,0)
43+
hasLocation(#20012,#20013)
44+
toplevels(#20001,0)
45+
#20014=@"loc,{#10000},1,1,2,0"
46+
locations_default(#20014,#10000,1,1,2,0)
47+
hasLocation(#20001,#20014)
48+
#20015=@"module;{#10000},1,1"
49+
scopes(#20015,3)
50+
scopenodes(#20001,#20015)
51+
scopenesting(#20015,#20000)
52+
isModule(#20001)
53+
isES2015Module(#20001)
54+
#20016=*
55+
stmts(#20016,30,#20001,0,"export class {}")
56+
hasLocation(#20016,#20003)
57+
stmtContainers(#20016,#20001)
58+
#20017=*
59+
stmts(#20017,26,#20016,-1,"class {}")
60+
#20018=@"loc,{#10000},1,8,1,15"
61+
locations_default(#20018,#10000,1,8,1,15)
62+
hasLocation(#20017,#20018)
63+
stmtContainers(#20017,#20001)
64+
#20019=*
65+
properties(#20019,#20017,2,0,"constructor() {}")
66+
#20020=@"loc,{#10000},1,6,1,5"
67+
locations_default(#20020,#10000,1,6,1,5)
68+
hasLocation(#20019,#20020)
69+
#20021=*
70+
exprs(#20021,0,#20019,0,"constructor")
71+
hasLocation(#20021,#20020)
72+
enclosingStmt(#20021,#20017)
73+
exprContainers(#20021,#20001)
74+
literals("constructor","constructor",#20021)
75+
#20022=*
76+
exprs(#20022,9,#20019,1,"() {}")
77+
hasLocation(#20022,#20020)
78+
enclosingStmt(#20022,#20017)
79+
exprContainers(#20022,#20001)
80+
#20023=*
81+
scopes(#20023,1)
82+
scopenodes(#20022,#20023)
83+
scopenesting(#20023,#20015)
84+
#20024=@"var;{arguments};{#20023}"
85+
variables(#20024,"arguments",#20023)
86+
isArgumentsObject(#20024)
87+
#20025=*
88+
stmts(#20025,1,#20022,-2,"{}")
89+
hasLocation(#20025,#20020)
90+
stmtContainers(#20025,#20022)
91+
isMethod(#20019)
92+
#20026=*
93+
entry_cfg_node(#20026,#20001)
94+
#20027=@"loc,{#10000},1,1,1,0"
95+
locations_default(#20027,#10000,1,1,1,0)
96+
hasLocation(#20026,#20027)
97+
#20028=*
98+
exit_cfg_node(#20028,#20001)
99+
hasLocation(#20028,#20013)
100+
successor(#20022,#20019)
101+
#20029=*
102+
entry_cfg_node(#20029,#20022)
103+
hasLocation(#20029,#20020)
104+
#20030=*
105+
exit_cfg_node(#20030,#20022)
106+
hasLocation(#20030,#20020)
107+
successor(#20025,#20030)
108+
successor(#20029,#20025)
109+
successor(#20021,#20022)
110+
successor(#20019,#20017)
111+
successor(#20017,#20028)
112+
successor(#20026,#20016)
113+
numlines(#10000,1,1,0)
114+
filetype(#10000,"typescript")

0 commit comments

Comments
 (0)