JSDoc type reference understands require with entity name (#34804)

* resolve require with entity name postfix

For example, `require("x").c`. This is the value equivalent of
`import("x").a.b.c`, but the syntax tree is not as nicely designed for
this purpose.

Fixes #34802

* Add bug number to test

* Add optional chain test
This commit is contained in:
Nathan Shively-Sanders 2019-10-29 14:56:33 -07:00 committed by GitHub
parent f7cb2f2b86
commit 7635884224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 152 additions and 5 deletions

View File

@ -10765,11 +10765,15 @@ namespace ts {
let typeType = valueType;
if (symbol.valueDeclaration) {
const decl = getRootDeclaration(symbol.valueDeclaration);
const isRequireAlias = isVariableDeclaration(decl)
&& decl.initializer
&& isCallExpression(decl.initializer)
&& isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true)
&& valueType.symbol;
let isRequireAlias = false;
if (isVariableDeclaration(decl) && decl.initializer) {
let expr = decl.initializer;
// skip past entity names, eg `require("x").a.b.c`
while (isPropertyAccessExpression(expr)) {
expr = expr.expression;
}
isRequireAlias = isCallExpression(expr) && isRequireCall(expr, /*requireStringLiteralLikeArgument*/ true) && !!valueType.symbol;
}
if (isRequireAlias || node.kind === SyntaxKind.ImportType) {
typeType = getTypeReferenceType(node, valueType.symbol);
}

View File

@ -0,0 +1,58 @@
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToImport.js ===
// #34802
const C = require('./ex').C;
>C : Symbol(C, Decl(jsdocTypeReferenceToImport.js, 2, 5))
>require('./ex').C : Symbol(C, Decl(ex.d.ts, 0, 0))
>require : Symbol(require)
>'./ex' : Symbol("tests/cases/conformance/jsdoc/ex", Decl(ex.d.ts, 0, 0))
>C : Symbol(C, Decl(ex.d.ts, 0, 0))
const D = require('./ex')?.C;
>D : Symbol(D, Decl(jsdocTypeReferenceToImport.js, 3, 5))
>require('./ex')?.C : Symbol(C, Decl(ex.d.ts, 0, 0))
>require : Symbol(require)
>'./ex' : Symbol("tests/cases/conformance/jsdoc/ex", Decl(ex.d.ts, 0, 0))
>C : Symbol(C, Decl(ex.d.ts, 0, 0))
/** @type {C} c */
var c = new C()
>c : Symbol(c, Decl(jsdocTypeReferenceToImport.js, 5, 3))
>C : Symbol(C, Decl(jsdocTypeReferenceToImport.js, 2, 5))
c.start
>c.start : Symbol(C.start, Decl(ex.d.ts, 0, 16))
>c : Symbol(c, Decl(jsdocTypeReferenceToImport.js, 5, 3))
>start : Symbol(C.start, Decl(ex.d.ts, 0, 16))
c.end
>c.end : Symbol(C.end, Decl(ex.d.ts, 1, 17))
>c : Symbol(c, Decl(jsdocTypeReferenceToImport.js, 5, 3))
>end : Symbol(C.end, Decl(ex.d.ts, 1, 17))
/** @type {D} c */
var d = new D()
>d : Symbol(d, Decl(jsdocTypeReferenceToImport.js, 10, 3))
>D : Symbol(D, Decl(jsdocTypeReferenceToImport.js, 3, 5))
d.start
>d.start : Symbol(C.start, Decl(ex.d.ts, 0, 16))
>d : Symbol(d, Decl(jsdocTypeReferenceToImport.js, 10, 3))
>start : Symbol(C.start, Decl(ex.d.ts, 0, 16))
d.end
>d.end : Symbol(C.end, Decl(ex.d.ts, 1, 17))
>d : Symbol(d, Decl(jsdocTypeReferenceToImport.js, 10, 3))
>end : Symbol(C.end, Decl(ex.d.ts, 1, 17))
=== tests/cases/conformance/jsdoc/ex.d.ts ===
export class C {
>C : Symbol(C, Decl(ex.d.ts, 0, 0))
start: number
>start : Symbol(C.start, Decl(ex.d.ts, 0, 16))
end: number
>end : Symbol(C.end, Decl(ex.d.ts, 1, 17))
}

View File

@ -0,0 +1,62 @@
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToImport.js ===
// #34802
const C = require('./ex').C;
>C : typeof import("tests/cases/conformance/jsdoc/ex").C
>require('./ex').C : typeof import("tests/cases/conformance/jsdoc/ex").C
>require('./ex') : typeof import("tests/cases/conformance/jsdoc/ex")
>require : any
>'./ex' : "./ex"
>C : typeof import("tests/cases/conformance/jsdoc/ex").C
const D = require('./ex')?.C;
>D : typeof import("tests/cases/conformance/jsdoc/ex").C
>require('./ex')?.C : typeof import("tests/cases/conformance/jsdoc/ex").C
>require('./ex') : typeof import("tests/cases/conformance/jsdoc/ex")
>require : any
>'./ex' : "./ex"
>C : typeof import("tests/cases/conformance/jsdoc/ex").C
/** @type {C} c */
var c = new C()
>c : import("tests/cases/conformance/jsdoc/ex").C
>new C() : import("tests/cases/conformance/jsdoc/ex").C
>C : typeof import("tests/cases/conformance/jsdoc/ex").C
c.start
>c.start : number
>c : import("tests/cases/conformance/jsdoc/ex").C
>start : number
c.end
>c.end : number
>c : import("tests/cases/conformance/jsdoc/ex").C
>end : number
/** @type {D} c */
var d = new D()
>d : import("tests/cases/conformance/jsdoc/ex").C
>new D() : import("tests/cases/conformance/jsdoc/ex").C
>D : typeof import("tests/cases/conformance/jsdoc/ex").C
d.start
>d.start : number
>d : import("tests/cases/conformance/jsdoc/ex").C
>start : number
d.end
>d.end : number
>d : import("tests/cases/conformance/jsdoc/ex").C
>end : number
=== tests/cases/conformance/jsdoc/ex.d.ts ===
export class C {
>C : C
start: number
>start : number
end: number
>end : number
}

View File

@ -0,0 +1,23 @@
// #34802
// @Filename: jsdocTypeReferenceToImport.js
// @noEmit: true
// @allowJs: true
// @checkJs: true
const C = require('./ex').C;
const D = require('./ex')?.C;
/** @type {C} c */
var c = new C()
c.start
c.end
/** @type {D} c */
var d = new D()
d.start
d.end
// @Filename: ex.d.ts
export class C {
start: number
end: number
}