Merge pull request #1227 from asger-semmle/typescript3.4

Approved by xiemaisi
This commit is contained in:
semmle-qlci
2019-04-11 10:39:57 +01:00
committed by GitHub
28 changed files with 2354 additions and 59 deletions

View File

@@ -585,6 +585,9 @@ class TypeExpr extends ExprOrType, @typeexpr {
/** Holds if this is the `bigint` type. */
predicate isBigInt() { none() }
/** Holds if this is the `const` keyword, occurring in a type assertion such as `x as const`. */
predicate isConstKeyword() { none() }
/** Gets this type expression, with any surrounding parentheses removed. */
override TypeExpr stripParens() { result = this }
@@ -638,6 +641,8 @@ private class KeywordTypeExpr extends @keywordtypeexpr, TypeExpr {
override predicate isUnknownKeyword() { getName() = "unknown" }
override predicate isBigInt() { getName() = "bigint" }
override predicate isConstKeyword() { getName() = "const" }
}
/**
@@ -970,6 +975,14 @@ class RestTypeExpr extends @resttypeexpr, TypeExpr {
TypeExpr getElementType() { result = getArrayType().(ArrayTypeExpr).getElementType() }
}
/**
* A type of form `readonly T`, such as `readonly number[]`.
*/
class ReadonlyTypeExpr extends @readonlytypeexpr, TypeExpr {
/** Gets the type `T` in `readonly T`. */
TypeExpr getElementType() { result = getChildTypeExpr(0) }
}
/**
* A possibly qualified name that refers to a variable from inside a type.
*

View File

@@ -573,6 +573,7 @@ case @typeexpr.kind of
| 33 = @optionaltypeexpr
| 34 = @resttypeexpr
| 35 = @bigintliteraltypeexpr
| 36 = @readonlytypeexpr
;
@typeref = @typeaccess | @typedecl;

View File

@@ -814,6 +814,10 @@
<v>100</v>
</e>
<e>
<k>@readonlytypeexpr</k>
<v>100</v>
</e>
<e>
<k>@bigintliteraltypeexpr</k>
<v>100</v>
</e>

View File

@@ -1,16 +1,20 @@
| (T \| ConcatArray<T>)[] | `T \| ConcatArray<T>` |
| (number \| ConcatArray<number>)[] | `number \| ConcatArray<number>` |
| (number[] \| ConcatArray<number[]>)[] | `number[] \| ConcatArray<number[]>` |
| (string \| number \| ConcatArray<string \| number>)[] | `string \| number \| ConcatArray<string \| number>` |
| (string \| number)[] | `string \| number` |
| ConcatArray<T>[] | `ConcatArray<T>` |
| ConcatArray<number>[] | `ConcatArray<number>` |
| ConcatArray<number[]>[] | `ConcatArray<number[]>` |
| ConcatArray<string \| number>[] | `ConcatArray<string \| number>` |
| ReadonlyArray<T> | `T` |
| ReadonlyArray<number> | `number` |
| S[] | `S` |
| T[] | `T` |
| U[] | `U` |
| [number, string] | `string \| number` |
| any[] | `any` |
| number[] | `number` |
| number[][] | `number[]` |
| readonly T[] | `T` |
| readonly number[] | `number` |
| readonly number[][] | `number[]` |
| string[] | `string` |

View File

@@ -1,18 +1,22 @@
| (T \| ConcatArray<T>)[] | T \| ConcatArray<T> |
| (number \| ConcatArray<number>)[] | number \| ConcatArray<number> |
| (number[] \| ConcatArray<number[]>)[] | number[] \| ConcatArray<number[]> |
| (string \| number \| ConcatArray<string \| number>)[] | string \| number \| ConcatArray<string \| number> |
| (string \| number)[] | string \| number |
| ConcatArray<T>[] | ConcatArray<T> |
| ConcatArray<number>[] | ConcatArray<number> |
| ConcatArray<number[]>[] | ConcatArray<number[]> |
| ConcatArray<string \| number>[] | ConcatArray<string \| number> |
| NumberIndexable | object |
| ReadonlyArray<T> | T |
| ReadonlyArray<number> | number |
| S[] | S |
| T[] | T |
| U[] | U |
| [number, string] | string \| number |
| any[] | any |
| number[] | number |
| number[][] | number[] |
| readonly T[] | T |
| readonly number[] | number |
| readonly number[][] | number[] |
| string | string |
| string[] | string |

View File

@@ -1,5 +1,5 @@
let plain: number[];
let radonly: ReadonlyArray<number>;
let readonly: ReadonlyArray<number>;
let tuple: [number, string];
interface NumberIndexable {
@@ -14,3 +14,6 @@ interface StringIndexable {
let numberIndexable: NumberIndexable;
let stringIndexable: StringIndexable;
let readonlySyntax: readonly number[];
let readonlySyntax2: readonly number[][];

View File

@@ -0,0 +1,6 @@
test_ConstKeyword
| tst.ts:1:19:1:23 | const |
| tst.ts:2:10:2:14 | const |
test_ConstTypeAssertion
| tst.ts:1:9:1:23 | [1, 2] as const |
| tst.ts:2:9:2:21 | <const>[1, 2] |

View File

@@ -0,0 +1,9 @@
import javascript
query predicate test_ConstKeyword(TypeExpr t) {
t.isConstKeyword()
}
query predicate test_ConstTypeAssertion(TypeAssertion t) {
t.getTypeAnnotation().isConstKeyword()
}

View File

@@ -0,0 +1,2 @@
var x = [1, 2] as const;
var x = <const>[1, 2];

View File

@@ -80,6 +80,16 @@
| tst.ts:38:5:38:24 | tupleWithRestElement | [number, ...string[]] |
| tst.ts:39:5:39:36 | tupleWi ... lements | [number, string?, ...number[]] |
| tst.ts:40:5:40:15 | unknownType | unknown |
| tst.ts:42:5:42:21 | constArrayLiteral | readonly [1, 2] |
| tst.ts:42:25:42:30 | [1, 2] | readonly [1, 2] |
| tst.ts:42:25:42:39 | [1, 2] as const | readonly [1, 2] |
| tst.ts:42:26:42:26 | 1 | 1 |
| tst.ts:42:29:42:29 | 2 | 2 |
| tst.ts:43:5:43:22 | constObjectLiteral | { readonly foo: "foo"; } |
| tst.ts:43:26:43:39 | { foo: "foo" } | { readonly foo: "foo"; } |
| tst.ts:43:26:43:48 | { foo: ... s const | { readonly foo: "foo"; } |
| tst.ts:43:28:43:30 | foo | "foo" |
| tst.ts:43:33:43:37 | "foo" | "foo" |
| type_alias.ts:3:5:3:5 | b | boolean |
| type_definition_objects.ts:1:13:1:17 | dummy | typeof dummy.ts |
| type_definition_objects.ts:1:24:1:32 | "./dummy" | any |

View File

@@ -8,3 +8,9 @@
| tst.ts:39:5:39:36 | tupleWi ... lements | [number, string?, ...number[]] | 0 | number | 1 | number |
| tst.ts:39:5:39:36 | tupleWi ... lements | [number, string?, ...number[]] | 1 | string | 1 | number |
| tst.ts:39:5:39:36 | tupleWi ... lements | [number, string?, ...number[]] | 2 | number | 1 | number |
| tst.ts:42:5:42:21 | constArrayLiteral | readonly [1, 2] | 0 | 1 | 2 | no-rest |
| tst.ts:42:5:42:21 | constArrayLiteral | readonly [1, 2] | 1 | 2 | 2 | no-rest |
| tst.ts:42:25:42:30 | [1, 2] | readonly [1, 2] | 0 | 1 | 2 | no-rest |
| tst.ts:42:25:42:30 | [1, 2] | readonly [1, 2] | 1 | 2 | 2 | no-rest |
| tst.ts:42:25:42:39 | [1, 2] as const | readonly [1, 2] | 0 | 1 | 2 | no-rest |
| tst.ts:42:25:42:39 | [1, 2] as const | readonly [1, 2] | 1 | 2 | 2 | no-rest |

View File

@@ -37,4 +37,7 @@ let tupleWithOptionalElement: [number, string, number?];
let emptyTuple: [];
let tupleWithRestElement: [number, ...string[]];
let tupleWithOptionalAndRestElements: [number, string?, ...number[]];
let unknownType: unknown;
let unknownType: unknown;
let constArrayLiteral = [1, 2] as const;
let constObjectLiteral = { foo: "foo" } as const;