From 227169aae925be91402a7c78e6f7bbbdf7adb2b2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 2 Jul 2018 17:35:45 -0700 Subject: [PATCH] Check if module reference requires type reference before path reference --- 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 8fe87324a0afe..84116ae00ac4b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3997,7 +3997,7 @@ namespace ts { const ambientDecls = filter(symbol.declarations, isAmbientModule); if (length(ambientDecls)) { for (const decl of ambientDecls) { - context!.tracker.trackReferencedAmbientModule!(decl); // TODO: GH#18217 + context!.tracker.trackReferencedAmbientModule!(decl, symbol); // TODO: GH#18217 } } } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 35fb8e99170bb..055fc3d2e0f5c 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 85efeb96ea5d7..68f8724865259 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5312,7 +5312,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 b0788c45a444c..e8a60ee28ec40 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4493,7 +4493,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 0000000000000..1bd413b2aaea5 --- /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 0000000000000..01ed9dc37c04a --- /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 0000000000000..ba443dd55e388 --- /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 0000000000000..deabc4d0ac44e --- /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();