Support augmenting module with export as namespace (#27281)

* Support augmenting module with `export as namespace`

* Warn on use of merged symbol containing 'export as namespace'
This commit is contained in:
Andy
2018-10-30 11:16:26 -07:00
committed by GitHub
parent acc34bd95d
commit 176627c818
7 changed files with 256 additions and 8 deletions

View File

@@ -854,7 +854,7 @@ namespace ts {
(source.flags | target.flags) & SymbolFlags.Assignment) {
Debug.assert(source !== target);
if (!(target.flags & SymbolFlags.Transient)) {
target = cloneSymbol(target);
target = cloneSymbol(resolveSymbol(target));
}
// Javascript static-property-assignment declarations always merge, even though they are also values
if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
@@ -883,7 +883,7 @@ namespace ts {
else if (target.flags & SymbolFlags.NamespaceModule) {
error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target));
}
else {
else { // error
const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum);
const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable);
const message = isEitherEnum
@@ -947,7 +947,8 @@ namespace ts {
function mergeSymbolTable(target: SymbolTable, source: SymbolTable) {
source.forEach((sourceSymbol, id) => {
target.set(id, target.has(id) ? mergeSymbol(target.get(id)!, sourceSymbol) : sourceSymbol);
const targetSymbol = target.get(id);
target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol) : sourceSymbol);
});
}
@@ -1549,8 +1550,7 @@ namespace ts {
// If we're in an external module, we can't reference value symbols created from UMD export declarations
if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) {
const decls = result.declarations;
if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) {
if (some(result.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) {
error(errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); // TODO: GH#18217
}
}

View File

@@ -34,10 +34,10 @@ var z = 0;
=== tests/cases/compiler/duplicateVarsAcrossFileBoundaries_4.ts ===
module P { }
>P : Symbol(P, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 0))
>P : Symbol(P, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 0), Decl(duplicateVarsAcrossFileBoundaries_5.ts, 2, 3))
import p = P;
>p : Symbol(p, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 12), Decl(duplicateVarsAcrossFileBoundaries_5.ts, 2, 3))
>p : Symbol(p, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 12))
>P : Symbol(P, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 0))
var q;
@@ -52,5 +52,5 @@ import q = Q;
>Q : Symbol(Q, Decl(duplicateVarsAcrossFileBoundaries_5.ts, 0, 0))
var p;
>p : Symbol(p, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 12), Decl(duplicateVarsAcrossFileBoundaries_5.ts, 2, 3))
>p : Symbol(P, Decl(duplicateVarsAcrossFileBoundaries_4.ts, 0, 0), Decl(duplicateVarsAcrossFileBoundaries_5.ts, 2, 3))

View File

@@ -0,0 +1,50 @@
/a.d.ts(3,14): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(6,22): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(12,18): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(15,1): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,7): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,13): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,19): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
==== /a.d.ts (1 errors) ====
export as namespace a;
export const x = 0;
export const conflict = 0;
~~~~~~~~
!!! error TS2451: Cannot redeclare block-scoped variable 'conflict'.
!!! related TS6203 /b.ts:6:22: 'conflict' was also declared here.
!!! related TS6204 /b.ts:6:22: and here.
==== /b.ts (6 errors) ====
import * as a2 from "./a";
declare global {
namespace a {
export const y = 0;
export const conflict = 0;
~~~~~~~~
!!! error TS2451: Cannot redeclare block-scoped variable 'conflict'.
!!! related TS6203 /a.d.ts:3:14: 'conflict' was also declared here.
}
}
declare module "./a" {
export const z = 0;
export const conflict = 0;
~~~~~~~~
!!! error TS2451: Cannot redeclare block-scoped variable 'conflict'.
!!! related TS6203 /a.d.ts:3:14: 'conflict' was also declared here.
}
a.x + a.y + a.z + a.conflict;
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
a2.x + a2.y + a2.z + a2.conflict;

View File

@@ -0,0 +1,32 @@
//// [tests/cases/compiler/exportAsNamespace_augment.ts] ////
//// [a.d.ts]
export as namespace a;
export const x = 0;
export const conflict = 0;
//// [b.ts]
import * as a2 from "./a";
declare global {
namespace a {
export const y = 0;
export const conflict = 0;
}
}
declare module "./a" {
export const z = 0;
export const conflict = 0;
}
a.x + a.y + a.z + a.conflict;
a2.x + a2.y + a2.z + a2.conflict;
//// [b.js]
"use strict";
exports.__esModule = true;
var a2 = require("./a");
a.x + a.y + a.z + a.conflict;
a2.x + a2.y + a2.z + a2.conflict;

View File

