Merge pull request #19078 from asgerf/js/name-resolution

JS: QL-side type/name resolution for TypeScript and JSDoc
This commit is contained in:
Asger F
2025-06-11 14:17:11 +02:00
committed by GitHub
79 changed files with 3729 additions and 2180 deletions

View File

@@ -0,0 +1,27 @@
namespace NS {
export class C {
/** name:NS.C.m */
m() { }
}
export class D extends C { }
}
function t1(c: NS.C, d: NS.D) {
/** calls:NS.C.m */
c.m();
/** calls:NS.C.m */
d.m();
}
async function t2(cp: Promise<NS.C>) {
const c = await cp;
/** calls:NS.C.m */
c.m();
cp.then(c2 => {
/** calls:NS.C.m */
c2.m();
})
}

View File

@@ -1514,6 +1514,7 @@ sources
| tst2.ts:7:1:9:1 | return of function setX |
| tst2.ts:8:3:8:5 | A.x |
| tst2.ts:11:11:11:13 | A.x |
| tst2.ts:11:11:11:23 | A.x as number |
| tst2.ts:13:1:13:40 | class S ... ing> {} |
| tst2.ts:13:26:13:29 | List |
| tst2.ts:13:39:13:38 | (...arg ... rgs); } |
@@ -1522,6 +1523,7 @@ sources
| tst2.ts:13:39:13:38 | super(...args) |
| tst2.ts:13:39:13:38 | this |
| tst2.ts:15:11:15:13 | A.x |
| tst2.ts:15:11:15:30 | A.x satisfies number |
| tst.js:1:1:1:0 | this |
| tst.js:1:1:1:24 | import ... m 'fs'; |
| tst.js:1:10:1:11 | fs |

View File

@@ -1,10 +1,10 @@
| bar.js:5:14:5:14 | x | x |
| bar.js:5:14:5:14 | x | ns.very.long.namespace |
| bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo |
| bar.js:12:14:12:17 | iife | iife |
| bar.js:12:14:12:17 | iife | IIFE |
| bar.js:12:14:12:21 | iife.Foo | IIFE.Foo |
| closure.js:8:12:8:15 | goog | goog |
| closure.js:8:12:8:19 | goog.net | goog.net |
| closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType |
| closure.js:9:12:9:14 | net | net |
| closure.js:9:12:9:14 | net | goog.net |
| closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType |
| closure.js:10:12:10:19 | SomeType | goog.net.SomeType |

View File

@@ -1,3 +1,3 @@
import javascript
query string test_hasQualifiedName(JSDocNamedTypeExpr expr) { expr.hasQualifiedName(result) }
query string test_hasUnderlyingType(JSDocNamedTypeExpr expr) { expr.hasUnderlyingType(result) }

View File

@@ -2,13 +2,14 @@ test_isString
| tst.js:2:12:2:17 | string |
test_isNumber
| tst.js:3:12:3:17 | number |
test_QualifiedName
test_hasUnderlyingType
| VarType | tst.js:9:13:9:19 | VarType |
| boolean | tst.js:5:14:5:20 | boolean |
| foo | tst.js:4:12:4:14 | foo |
| foo.bar | tst.js:4:12:4:18 | foo.bar |
| foo.bar.baz | tst.js:4:12:4:22 | foo.bar.baz |
| number | tst.js:3:12:3:17 | number |
| number | tst.js:3:12:3:18 | number? |
| string | tst.js:2:12:2:17 | string |
test_ParameterType
| tst.js:7:12:7:12 | x | tst.js:2:12:2:17 | string |

View File

@@ -4,7 +4,7 @@ query TypeAnnotation test_isString() { result.isString() }
query TypeAnnotation test_isNumber() { result.isNumber() }
query TypeAnnotation test_QualifiedName(string name) { result.hasQualifiedName(name) }
query TypeAnnotation test_hasUnderlyingType(string name) { result.hasUnderlyingType(name) }
query TypeAnnotation test_ParameterType(Parameter p) { result = p.getTypeAnnotation() }

View File

@@ -1,5 +1,5 @@
import javascript
from TypeAnnotation type, string mod, string name
where type.hasQualifiedName(mod, name)
where type.hasUnderlyingType(mod, name)
select type, mod, name

