Change import type determination to not use a RE on the symbol name (#25381)

This commit is contained in:
Wesley Wigham
2018-07-02 17:43:39 -07:00
committed by GitHub
parent 5c57e14000
commit 65655f2c6b
44 changed files with 189 additions and 106 deletions
+43 -41
View File
@@ -3733,19 +3733,56 @@ namespace ts {
return top;
}
function getSpecifierForModuleSymbol(symbol: Symbol, context: NodeBuilderContext) {
const file = getDeclarationOfKind<SourceFile>(symbol, SyntaxKind.SourceFile);
if (file && file.moduleName !== undefined) {
// Use the amd name if it is available
return file.moduleName;
}
if (!file) {
if (context.tracker.trackReferencedAmbientModule) {
const ambientDecls = filter(symbol.declarations, isAmbientModule);
if (length(ambientDecls)) {
for (const decl of ambientDecls) {
context.tracker.trackReferencedAmbientModule(decl);
}
}
}
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
}
else {
if (!context.enclosingDeclaration || !context.tracker.moduleResolverHost) {
// If there's no context declaration, we can't lookup a non-ambient specifier, so we just use the symbol name
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
}
const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration));
const links = getSymbolLinks(symbol);
let specifier = links.specifierCache && links.specifierCache.get(contextFile.path);
if (!specifier) {
specifier = flatten(moduleSpecifiers.getModuleSpecifiers(
symbol,
compilerOptions,
contextFile,
context.tracker.moduleResolverHost,
context.tracker.moduleResolverHost.getSourceFiles!(), // TODO: GH#18217
{ importModuleSpecifierPreference: "non-relative" }
))[0];
links.specifierCache = links.specifierCache || createMap();
links.specifierCache.set(contextFile.path, specifier);
}
return specifier;
}
}
function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, overrideTypeArguments?: ReadonlyArray<TypeNode>): TypeNode {
const chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope)); // If we're using aliases outside the current scope, dont bother with the module
context.flags |= NodeBuilderFlags.InInitialEntityName;
const rootName = getNameOfSymbolAsWritten(chain[0], context);
context.flags ^= NodeBuilderFlags.InInitialEntityName;
const isTypeOf = meaning === SymbolFlags.Value;
if (ambientModuleSymbolRegex.test(rootName)) {
if (some(chain[0].declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
// module is root, must use `ImportTypeNode`
const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined;
const typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context);
const lit = createLiteralTypeNode(createLiteral(rootName.substring(1, rootName.length - 1)));
const lit = createLiteralTypeNode(createLiteral(getSpecifierForModuleSymbol(chain[0], context)));
if (!nonRootParts || isEntityName(nonRootParts)) {
if (nonRootParts) {
const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right;
@@ -3990,41 +4027,6 @@ namespace ts {
return "default";
}
if (symbol.declarations && symbol.declarations.length) {
if (some(symbol.declarations, hasExternalModuleSymbol) && context!.enclosingDeclaration) { // TODO: GH#18217
const file = getDeclarationOfKind<SourceFile>(symbol, SyntaxKind.SourceFile);
if (!file || !context!.tracker.moduleResolverHost) {
if (context!.tracker.trackReferencedAmbientModule) {
const ambientDecls = filter(symbol.declarations, isAmbientModule);
if (length(ambientDecls)) {
for (const decl of ambientDecls) {
context!.tracker.trackReferencedAmbientModule!(decl); // TODO: GH#18217
}
}
}
// ambient module, just use declaration/symbol name (fallthrough)
}
else {
if (file.moduleName) {
return `"${file.moduleName}"`;
}
const contextFile = getSourceFileOfNode(getOriginalNode(context!.enclosingDeclaration))!;
const links = getSymbolLinks(symbol);
let specifier = links.specifierCache && links.specifierCache.get(contextFile.path);
if (!specifier) {
specifier = flatten(moduleSpecifiers.getModuleSpecifiers(
symbol,
compilerOptions,
contextFile,
context!.tracker.moduleResolverHost!,
context!.tracker.moduleResolverHost!.getSourceFiles!(),
{ importModuleSpecifierPreference: "non-relative" }
))[0];
links.specifierCache = links.specifierCache || createMap();
links.specifierCache.set(contextFile.path, specifier);
}
return `"${specifier}"`;
}
}
const declaration = symbol.declarations[0];
const name = getNameOfDeclaration(declaration);
if (name) {
@@ -6,7 +6,7 @@ declare namespace demoNS {
>f : () => void
}
declare module 'demoModule' {
>'demoModule' : typeof 'demoModule'
>'demoModule' : typeof import("demoModule")
import alias = demoNS;
>alias : typeof alias
@@ -163,7 +163,7 @@ var q = M1.fn();
// Ambient external module in the global module
// Ambient external module with a string literal name that is a top level external module name
declare module 'external1' {
>'external1' : typeof 'external1'
>'external1' : typeof import("external1")
var q;
>q : any
@@ -20,7 +20,7 @@ var n: number;
=== tests/cases/conformance/ambient/decls.ts ===
// Ambient external module with export assignment
declare module 'equ' {
>'equ' : typeof 'equ'
>'equ' : typeof import("equ")
var x;
>x : any
@@ -30,7 +30,7 @@ declare module 'equ' {
}
declare module 'equ2' {
>'equ2' : typeof 'equ2'
>'equ2' : typeof import("equ2")
var x: number;
>x : number
@@ -97,16 +97,16 @@ module M2 {
>M2 : any
declare module 'nope' { }
>'nope' : typeof 'nope'
>'nope' : typeof import("nope")
}
// Ambient external module with a string literal name that isn't a top level external module name
declare module '../foo' { }
>'../foo' : typeof '../foo'
>'../foo' : typeof import("../foo")
// Ambient external module with export assignment and other exported members
declare module 'bar' {
>'bar' : typeof 'bar'
>'bar' : typeof import("bar")
var n;
>n : any
@@ -10,7 +10,7 @@ var c = new A();
=== tests/cases/compiler/ambientExternalModuleWithInternalImportDeclaration_0.ts ===
declare module 'M' {
>'M' : typeof 'M'
>'M' : typeof import("M")
module C {
>C : typeof C
@@ -7,7 +7,7 @@ declare module "./relativeModule" {
}
declare module ".\\relativeModule" {
>".\\relativeModule" : typeof import(".\\\\relativeModule")
>".\\relativeModule" : typeof import(".\\relativeModule")
var x: string;
>x : string
@@ -10,7 +10,7 @@ var c = new A();
=== tests/cases/compiler/ambientExternalModuleWithoutInternalImportDeclaration_0.ts ===
declare module 'M' {
>'M' : typeof 'M'
>'M' : typeof import("M")
module C {
>C : typeof C
@@ -1,9 +1,9 @@
=== tests/cases/compiler/file1.ts ===
function foo() {}
>foo : typeof foo
>foo : typeof import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export var v = 1;
>v : number
@@ -3,10 +3,10 @@ declare module "file1" {
>"file1" : typeof import("file1")
function foo(): void;
>foo : typeof foo
>foo : typeof import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export var v: number;
>v : number
@@ -1,9 +1,9 @@
=== tests/cases/compiler/file1.ts ===
class foo {}
>foo : foo
>foo : import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export var v = 1;
>v : number
@@ -3,10 +3,10 @@ declare module "file1" {
>"file1" : typeof import("file1")
class foo {}
>foo : foo
>foo : import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export var v: number;
>v : number
@@ -16,12 +16,12 @@ declare module "express" {
>"express" : typeof import("express")
function e(): e.Express;
>e : typeof e
>e : typeof import("e")
>e : any
>Express : e.Express
>Express : import("e").Express
namespace e {
>e : typeof e
>e : typeof import("e")
interface IRoute {
>IRoute : IRoute
@@ -1,9 +1,9 @@
=== tests/cases/compiler/file1.ts ===
class foo {}
>foo : foo
>foo : import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export class A {}
>A : A
@@ -3,10 +3,10 @@ declare module "file1" {
>"file1" : typeof import("file1")
class foo {}
>foo : foo
>foo : import("o")
namespace foo {
>foo : typeof foo
>foo : typeof import("o")
class A {}
>A : A
@@ -10,7 +10,7 @@ declare module "http" {
}
declare module 'intern/dojo/node!http' {
>'intern/dojo/node!http' : typeof 'intern/dojo/node!http'
>'intern/dojo/node!http' : typeof import("intern/dojo/node!http")
import http = require('http');
>http : typeof http
@@ -4,7 +4,7 @@ class List<T> { }
>T : T
declare module 'mod1' {
>'mod1' : typeof 'mod1'
>'mod1' : typeof import("mod1")
class Foo {
>Foo : Foo
@@ -12,7 +12,7 @@ declare module 'mod1' {
}
declare module 'moo' {
>'moo' : typeof 'moo'
>'moo' : typeof import("moo")
import x = require('mod1');
>x : typeof x
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/declarationEmitCrossFileImportTypeOfAmbientModule.ts] ////
//// [component.d.ts]
declare module '@namespace/component' {
export class Foo {}
}
//// [index.d.ts]
import { Foo } from "@namespace/component";
export declare const item: typeof Foo;
//// [index.ts]
import { item } from "../somepackage";
export const reeexported = item;
//// [index.js]
"use strict";
exports.__esModule = true;
var somepackage_1 = require("../somepackage");
exports.reeexported = somepackage_1.item;
//// [index.d.ts]
/// <reference path="../../types/component.d.ts" />
export declare const reeexported: typeof import("@namespace/component").Foo;
@@ -0,0 +1,23 @@
=== tests/cases/compiler/types/component.d.ts ===
declare module '@namespace/component' {
>'@namespace/component' : Symbol('@namespace/component', Decl(component.d.ts, 0, 0))
export class Foo {}
>Foo : Symbol(Foo, Decl(component.d.ts, 0, 39))
}
=== tests/cases/compiler/packages/somepackage/index.d.ts ===
import { Foo } from "@namespace/component";
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8))
export declare const item: typeof Foo;
>item : Symbol(item, Decl(index.d.ts, 1, 20))
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8))
=== tests/cases/compiler/packages/secondpackage/index.ts ===
import { item } from "../somepackage";
>item : Symbol(item, Decl(index.ts, 0, 8))
export const reeexported = item;
>reeexported : Symbol(reeexported, Decl(index.ts, 1, 12))
>item : Symbol(item, Decl(index.ts, 0, 8))
@@ -0,0 +1,23 @@
=== tests/cases/compiler/types/component.d.ts ===
declare module '@namespace/component' {
>'@namespace/component' : typeof import("@namespace/component")
export class Foo {}
>Foo : Foo
}
=== tests/cases/compiler/packages/somepackage/index.d.ts ===
import { Foo } from "@namespace/component";
>Foo : typeof Foo
export declare const item: typeof Foo;
>item : typeof Foo
>Foo : typeof Foo
=== tests/cases/compiler/packages/secondpackage/index.ts ===
import { item } from "../somepackage";
>item : typeof import("@namespace/component").Foo
export const reeexported = item;
>reeexported : typeof import("@namespace/component").Foo
>item : typeof import("@namespace/component").Foo
@@ -1,6 +1,6 @@
=== tests/cases/compiler/declaredExternalModule.ts ===
declare module 'connect' {
>'connect' : typeof 'connect'
>'connect' : typeof import("connect")
interface connectModule {
>connectModule : connectModule
@@ -1,6 +1,6 @@
=== tests/cases/compiler/declaredExternalModuleWithExportAssignment.ts ===
declare module 'connect' {
>'connect' : typeof 'connect'
>'connect' : typeof import("connect")
interface connectModule {
>connectModule : connectModule
@@ -3,7 +3,7 @@ export = foo;
>foo : any
declare namespace foo {
>foo : typeof foo
>foo : typeof import("o")
export type T = number;
>T : number
@@ -5,7 +5,7 @@ declare var io: any;
>io : any
declare module 'module' {
>'module' : typeof 'module'
>'module' : typeof import("module")
export default io;
>io : any
@@ -1,13 +1,13 @@
=== tests/cases/compiler/exportEqualsOfModule.ts ===
declare module '~popsicle/dist/request' {
>'~popsicle/dist/request' : typeof '~popsicle/dist/request'
>'~popsicle/dist/request' : typeof import("~popsicle/dist/request")
export class Request {}
>Request : Request
}
declare module '~popsicle/dist/common' {
>'~popsicle/dist/common' : typeof '~popsicle/dist/common'
>'~popsicle/dist/common' : typeof import("~popsicle/dist/common")
import { Request } from '~popsicle/dist/request';
>Request : typeof Request
@@ -17,7 +17,7 @@ declare module '~popsicle/dist/common' {
}
declare module 'popsicle' {
>'popsicle' : typeof 'popsicle'
>'popsicle' : typeof import("popsicle")
import alias = require('~popsicle/dist/common');
>alias : typeof alias
@@ -27,7 +27,7 @@ declare module 'popsicle' {
}
declare module 'popsicle-proxy-agent' {
>'popsicle-proxy-agent' : typeof 'popsicle-proxy-agent'
>'popsicle-proxy-agent' : typeof import("popsicle-proxy-agent")
import { Request } from 'popsicle';
>Request : typeof Request
@@ -1,6 +1,6 @@
=== tests/cases/compiler/externalModuleReferenceDoubleUnderscore1.ts ===
declare module 'timezonecomplete' {
>'timezonecomplete' : typeof 'timezonecomplete'
>'timezonecomplete' : typeof import("timezonecomplete")
import basics = require("__timezonecomplete/basics");
>basics : typeof basics
@@ -12,7 +12,7 @@ declare module 'timezonecomplete' {
}
declare module '__timezonecomplete/basics' {
>'__timezonecomplete/basics' : typeof '__timezonecomplete/basics'
>'__timezonecomplete/basics' : typeof import("__timezonecomplete/basics")
export enum TimeUnit {
>TimeUnit : TimeUnit
@@ -1,6 +1,6 @@
=== tests/cases/compiler/passport.d.ts ===
declare module 'passport' {
>'passport' : typeof 'passport'
>'passport' : typeof import("passport")
namespace passport {
>passport : PassportStatic
@@ -6,9 +6,9 @@ import moment = require("moment-timezone");
=== tests/cases/compiler/node_modules/moment/index.d.ts ===
declare function moment(): moment.Moment;
>moment : () => moment.Moment
>moment : () => import("omen").Moment
>moment : any
>Moment : moment.Moment
>Moment : import("omen").Moment
declare namespace moment {
>moment : () => Moment
@@ -22,7 +22,7 @@ declare namespace moment {
}
}
export = moment;
>moment : () => moment.Moment
>moment : () => import("omen").Moment
=== tests/cases/compiler/node_modules/moment-timezone/index.d.ts ===
import * as moment from 'moment';
@@ -92,7 +92,7 @@ export class c_public {
// private elements
// Export - Error ambient modules allowed only in global
declare module 'm' {
>'m' : typeof 'm'
>'m' : typeof import("m")
export class c_private {
>c_private : c_private
@@ -105,7 +105,7 @@ declare module 'm' {
=== tests/cases/compiler/privacyTopLevelAmbientExternalModuleImportWithExport_require3.ts ===
declare module 'm2' {
>'m2' : typeof 'm2'
>'m2' : typeof import("m2")
export class c_private {
>c_private : c_private
@@ -92,7 +92,7 @@ export class c_public {
// private elements
// Export - Error ambient modules allowed only in global
declare module 'm' {
>'m' : typeof 'm'
>'m' : typeof import("m")
export class c_private {
>c_private : c_private
@@ -104,7 +104,7 @@ declare module 'm' {
=== tests/cases/compiler/privacyTopLevelAmbientExternalModuleImportWithoutExport_require3.ts ===
declare module 'm2' {
>'m2' : typeof 'm2'
>'m2' : typeof import("m2")
export class c_private {
>c_private : c_private
@@ -38,7 +38,7 @@ var y: Foo2;
=== tests/cases/compiler/propertyIdentityWithPrivacyMismatch_0.ts ===
declare module 'mod1' {
>'mod1' : typeof 'mod1'
>'mod1' : typeof import("mod1")
class Foo {
>Foo : Foo
@@ -48,7 +48,7 @@ declare module 'mod1' {
}
}
declare module 'mod2' {
>'mod2' : typeof 'mod2'
>'mod2' : typeof import("mod2")
class Foo {
>Foo : Foo
@@ -1,7 +1,7 @@
=== tests/cases/compiler/quotedModuleNameMustBeAmbient.ts ===
module 'M' {}
>'M' : typeof 'M'
>'M' : typeof import("M")
declare module 'M2' {}
>'M2' : typeof 'M2'
>'M2' : typeof import("M2")
@@ -7,7 +7,7 @@ foobar;
>foobar : any
declare module 'barfoo' { export const x: number; }
>'barfoo' : typeof 'barfoo'
>'barfoo' : typeof import("barfoo")
>x : number
barfoo;
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
class Component<T, U> { }
>Component : Component<T, U>
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
class Component<T, U> { }
>Component : Component<T, U>
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
class Component<T, U> { }
>Component : Component<T, U>
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
class Component<T, U> { }
>Component : Component<T, U>
@@ -25,7 +25,7 @@ declare module JSX {
}
declare module 'elements1' {
>'elements1' : typeof 'elements1'
>'elements1' : typeof import("elements1")
class MyElement {
>MyElement : MyElement
@@ -34,7 +34,7 @@ declare module 'elements1' {
}
declare module 'elements2' {
>'elements2' : typeof 'elements2'
>'elements2' : typeof import("elements2")
class MyElement {
>MyElement : MyElement
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
class Component<T, U> { }
>Component : Component<T, U>
@@ -1,6 +1,6 @@
=== tests/cases/conformance/jsx/modules.d.ts ===
declare module 'mod' {
>'mod' : typeof 'mod'
>'mod' : typeof import("mod")
var y: any;
>y : any
@@ -35,7 +35,7 @@ module M {
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
>'react' : typeof 'react'
>'react' : typeof import("react")
var x: any;
>x : any
@@ -54,7 +54,7 @@ declare module ReactRouter {
>Thing : Thing
}
declare module 'react-router' {
>'react-router' : typeof 'react-router'
>'react-router' : typeof import("react-router")
export = ReactRouter;
>ReactRouter : typeof ReactRouter
@@ -47,13 +47,13 @@ var t = p.x;
=== tests/cases/conformance/externalModules/node_modules/math2d/index.d.ts ===
export as namespace Math2d;
>Math2d : typeof M2D
>Math2d : typeof import("2")
export = M2D;
>M2D : typeof M2D
declare namespace M2D {
>M2D : typeof M2D
>M2D : typeof import("2")
interface Point {
>Point : Point
@@ -45,13 +45,13 @@ var t = p.x;
=== tests/cases/conformance/externalModules/node_modules/math2d/index.d.ts ===
export as namespace Math2d;
>Math2d : typeof M2D
>Math2d : typeof import("2")
export = M2D;
>M2D : typeof M2D
declare namespace M2D {
>M2D : typeof M2D
>M2D : typeof import("2")
interface Point {
>Point : Point
@@ -0,0 +1,11 @@
// @declaration: true
// @filename: types/component.d.ts
declare module '@namespace/component' {
export class Foo {}
}
// @filename: packages/somepackage/index.d.ts
import { Foo } from "@namespace/component";
export declare const item: typeof Foo;
// @filename: packages/secondpackage/index.ts
import { item } from "../somepackage";
export const reeexported = item;