From a21ac115828cd76f5c500e1d2d3f440edded72e9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 31 Jul 2018 11:07:06 -0700 Subject: [PATCH] In JSDoc, resolve import types as values too (#26066) * In JSDoc, resolve import types as values too This is something that we probably should have been doing for some time. Fixes #26049 * Fix whitespace lint --- src/compiler/checker.ts | 4 +- .../reference/enumTagImported.symbols | 34 ++++++++++++++++ .../baselines/reference/enumTagImported.types | 39 +++++++++++++++++++ .../conformance/jsdoc/enumTagImported.ts | 23 +++++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/enumTagImported.symbols create mode 100644 tests/baselines/reference/enumTagImported.types create mode 100644 tests/cases/conformance/jsdoc/enumTagImported.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1e5d5984ab7..fa19694dd61 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8189,7 +8189,7 @@ namespace ts { } function isJSDocTypeReference(node: Node): node is TypeReferenceNode { - return !!(node.flags & NodeFlags.JSDoc) && node.kind === SyntaxKind.TypeReference; + return !!(node.flags & NodeFlags.JSDoc) && (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ImportType); } function checkNoTypeArguments(node: NodeWithTypeArguments, symbol?: Symbol) { @@ -9462,7 +9462,7 @@ namespace ts { links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - const targetMeaning = node.isTypeOf ? SymbolFlags.Value : SymbolFlags.Type; + const targetMeaning = node.isTypeOf ? SymbolFlags.Value : node.flags & NodeFlags.JSDoc ? SymbolFlags.Value | SymbolFlags.Type : SymbolFlags.Type; // TODO: Future work: support unions/generics/whatever via a deferred import-type const innerModuleSymbol = resolveExternalModuleName(node, node.argument.literal); if (!innerModuleSymbol) { diff --git a/tests/baselines/reference/enumTagImported.symbols b/tests/baselines/reference/enumTagImported.symbols new file mode 100644 index 00000000000..ab9ab5eceb1 --- /dev/null +++ b/tests/baselines/reference/enumTagImported.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/jsdoc/type.js === +/** @typedef {import("./mod1").TestEnum} TE */ +/** @type {TE} */ +const test = 'add' +>test : Symbol(test, Decl(type.js, 2, 5)) + +/** @type {import("./mod1").TestEnum} */ +const tost = 'remove' +>tost : Symbol(tost, Decl(type.js, 4, 5)) + +=== tests/cases/conformance/jsdoc/value.js === +import { TestEnum } from "./mod1" +>TestEnum : Symbol(TestEnum, Decl(value.js, 0, 8)) + +/** @type {TestEnum} */ +const tist = TestEnum.ADD +>tist : Symbol(tist, Decl(value.js, 2, 5)) +>TestEnum.ADD : Symbol(ADD, Decl(mod1.js, 1, 25)) +>TestEnum : Symbol(TestEnum, Decl(value.js, 0, 8)) +>ADD : Symbol(ADD, Decl(mod1.js, 1, 25)) + + +=== tests/cases/conformance/jsdoc/mod1.js === +/** @enum {string} */ +export const TestEnum = { +>TestEnum : Symbol(TestEnum, Decl(mod1.js, 1, 12)) + + ADD: 'add', +>ADD : Symbol(ADD, Decl(mod1.js, 1, 25)) + + REMOVE: 'remove' +>REMOVE : Symbol(REMOVE, Decl(mod1.js, 2, 15)) +} + diff --git a/tests/baselines/reference/enumTagImported.types b/tests/baselines/reference/enumTagImported.types new file mode 100644 index 00000000000..bd02d08d8cd --- /dev/null +++ b/tests/baselines/reference/enumTagImported.types @@ -0,0 +1,39 @@ +=== tests/cases/conformance/jsdoc/type.js === +/** @typedef {import("./mod1").TestEnum} TE */ +/** @type {TE} */ +const test = 'add' +>test : string +>'add' : "add" + +/** @type {import("./mod1").TestEnum} */ +const tost = 'remove' +>tost : string +>'remove' : "remove" + +=== tests/cases/conformance/jsdoc/value.js === +import { TestEnum } from "./mod1" +>TestEnum : { ADD: string; REMOVE: string; } + +/** @type {TestEnum} */ +const tist = TestEnum.ADD +>tist : string +>TestEnum.ADD : string +>TestEnum : { ADD: string; REMOVE: string; } +>ADD : string + + +=== tests/cases/conformance/jsdoc/mod1.js === +/** @enum {string} */ +export const TestEnum = { +>TestEnum : { ADD: string; REMOVE: string; } +>{ ADD: 'add', REMOVE: 'remove'} : { ADD: string; REMOVE: string; } + + ADD: 'add', +>ADD : string +>'add' : "add" + + REMOVE: 'remove' +>REMOVE : string +>'remove' : "remove" +} + diff --git a/tests/cases/conformance/jsdoc/enumTagImported.ts b/tests/cases/conformance/jsdoc/enumTagImported.ts new file mode 100644 index 00000000000..84ce46aa1a3 --- /dev/null +++ b/tests/cases/conformance/jsdoc/enumTagImported.ts @@ -0,0 +1,23 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: type.js +/** @typedef {import("./mod1").TestEnum} TE */ +/** @type {TE} */ +const test = 'add' +/** @type {import("./mod1").TestEnum} */ +const tost = 'remove' + +// @Filename: value.js +import { TestEnum } from "./mod1" +/** @type {TestEnum} */ +const tist = TestEnum.ADD + + +// @Filename: mod1.js + +/** @enum {string} */ +export const TestEnum = { + ADD: 'add', + REMOVE: 'remove' +}