Resolve SymbolFlags.Type only at first in jsdoc getTypeFromTypeReference (#32947)

* Fix lookup of exported eunm type alias in local scope in JS

* Fix by adjusting type lookup fallback behavior to not include SymbolFlags.Value in its initial lookup instead
This commit is contained in:
Wesley Wigham 2019-08-19 11:31:47 -07:00 committed by GitHub
parent 2cde3b722a
commit d9f0212324
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 248 additions and 7 deletions

View File

@ -9165,12 +9165,12 @@ namespace ts {
return undefined;
}
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags) {
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags, ignoreErrors?: boolean) {
if (!typeReferenceName) {
return unknownSymbol;
}
return resolveEntityName(typeReferenceName, meaning) || unknownSymbol;
return resolveEntityName(typeReferenceName, meaning, ignoreErrors) || unknownSymbol;
}
function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type {
@ -9362,10 +9362,19 @@ namespace ts {
if (!links.resolvedType) {
let symbol: Symbol | undefined;
let type: Type | undefined;
let meaning = SymbolFlags.Type;
const meaning = SymbolFlags.Type;
if (isJSDocTypeReference(node)) {
type = getIntendedTypeFromJSDocTypeReference(node);
meaning |= SymbolFlags.Value;
if (!type) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning, /*ignoreErrors*/ true);
if (symbol === unknownSymbol) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning | SymbolFlags.Value);
}
else {
resolveTypeReferenceName(getTypeReferenceName(node), meaning); // Resolve again to mark errors, if any
}
type = getTypeReferenceType(node, symbol);
}
}
if (!type) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning);

View File

@ -0,0 +1,86 @@
=== tests/cases/compiler/usage.js ===
const { Thing, useThing, cbThing } = require("./index");
>Thing : Symbol(Thing, Decl(usage.js, 0, 7))
>useThing : Symbol(useThing, Decl(usage.js, 0, 14))
>cbThing : Symbol(cbThing, Decl(usage.js, 0, 24))
>require : Symbol(require)
>"./index" : Symbol("tests/cases/compiler/index", Decl(index.js, 0, 0))
useThing(Thing.a);
>useThing : Symbol(useThing, Decl(usage.js, 0, 14))
>Thing : Symbol(Thing, Decl(usage.js, 0, 7))
/**
* @typedef {Object} LogEntry
* @property {string} type
* @property {number} time
*/
cbThing(type => {
>cbThing : Symbol(cbThing, Decl(usage.js, 0, 24))
>type : Symbol(type, Decl(usage.js, 10, 8))
/** @type {LogEntry} */
const logEntry = {
>logEntry : Symbol(logEntry, Decl(usage.js, 12, 9))
time: Date.now(),
>time : Symbol(time, Decl(usage.js, 12, 22))
>Date.now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
>now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --))
type,
>type : Symbol(type, Decl(usage.js, 13, 25))
};
});
=== tests/cases/compiler/index.js ===
/** @enum {string} */
const Thing = Object.freeze({
>Thing : Symbol(Thing, Decl(index.js, 1, 5), Decl(index.js, 0, 4))
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
a: "thing",
>a : Symbol(a, Decl(index.js, 1, 29))
b: "chill"
>b : Symbol(b, Decl(index.js, 2, 15))
});
exports.Thing = Thing;
>exports.Thing : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
>exports : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
>Thing : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
>Thing : Symbol(Thing, Decl(index.js, 1, 5), Decl(index.js, 0, 4))
/**
* @param {Thing} x
*/
function useThing(x) {}
>useThing : Symbol(useThing, Decl(index.js, 6, 22))
>x : Symbol(x, Decl(index.js, 11, 18))
exports.useThing = useThing;
>exports.useThing : Symbol(useThing, Decl(index.js, 11, 23))
>exports : Symbol(useThing, Decl(index.js, 11, 23))
>useThing : Symbol(useThing, Decl(index.js, 11, 23))
>useThing : Symbol(useThing, Decl(index.js, 6, 22))
/**
* @param {(x: Thing) => void} x
*/
function cbThing(x) {}
>cbThing : Symbol(cbThing, Decl(index.js, 13, 28))
>x : Symbol(x, Decl(index.js, 18, 17))
exports.cbThing = cbThing;
>exports.cbThing : Symbol(cbThing, Decl(index.js, 18, 22))
>exports : Symbol(cbThing, Decl(index.js, 18, 22))
>cbThing : Symbol(cbThing, Decl(index.js, 18, 22))
>cbThing : Symbol(cbThing, Decl(index.js, 13, 28))

