Skip to content

Commit a27a14d

Browse files
author
Max Schaefer
authored
Merge pull request #69 from asger-semmle/ts-typescript2.9
TypeScript: support for v2.9 features
2 parents 44e4b25 + b2e3049 commit a27a14d

File tree

10 files changed

+101
-5
lines changed

10 files changed

+101
-5
lines changed

change-notes/1.18/analysis-javascript.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@
9898

9999
## Changes to QL libraries
100100

101+
* HTTP and HTTPS requests made using the Node.js `http.request` and `https.request` APIs and the Electron `Electron.net.request` and `Electron.ClientRequest` APIs are modeled as `RemoteFlowSources`.
101102
* HTTP header names are now always normalized to lower case to reflect the fact that they are case insensitive. In particular, the result of `HeaderDefinition.getAHeaderName`, and the first parameter of `HeaderDefinition.defines`, `ExplicitHeaderDefinition.definesExplicitly` and `RouteHandler.getAResponseHeader` is now always a lower-case string.
103+
* New AST nodes for TypeScript 2.9 features have been added.
102104
* The class `JsonParseCall` has been deprecated. Use `JsonParserCall` instead.
103105
* The handling of spread arguments in the data flow library has been changed: `DataFlow::InvokeNode.getArgument(i)` is now only defined when there is no spread argument at or before argument position `i`, and similarly `InvokeNode.getNumArgument` is only defined for invocations without spread arguments.
104-
* HTTP and HTTPS requests made using the Node.js `http.request` and `https.request` APIs and the Electron `Electron.net.request` and `Electron.ClientRequest` APIs are modeled as `RemoteFlowSources`.

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,58 @@ class QualifiedNamespaceAccess extends NamespaceAccess, @qualifiednamespaceacces
13961396
override Identifier getIdentifier() { result = getChildTypeExpr(1) }
13971397
}
13981398

