Skip to content

Commit 1aa7a2c

Browse files
author
Max Schaefer
authored
Merge pull request #80 from asger-semmle/ts-typescript3.0
TypeScript: support TypeScript 3.0 features
2 parents 7c52170 + 35aa2e6 commit 1aa7a2c

20 files changed

+271
-2
lines changed

javascript/ql/src/semmle/javascript/TypeScript.qll

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,9 @@ class TypeExpr extends ExprOrType, @typeexpr {
686686
/** Holds if this is the `object` type. */
687687
predicate isObjectKeyword() { none() }
688688

689+
/** Holds if this is the `unknown` type. */
690+
predicate isUnknownKeyword() { none() }
691+
689692
/** Gets this type expression, with any surrounding parentheses removed. */
690693
override TypeExpr stripParens() {
691694
result = this
@@ -725,6 +728,7 @@ private class KeywordTypeExpr extends @keywordtypeexpr, TypeExpr {
725728
override predicate isSymbol() { getName() = "symbol" }
726729
override predicate isUniqueSymbol() { getName() = "unique symbol" }
727730
override predicate isObjectKeyword() { getName() = "object" }
731+
override predicate isUnknownKeyword() { getName() = "unknown" }
728732
}
729733

730734
/**
@@ -1073,6 +1077,25 @@ class IsTypeExpr extends @istypeexpr, TypeExpr {
10731077
TypeExpr getPredicateType() { result = this.getChildTypeExpr(1) }
10741078
}
10751079

1080+
/**
1081+
* An optional type element in a tuple type, such as `number?` in `[string, number?]`.
1082+
*/
1083+
class OptionalTypeExpr extends @optionaltypeexpr, TypeExpr {
1084+
/** Gets the type `T` in `T?` */
1085+
TypeExpr getElementType() { result = getChildTypeExpr(0) }
1086+
}
1087+
1088+
/**
1089+
* A rest element in a tuple type, such as `...string[]` in `[number, ...string[]]`.
1090+
*/
1091+
class RestTypeExpr extends @resttypeexpr, TypeExpr {
1092+
/** Gets the type `T[]` in `...T[]`, such as `string[]` in `[number, ...string[]]`. */
1093+
TypeExpr getArrayType() { result = getChildTypeExpr(0) }
1094+
1095+
/** Gets the type `T` in `...T[]`, such as `string` in `[number, ...string[]]`. */
1096+
TypeExpr getElementType() { result = getArrayType().(ArrayTypeExpr).getElementType() }
1097+
}
1098+
10761099
/**
10771100
* A possibly qualified name that refers to a variable from inside a type.
10781101
*
@@ -2143,7 +2166,7 @@ class TupleType extends ArrayType, @tupletype {
21432166
}
21442167

21452168
/**
2146-
* Gets the number of elements in this tuple type.
2169+
* Gets the number of elements in this tuple type, including optional elements and the rest element.
21472170
*/
21482171
int getNumElementType() {
21492172
result = count(int i | exists(getElementType(i)))
@@ -2158,13 +2181,43 @@ class TupleType extends ArrayType, @tupletype {
21582181
PlainArrayType getUnderlyingArrayType() {
21592182
result.getArrayElementType() = getArrayElementType()
21602183
}
2184+
2185+
/**
2186+
* Gets the number of required tuple elements, that is, excluding optional and rest elements.
2187+
*
2188+
* For example, the minimum length of `[number, string?, ...number[]]` is 1.
2189+
*/
2190+
int getMinimumLength() {
2191+
tuple_type_min_length(this, result)
2192+
}
2193+
2194+
/**
2195+
* Holds if this tuple type ends with a rest element, such as `[number, ...string[]]`.
2196+
*/
2197+
predicate hasRestElement() {
2198+
tuple_type_rest(this)
2199+
}
2200+
2201+
/**
2202+
* Gets the type of the rest element, if there is one.
2203+
*
2204+
* For example, the rest element of `[number, ...string[]]` is `string`.
2205+
*/
2206+
Type getRestElementType() {
2207+
hasRestElement() and result = getElementType(getNumElementType() - 1)
2208+
}
21612209
}
21622210

21632211
/**
21642212
* The predefined `any` type.
21652213
*/
21662214
class AnyType extends Type, @anytype {}
21672215

2216+
/**
2217+
* The predefined `unknown` type.
2218+
*/
2219+
class UnknownType extends Type, @unknowntype {}
2220+
21682221
/**
21692222
* The predefined `string` type.
21702223
*/

javascript/ql/src/semmlecode.javascript.dbscheme

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,10 @@ case @typeexpr.kind of
556556
| 29 = @infertypeexpr
557557
| 30 = @importtypeaccess
558558
| 31 = @importnamespaceaccess
559-
| 32 = @importvartypeaccess;
559+
| 32 = @importvartypeaccess
560+
| 33 = @optionaltypeexpr
561+
| 34 = @resttypeexpr
562+
;
560563

561564
@typeref = @typeaccess | @typedecl;
562565
@typeidentifier = @typedecl | @localtypeaccess | @typelabel | @localvartypeaccess | @localnamespaceaccess;
@@ -607,6 +610,7 @@ case @type.kind of
607610
| 20 = @thistype
608611
| 21 = @numberliteraltype
609612
| 22 = @stringliteraltype
613+
| 23 = @unknowntype
610614
;
611615

612616
@booleanliteraltype = @truetype | @falsetype;
@@ -734,6 +738,15 @@ self_types(
734738
int selfType: @typereference ref
735739
);
736740

741+
tuple_type_min_length(
742+
unique int typ: @type ref,
743+
int minLength: int ref
744+
);
745+
746+
tuple_type_rest(
747+
unique int typ: @type ref
748+
);
749+
737750
// comments
738751
comments (unique int id: @comment,
739752
int kind: int ref,

javascript/ql/src/semmlecode.javascript.dbscheme.stats

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,14 @@
806806
<v>100</v>
807807
</e>
808808
<e>
809+
<k>@optionaltypeexpr</k>
810+
<v>100</v>
811+
</e>
812+
<e>
813+
<k>@resttypeexpr</k>
814+
<v>100</v>
815+
</e>
816+
<e>
809817
<k>@generictypeexpr</k>
810818
<v>5220</v>
811819
</e>
@@ -962,6 +970,10 @@
962970
<v>30638</v>
963971
</e>
964972
<e>
973+
<k>@unknowntype</k>
974+
<v>100</v>
975+
</e>
976+
<e>
965977
<k>@uniquesymboltype</k>
966978
<v>100</v>
967979
</e>
@@ -15385,6 +15397,100 @@
1538515397
</dependencies>
1538615398
</relation>
1538715399
<relation>
15400+
<name>tuple_type_min_length</name>
15401+
<cardinality>241</cardinality>
15402+
<columnsizes>
15403+
<e>
15404+
<k>typ</k>
15405+
<v>241</v>
15406+
</e>
15407+
<e>
15408+
<k>minLength</k>
15409+
<v>10</v>
15410+
</e>
15411+
</columnsizes>
15412+
<dependencies>
15413+
<dep>
15414+
<src>typ</src>
15415+
<trg>minLength</trg>
15416+
<val>
15417+
<hist>
15418+
<budget>12</budget>
15419+
<bs>
15420+
<b>
15421+
<a>1</a>
15422+
<b>2</b>
15423+
<v>241</v>
15424+
</b>
15425+
</bs>
15426+
</hist>
15427+
</val>
15428+
</dep>
15429+
<dep>
15430+
<src>minLength</src>
15431+
<trg>typ</trg>
15432+
<val>
15433+
<hist>
15434+
<budget>12</budget>
15435+
<bs>
15436+
<b>
15437+
<a>2</a>
15438+
<b>3</b>
15439+
<v>3</v>
15440+
</b>
15441+
<b>
15442+
<a>3</a>
15443+
<b>4</b>
15444+
<v>1</v>
15445+
</b>
15446+
<b>
15447+
<a>4</a>
15448+
<b>5</b>
15449+
<v>1</v>
15450+
</b>
15451+
<b>
15452+
<a>7</a>
15453+
<b>8</b>
15454+
<v>1</v>
15455+
</b>
15456+
<b>
15457+
<a>20</a>
15458+
<b>21</b>
15459+
<v>1</v>
15460+
</b>
15461+
<b>
15462+
<a>42</a>
15463+
<b>43</b>
15464+
<v>1</v>
15465+
</b>
15466+
<b>
15467+
<a>66</a>
15468+
<b>67</b>
15469+
<v>1</v>
15470+
</b>
15471+
<b>
15472+
<a>93</a>
15473+
<b>94</b>
15474+
<v>1</v>
15475+
</b>
15476+
</bs>
15477+
</hist>
15478+
</val>
15479+
</dep>
15480+
</dependencies>
15481+
</relation>
15482+
<relation>
15483+
<name>tuple_type_rest</name>
15484+
<cardinality>100</cardinality>
15485+
<columnsizes>
15486+
<e>
15487+
<k>typ</k>
15488+
<v>100</v>
15489+
</e>
15490+
</columnsizes>
15491+
<dependencies/>
15492+
</relation>
15493+
<relation>
1538815494
<name>comments</name>
1538915495
<key>id</key>
1539015496
<cardinality>104947</cardinality>

javascript/ql/test/library-tests/TypeScript/TypeAnnotations/ArrayTypeExpr.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
| tst.ts:40:17:40:28 | string[][][] | tst.ts:40:17:40:26 | string[][] |
77
| tst.ts:80:49:80:54 | Leaf[] | tst.ts:80:49:80:52 | Leaf |
88
| tst.ts:81:27:81:34 | string[] | tst.ts:81:27:81:32 | string |
9+
| tst.ts:135:39:135:46 | string[] | tst.ts:135:39:135:44 | string |
10+
| tst.ts:136:60:136:67 | number[] | tst.ts:136:60:136:65 | number |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| tst.ts:133:48:133:54 | number? | tst.ts:133:48:133:53 | number |
2+
| tst.ts:136:48:136:54 | string? | tst.ts:136:48:136:53 | string |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from OptionalTypeExpr type
4+
select type, type.getElementType()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| tst.ts:135:36:135:46 | ...string[] | tst.ts:135:39:135:46 | string[] | tst.ts:135:39:135:44 | string |
2+
| tst.ts:136:57:136:67 | ...number[] | tst.ts:136:60:136:67 | number[] | tst.ts:136:60:136:65 | number |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from RestTypeExpr rest
4+
select rest, rest.getArrayType(), rest.getElementType()

javascript/ql/test/library-tests/TypeScript/TypeAnnotations/TupleTypeExpr.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,11 @@
33
| tst.ts:48:16:48:40 | [number ... oolean] | 2 | 3 | tst.ts:48:33:48:39 | boolean |
44
| tst.ts:95:31:95:35 | [S,T] | 0 | 2 | tst.ts:95:32:95:32 | S |
55
| tst.ts:95:31:95:35 | [S,T] | 1 | 2 | tst.ts:95:34:95:34 | T |
6+
| tst.ts:133:31:133:55 | [number ... umber?] | 0 | 3 | tst.ts:133:32:133:37 | number |
7+
| tst.ts:133:31:133:55 | [number ... umber?] | 1 | 3 | tst.ts:133:40:133:45 | string |
8+
| tst.ts:133:31:133:55 | [number ... umber?] | 2 | 3 | tst.ts:133:48:133:54 | number? |
9+
| tst.ts:135:27:135:47 | [number ... ring[]] | 0 | 2 | tst.ts:135:28:135:33 | number |
10+
| tst.ts:135:27:135:47 | [number ... ring[]] | 1 | 2 | tst.ts:135:36:135:46 | ...string[] |
11+
| tst.ts:136:39:136:68 | [number ... mber[]] | 0 | 3 | tst.ts:136:40:136:45 | number |
12+
| tst.ts:136:39:136:68 | [number ... mber[]] | 1 | 3 | tst.ts:136:48:136:54 | string? |
13+
| tst.ts:136:39:136:68 | [number ... mber[]] | 2 | 3 | tst.ts:136:57:136:67 | ...number[] |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| tst.ts:137:18:137:24 | unknown |

0 commit comments

Comments
 (0)