View File

@@ -1 +1,7 @@
| tst.ts:38:3:38:19 | resolveAmbient(x) | x should not resolve to a global |
| tst.ts:22:3:22:18 | resolveGlobal(x) | x should resolve to a global variable |
| tst.ts:23:3:23:18 | resolveGlobal(y) | y should resolve to a global variable |
| tst.ts:24:3:24:18 | resolveGlobal(z) | z should resolve to a global variable |
| tst.ts:25:3:25:18 | resolveGlobal(w) | w should resolve to a global variable |
| tst.ts:39:3:39:18 | resolveGlobal(y) | y should resolve to a global variable |
| tst.ts:40:3:40:18 | resolveGlobal(z) | z should resolve to a global variable |
| tst.ts:41:3:41:18 | resolveGlobal(w) | w should resolve to a global variable |

View File

@@ -1,16 +1,36 @@
| tst.ts:52:3:52:23 | obj.sim ... od(str) | TestInterface.simpleMethod in global scope | no concrete target |
| tst.ts:53:3:53:24 | obj.gen ... od(str) | TestInterface.genericMethod in global scope | no concrete target |
| tst.ts:54:3:54:24 | obj.gen ... od(num) | TestInterface.genericMethod in global scope | no concrete target |
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | no concrete target |
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | no concrete target |
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | no concrete target |
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | no concrete target |
| tst.ts:52:3:52:23 | obj.sim ... od(str) | TestInterface.simpleMethod in global scope | simpleM ... number; |
| tst.ts:53:3:53:24 | obj.gen ... od(str) | TestInterface.genericMethod in global scope | generic ... T): T; |
| tst.ts:54:3:54:24 | obj.gen ... od(num) | TestInterface.genericMethod in global scope | generic ... T): T; |
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... number; |
| tst.ts:55:3:55:27 | obj.ove ... od(num) | TestInterface.overloadedMethod in global scope | overloa ... string; |
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... number; |
| tst.ts:56:3:56:27 | obj.ove ... od(str) | TestInterface.overloadedMethod in global scope | overloa ... string; |
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... ): any; |
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... number; |
| tst.ts:57:3:57:26 | obj.ove ... hod([]) | TestInterface.overloadedMethod in global scope | overloa ... string; |
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
| tst.ts:58:3:58:36 | obj.gen ... ([num]) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
| tst.ts:59:3:59:39 | obj.gen ... : str}) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... ): any; |
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... T>): T; |
| tst.ts:60:3:60:34 | obj.gen ... od(num) | TestInterface.genericOverloadedMethod in global scope | generic ... []): T; |
| tst.ts:64:3:64:23 | obj.sim ... od(str) | TestClass.simpleMethod in global scope | simpleM ... ength } |
| tst.ts:65:3:65:24 | obj.gen ... od(str) | TestClass.genericMethod in global scope | generic ... rn x; } |
| tst.ts:66:3:66:24 | obj.gen ... od(num) | TestClass.genericMethod in global scope | generic ... rn x; } |
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... number; |
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... rn x; } |
| tst.ts:67:3:67:27 | obj.ove ... od(num) | TestClass.overloadedMethod in global scope | overloa ... string; |
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... number; |
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... rn x; } |
| tst.ts:68:3:68:27 | obj.ove ... od(str) | TestClass.overloadedMethod in global scope | overloa ... string; |
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... T>): T; |
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... []): T; |
| tst.ts:69:3:69:36 | obj.gen ... ([num]) | TestClass.genericOverloadedMethod in global scope | generic ... null; } |
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... T>): T; |
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... []): T; |
| tst.ts:70:3:70:39 | obj.gen ... : str}) | TestClass.genericOverloadedMethod in global scope | generic ... null; } |

View File

