mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
TS: Support assertion types
This commit is contained in:
@@ -719,7 +719,10 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
@Override
|
||||
public INode visit(PredicateTypeExpr nd, Void c) {
|
||||
return new PredicateTypeExpr(
|
||||
visit(nd.getLoc()), copy(nd.getExpression()), copy(nd.getTypeExpr()));
|
||||
visit(nd.getLoc()),
|
||||
copy(nd.getExpression()),
|
||||
copy(nd.getTypeExpr()),
|
||||
nd.hasAssertsKeyword());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1711,6 +1711,9 @@ public class ASTExtractor {
|
||||
Label key = super.visit(nd, c);
|
||||
visit(nd.getExpression(), key, 0, IdContext.varInTypeBind);
|
||||
visit(nd.getTypeExpr(), key, 1, IdContext.typeBind);
|
||||
if (nd.hasAssertsKeyword()) {
|
||||
trapwriter.addTuple("hasAssertsKeyword", key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
@@ -2200,7 +2200,10 @@ public class TypeScriptASTConverter {
|
||||
|
||||
private Node convertTypePredicate(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
return new PredicateTypeExpr(
|
||||
loc, convertChildAsType(node, "parameterName"), convertChildAsType(node, "type"));
|
||||
loc,
|
||||
convertChildAsType(node, "parameterName"),
|
||||
convertChildAsType(node, "type"),
|
||||
node.has("assertsModifier"));
|
||||
}
|
||||
|
||||
private Node convertTypeReference(JsonObject node, SourceLocation loc) throws ParseError {
|
||||
|
||||
@@ -10,11 +10,17 @@ import com.semmle.js.ast.Visitor;
|
||||
public class PredicateTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression expression;
|
||||
private final ITypeExpression type;
|
||||
private final boolean hasAssertsKeyword;
|
||||
|
||||
public PredicateTypeExpr(SourceLocation loc, ITypeExpression expression, ITypeExpression type) {
|
||||
public PredicateTypeExpr(
|
||||
SourceLocation loc,
|
||||
ITypeExpression expression,
|
||||
ITypeExpression type,
|
||||
boolean hasAssertsKeyword) {
|
||||
super("PredicateTypeExpr", loc);
|
||||
this.expression = expression;
|
||||
this.type = type;
|
||||
this.hasAssertsKeyword = hasAssertsKeyword;
|
||||
}
|
||||
|
||||
/** Returns the <tt>E</tt> in <tt>E is T</tt>. */
|
||||
@@ -27,6 +33,10 @@ public class PredicateTypeExpr extends TypeExpression {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean hasAssertsKeyword() {
|
||||
return hasAssertsKeyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
|
||||
@@ -914,20 +914,49 @@ class TypeofTypeExpr extends @typeoftypeexpr, TypeExpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A type of form `E is T` where `E` is a parameter name or `this`, and `T` is a type.
|
||||
* A function return type that refines the type of one of its parameters or `this`.
|
||||
*
|
||||
* This can only occur as the return type of a function type.
|
||||
* Examples:
|
||||
* ```js
|
||||
* function f(x): x is string {}
|
||||
* function f(x): asserts x is string {}
|
||||
* function f(x): asserts x {}
|
||||
* ```
|
||||
*/
|
||||
class IsTypeExpr extends @predicatetypeexpr, TypeExpr {
|
||||
class PredicateTypeExpr extends @predicatetypeexpr, TypeExpr {
|
||||
/**
|
||||
* Gets the parameter name or `this` token `E` in `E is T`.
|
||||
*/
|
||||
VarTypeAccess getParameterName() { result = this.getChildTypeExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the type `T` in `E is T`.
|
||||
* Gets the type `T` in `E is T` or `asserts E is T`.
|
||||
*
|
||||
* Has no results for types of form `asserts E`.
|
||||
*/
|
||||
TypeExpr getPredicateType() { result = this.getChildTypeExpr(1) }
|
||||
|
||||
/**
|
||||
* Holds if this is a type of form `asserts E is T` or `asserts E`.
|
||||
*/
|
||||
predicate hasAssertsKeyword() {
|
||||
hasAssertsKeyword(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function return type of form `x is T` or `asserts x is T`.
|
||||
*
|
||||
* Examples:
|
||||
* ```js
|
||||
* function f(x): x is string {}
|
||||
* function f(x): asserts x is string {}
|
||||
* ```
|
||||
*/
|
||||
class IsTypeExpr extends PredicateTypeExpr {
|
||||
IsTypeExpr() {
|
||||
exists(getPredicateType())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -966,15 +995,16 @@ class ReadonlyTypeExpr extends @readonlytypeexpr, TypeExpr {
|
||||
*
|
||||
* This can occur as
|
||||
* - part of the operand to a `typeof` type, or
|
||||
* - as the first operand to an `is` type.
|
||||
* - as the first operand to a predicate type
|
||||
*
|
||||
* For example, it may occur as the `E` in these examples:
|
||||
* ```
|
||||
* var x : typeof E
|
||||
* function f(...) : E is T {}
|
||||
* function f(...) : asserts E {}
|
||||
* ```
|
||||
*
|
||||
* In the latter case, this may also refer to the pseudo-variable `this`.
|
||||
* In the latter two cases, this may also refer to the pseudo-variable `this`.
|
||||
*/
|
||||
class VarTypeAccess extends @vartypeaccess, TypeExpr { }
|
||||
|
||||
|
||||
@@ -637,6 +637,8 @@ case @type.kind of
|
||||
@unionorintersectiontype = @uniontype | @intersectiontype;
|
||||
@typevariabletype = @canonicaltypevariabletype | @lexicaltypevariabletype;
|
||||
|
||||
hasAssertsKeyword(int node: @predicatetypeexpr ref);
|
||||
|
||||
@typed_ast_node = @expr | @typeexpr | @function;
|
||||
ast_node_type(
|
||||
unique int node: @typed_ast_node ref,
|
||||
|
||||
@@ -7918,6 +7918,17 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>hasAssertsKeyword</name>
|
||||
<cardinality>66</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>stmt</k>
|
||||
<v>66</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isAbstractMember</name>
|
||||
<cardinality>66</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_IsTypeExpr(IsTypeExpr type, VarTypeAccess res0, TypeExpr res1) {
|
||||
res0 = type.getParameterName() and res1 = type.getPredicateType()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_IsTypeExpr(IsTypeExpr type, VarTypeAccess res0, TypeExpr res1) {
|
||||
res0 = type.getParameterName() and res1 = type.getPredicateType()
|
||||
}
|
||||
|
||||
query predicate test_PredicateTypeExpr(PredicateTypeExpr type, VarTypeAccess res0) {
|
||||
res0 = type.getParameterName()
|
||||
}
|
||||
|
||||
query predicate test_hasAssertsKeyword(PredicateTypeExpr type) {
|
||||
type.hasAssertsKeyword()
|
||||
}
|
||||
@@ -105,6 +105,9 @@ test_VariableTypes
|
||||
| tst.ts:135:5:135:24 | tupleWithRestElement | tupleWithRestElement | tst.ts:135:27:135:47 | [number ... ring[]] |
|
||||
| tst.ts:136:5:136:36 | tupleWi ... lements | tupleWithOptionalAndRestElements | tst.ts:136:39:136:68 | [number ... mber[]] |
|
||||
| tst.ts:137:5:137:15 | unknownType | unknownType | tst.ts:137:18:137:24 | unknown |
|
||||
| tst.ts:142:17:142:25 | condition | condition | tst.ts:142:28:142:30 | any |
|
||||
| tst.ts:142:33:142:35 | msg | msg | tst.ts:142:39:142:44 | string |
|
||||
| tst.ts:148:25:148:27 | val | val | tst.ts:148:30:148:32 | any |
|
||||
test_QualifiedTypeAccess
|
||||
| tst.ts:63:19:63:21 | N.I | tst.ts:63:19:63:19 | N | tst.ts:63:21:63:21 | I |
|
||||
| tst.ts:64:20:64:24 | N.M.I | tst.ts:64:20:64:22 | N.M | tst.ts:64:24:64:24 | I |
|
||||
@@ -148,6 +151,17 @@ test_IsTypeExpr
|
||||
| tst.ts:76:21:76:32 | that is Leaf | tst.ts:76:21:76:24 | that | tst.ts:76:29:76:32 | Leaf |
|
||||
| tst.ts:80:36:80:55 | x is Generic<Leaf[]> | tst.ts:80:36:80:36 | x | tst.ts:80:41:80:55 | Generic<Leaf[]> |
|
||||
| tst.ts:81:38:81:50 | x is typeof x | tst.ts:81:38:81:38 | x | tst.ts:81:43:81:50 | typeof x |
|
||||
| tst.ts:148:36:148:56 | asserts ... string | tst.ts:148:44:148:46 | val | tst.ts:148:51:148:56 | string |
|
||||
test_PredicateTypeExpr
|
||||
| tst.ts:75:17:75:28 | this is Leaf | tst.ts:75:17:75:20 | this |
|
||||
| tst.ts:76:21:76:32 | that is Leaf | tst.ts:76:21:76:24 | that |
|
||||
| tst.ts:80:36:80:55 | x is Generic<Leaf[]> | tst.ts:80:36:80:36 | x |
|
||||
| tst.ts:81:38:81:50 | x is typeof x | tst.ts:81:38:81:38 | x |
|
||||
| tst.ts:142:48:142:64 | asserts condition | tst.ts:142:56:142:64 | condition |
|
||||
| tst.ts:148:36:148:56 | asserts ... string | tst.ts:148:44:148:46 | val |
|
||||
test_hasAssertsKeyword
|
||||
| tst.ts:142:48:142:64 | asserts condition |
|
||||
| tst.ts:148:36:148:56 | asserts ... string |
|
||||
test_ThisParameterTypes
|
||||
| function hasThisParam | tst.ts:116:29:116:32 | void |
|
||||
| method hasThisParam of interface InterfaceWithThisParam | tst.ts:119:22:119:43 | Interfa ... isParam |
|
||||
@@ -254,6 +268,8 @@ test_ReturnTypes
|
||||
| tst.ts:94:1:94:37 | functio ... rn x; } | function f1 | tst.ts:94:23:94:23 | S |
|
||||
| tst.ts:95:1:95:53 | functio ... x,y]; } | function f2 | tst.ts:95:31:95:35 | [S,T] |
|
||||
| tst.ts:96:1:96:52 | functio ... rn x; } | function f3 | tst.ts:96:38:96:38 | S |
|
||||
| tst.ts:142:1:146:1 | functio ... )\\n }\\n} | function assert | tst.ts:142:48:142:64 | asserts condition |
|
||||
| tst.ts:148:1:152:1 | functio ... ;\\n }\\n} | function assertIsString | tst.ts:148:36:148:56 | asserts ... string |
|
||||
test_KeyofTypeExpr
|
||||
| tst.ts:49:16:49:30 | keyof Interface | tst.ts:49:22:49:30 | Interface |
|
||||
| tst.ts:113:26:113:35 | keyof Node | tst.ts:113:32:113:35 | Node |
|
||||
|
||||
@@ -11,7 +11,7 @@ import GenericTypeExpr
|
||||
import IntersectionTypeExpr
|
||||
import FunctionTypeReturns
|
||||
import InterfaceTypeExpr
|
||||
import IsTypeExpr
|
||||
import PredicateTypeExpr
|
||||
import ThisParameterTypes
|
||||
import ChildIndex
|
||||
import TypeArguments
|
||||
|
||||
@@ -138,3 +138,15 @@ let unknownType: unknown;
|
||||
|
||||
let taggedTemplateLiteralTypeArg1 = someTag<number>`Hello`;
|
||||
let taggedTemplateLiteralTypeArg2 = someTag<number, string>`Hello`;
|
||||
|
||||
function assert(condition: any, msg?: string): asserts condition {
|
||||
if (!condition) {
|
||||
throw new AssertionError(msg)
|
||||
}
|
||||
}
|
||||
|
||||
function assertIsString(val: any): asserts val is string {
|
||||
if (typeof val !== "string") {
|
||||
throw new AssertionError("Not a string!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user