Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f385c55

Browse files
committed
add support for rest types elements in the middle of a tuple
1 parent 74630b0 commit f385c55

10 files changed

Lines changed: 2479 additions & 11 deletions

File tree

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,14 @@ export class TypeTable {
632632
? tupleType.minLength
633633
: this.typeChecker.getTypeArguments(tupleReference).length;
634634
let hasRestElement = tupleType.hasRestElement ? 't' : 'f';
635-
let prefix = `tuple;${minLength};${hasRestElement}`;
635+
let restIndex = -1;
636+
for (let i = 0; i < tupleType.elementFlags.length; i++) {
637+
if (tupleType.elementFlags[i] & ts.ElementFlags.Rest) {
638+
restIndex = i;
639+
break;
640+
}
641+
}
642+
let prefix = `tuple;${minLength};${restIndex}`;
636643
return this.makeTypeStringVectorFromTypeReferenceArguments(prefix, type);
637644
}
638645
if (objectFlags & ts.ObjectFlags.Anonymous) {

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ private void extractType(int id) {
118118
}
119119
case tupleKind:
120120
{
121-
// The first two parts denote minimum length and presence of rest element.
121+
// The first two parts denote minimum length and index of rest element (or -1 if no rest element).
122122
trapWriter.addTuple("tuple_type_min_length", lbl, Integer.parseInt(parts[1]));
123-
if (parts[2].equals("t")) {
124-
trapWriter.addTuple("tuple_type_rest", lbl);
123+
int restIndex = Integer.parseInt(parts[2]);
124+
if (restIndex != -1) {
125+
trapWriter.addTuple("tuple_type_rest_index", lbl, restIndex);
125126
}
126127
firstChild += 2;
127128
break;

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,18 +2149,23 @@ class TupleType extends ArrayType, @tuple_type {
21492149
int getMinimumLength() { tuple_type_min_length(this, result) }
21502150

21512151
/**
2152-
* Holds if this tuple type ends with a rest element, such as `[number, ...string[]]`.
2152+
* Gets the index of the rest element.
2153+
* E.g. for a type `[number, ...string[]]` the result is 1,
2154+
* or for a type `[...number[], string]` the result is 0.
21532155
*/
2154-
predicate hasRestElement() { tuple_type_rest(this) }
2156+
int getRestElementIndex() { tuple_type_rest_index(this, result) }
2157+
2158+
/**
2159+
* Holds if this tuple type has a rest element, such as `[number, ...string[]]` or `[...number[], string]`.
2160+
*/
2161+
predicate hasRestElement() { exists(getRestElementIndex()) }
21552162

21562163
/**
21572164
* Gets the type of the rest element, if there is one.
21582165
*
21592166
* For example, the rest element of `[number, ...string[]]` is `string`.
21602167
*/
2161-
Type getRestElementType() {
2162-
hasRestElement() and result = getElementType(getNumElementType() - 1)
2163-
}
2168+
Type getRestElementType() { result = getElementType(getRestElementIndex()) }
21642169
}
21652170

21662171
/**

javascript/ql/src/semmlecode.javascript.dbscheme

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -799,8 +799,9 @@ tuple_type_min_length(
799799
int minLength: int ref
800800
);
801801

802-
tuple_type_rest(
803-
unique int typ: @type ref
802+
tuple_type_rest_index(
803+
unique int typ: @type ref,
804+
int index: int ref
804805
);
805806

806807
// comments
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let foo: [boolean, ...string[], number];
2+
3+
foo = [true, "hello", 123];

javascript/ql/test/library-tests/TypeScript/Types/tests.expected

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ getExprType
1515
| boolean-type.ts:15:5:15:12 | boolean6 | boolean |
1616
| dummy.ts:2:12:2:12 | x | number |
1717
| dummy.ts:2:16:2:16 | 5 | 5 |
18+
| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] |
19+
| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] |
20+
| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] |
21+
| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] |
22+
| middle-rest.ts:3:8:3:11 | true | true |
23+
| middle-rest.ts:3:14:3:20 | "hello" | "hello" |
24+
| middle-rest.ts:3:23:3:25 | 123 | 123 |
1825
| tst.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts |
1926
| tst.ts:1:24:1:32 | "./dummy" | any |
2027
| tst.ts:3:5:3:10 | numVar | number |
@@ -185,6 +192,12 @@ getTypeExprType
185192
| boolean-type.ts:15:15:15:19 | false | false |
186193
| boolean-type.ts:15:15:15:29 | false \| boolean | boolean |
187194
| boolean-type.ts:15:23:15:29 | boolean | boolean |
195+
| middle-rest.ts:1:10:1:39 | [boolea ... number] | [boolean, ...string[], number] |
196+
| middle-rest.ts:1:11:1:17 | boolean | boolean |
197+
| middle-rest.ts:1:20:1:30 | ...string[] | string |
198+
| middle-rest.ts:1:23:1:28 | string | string |
199+
| middle-rest.ts:1:23:1:30 | string[] | string[] |
200+
| middle-rest.ts:1:33:1:38 | number | number |
188201
| tst.ts:3:13:3:18 | number | number |
189202
| tst.ts:9:13:9:18 | string | string |
190203
| tst.ts:14:20:14:25 | string | string |
@@ -311,6 +324,18 @@ referenceDefinition
311324
| ValueOrArray<number> | type_alias.ts:5:1:5:50 | type Va ... ay<T>>; |
312325
| VirtualNode | type_alias.ts:19:1:21:57 | type Vi ... ode[]]; |
313326
tupleTypes
327+
| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 0 | boolean | 2 | string |
328+
| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 1 | string | 2 | string |
329+
| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 2 | number | 2 | string |
330+
| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 0 | boolean | 2 | string |
331+
| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 1 | string | 2 | string |
332+
| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 2 | number | 2 | string |
333+
| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 0 | true | 3 | no-rest |
334+
| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 1 | string | 3 | no-rest |
335+
| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 2 | number | 3 | no-rest |
336+
| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 0 | boolean | 2 | string |
337+
| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 1 | string | 2 | string |
338+
| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 2 | number | 2 | string |
314339
| tst.ts:34:5:34:9 | tuple | [number, string] | 0 | number | 2 | no-rest |
315340
| tst.ts:34:5:34:9 | tuple | [number, string] | 1 | string | 2 | no-rest |
316341
| tst.ts:36:5:36:28 | tupleWi ... Element | [number, string, number?] | 0 | number | 2 | no-rest |

0 commit comments

Comments
 (0)