@@ -1,13 +1,15 @@
hasQualifiedNameModule
| default-import | default | tst.ts:11:9:11:21 | DefaultImport |
hasUnderlyingTypeModule
| default-import | | tst.ts:11:9:11:21 | DefaultImport |
| global | UnresolvedName | tst.ts:12:9:12:22 | UnresolvedName |
| import-assign | | tst.ts:10:9:10:11 | asn |
| import-assign | Foo | tst.ts:10:9:10:15 | asn.Foo |
| named-import | Name1 | tst.ts:7:9:7:13 | Name1 |
| named-import | Name1 | tst.ts:13:9:13:13 | Name1 |
| named-import | Name1 | tst.ts:13:9:13:21 | Name1<number> |
| named-import | Name2 | tst.ts:8:9:8:13 | Name2 |
| namespace-import | | tst.ts:9:9:9:17 | namespace |
| namespace-import | Foo | tst.ts:9:9:9:21 | namespace.Foo |
| tst.ts | ExportedClass | relative.ts:4:8:4:20 | ExportedClass |
hasQualifiedNameGlobal
hasUnderlyingTypeGlobal
| UnresolvedName | tst.ts:12:9:12:22 | UnresolvedName |
paramExample
| tst.ts:7:5:7:6 | x1 |

View File

@@ -1,13 +1,13 @@
import javascript
query TypeAnnotation hasQualifiedNameModule(string moduleName, string member) {
result.hasQualifiedName(moduleName, member)
query TypeAnnotation hasUnderlyingTypeModule(string moduleName, string member) {
result.hasUnderlyingType(moduleName, member)
}
query TypeAnnotation hasQualifiedNameGlobal(string globalName) {
result.hasQualifiedName(globalName)
query TypeAnnotation hasUnderlyingTypeGlobal(string globalName) {
result.hasUnderlyingType(globalName)
}
query Parameter paramExample() {
result.getTypeAnnotation().hasQualifiedName("named-import", "Name1")
result.getTypeAnnotation().hasUnderlyingType("named-import", "Name1")
}

View File

@@ -5,6 +5,6 @@
| tst.ts:8:14:8:16 | arg | Sub in global scope |
underlyingTypeNode
| foo | | file://:0:0:0:0 | use moduleImport("foo").getMember("exports") |
| foo | | file://:0:0:0:0 | use moduleImport("foo").getMember("exports").getMember("") |
| foo | | foo.ts:1:8:1:10 | use moduleImport("foo").getMember("exports").getMember("default") |
| foo | Bar | foo.ts:3:1:5:1 | use moduleImport("foo").getMember("exports").getMember("Bar").getInstance() |
| foo | Bar | foo.ts:3:12:3:12 | use moduleImport("foo").getMember("exports").getMember("Bar").getInstance() |

View File

@@ -0,0 +1,32 @@
import * as express from 'express';
function getRequest(): express.Request { }
function t1() {
getRequest(); // $ hasUnderlyingType='express'.Request
}
declare function getRequestAmbient(): express.Request;
function t2() {
getRequestAmbient(); // $ hasUnderlyingType='express'.Request
}
class C {
method(): express.Request { }
}
function t3(c: C) {
c.method(); // $ hasUnderlyingType='express'.Request
new C().method(); // $ hasUnderlyingType='express'.Request
}
function callback(fn: (req: express.Request) => void) { // $ SPURIOUS: hasUnderlyingType='express'.Request // req seems to be a SourceNode
}
function t4() {
callback(function (
req // $ hasUnderlyingType='express'.Request
) { }
);
}

View File

@@ -0,0 +1,5 @@
goog.declareModuleId("closure.es")
const Bar = goog.require('closure.reexported.Bar');
export { Bar }

View File

@@ -0,0 +1,3 @@
goog.module("closure.lib")
exports.Foo = goog.require('closure.reexported.Foo');

View File

@@ -0,0 +1,16 @@
goog.module("closure.use")
const lib = goog.require("closure.lib");
const es = goog.require("closure.es");
/**
* @param {lib.Foo} x
*/
function t1(x) { // $ hasUnderlyingType=closure.reexported.Foo hasUnderlyingType=closure.lib.Foo
}
/**
* @param {es.Bar} x
*/
function t2(x) { // $ hasUnderlyingType=closure.reexported.Bar hasUnderlyingType=closure.es.Bar
}

View File

@@ -0,0 +1,45 @@
import * as express from 'express';
interface Options {
handle(req: express.Request): void; // $ hasUnderlyingType='express'.Request
}
declare function doSomething(options: Options);
function t1() {
doSomething({
handle(req) { // $ hasUnderlyingType='express'.Request
}
});
}
function t2(callback: ((opts: Options) => void) | undefined) {
callback({
handle(req) { } // $ hasUnderlyingType='express'.Request
})
callback!({
handle(req) { } // $ hasUnderlyingType='express'.Request
})
}
function t3(): Options {
return {
handle(req) { } // $ hasUnderlyingType='express'.Request
}
}
function t4(): Options[] {
return [
{
handle(req) { } // $ hasUnderlyingType='express'.Request
}
]
}
async function t5(): Promise<Options> {
return {
handle(req) { // $ hasUnderlyingType='express'.Request
}
}
}

View File

@@ -0,0 +1 @@
export * from 'express';

View File

@@ -0,0 +1,7 @@
import { Request, Response } from './expressBulkExport';
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
}
function t2(res: Response) { // $ hasUnderlyingType='express'.Response
}

View File

@@ -0,0 +1,2 @@
import E = require('express');
export = E;

View File

@@ -0,0 +1,4 @@
import { Request } from "./expressExportAssign";
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
}

