From cb4cb7a75ff1ff5c262d6e67b169558c32b6db7f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 3 Jul 2018 11:41:07 -0700 Subject: [PATCH] Check if module reference requires type reference before path reference (#25385) --- src/compiler/checker.ts | 2 +- src/compiler/transformers/declarations.ts | 8 ++++++- src/compiler/types.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- .../referenceTypesPreferedToPathIfPossible.js | 22 +++++++++++++++++++ ...renceTypesPreferedToPathIfPossible.symbols | 19 ++++++++++++++++ ...ferenceTypesPreferedToPathIfPossible.types | 21 ++++++++++++++++++ .../referenceTypesPreferedToPathIfPossible.ts | 10 +++++++++ 8 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/referenceTypesPreferedToPathIfPossible.js create mode 100644 tests/baselines/reference/referenceTypesPreferedToPathIfPossible.symbols create mode 100644 tests/baselines/reference/referenceTypesPreferedToPathIfPossible.types create mode 100644 tests/cases/compiler/referenceTypesPreferedToPathIfPossible.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d202bad90c5..a7ef73e0730 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3747,7 +3747,7 @@ namespace ts { const ambientDecls = filter(symbol.declarations, isAmbientModule); if (length(ambientDecls)) { for (const decl of ambientDecls) { - context.tracker.trackReferencedAmbientModule(decl); + context.tracker.trackReferencedAmbientModule(decl, symbol); } } } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 35fb8e99170..055fc3d2e0f 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -66,7 +66,13 @@ namespace ts { } } - function trackReferencedAmbientModule(node: ModuleDeclaration) { + function trackReferencedAmbientModule(node: ModuleDeclaration, symbol: Symbol) { + // If it is visible via `// `, then we should just use that + const directives = resolver.getTypeReferenceDirectivesForSymbol(symbol, SymbolFlags.All); + if (length(directives)) { + return recordTypeReferenceDirectivesIfNecessary(directives); + } + // Otherwise we should emit a path-based reference const container = getSourceFileOfNode(node); refs.set("" + getOriginalNodeId(container), container); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4f1678b8c7a..a6759fa60dc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5316,7 +5316,7 @@ namespace ts { reportPrivateInBaseOfClassExpression?(propertyName: string): void; reportInaccessibleUniqueSymbolError?(): void; moduleResolverHost?: ModuleSpecifierResolutionHost; - trackReferencedAmbientModule?(decl: ModuleDeclaration): void; + trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void; } export interface TextSpan { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 848e3394327..5f428dce852 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4497,7 +4497,7 @@ declare namespace ts { reportPrivateInBaseOfClassExpression?(propertyName: string): void; reportInaccessibleUniqueSymbolError?(): void; moduleResolverHost?: ModuleSpecifierResolutionHost; - trackReferencedAmbientModule?(decl: ModuleDeclaration): void; + trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void; } interface TextSpan { start: number; diff --git a/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.js b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.js new file mode 100644 index 00000000000..1bd413b2aae --- /dev/null +++ b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.js @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/referenceTypesPreferedToPathIfPossible.ts] //// + +//// [index.d.ts] +declare module "url" { + export class Url {} + export function parse(): Url; +} +//// [usage.ts] +import { parse } from "url"; +export const thing = () => parse(); + + +//// [usage.js] +"use strict"; +exports.__esModule = true; +var url_1 = require("url"); +exports.thing = function () { return url_1.parse(); }; + + +//// [usage.d.ts] +/// +export declare const thing: () => import("url").Url; diff --git a/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.symbols b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.symbols new file mode 100644 index 00000000000..01ed9dc37c0 --- /dev/null +++ b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/usage.ts === +import { parse } from "url"; +>parse : Symbol(parse, Decl(usage.ts, 0, 8)) + +export const thing = () => parse(); +>thing : Symbol(thing, Decl(usage.ts, 1, 12)) +>parse : Symbol(parse, Decl(usage.ts, 0, 8)) + +=== node_modules/@types/node/index.d.ts === +declare module "url" { +>"url" : Symbol("url", Decl(index.d.ts, 0, 0)) + + export class Url {} +>Url : Symbol(Url, Decl(index.d.ts, 0, 22)) + + export function parse(): Url; +>parse : Symbol(parse, Decl(index.d.ts, 1, 23)) +>Url : Symbol(Url, Decl(index.d.ts, 0, 22)) +} diff --git a/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.types b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.types new file mode 100644 index 00000000000..ba443dd55e3 --- /dev/null +++ b/tests/baselines/reference/referenceTypesPreferedToPathIfPossible.types @@ -0,0 +1,21 @@ +=== tests/cases/compiler/usage.ts === +import { parse } from "url"; +>parse : () => import("url").Url + +export const thing = () => parse(); +>thing : () => import("url").Url +>() => parse() : () => import("url").Url +>parse() : import("url").Url +>parse : () => import("url").Url + +=== node_modules/@types/node/index.d.ts === +declare module "url" { +>"url" : typeof import("url") + + export class Url {} +>Url : Url + + export function parse(): Url; +>parse : () => Url +>Url : Url +} diff --git a/tests/cases/compiler/referenceTypesPreferedToPathIfPossible.ts b/tests/cases/compiler/referenceTypesPreferedToPathIfPossible.ts new file mode 100644 index 00000000000..deabc4d0ac4 --- /dev/null +++ b/tests/cases/compiler/referenceTypesPreferedToPathIfPossible.ts @@ -0,0 +1,10 @@ +// @declaration: true +// @noImplicitReferences: true +// @filename: /.src/node_modules/@types/node/index.d.ts +declare module "url" { + export class Url {} + export function parse(): Url; +} +// @filename: usage.ts +import { parse } from "url"; +export const thing = () => parse();