Skip to content

Commit 813d147

Browse files
authored
Merge pull request #4043 from erik-krogh/ts4
JS: Add support for TypeScript 4
2 parents 93e0bd9 + f406072 commit 813d147

File tree

27 files changed

+3313
-15
lines changed

27 files changed

+3313
-15
lines changed

change-notes/1.25/analysis-javascript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
- [yargs](https://www.npmjs.com/package/yargs)
3131
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
3232

33-
* TypeScript 3.9 is now supported.
33+
* TypeScript 4.0 is now supported.
3434

3535
* TypeScript code embedded in HTML and Vue files is now extracted and analyzed.
3636

javascript/extractor/lib/typescript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "typescript-parser-wrapper",
33
"private": true,
44
"dependencies": {
5-
"typescript": "3.9.2"
5+
"typescript": "4.0.2"
66
},
77
"scripts": {
88
"build": "tsc --project tsconfig.json",

javascript/extractor/lib/typescript/yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ tsutils@^2.12.1:
225225
dependencies:
226226
tslib "^1.8.1"
227227

228-
typescript@3.9.2:
229-
version "3.9.2"
230-
resolved typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9
228+
typescript@4.0.2:
229+
version "4.0.2"
230+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2"
231231

232232
wrappy@1:
233233
version "1.0.2"

javascript/extractor/src/com/semmle/js/ast/NodeCopier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ public INode visit(ParenthesizedTypeExpr nd, Void c) {
711711

712712
@Override
713713
public INode visit(TupleTypeExpr nd, Void c) {
714-
return new TupleTypeExpr(visit(nd.getLoc()), copy(nd.getElementTypes()));
714+
return new TupleTypeExpr(visit(nd.getLoc()), copy(nd.getElementTypes()), copy(nd.getElementNames()));
715715
}
716716

717717
@Override

javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,10 @@ public Label visit(ParenthesizedTypeExpr nd, Context c) {
18301830
@Override
18311831
public Label visit(TupleTypeExpr nd, Context c) {
18321832
Label key = super.visit(nd, c);
1833+
if (nd.getElementNames() != null) {
1834+
// Element names are index -1, -2, -3...
1835+
visitAll(nd.getElementNames(), key, IdContext.typeLabel, -1, -1);
1836+
}
18331837
visitAll(nd.getElementTypes(), key, IdContext.typeBind, 0);
18341838
return key;
18351839
}

javascript/extractor/src/com/semmle/js/extractor/CFGExtractor.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,8 +1551,27 @@ public Void visit(MemberDefinition<?> nd, SuccessorInfo i) {
15511551

15521552
@Override
15531553
public Void visit(AssignmentExpression nd, SuccessorInfo i) {
1554-
visitAssign(nd, nd.getLeft(), nd.getRight());
1555-
succ(nd, i.getGuardedSuccessors(nd));
1554+
// `a &&= b` expands to `a || (a = b);`
1555+
// The CFG is a conditional assignment, so we go through the assignment `nd` last.
1556+
if ("&&=".equals(nd.getOperator()) || "||=".equals(nd.getOperator()) || "??=".equals(nd.getOperator())) {
1557+
if ("&&=".equals(nd.getOperator())) {
1558+
// from lhs to rhs on truthy. from lhs to false-branch on falsy.
1559+
visit(nd.getLeft(), First.of(nd.getRight()), i.getSuccessors(false));
1560+
} else if ("||=".equals(nd.getOperator())) {
1561+
// from lhs to true-branch on truthy. from lhs to rhs on falsy.
1562+
visit(nd.getLeft(), i.getSuccessors(true), First.of(nd.getRight()));
1563+
} else { // "??="
1564+
// the union of the above - truthyness is unknown.
1565+
visit(nd.getLeft(), union(First.of(nd.getRight()), i.getAllSuccessors()), null);
1566+
}
1567+
1568+
visit(nd.getRight(), First.of(nd), null); // from right to assignment.
1569+
1570+
succ(nd, i.getGuardedSuccessors(nd));
1571+
} else {
1572+
visitAssign(nd, nd.getLeft(), nd.getRight());
1573+
succ(nd, i.getGuardedSuccessors(nd));
1574+
}
15561575
return null;
15571576
}
15581577

javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public class ExprKinds {
7979
binOpKinds.put("**", 87);
8080
binOpKinds.put("**=", 88);
8181
binOpKinds.put("??", 107);
82+
binOpKinds.put("&&=", 116);
83+
binOpKinds.put("||=", 117);
84+
binOpKinds.put("??=", 118);
8285
}
8386

8487
private static final Map<String, Integer> unOpKinds = new LinkedHashMap<String, Integer>();

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

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

910
import com.google.gson.JsonArray;
1011
import com.google.gson.JsonElement;
@@ -586,6 +587,8 @@ private Node convertNodeUntyped(JsonObject node, String defaultKind) throws Pars
586587
return convertTryStatement(node, loc);
587588
case "TupleType":
588589
return convertTupleType(node, loc);
590+
case "NamedTupleMember":
591+
return convertNamedTupleMember(node, loc);
589592
case "TypeAliasDeclaration":
590593
return convertTypeAliasDeclaration(node, loc);
591594
case "TypeAssertionExpression":
@@ -850,6 +853,9 @@ private Node convertBinaryExpression(JsonObject node, SourceLocation loc) throws
850853
case ">>=":
851854
case "<<=":
852855
case ">>>=":
856+
case "??=":
857+
case "&&=":
858+
case "||=":
853859
return new AssignmentExpression(loc, operator, convertLValue(left), right);
854860

855861
default:
@@ -2178,7 +2184,22 @@ private Node convertTryStatement(JsonObject node, SourceLocation loc) throws Par
21782184
}
21792185

21802186
private Node convertTupleType(JsonObject node, SourceLocation loc) throws ParseError {
2181-
return new TupleTypeExpr(loc, convertChildrenAsTypes(node, "elementTypes"));
2187+
List<Identifier> names = new ArrayList<>();
2188+
2189+
for (JsonElement element : node.get("elements").getAsJsonArray()) {
2190+
Identifier id = null;
2191+
if (getKind(element).equals("NamedTupleMember")) {
2192+
id = (Identifier)convertNode(element.getAsJsonObject().get("name").getAsJsonObject());
2193+
}
2194+
names.add(id);
2195+
}
2196+
2197+
return new TupleTypeExpr(loc, convertChildrenAsTypes(node, "elements"), names);
2198+
}
2199+
2200+
// This method just does a trivial forward to the type. The names have already been extracted in `convertTupleType`.
2201+
private Node convertNamedTupleMember(JsonObject node, SourceLocation loc) throws ParseError {
2202+
return convertChild(node, "type");
21822203
}
21832204

21842205
private Node convertTypeAliasDeclaration(JsonObject node, SourceLocation loc) throws ParseError {

javascript/extractor/src/com/semmle/ts/ast/TupleTypeExpr.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
package com.semmle.ts.ast;
22

3+
import com.semmle.js.ast.Identifier;
34
import com.semmle.js.ast.SourceLocation;
45
import com.semmle.js.ast.Visitor;
56
import java.util.List;
67

78
/** A tuple type, such as <tt>[number, string]</tt>. */
89
public class TupleTypeExpr extends TypeExpression {
910
private final List<ITypeExpression> elementTypes;
11+
private final List<Identifier> elementNames;
1012

11-
public TupleTypeExpr(SourceLocation loc, List<ITypeExpression> elementTypes) {
13+
public TupleTypeExpr(SourceLocation loc, List<ITypeExpression> elementTypes, List<Identifier> elementNames) {
1214
super("TupleTypeExpr", loc);
1315
this.elementTypes = elementTypes;
16+
this.elementNames = elementNames;
1417
}
1518

1619
public List<ITypeExpression> getElementTypes() {
1720
return elementTypes;
1821
}
1922

23+
public List<Identifier> getElementNames() {
24+
return elementNames;
25+
}
26+
2027
@Override
2128
public <C, R> R accept(Visitor<C, R> v, C c) {
2229
return v.visit(this, c);

javascript/ql/src/semmle/javascript/Expr.qll

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,8 @@ class AssignExpr extends @assignexpr, Assignment {
18511851
private class TCompoundAssignExpr =
18521852
@assignaddexpr or @assignsubexpr or @assignmulexpr or @assigndivexpr or @assignmodexpr or
18531853
@assignexpexpr or @assignlshiftexpr or @assignrshiftexpr or @assignurshiftexpr or
1854-
@assignorexpr or @assignxorexpr or @assignandexpr;
1854+
@assignorexpr or @assignxorexpr or @assignandexpr or @assignlogandexpr or @assignlogorexpr or
1855+
@assignnullishcoalescingexpr;
18551856

18561857
/**
18571858
* A compound assign expression.
@@ -1997,6 +1998,39 @@ class AssignXOrExpr extends @assignxorexpr, CompoundAssignExpr { }
19971998
*/
19981999
class AssignAndExpr extends @assignandexpr, CompoundAssignExpr { }
19992000

2001+
/**
2002+
* A logical-'or'-assign expression.
2003+
*
2004+
* Example:
2005+
*
2006+
* ```
2007+
* x ||= y
2008+
* ```
2009+
*/
2010+
class AssignLogOrExpr extends @assignlogandexpr, CompoundAssignExpr { }
2011+
2012+
/**
2013+
* A logical-'and'-assign expression.
2014+
*
2015+
* Example:
2016+
*
2017+
* ```
2018+
* x &&= y
2019+
* ```
2020+
*/
2021+
class AssignLogAndExpr extends @assignlogorexpr, CompoundAssignExpr { }
2022+
2023+
/**
2024+
* A 'nullish-coalescing'-assign expression.
2025+
*
2026+
* Example:
2027+
*
2028+
* ```
2029+
* x ??= y
2030+
* ```
2031+
*/
2032+
class AssignNullishCoalescingExpr extends @assignnullishcoalescingexpr, CompoundAssignExpr { }
2033+
20002034
/**
20012035
* An update expression, that is, an increment or decrement expression.
20022036
*

0 commit comments

Comments
 (0)