View File

@@ -0,0 +1,5 @@
import Express = require('express');
namespace Wrapper {
export import E = Express;
}
export = Wrapper;

View File

@@ -0,0 +1,4 @@
import { E } from "./expressExportAssignWrapper";
function t1(req: E.Request) { // $ hasUnderlyingType='express'.Request
}

View File

@@ -0,0 +1,2 @@
export { Request } from 'express';
export { Response as R } from 'express';

View File

@@ -0,0 +1,10 @@
import { Request, Response, R } from './expressSelectiveExport';
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
}
function t2(res: Response) { // none, not exported
}
function t3(res: R) { // $ hasUnderlyingType='express'.Response
}

View File

@@ -0,0 +1 @@
export * as wrapper from 'express';

View File

@@ -0,0 +1,29 @@
import { Request, Response, wrapper } from './expressWrapperExport';
import * as w from './expressWrapperExport';
function t1(req: Request) { // none
}
function t2(res: Response) { // none
}
function t3(req: wrapper.Request) { // $ hasUnderlyingType='express'.Request
}
function t4(res: wrapper.Response) { // $ hasUnderlyingType='express'.Response
}
function t5(req: w.wrapper.Request) { // $ hasUnderlyingType='express'.Request
}
function t6(res: w.wrapper.Response) { // $ hasUnderlyingType='express'.Response
}
function t7(req: w.Request) { // none
}
function t8(res: w.Response) { // none
}
function t9(e: typeof w.wrapper) { // $ hasUnderlyingType='express'
}

View File

@@ -0,0 +1,46 @@
import * as express from 'express';
type Box1<T> = {
value: T;
other: string;
};
function t1(b: Box1<express.Request>) {
b.value; // $ MISSING: hasUnderlyingType='express'.Request
b.other;
}
interface Box2<T> {
value: T;
other: string;
}
function t2(b: Box2<express.Request>) {
b.value; // $ MISSING: hasUnderlyingType='express'.Request
b.other;
}
class Box3<T> {
value: T;
other: string;
}
function t3(b: Box3<express.Request>) {
b.value; // $ MISSING: hasUnderlyingType='express'.Request
b.other;
}
abstract class Box4<T> {
abstract getValue(): T;
abstract getOther(): string;
}
function t4(b: Box4<express.Request>) {
b.getValue(); // $ MISSING: hasUnderlyingType='express'.Request
b.getOther();
}
type Box5<T> = {
value: T & { blah: string };
other: string;
};
function t5(b: Box5<express.Request>) {
b.value; // $ MISSING: hasUnderlyingType='express'.Request
b.other;
}

View File

@@ -0,0 +1,10 @@
function t1(el: HTMLElement) { } // $ hasUnderlyingType=HTMLElement
/**
* @param {HTMLInputElement} el
*/
function t2(el) { // $ hasUnderlyingType=HTMLInputElement
}
function t3(req: Express.Request) { // $ hasUnderlyingType=Express.Request
}

View File

