Skip to content

Commit 75ef5b1

Browse files
committed
add support for satisfies-expressions
1 parent 30c6630 commit 75ef5b1

File tree

15 files changed

+385
-31
lines changed

15 files changed

+385
-31
lines changed

javascript/extractor/lib/typescript/src/ast_extractor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ function isTypedNode(node: ts.Node): boolean {
317317
case ts.SyntaxKind.ArrayLiteralExpression:
318318
case ts.SyntaxKind.ArrowFunction:
319319
case ts.SyntaxKind.AsExpression:
320+
case ts.SyntaxKind.SatisfiesExpression:
320321
case ts.SyntaxKind.AwaitExpression:
321322
case ts.SyntaxKind.BinaryExpression:
322323
case ts.SyntaxKind.CallExpression:

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.semmle.ts.ast.TupleTypeExpr;
4848
import com.semmle.ts.ast.TypeAliasDeclaration;
4949
import com.semmle.ts.ast.TypeAssertion;
50+
import com.semmle.ts.ast.SatisfiesExpr;
5051
import com.semmle.ts.ast.TypeExpression;
5152
import com.semmle.ts.ast.TypeParameter;
5253
import com.semmle.ts.ast.TypeofTypeExpr;
@@ -683,6 +684,11 @@ public R visit(TypeAssertion nd, C c) {
683684
return visit((Expression) nd, c);
684685
}
685686

687+
@Override
688+
public R visit(SatisfiesExpr nd, C c) {
689+
return visit((Expression) nd, c);
690+
}
691+
686692
@Override
687693
public R visit(MappedTypeExpr nd, C c) {
688694
return visit((TypeExpression) nd, c);

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.semmle.ts.ast.TupleTypeExpr;
4747
import com.semmle.ts.ast.TypeAliasDeclaration;
4848
import com.semmle.ts.ast.TypeAssertion;
49+
import com.semmle.ts.ast.SatisfiesExpr;
4950
import com.semmle.ts.ast.TypeParameter;
5051
import com.semmle.ts.ast.TypeofTypeExpr;
5152
import com.semmle.ts.ast.UnaryTypeExpr;
@@ -782,6 +783,14 @@ public INode visit(TypeAssertion nd, Void c) {
782783
nd.isAsExpression());
783784
}
784785

786+
@Override
787+
public INode visit(SatisfiesExpr nd, Void c) {
788+
return new SatisfiesExpr(
789+
visit(nd.getLoc()),
790+
copy(nd.getExpression()),
791+
copy(nd.getTypeAnnotation()));
792+
}
793+
785794
@Override
786795
public INode visit(MappedTypeExpr nd, Void c) {
787796
return new MappedTypeExpr(

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.semmle.ts.ast.TupleTypeExpr;
4444
import com.semmle.ts.ast.TypeAliasDeclaration;
4545
import com.semmle.ts.ast.TypeAssertion;
46+
import com.semmle.ts.ast.SatisfiesExpr;
4647
import com.semmle.ts.ast.TypeParameter;
4748
import com.semmle.ts.ast.TypeofTypeExpr;
4849
import com.semmle.ts.ast.UnaryTypeExpr;
@@ -276,6 +277,8 @@ public interface Visitor<C, R> {
276277

277278
public R visit(TypeAssertion nd, C c);
278279

280+
public R visit(SatisfiesExpr nd, C c);
281+
279282
public R visit(MappedTypeExpr nd, C c);
280283

281284
public R visit(TypeAliasDeclaration nd, C c);

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
import com.semmle.ts.ast.TupleTypeExpr;
155155
import com.semmle.ts.ast.TypeAliasDeclaration;
156156
import com.semmle.ts.ast.TypeAssertion;
157+
import com.semmle.ts.ast.SatisfiesExpr;
157158
import com.semmle.ts.ast.TypeExpression;
158159
import com.semmle.ts.ast.TypeParameter;
159160
import com.semmle.ts.ast.TypeofTypeExpr;
@@ -2111,6 +2112,14 @@ public Label visit(TypeAssertion nd, Context c) {
21112112
return key;
21122113
}
21132114

2115+
@Override
2116+
public Label visit(SatisfiesExpr nd, Context c) {
2117+
Label key = super.visit(nd, c);
2118+
visit(nd.getExpression(), key, 0);
2119+
visit(nd.getTypeAnnotation(), key, 1, IdContext.TYPE_BIND);
2120+
return key;
2121+
}
2122+
21142123
@Override
21152124
public Label visit(MappedTypeExpr nd, Context c) {
21162125
Label key = super.visit(nd, c);

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import com.semmle.ts.ast.NamespaceDeclaration;
106106
import com.semmle.ts.ast.NonNullAssertion;
107107
import com.semmle.ts.ast.TypeAssertion;
108+
import com.semmle.ts.ast.SatisfiesExpr;
108109
import com.semmle.util.collections.CollectionUtil;
109110
import com.semmle.util.data.Pair;
110111
import com.semmle.util.trap.TrapWriter;
@@ -474,6 +475,11 @@ public Node visit(TypeAssertion nd, Void c) {
474475
return nd.getExpression().accept(this, c);
475476
}
476477

478+
@Override
479+
public Node visit(SatisfiesExpr nd, Void c) {
480+
return nd.getExpression().accept(this, c);
481+
}
482+
477483
@Override
478484
public Node visit(NonNullAssertion nd, Void c) {
479485
return nd.getExpression().accept(this, c);
@@ -2028,6 +2034,13 @@ public Void visit(TypeAssertion nd, SuccessorInfo c) {
20282034
return null;
20292035
}
20302036

2037+
@Override
2038+
public Void visit(SatisfiesExpr nd, SuccessorInfo c) {
2039+
visitSequence(nd.getExpression(), nd);
2040+
writeSuccessors(nd, c.getAllSuccessors());
2041+
return null;
2042+
}
2043+
20312044
@Override
20322045
public Void visit(NonNullAssertion nd, SuccessorInfo c) {
20332046
visitSequence(nd.getExpression(), nd);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.semmle.ts.ast.DecoratorList;
3535
import com.semmle.ts.ast.ExpressionWithTypeArguments;
3636
import com.semmle.ts.ast.TypeAssertion;
37+
import com.semmle.ts.ast.SatisfiesExpr;
3738
import com.semmle.util.exception.CatastrophicError;
3839

3940
/** Map from SpiderMonkey expression types to the numeric kinds used in the DB scheme. */
@@ -283,6 +284,11 @@ public Integer visit(TypeAssertion nd, Void c) {
283284
return nd.isAsExpression() ? 102 : 101;
284285
}
285286

287+
@Override
288+
public Integer visit(SatisfiesExpr nd, Void c) {
289+
return 121;
290+
}
291+
286292
@Override
287293
public Integer visit(DecoratorList nd, Void c) {
288294
return 104;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.semmle.ts.ast;
2+
3+
import com.semmle.js.ast.Expression;
4+
import com.semmle.js.ast.SourceLocation;
5+
import com.semmle.js.ast.Visitor;
6+
7+
/** An expression of form <code>E satisfies T</code>. */
8+
public class SatisfiesExpr extends Expression {
9+
private final Expression expression;
10+
private final ITypeExpression typeAnnotation;
11+
12+
public SatisfiesExpr(
13+
SourceLocation loc,
14+
Expression expression,
15+
ITypeExpression typeAnnotation) {
16+
super("SatisfiesExpr", loc);
17+
this.expression = expression;
18+
this.typeAnnotation = typeAnnotation;
19+
}
20+
21+
public Expression getExpression() {
22+
return expression;
23+
}
24+
25+
public ITypeExpression getTypeAnnotation() {
26+
return typeAnnotation;
27+
}
28+
29+
@Override
30+
public <C, R> R accept(Visitor<C, R> v, C c) {
31+
return v.visit(this, c);
32+
}
33+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
import com.semmle.ts.ast.TupleTypeExpr;
150150
import com.semmle.ts.ast.TypeAliasDeclaration;
151151
import com.semmle.ts.ast.TypeAssertion;
152+
import com.semmle.ts.ast.SatisfiesExpr;
152153
import com.semmle.ts.ast.TypeParameter;
153154
import com.semmle.ts.ast.TypeofTypeExpr;
154155
import com.semmle.ts.ast.UnaryTypeExpr;
@@ -341,6 +342,8 @@ private Node convertNodeUntyped(JsonObject node, String defaultKind) throws Pars
341342
return convertArrowFunction(node, loc);
342343
case "AsExpression":
343344
return convertTypeAssertionExpression(node, loc);
345+
case "SatisfiesExpression":
346+
return convertSatisfiesExpression(node, loc);
344347
case "AwaitExpression":
345348
return convertAwaitExpression(node, loc);
346349
case "BigIntKeyword":
@@ -2273,6 +2276,11 @@ private Node convertTypeAssertionExpression(JsonObject node, SourceLocation loc)
22732276
return new TypeAssertion(loc, convertChild(node, "expression"), type, false);
22742277
}
22752278

2279+
private Node convertSatisfiesExpression(JsonObject node, SourceLocation loc) throws ParseError {
2280+
ITypeExpression type = convertChildAsType(node, "type");
2281+
return new SatisfiesExpr(loc, convertChild(node, "expression"), type);
2282+
}
2283+
22762284
private Node convertTypeLiteral(JsonObject obj, SourceLocation loc) throws ParseError {
22772285
return new InterfaceTypeExpr(loc, convertChildren(obj, "members"));
22782286
}

javascript/ql/lib/semmle/javascript/TypeScript.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,27 @@ class AsTypeAssertion extends TypeAssertion, @as_type_assertion { }
13751375
*/
13761376
class PrefixTypeAssertion extends TypeAssertion, @prefix_type_assertion { }
13771377

1378+
/**
1379+
* A satisfies type asserion of the form `E satisfies T` where `E` is an expression and `T` is a type.
1380+
*/
1381+
class SatisfiesExpr extends Expr, @satisfies_expr {
1382+
/** Gets the expression whose type to assert, that is, the `E` in `E as T` or `<T> E`. */
1383+
Expr getExpression() { result = this.getChildExpr(0) }
1384+
1385+
/** Gets the type to cast to, that is, the `T` in `E as T` or `<T> E`. */
1386+
TypeExpr getTypeAnnotation() { result = this.getChildTypeExpr(1) }
1387+
1388+
override ControlFlowNode getFirstControlFlowNode() {
1389+
result = this.getExpression().getFirstControlFlowNode()
1390+
}
1391+
1392+
override Expr getUnderlyingValue() { result = this.getExpression().getUnderlyingValue() }
1393+
1394+
override Expr getUnderlyingReference() { result = this.getExpression().getUnderlyingReference() }
1395+
1396+
override string getAPrimaryQlClass() { result = "SatisfiesExpr" }
1397+
}
1398+
13781399
/**
13791400
* A TypeScript expression of form `E!`, asserting that `E` is not null.
13801401
*/

0 commit comments

Comments
 (0)