@@ -0,0 +1,66 @@
=== /a.d.ts ===
export as namespace a;
>a : Symbol(a, Decl(a.d.ts, 0, 0))
export const x = 0;
>x : Symbol(x, Decl(a.d.ts, 1, 12))
export const conflict = 0;
>conflict : Symbol(conflict, Decl(a.d.ts, 2, 12))
=== /b.ts ===
import * as a2 from "./a";
>a2 : Symbol(a2, Decl(b.ts, 0, 6))
declare global {
>global : Symbol(global, Decl(b.ts, 0, 26))
namespace a {
>a : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
export const y = 0;
>y : Symbol(y, Decl(b.ts, 4, 20))
export const conflict = 0;
>conflict : Symbol(conflict, Decl(b.ts, 5, 20))
}
}
declare module "./a" {
>"./a" : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
export const z = 0;
>z : Symbol(z, Decl(b.ts, 10, 16))
export const conflict = 0;
>conflict : Symbol(conflict, Decl(b.ts, 11, 16))
}
a.x + a.y + a.z + a.conflict;
>a.x : Symbol(a2.x, Decl(a.d.ts, 1, 12))
>a : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
>x : Symbol(a2.x, Decl(a.d.ts, 1, 12))
>a.y : Symbol(a2.y, Decl(b.ts, 4, 20))
>a : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
>y : Symbol(a2.y, Decl(b.ts, 4, 20))
>a.z : Symbol(a2.z, Decl(b.ts, 10, 16))
>a : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
>z : Symbol(a2.z, Decl(b.ts, 10, 16))
>a.conflict : Symbol(a2.conflict, Decl(a.d.ts, 2, 12))
>a : Symbol(a2, Decl(a.d.ts, 0, 0), Decl(b.ts, 2, 16), Decl(b.ts, 7, 1))
>conflict : Symbol(a2.conflict, Decl(a.d.ts, 2, 12))
a2.x + a2.y + a2.z + a2.conflict;
>a2.x : Symbol(a2.x, Decl(a.d.ts, 1, 12))
>a2 : Symbol(a2, Decl(b.ts, 0, 6))
>x : Symbol(a2.x, Decl(a.d.ts, 1, 12))
>a2.y : Symbol(a2.y, Decl(b.ts, 4, 20))
>a2 : Symbol(a2, Decl(b.ts, 0, 6))
>y : Symbol(a2.y, Decl(b.ts, 4, 20))
>a2.z : Symbol(a2.z, Decl(b.ts, 10, 16))
>a2 : Symbol(a2, Decl(b.ts, 0, 6))
>z : Symbol(a2.z, Decl(b.ts, 10, 16))
>a2.conflict : Symbol(a2.conflict, Decl(a.d.ts, 2, 12))
>a2 : Symbol(a2, Decl(b.ts, 0, 6))
>conflict : Symbol(a2.conflict, Decl(a.d.ts, 2, 12))

View File

@@ -0,0 +1,78 @@
=== /a.d.ts ===
export as namespace a;
>a : typeof import("/a")
export const x = 0;
>x : 0
>0 : 0
export const conflict = 0;
>conflict : 0
>0 : 0
=== /b.ts ===
import * as a2 from "./a";
>a2 : typeof a2
declare global {
>global : typeof global
namespace a {
>a : typeof a2
export const y = 0;
>y : 0
>0 : 0
export const conflict = 0;
>conflict : 0
>0 : 0
}
}
declare module "./a" {
>"./a" : typeof a2
export const z = 0;
>z : 0
>0 : 0
export const conflict = 0;
>conflict : 0
>0 : 0
}
a.x + a.y + a.z + a.conflict;
>a.x + a.y + a.z + a.conflict : number
>a.x + a.y + a.z : number
>a.x + a.y : number
>a.x : 0
>a : typeof a2
>x : 0
>a.y : 0
>a : typeof a2
>y : 0
>a.z : 0
>a : typeof a2
>z : 0
>a.conflict : 0
>a : typeof a2
>conflict : 0
a2.x + a2.y + a2.z + a2.conflict;
>a2.x + a2.y + a2.z + a2.conflict : number
>a2.x + a2.y + a2.z : number
>a2.x + a2.y : number
>a2.x : 0
>a2 : typeof a2
>x : 0
>a2.y : 0
>a2 : typeof a2
>y : 0
>a2.z : 0
>a2 : typeof a2
>z : 0
>a2.conflict : 0
>a2 : typeof a2
>conflict : 0

View File

@@ -0,0 +1,22 @@
// @Filename: /a.d.ts
export as namespace a;
export const x = 0;
export const conflict = 0;
// @Filename: /b.ts
import * as a2 from "./a";
declare global {
namespace a {
export const y = 0;
export const conflict = 0;
}
}
declare module "./a" {
export const z = 0;
export const conflict = 0;
}
a.x + a.y + a.z + a.conflict;
a2.x + a2.y + a2.z + a2.conflict;