@@ -0,0 +1,14 @@
import * as e from 'express';
import { Response } from 'express';
/**
* @param {e.Request} req
*/
function t1(req) { // $ hasUnderlyingType='express'.Request
}
/**
* @param {Response} res
*/
function t2(res) { // $ hasUnderlyingType='express'.Response
}

View File

@@ -0,0 +1,4 @@
import { Request } from 'express';
function t1(req: Request) { // $ hasUnderlyingType='express'.Request
}

View File

@@ -0,0 +1,27 @@
import Express = require('express');
namespace A {
export import E = Express;
}
namespace B {
export import Q = A
}
namespace C {
import E = Express;
export const A = E;
}
function t1(x: A.E.Request) { // $ hasUnderlyingType='express'.Request
}
function t2(x: B.Q.E.Request) { // $ hasUnderlyingType='express'.Request
}
function t3(x: typeof Express) { // $ hasUnderlyingType='express'
}
function t4(x: typeof A.E) { // $ hasUnderlyingType='express'
}
function t5(x: typeof C.A) { // $ hasUnderlyingType='express'
}

View File

@@ -0,0 +1,15 @@
import * as express from 'express';
function t1(e: typeof express) { // $ hasUnderlyingType='express'
}
function t2(req: express.Request) { // $ hasUnderlyingType='express'.Request
}
function t3(req: Request) { // $ hasUnderlyingType=Request // not in scope, refers to a global
}
type E = typeof express;
function t4(e: E) { // $ hasUnderlyingType='express'
}

View File

@@ -0,0 +1,16 @@
import * as express from 'express';
interface Foo {
req: express.Request;
e: typeof express;
}
function t1(f: Foo) {
f.req; // $ hasUnderlyingType='express'.Request
f.e; // $ hasUnderlyingType='express'
const {
req, // $ hasUnderlyingType='express'.Request
e // $ hasUnderlyingType='express'
} = f;
}

View File

@@ -0,0 +1,20 @@
import * as express from 'express';
interface MyRequest extends express.Request {
}
function t1(req: MyRequest) { // $ hasUnderlyingType='express'.Request
}
class MyRequestClass extends express.Request {
}
function t2(req: MyRequestClass) { // $ hasUnderlyingType='express'.Request
}
class MyRequestClass2 implements express.Request {
}
function t3(req: MyRequestClass2) { // $ hasUnderlyingType='express'.Request
}

View File