View File

@ -0,0 +1,101 @@
=== tests/cases/compiler/usage.js ===
const { Thing, useThing, cbThing } = require("./index");
>Thing : any
>useThing : (x: string) => void
>cbThing : (x: (x: string) => void) => void
>require("./index") : typeof import("tests/cases/compiler/index")
>require : any
>"./index" : "./index"
useThing(Thing.a);
>useThing(Thing.a) : void
>useThing : (x: string) => void
>Thing.a : error
>Thing : any
>a : any
/**
* @typedef {Object} LogEntry
* @property {string} type
* @property {number} time
*/
cbThing(type => {
>cbThing(type => { /** @type {LogEntry} */ const logEntry = { time: Date.now(), type, };}) : void
>cbThing : (x: (x: string) => void) => void
>type => { /** @type {LogEntry} */ const logEntry = { time: Date.now(), type, };} : (type: string) => void
>type : string
/** @type {LogEntry} */
const logEntry = {
>logEntry : LogEntry
>{ time: Date.now(), type, } : { time: number; type: string; }
time: Date.now(),
>time : number
>Date.now() : number
>Date.now : () => number
>Date : DateConstructor
>now : () => number
type,
>type : string
};
});
=== tests/cases/compiler/index.js ===
/** @enum {string} */
const Thing = Object.freeze({
>Thing : Readonly<{ a: string; b: string; }>
>Object.freeze({ a: "thing", b: "chill"}) : Readonly<{ a: string; b: string; }>
>Object.freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T>(a: T[]): readonly T[]; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>{ a: "thing", b: "chill"} : { a: string; b: string; }
a: "thing",
>a : string
>"thing" : "thing"
b: "chill"
>b : string
>"chill" : "chill"
});
exports.Thing = Thing;
>exports.Thing = Thing : Readonly<{ a: string; b: string; }>
>exports.Thing : error
>exports : typeof import("tests/cases/compiler/index")
>Thing : any
>Thing : Readonly<{ a: string; b: string; }>
/**
* @param {Thing} x
*/
function useThing(x) {}
>useThing : (x: string) => void
>x : string
exports.useThing = useThing;
>exports.useThing = useThing : (x: string) => void
>exports.useThing : (x: string) => void
>exports : typeof import("tests/cases/compiler/index")
>useThing : (x: string) => void
>useThing : (x: string) => void
/**
* @param {(x: Thing) => void} x
*/
function cbThing(x) {}
>cbThing : (x: (x: string) => void) => void
>x : (x: string) => void
exports.cbThing = cbThing;
>exports.cbThing = cbThing : (x: (x: string) => void) => void
>exports.cbThing : (x: (x: string) => void) => void
>exports : typeof import("tests/cases/compiler/index")
>cbThing : (x: (x: string) => void) => void
>cbThing : (x: (x: string) => void) => void

View File

@ -0,0 +1,45 @@
// @noEmit: true
// @checkJs: true
// @allowJs: true
// @filename: index.js
/** @enum {string} */
const Thing = Object.freeze({
a: "thing",
b: "chill"
});
exports.Thing = Thing;
/**
* @param {Thing} x
*/
function useThing(x) {}
exports.useThing = useThing;
/**
* @param {(x: Thing) => void} x
*/
function cbThing(x) {}
exports.cbThing = cbThing;
// @filename: usage.js
const { Thing, useThing, cbThing } = require("./index");
useThing(Thing.a);
/**
* @typedef {Object} LogEntry
* @property {string} type
* @property {number} time
*/
cbThing(type => {
/** @type {LogEntry} */
const logEntry = {
time: Date.now(),
type,
};
});

@ -1 +1 @@
Subproject commit 24780bbc608810d874575791bffeb0148e311fef
Subproject commit 437b83f0337a5d57ce7dd976d2c3b44cb2037e45

@ -1 +1 @@
Subproject commit faa452718e5b257ffe262f410e52f676b6587e80
Subproject commit b6b29502eb6a75fe3869806f0e7b27195fe51b0d

@ -1 +1 @@
Subproject commit 3675f64e518c358c22e044624787ad0446e59cf9
Subproject commit 743ae6da9a6fc3b459a7ab3bb250fb07d14f9c5d