1399+
/**
1400+
* An import inside a type annotation, such as in `import("http").ServerRequest`.
1401+
*/
1402+
class ImportTypeExpr extends TypeExpr, @importtypeexpr {
1403+
/**
1404+
* Gets the string literal with the imported path, such as `"http"` in `import("http")`.
1405+
*/
1406+
TypeExpr getPathExpr() {
1407+
result = getChildTypeExpr(0)
1408+
}
1409+
1410+
/**
1411+
* Gets the unresolved path string, such as `http` in `import("http")`.
1412+
*/
1413+
string getPath() {
1414+
result = getPathExpr().(StringLiteralTypeExpr).getValue()
1415+
}
1416+
1417+
/** Holds if this import is used in the context of a type, such as in `let x: import("foo")`. */
1418+
predicate isTypeAccess() {
1419+
this instanceof @importtypeaccess
1420+
}
1421+
1422+
/** Holds if this import is used in the context of a namespace, such as in `let x: import("http").ServerRequest"`. */
1423+
predicate isNamespaceAccess() {
1424+
this instanceof @importnamespaceaccess
1425+
}
1426+
1427+
/** Holds if this import is used in the context of a variable type, such as `let x: typeof import("fs")`. */
1428+
predicate isVarTypeAccess() {
1429+
this instanceof @importvartypeaccess
1430+
}
1431+
}
1432+
1433+
/**
1434+
* An import used in the context of a type, such as in `let x: import("foo")`.
1435+
*/
1436+
class ImportTypeAccess extends TypeAccess, ImportTypeExpr, @importtypeaccess {
1437+
}
1438+
1439+
/**
1440+
* An import used in the context of a namespace inside a type annotation, such as in `let x: import("http").ServerRequest`.
1441+
*/
1442+
class ImportNamespaceAccess extends NamespaceAccess, ImportTypeExpr, @importnamespaceaccess {
1443+
}
1444+
1445+
/**
1446+
* An import used in the context of a variable type, such as in `let x: typeof import("fs")`.
1447+
*/
1448+
class ImportVarTypeAccess extends VarTypeAccess, ImportTypeExpr, @importvartypeaccess {
1449+
}
1450+
13991451
/**
14001452
* A TypeScript enum declaration, such as the following declaration:
14011453
* ```

javascript/ql/src/semmlecode.javascript.dbscheme

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,15 +553,19 @@ case @typeexpr.kind of
553553
| 26 = @qualifiednamespaceaccess
554554
| 27 = @mappedtypeexpr
555555
| 28 = @conditionaltypeexpr
556-
| 29 = @infertypeexpr;
556+
| 29 = @infertypeexpr
557+
| 30 = @importtypeaccess
558+
| 31 = @importnamespaceaccess
559+
| 32 = @importvartypeaccess;
557560

558561
@typeref = @typeaccess | @typedecl;
559562
@typeidentifier = @typedecl | @localtypeaccess | @typelabel | @localvartypeaccess | @localnamespaceaccess;
560563
@typeexpr_parent = @expr | @stmt | @property | @typeexpr;
561564
@literaltypeexpr = @stringliteraltypeexpr | @numberliteraltypeexpr | @booleanliteraltypeexpr;
562-
@typeaccess = @localtypeaccess | @qualifiedtypeaccess;
563-
@vartypeaccess = @localvartypeaccess | @qualifiedvartypeaccess | @thisvartypeaccess;
564-
@namespaceaccess = @localnamespaceaccess | @qualifiednamespaceaccess;
565+
@typeaccess = @localtypeaccess | @qualifiedtypeaccess | @importtypeaccess;
566+
@vartypeaccess = @localvartypeaccess | @qualifiedvartypeaccess | @thisvartypeaccess | @importvartypeaccess;
567+
@namespaceaccess = @localnamespaceaccess | @qualifiednamespaceaccess | @importnamespaceaccess;
568+
@importtypeexpr = @importtypeaccess | @importnamespaceaccess | @importvartypeaccess;
565569

566570
@functiontypeexpr = @plainfunctiontypeexpr | @constructortypeexpr;
567571

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,18 @@
794794
<v>3559</v>
795795
</e>
796796
<e>
797+
<k>@importnamespaceaccess</k>
798+
<v>100</v>
799+
</e>
800+
<e>
801+
<k>@importtypeaccess</k>
802+
<v>100</v>
803+
</e>
804+
<e>
805+
<k>@importvartypeaccess</k>
806+
<v>100</v>
807+
</e>
808+
<e>
797809
<k>@generictypeexpr</k>
798810
<v>5220</v>
799811
</e>

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
| tst.ts:69:18:69:54 | ManyTyp ... oolean> | tst.ts:69:18:69:29 | ManyTypeArgs | 1 | 3 | tst.ts:69:39:69:44 | string |
88
| tst.ts:69:18:69:54 | ManyTyp ... oolean> | tst.ts:69:18:69:29 | ManyTypeArgs | 2 | 3 | tst.ts:69:47:69:53 | boolean |
99
| tst.ts:80:41:80:55 | Generic<Leaf[]> | tst.ts:80:41:80:47 | Generic | 0 | 1 | tst.ts:80:49:80:54 | Leaf[] |
10+
| tst.ts:123:26:123:47 | import( ... string> | tst.ts:123:26:123:39 | import("type") | 0 | 1 | tst.ts:123:41:123:46 | string |
11+
| tst.ts:125:35:125:65 | import( ... string> | tst.ts:125:55:125:57 | Foo | 0 | 1 | tst.ts:125:59:125:64 | string |

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
| tst.ts:66:18:66:32 | N.InnerGeneric1 | tst.ts:66:18:66:18 | N | tst.ts:66:20:66:32 | InnerGeneric1 |
44
| tst.ts:67:18:67:34 | N.M.InnerGeneric2 | tst.ts:67:18:67:20 | N.M | tst.ts:67:22:67:34 | InnerGeneric2 |
55
| tst.ts:68:26:68:40 | N.InnerGeneric1 | tst.ts:68:26:68:26 | N | tst.ts:68:28:68:40 | InnerGeneric1 |
6+
| tst.ts:124:48:124:50 | Foo | tst.ts:124:28:124:46 | import("namespace") | tst.ts:124:48:124:50 | Foo |
7+
| tst.ts:125:55:125:57 | Foo | tst.ts:125:35:125:53 | import("namespace") | tst.ts:125:55:125:57 | Foo |
8+
| tst.ts:131:4:131:6 | bar | tst.ts:128:38:130:3 | import( ... ce'\\n ) | tst.ts:131:4:131:6 | bar |

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
| tst.ts:69:18:69:29 | ManyTypeArgs | 3 | 1 | tst.ts:69:39:69:44 | string |
88
| tst.ts:69:18:69:29 | ManyTypeArgs | 3 | 2 | tst.ts:69:47:69:53 | boolean |
99
| tst.ts:80:41:80:47 | Generic | 1 | 0 | tst.ts:80:49:80:54 | Leaf[] |
10+
| tst.ts:123:26:123:39 | import("type") | 1 | 0 | tst.ts:123:41:123:46 | string |
11+
| tst.ts:125:55:125:57 | Foo | 1 | 0 | tst.ts:125:59:125:64 | string |

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
| tst.ts:71:17:71:26 | typeof N.x | tst.ts:71:24:71:26 | N.x |
33
| tst.ts:72:17:72:35 | typeof qualifiedVar | tst.ts:72:24:72:35 | qualifiedVar |
44
| tst.ts:81:43:81:50 | typeof x | tst.ts:81:50:81:50 | x |
5+
| tst.ts:126:21:126:42 | typeof ... value") | tst.ts:126:28:126:42 | import("value") |
6+
| tst.ts:127:30:127:53 | typeof ... lue").x | tst.ts:127:53:127:53 | x |

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,10 @@
6262
| tst.ts:114:5:114:15 | mappedType2 | mappedType2 | tst.ts:114:18:114:41 | { [K in ... umber } |
6363
| tst.ts:116:35:116:35 | x | x | tst.ts:116:38:116:43 | number |
6464
| tst.ts:116:46:116:46 | y | y | tst.ts:116:49:116:54 | string |
65+
| tst.ts:122:5:122:16 | importedType | importedType | tst.ts:122:19:122:32 | import("type") |
66+
| tst.ts:123:5:123:23 | importedTypeGeneric | importedTypeGeneric | tst.ts:123:26:123:47 | import( ... string> |
67+
| tst.ts:124:5:124:25 | importe ... iedType | importedQualifiedType | tst.ts:124:48:124:50 | Foo |
68+
| tst.ts:125:5:125:32 | importe ... Generic | importedQualifiedTypeGeneric | tst.ts:125:35:125:65 | import( ... string> |
69+
| tst.ts:126:5:126:18 | importedTypeof | importedTypeof | tst.ts:126:21:126:42 | typeof ... value") |
70+
| tst.ts:127:5:127:27 | importe ... dTypeof | importedQualifiedTypeof | tst.ts:127:30:127:53 | typeof ... lue").x |
71+
| tst.ts:128:5:128:35 | importe ... tespace | importedQualifiedTypeWhitespace | tst.ts:131:4:131:6 | bar |

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,14 @@ function hasThisParam(this: void, x: number, y: string) {}
118118
interface InterfaceWithThisParam {
119119
hasThisParam(this: InterfaceWithThisParam);
120120
}
121+
122+
var importedType: import("type");
123+
var importedTypeGeneric: import("type")<string>;
124+
var importedQualifiedType: import("namespace").Foo;
125+
var importedQualifiedTypeGeneric: import("namespace").Foo<string>;
126+
var importedTypeof: typeof import("value");
127+
var importedQualifiedTypeof: typeof import("value").x;
128+
var importedQualifiedTypeWhitespace: import(
129+
'awkard-namespace'
130+
)
131+
.bar;

0 commit comments

Comments
 (0)