@@ -0,0 +1,54 @@
| calls.ts:6:5:6:16 | getRequest() | 'express'.Request |
| calls.ts:12:5:12:23 | getRequestAmbient() | 'express'.Request |
| calls.ts:20:5:20:14 | c.method() | 'express'.Request |
| calls.ts:21:5:21:20 | new C().method() | 'express'.Request |
| calls.ts:24:24:24:26 | req | 'express'.Request |
| calls.ts:29:9:29:11 | req | 'express'.Request |
| closure.use.js:9:13:9:13 | x | closure.lib.Foo |
| closure.use.js:9:13:9:13 | x | closure.reexported.Foo |
| closure.use.js:15:13:15:13 | x | closure.es.Bar |
| closure.use.js:15:13:15:13 | x | closure.reexported.Bar |
| contextualTypes.ts:4:12:4:14 | req | 'express'.Request |
| contextualTypes.ts:11:16:11:18 | req | 'express'.Request |
| contextualTypes.ts:18:16:18:18 | req | 'express'.Request |
| contextualTypes.ts:21:16:21:18 | req | 'express'.Request |
| contextualTypes.ts:27:16:27:18 | req | 'express'.Request |
| contextualTypes.ts:34:20:34:22 | req | 'express'.Request |
| contextualTypes.ts:41:16:41:18 | req | 'express'.Request |
| expressBulkExport.use.ts:3:13:3:15 | req | 'express'.Request |
| expressBulkExport.use.ts:6:13:6:15 | res | 'express'.Response |
| expressExportAssign.use.ts:3:13:3:15 | req | 'express'.Request |
| expressExportAssignWrapper.use.ts:3:13:3:15 | req | 'express'.Request |
| expressSelectiveExport.use.ts:3:13:3:15 | req | 'express'.Request |
| expressSelectiveExport.use.ts:9:13:9:15 | res | 'express'.Response |
| expressWrapperExport.use.ts:10:13:10:15 | req | 'express'.Request |
| expressWrapperExport.use.ts:13:13:13:15 | res | 'express'.Response |
| expressWrapperExport.use.ts:16:13:16:15 | req | 'express'.Request |
| expressWrapperExport.use.ts:19:13:19:15 | res | 'express'.Response |
| expressWrapperExport.use.ts:28:13:28:13 | e | 'express' |
| globals.ts:1:13:1:14 | el | HTMLElement |
| globals.ts:6:13:6:14 | el | HTMLInputElement |
| globals.ts:9:13:9:15 | req | Express.Request |
| jsdoc.js:7:13:7:15 | req | 'express'.Request |
| jsdoc.js:13:13:13:15 | res | 'express'.Response |
| namedImport.ts:3:13:3:15 | req | 'express'.Request |
| namespaceDecls.ts:14:13:14:13 | x | 'express'.Request |
| namespaceDecls.ts:17:13:17:13 | x | 'express'.Request |
| namespaceDecls.ts:20:13:20:13 | x | 'express' |
| namespaceDecls.ts:23:13:23:13 | x | 'express' |
| namespaceDecls.ts:26:13:26:13 | x | 'express' |
| namespaceImport.ts:3:13:3:13 | e | 'express' |
| namespaceImport.ts:6:13:6:15 | req | 'express'.Request |
| namespaceImport.ts:9:13:9:15 | req | Request |
| namespaceImport.ts:14:13:14:13 | e | 'express' |
| props.ts:9:5:9:9 | f.req | 'express'.Request |
| props.ts:10:5:10:7 | f.e | 'express' |
| props.ts:13:9:13:11 | req | 'express'.Request |
| props.ts:14:9:14:9 | e | 'express' |
| subtype.ts:7:13:7:15 | req | 'express'.Request |
| subtype.ts:13:13:13:15 | req | 'express'.Request |
| subtype.ts:19:13:19:15 | req | 'express'.Request |
| typeCast.ts:4:16:4:35 | e as express.Request | 'express'.Request |
| typeCast.ts:5:16:5:33 | <express.Request>e | 'express'.Request |
| typeCast.ts:6:16:6:42 | e satis ... Request | 'express'.Request |
| varAssignment.ts:4:9:4:11 | req | 'express'.Request |

View File

@@ -0,0 +1,15 @@
import javascript
bindingset[x, y]
private string join(string x, string y) {
if x = "" or y = "" then result = x + y else result = x + "." + y
}
query predicate hasUnderlyingType(DataFlow::SourceNode node, string value) {
node.hasUnderlyingType(value)
or
exists(string mod, string name |
node.hasUnderlyingType(mod, name) and
value = join("'" + mod + "'", name)
)
}

View File

@@ -0,0 +1,2 @@
query: test.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,3 @@
{
"include": ["."]
}

View File

@@ -0,0 +1,7 @@
import * as express from 'express';
function t1(e) {
var req1 = e as express.Request; // $ hasUnderlyingType='express'.Request
var req2 = <express.Request>e; // $ hasUnderlyingType='express'.Request
var req3 = e satisfies express.Request; // $ hasUnderlyingType='express'.Request
}

View File

@@ -0,0 +1,5 @@
import * as express from 'express';
function t1(e) {
var req: express.Request = e; // $ hasUnderlyingType='express'.Request
}

View File

@@ -71,6 +71,9 @@ responseSendArgument
| local/customPipe.ts:37:16:37:31 | '' + unsanitized |
| local/customPipe.ts:42:16:42:31 | '' + unsanitized |
| local/customPipe.ts:48:16:48:31 | '' + unsanitized |
| local/routes.ts:7:12:7:16 | 'foo' |
| local/routes.ts:12:12:12:16 | 'foo' |
| local/routes.ts:17:12:17:16 | 'foo' |
| local/routes.ts:32:31:32:31 | x |
| local/routes.ts:33:31:33:38 | queryObj |
| local/routes.ts:34:31:34:34 | name |