From b4f326ab0468f44f7a1804c5f14ceacd156f8151 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 29 Sep 2015 15:06:03 -0700 Subject: [PATCH] collect imports and exports in ambient external modules --- src/compiler/checker.ts | 6 ----- src/compiler/program.ts | 26 +++++++++---------- src/compiler/utilities.ts | 6 +++++ .../reference/exportsInAmbientModules1.js | 13 ++++++++++ .../exportsInAmbientModules1.symbols | 11 ++++++++ .../reference/exportsInAmbientModules1.types | 11 ++++++++ .../reference/exportsInAmbientModules2.js | 13 ++++++++++ .../exportsInAmbientModules2.symbols | 11 ++++++++ .../reference/exportsInAmbientModules2.types | 11 ++++++++ .../reference/importsInAmbientModules1.js | 13 ++++++++++ .../importsInAmbientModules1.symbols | 11 ++++++++ .../reference/importsInAmbientModules1.types | 11 ++++++++ .../reference/importsInAmbientModules2.js | 13 ++++++++++ .../importsInAmbientModules2.symbols | 11 ++++++++ .../reference/importsInAmbientModules2.types | 11 ++++++++ .../reference/importsInAmbientModules3.js | 13 ++++++++++ .../importsInAmbientModules3.symbols | 11 ++++++++ .../reference/importsInAmbientModules3.types | 11 ++++++++ .../compiler/exportsInAmbientModules1.ts | 10 +++++++ .../compiler/exportsInAmbientModules2.ts | 10 +++++++ .../compiler/importsInAmbientModules1.ts | 10 +++++++ .../compiler/importsInAmbientModules2.ts | 10 +++++++ .../compiler/importsInAmbientModules3.ts | 10 +++++++ 23 files changed, 244 insertions(+), 19 deletions(-) create mode 100644 tests/baselines/reference/exportsInAmbientModules1.js create mode 100644 tests/baselines/reference/exportsInAmbientModules1.symbols create mode 100644 tests/baselines/reference/exportsInAmbientModules1.types create mode 100644 tests/baselines/reference/exportsInAmbientModules2.js create mode 100644 tests/baselines/reference/exportsInAmbientModules2.symbols create mode 100644 tests/baselines/reference/exportsInAmbientModules2.types create mode 100644 tests/baselines/reference/importsInAmbientModules1.js create mode 100644 tests/baselines/reference/importsInAmbientModules1.symbols create mode 100644 tests/baselines/reference/importsInAmbientModules1.types create mode 100644 tests/baselines/reference/importsInAmbientModules2.js create mode 100644 tests/baselines/reference/importsInAmbientModules2.symbols create mode 100644 tests/baselines/reference/importsInAmbientModules2.types create mode 100644 tests/baselines/reference/importsInAmbientModules3.js create mode 100644 tests/baselines/reference/importsInAmbientModules3.symbols create mode 100644 tests/baselines/reference/importsInAmbientModules3.types create mode 100644 tests/cases/compiler/exportsInAmbientModules1.ts create mode 100644 tests/cases/compiler/exportsInAmbientModules2.ts create mode 100644 tests/cases/compiler/importsInAmbientModules1.ts create mode 100644 tests/cases/compiler/importsInAmbientModules2.ts create mode 100644 tests/cases/compiler/importsInAmbientModules3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f1bf504a0e..d57f9eaed1b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -948,12 +948,6 @@ namespace ts { return symbol.flags & meaning ? symbol : resolveAlias(symbol); } - function isExternalModuleNameRelative(moduleName: string): boolean { - // TypeScript 1.0 spec (April 2014): 11.2.1 - // An external module name is "relative" if the first term is "." or "..". - return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\"; - } - function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol { if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) { return; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 65eea1f9f9e..3cccb4d477a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -692,6 +692,12 @@ namespace ts { let imports: LiteralExpression[]; for (let node of file.statements) { + collect(node, /* allowRelativeModuleNames */ true); + } + + file.imports = imports || emptyArray; + + function collect(node: Node, allowRelativeModuleNames: boolean): void { switch (node.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ImportEqualsDeclaration: @@ -704,7 +710,9 @@ namespace ts { break; } - (imports || (imports = [])).push(moduleNameExpr); + if (allowRelativeModuleNames || !isExternalModuleNameRelative((moduleNameExpr).text)) { + (imports || (imports = [])).push(moduleNameExpr); + } break; case SyntaxKind.ModuleDeclaration: if ((node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) { @@ -714,23 +722,15 @@ namespace ts { // The StringLiteral must specify a top - level external module name. // Relative external module names are not permitted forEachChild((node).body, node => { - if (isExternalModuleImportEqualsDeclaration(node) && - getExternalModuleImportEqualsDeclarationExpression(node).kind === SyntaxKind.StringLiteral) { - let moduleName = getExternalModuleImportEqualsDeclarationExpression(node); - // TypeScript 1.0 spec (April 2014): 12.1.6 - // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules - // only through top - level external module names. Relative external module names are not permitted. - if (moduleName) { - (imports || (imports = [])).push(moduleName); - } - } + // TypeScript 1.0 spec (April 2014): 12.1.6 + // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules + // only through top - level external module names. Relative external module names are not permitted. + collect(node, /* allowRelativeModuleNames */ false); }); } break; } } - - file.imports = imports || emptyArray; } function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9928be4529b..0d687d599aa 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -992,6 +992,12 @@ namespace ts { } return false; } + + export function isExternalModuleNameRelative(moduleName: string): boolean { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\"; + } export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { let moduleState = getModuleInstanceState(node); diff --git a/tests/baselines/reference/exportsInAmbientModules1.js b/tests/baselines/reference/exportsInAmbientModules1.js new file mode 100644 index 00000000000..4370b197403 --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules1.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/exportsInAmbientModules1.ts] //// + +//// [external.d.ts] + +export var x: number + +//// [main.ts] + +declare module "M" { + export {x} from "external" +} + +//// [main.js] diff --git a/tests/baselines/reference/exportsInAmbientModules1.symbols b/tests/baselines/reference/exportsInAmbientModules1.symbols new file mode 100644 index 00000000000..58cdf8663a7 --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules1.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export var x: number +>x : Symbol(x, Decl(external.d.ts, 1, 10)) + +=== tests/cases/compiler/main.ts === + +declare module "M" { + export {x} from "external" +>x : Symbol(x, Decl(main.ts, 2, 12)) +} diff --git a/tests/baselines/reference/exportsInAmbientModules1.types b/tests/baselines/reference/exportsInAmbientModules1.types new file mode 100644 index 00000000000..490a63caf92 --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules1.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export var x: number +>x : number + +=== tests/cases/compiler/main.ts === + +declare module "M" { + export {x} from "external" +>x : number +} diff --git a/tests/baselines/reference/exportsInAmbientModules2.js b/tests/baselines/reference/exportsInAmbientModules2.js new file mode 100644 index 00000000000..f08ff17f8ba --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules2.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/exportsInAmbientModules2.ts] //// + +//// [external.d.ts] + +export default class C {} + +//// [main.ts] + +declare module "M" { + export * from "external" +} + +//// [main.js] diff --git a/tests/baselines/reference/exportsInAmbientModules2.symbols b/tests/baselines/reference/exportsInAmbientModules2.symbols new file mode 100644 index 00000000000..54e8b44ec34 --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules2.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : Symbol(C, Decl(external.d.ts, 0, 0)) + +=== tests/cases/compiler/main.ts === + +No type information for this code.declare module "M" { +No type information for this code. export * from "external" +No type information for this code.} +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/exportsInAmbientModules2.types b/tests/baselines/reference/exportsInAmbientModules2.types new file mode 100644 index 00000000000..3472a35bf75 --- /dev/null +++ b/tests/baselines/reference/exportsInAmbientModules2.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : C + +=== tests/cases/compiler/main.ts === + +No type information for this code.declare module "M" { +No type information for this code. export * from "external" +No type information for this code.} +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/importsInAmbientModules1.js b/tests/baselines/reference/importsInAmbientModules1.js new file mode 100644 index 00000000000..4c888f2dfe5 --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules1.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/importsInAmbientModules1.ts] //// + +//// [external.d.ts] + +export var x: number + +//// [main.ts] + +declare module "M" { + import {x} from "external" +} + +//// [main.js] diff --git a/tests/baselines/reference/importsInAmbientModules1.symbols b/tests/baselines/reference/importsInAmbientModules1.symbols new file mode 100644 index 00000000000..d220ba2bf45 --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules1.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export var x: number +>x : Symbol(x, Decl(external.d.ts, 1, 10)) + +=== tests/cases/compiler/main.ts === + +declare module "M" { + import {x} from "external" +>x : Symbol(x, Decl(main.ts, 2, 12)) +} diff --git a/tests/baselines/reference/importsInAmbientModules1.types b/tests/baselines/reference/importsInAmbientModules1.types new file mode 100644 index 00000000000..634de9f1f0f --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules1.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export var x: number +>x : number + +=== tests/cases/compiler/main.ts === + +declare module "M" { + import {x} from "external" +>x : number +} diff --git a/tests/baselines/reference/importsInAmbientModules2.js b/tests/baselines/reference/importsInAmbientModules2.js new file mode 100644 index 00000000000..84d5dd84f10 --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules2.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/importsInAmbientModules2.ts] //// + +//// [external.d.ts] + +export default class C {} + +//// [main.ts] + +declare module "M" { + import C from "external" +} + +//// [main.js] diff --git a/tests/baselines/reference/importsInAmbientModules2.symbols b/tests/baselines/reference/importsInAmbientModules2.symbols new file mode 100644 index 00000000000..02333798e8b --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules2.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : Symbol(C, Decl(external.d.ts, 0, 0)) + +=== tests/cases/compiler/main.ts === + +declare module "M" { + import C from "external" +>C : Symbol(C, Decl(main.ts, 2, 10)) +} diff --git a/tests/baselines/reference/importsInAmbientModules2.types b/tests/baselines/reference/importsInAmbientModules2.types new file mode 100644 index 00000000000..d6c4eddc07c --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules2.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : C + +=== tests/cases/compiler/main.ts === + +declare module "M" { + import C from "external" +>C : typeof C +} diff --git a/tests/baselines/reference/importsInAmbientModules3.js b/tests/baselines/reference/importsInAmbientModules3.js new file mode 100644 index 00000000000..2a8e09b53e1 --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules3.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/importsInAmbientModules3.ts] //// + +//// [external.d.ts] + +export default class C {} + +//// [main.ts] + +declare module "M" { + import C = require("external"); +} + +//// [main.js] diff --git a/tests/baselines/reference/importsInAmbientModules3.symbols b/tests/baselines/reference/importsInAmbientModules3.symbols new file mode 100644 index 00000000000..15b2c7173dc --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules3.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/main.ts === + +declare module "M" { + import C = require("external"); +>C : Symbol(C, Decl(main.ts, 1, 20)) +} +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : Symbol(C, Decl(external.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/importsInAmbientModules3.types b/tests/baselines/reference/importsInAmbientModules3.types new file mode 100644 index 00000000000..6c613687b08 --- /dev/null +++ b/tests/baselines/reference/importsInAmbientModules3.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/main.ts === + +declare module "M" { + import C = require("external"); +>C : typeof C +} +=== tests/cases/compiler/external.d.ts === + +export default class C {} +>C : C + diff --git a/tests/cases/compiler/exportsInAmbientModules1.ts b/tests/cases/compiler/exportsInAmbientModules1.ts new file mode 100644 index 00000000000..53e169fcf5d --- /dev/null +++ b/tests/cases/compiler/exportsInAmbientModules1.ts @@ -0,0 +1,10 @@ +// @module: amd + +// @filename: external.d.ts +export var x: number + +// @filename: main.ts + +declare module "M" { + export {x} from "external" +} \ No newline at end of file diff --git a/tests/cases/compiler/exportsInAmbientModules2.ts b/tests/cases/compiler/exportsInAmbientModules2.ts new file mode 100644 index 00000000000..0fbfa022d13 --- /dev/null +++ b/tests/cases/compiler/exportsInAmbientModules2.ts @@ -0,0 +1,10 @@ +// @module: amd + +// @filename: external.d.ts +export default class C {} + +// @filename: main.ts + +declare module "M" { + export * from "external" +} \ No newline at end of file diff --git a/tests/cases/compiler/importsInAmbientModules1.ts b/tests/cases/compiler/importsInAmbientModules1.ts new file mode 100644 index 00000000000..afd3b071af6 --- /dev/null +++ b/tests/cases/compiler/importsInAmbientModules1.ts @@ -0,0 +1,10 @@ +// @module: amd + +// @filename: external.d.ts +export var x: number + +// @filename: main.ts + +declare module "M" { + import {x} from "external" +} \ No newline at end of file diff --git a/tests/cases/compiler/importsInAmbientModules2.ts b/tests/cases/compiler/importsInAmbientModules2.ts new file mode 100644 index 00000000000..587d7d2069d --- /dev/null +++ b/tests/cases/compiler/importsInAmbientModules2.ts @@ -0,0 +1,10 @@ +// @module: amd + +// @filename: external.d.ts +export default class C {} + +// @filename: main.ts + +declare module "M" { + import C from "external" +} \ No newline at end of file diff --git a/tests/cases/compiler/importsInAmbientModules3.ts b/tests/cases/compiler/importsInAmbientModules3.ts new file mode 100644 index 00000000000..cae5b404b9c --- /dev/null +++ b/tests/cases/compiler/importsInAmbientModules3.ts @@ -0,0 +1,10 @@ +// @module: amd + +// @filename: external.d.ts +export default class C {} + +// @filename: main.ts + +declare module "M" { + import C = require("external"); +} \ No newline at end of file