Skip to content

Commit d5ae69d

Browse files
committed
TS: Support readonly type expressions
1 parent 11f460c commit d5ae69d

File tree

7 files changed

+30
-2
lines changed

7 files changed

+30
-2
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class TypeExprKinds {
6666
private static final int optionalTypeExpr = 33;
6767
private static final int restTypeExpr = 34;
6868
private static final int bigintLiteralTypeExpr = 35;
69+
private static final int readonlyTypeExpr = 36;
6970

7071
public static int getTypeExprKind(final INode type, final IdContext idcontext) {
7172
Integer kind =
@@ -127,7 +128,11 @@ public Integer visit(TupleTypeExpr nd, Void c) {
127128

128129
@Override
129130
public Integer visit(UnaryTypeExpr nd, Void c) {
130-
return keyofTypeExpr;
131+
switch (nd.getKind()) {
132+
case Keyof: return keyofTypeExpr;
133+
case Readonly: return readonlyTypeExpr;
134+
}
135+
throw new CatastrophicError("Unhandled UnaryTypeExpr kind: " + nd.getKind());
131136
}
132137

133138
@Override

javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,6 +2132,9 @@ private Node convertTypeOperator(JsonObject node, SourceLocation loc) throws Par
21322132
if (operator.equals("KeyOfKeyword")) {
21332133
return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.Keyof, convertChildAsType(node, "type"));
21342134
}
2135+
if (operator.equals("ReadonlyKeyword")) {
2136+
return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.Readonly, convertChildAsType(node, "type"));
2137+
}
21352138
if (operator.equals("UniqueKeyword")) {
21362139
return new KeywordTypeExpr(loc, "unique symbol");
21372140
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,14 @@ class RestTypeExpr extends @resttypeexpr, TypeExpr {
970970
TypeExpr getElementType() { result = getArrayType().(ArrayTypeExpr).getElementType() }
971971
}
972972

973+
/**
974+
* A type of form `readonly T`, such as `readonly number[]`.
975+
*/
976+
class ReadonlyTypeExpr extends @readonlytypeexpr, TypeExpr {
977+
/** Gets the type `T` in `readonly T`. */
978+
TypeExpr getElementType() { result = getChildTypeExpr(0) }
979+
}
980+
973981
/**
974982
* A possibly qualified name that refers to a variable from inside a type.
975983
*

javascript/ql/src/semmlecode.javascript.dbscheme

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ case @typeexpr.kind of
573573
| 33 = @optionaltypeexpr
574574
| 34 = @resttypeexpr
575575
| 35 = @bigintliteraltypeexpr
576+
| 36 = @readonlytypeexpr
576577
;
577578

578579
@typeref = @typeaccess | @typedecl;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
| (T \| ConcatArray<T>)[] | `T \| ConcatArray<T>` |
22
| (number \| ConcatArray<number>)[] | `number \| ConcatArray<number>` |
3+
| (number[] \| ConcatArray<number[]>)[] | `number[] \| ConcatArray<number[]>` |
34
| (string \| number \| ConcatArray<string \| number>)[] | `string \| number \| ConcatArray<string \| number>` |
45
| (string \| number)[] | `string \| number` |
56
| ConcatArray<T>[] | `ConcatArray<T>` |
67
| ConcatArray<number>[] | `ConcatArray<number>` |
8+
| ConcatArray<number[]>[] | `ConcatArray<number[]>` |
79
| ConcatArray<string \| number>[] | `ConcatArray<string \| number>` |
810
| S[] | `S` |
911
| T[] | `T` |
1012
| U[] | `U` |
1113
| [number, string] | `string \| number` |
1214
| any[] | `any` |
1315
| number[] | `number` |
16+
| number[][] | `number[]` |
1417
| readonly T[] | `T` |
1518
| readonly number[] | `number` |
19+
| readonly number[][] | `number[]` |
1620
| string[] | `string` |

javascript/ql/test/library-tests/TypeScript/ArrayTypes/NumberIndexTypes.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
| (T \| ConcatArray<T>)[] | T \| ConcatArray<T> |
22
| (number \| ConcatArray<number>)[] | number \| ConcatArray<number> |
3+
| (number[] \| ConcatArray<number[]>)[] | number[] \| ConcatArray<number[]> |
34
| (string \| number \| ConcatArray<string \| number>)[] | string \| number \| ConcatArray<string \| number> |
45
| (string \| number)[] | string \| number |
56
| ConcatArray<T>[] | ConcatArray<T> |
67
| ConcatArray<number>[] | ConcatArray<number> |
8+
| ConcatArray<number[]>[] | ConcatArray<number[]> |
79
| ConcatArray<string \| number>[] | ConcatArray<string \| number> |
810
| NumberIndexable | object |
911
| S[] | S |
@@ -12,7 +14,9 @@
1214
| [number, string] | string \| number |
1315
| any[] | any |
1416
| number[] | number |
17+
| number[][] | number[] |
1518
| readonly T[] | T |
1619
| readonly number[] | number |
20+
| readonly number[][] | number[] |
1721
| string | string |
1822
| string[] | string |

javascript/ql/test/library-tests/TypeScript/ArrayTypes/tst.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
let plain: number[];
2-
let radonly: ReadonlyArray<number>;
2+
let readonly: ReadonlyArray<number>;
33
let tuple: [number, string];
44

55
interface NumberIndexable {
@@ -14,3 +14,6 @@ interface StringIndexable {
1414

1515
let numberIndexable: NumberIndexable;
1616
let stringIndexable: StringIndexable;
17+
18+
let readonlySyntax: readonly number[];
19+
let readonlySyntax2: readonly number[][];

0 commit comments

Comments
 (0)