Merge pull request #3532 from Microsoft/exportSpecifierScoping

Make resolveName ignore export specifiers without calling getSymbol
This commit is contained in:
Jason Freeman 2015-06-17 15:05:34 -07:00
commit ab61bf2a6d
22 changed files with 303 additions and 8 deletions

View file

@ -344,21 +344,38 @@ module ts {
case SyntaxKind.SourceFile:
if (!isExternalModule(<SourceFile>location)) break;
case SyntaxKind.ModuleDeclaration:
if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.ModuleMember)) {
if (result.flags & meaning || !(result.flags & SymbolFlags.Alias && getDeclarationOfAliasSymbol(result).kind === SyntaxKind.ExportSpecifier)) {
break loop;
}
result = undefined;
}
else if (location.kind === SyntaxKind.SourceFile ||
let moduleExports = getSymbolOfNode(location).exports;
if (location.kind === SyntaxKind.SourceFile ||
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
result = getSymbolOfNode(location).exports["default"];
// It's an external module. Because of module/namespace merging, a module's exports are in scope,
// yet we never want to treat an export specifier as putting a member in scope. Therefore,
// if the name we find is purely an export specifier, it is not actually considered in scope.
// Two things to note about this:
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
// on an export specifier is that it might find the export specifier itself, and try to
// resolve it as an alias. This will cause the checker to consider the export specifier
// a circular alias reference when it might not be.
// 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely*
// an alias. If we used &, we'd be throwing out symbols that have non alias aspects,
// which is not the desired behavior.
if (hasProperty(moduleExports, name) &&
moduleExports[name].flags === SymbolFlags.Alias &&
getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) {
break;
}
result = moduleExports["default"];
let localSymbol = getLocalSymbolForExportDefault(result);
if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) {
break loop;
}
result = undefined;
}
if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) {
break loop;
}
break;
case SyntaxKind.EnumDeclaration:
if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.EnumMember)) {

View file

@ -0,0 +1,15 @@
//// [exportSpecifierAndExportedMemberDeclaration.ts]
declare module "m2" {
export module X {
interface I { }
}
function Y();
export { Y as X };
function Z(): X.I;
}
declare module "m2" {
function Z2(): X.I;
}
//// [exportSpecifierAndExportedMemberDeclaration.js]

View file

@ -0,0 +1,27 @@
=== tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts ===
declare module "m2" {
export module X {
>X : Symbol(X, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 0, 21), Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 12))
interface I { }
>I : Symbol(I, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 1, 21))
}
function Y();
>Y : Symbol(Y, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 3, 5))
export { Y as X };
>Y : Symbol(X, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 0, 21), Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 12))
>X : Symbol(X, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 0, 21), Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 12))
function Z(): X.I;
>Z : Symbol(Z, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 22))
>X : Symbol(X, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 0, 21), Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 12))
>I : Symbol(X.I, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 1, 21))
}
declare module "m2" {
function Z2(): X.I;
>Z2 : Symbol(Z2, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 9, 21))
>X : Symbol(X, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 0, 21), Decl(exportSpecifierAndExportedMemberDeclaration.ts, 5, 12))
>I : Symbol(X.I, Decl(exportSpecifierAndExportedMemberDeclaration.ts, 1, 21))
}

View file

@ -0,0 +1,27 @@
=== tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts ===
declare module "m2" {
export module X {
>X : () => any
interface I { }
>I : I
}
function Y();
>Y : () => any
export { Y as X };
>Y : () => any
>X : () => any
function Z(): X.I;
>Z : () => X.I
>X : any
>I : X.I
}
declare module "m2" {
function Z2(): X.I;
>Z2 : () => X.I
>X : any
>I : X.I
}

View file

@ -0,0 +1,18 @@
tests/cases/compiler/exportSpecifierAndLocalMemberDeclaration.ts(11,20): error TS2503: Cannot find namespace 'X'.
==== tests/cases/compiler/exportSpecifierAndLocalMemberDeclaration.ts (1 errors) ====
declare module "m2" {
module X {
interface I { }
}
function Y();
export { Y as X };
function Z(): X.I;
}
declare module "m2" {
function Z2(): X.I;
~
!!! error TS2503: Cannot find namespace 'X'.
}

View file

@ -0,0 +1,15 @@
//// [exportSpecifierAndLocalMemberDeclaration.ts]
declare module "m2" {
module X {
interface I { }
}
function Y();
export { Y as X };
function Z(): X.I;
}
declare module "m2" {
function Z2(): X.I;
}
//// [exportSpecifierAndLocalMemberDeclaration.js]

View file

@ -0,0 +1,8 @@
//// [exportSpecifierReferencingOuterDeclaration1.ts]
declare module X { export interface bar { } }
declare module "m" {
export { X };
export function foo(): X.bar;
}
//// [exportSpecifierReferencingOuterDeclaration1.js]

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration1.ts ===
declare module X { export interface bar { } }
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 0, 0))
>bar : Symbol(bar, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 0, 18))
declare module "m" {
export { X };
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 2, 12))
export function foo(): X.bar;
>foo : Symbol(foo, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 2, 17))
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 0, 0))
>bar : Symbol(X.bar, Decl(exportSpecifierReferencingOuterDeclaration1.ts, 0, 18))
}

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration1.ts ===
declare module X { export interface bar { } }
>X : any
>bar : bar
declare module "m" {
export { X };
>X : any
export function foo(): X.bar;
>foo : () => X.bar
>X : any
>bar : X.bar
}

View file

@ -0,0 +1,11 @@
//// [tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2.ts] ////
//// [exportSpecifierReferencingOuterDeclaration2_A.ts]
declare module X { export interface bar { } }
//// [exportSpecifierReferencingOuterDeclaration2_B.ts]
export { X };
export declare function foo(): X.bar;
//// [exportSpecifierReferencingOuterDeclaration2_A.js]
//// [exportSpecifierReferencingOuterDeclaration2_B.js]

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_A.ts ===
declare module X { export interface bar { } }
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration2_A.ts, 0, 0))
>bar : Symbol(bar, Decl(exportSpecifierReferencingOuterDeclaration2_A.ts, 0, 18))
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_B.ts ===
export { X };
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration2_B.ts, 0, 8))
export declare function foo(): X.bar;
>foo : Symbol(foo, Decl(exportSpecifierReferencingOuterDeclaration2_B.ts, 0, 13))
>X : Symbol(X, Decl(exportSpecifierReferencingOuterDeclaration2_A.ts, 0, 0))
>bar : Symbol(X.bar, Decl(exportSpecifierReferencingOuterDeclaration2_A.ts, 0, 18))

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_A.ts ===
declare module X { export interface bar { } }
>X : any
>bar : bar
=== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_B.ts ===
export { X };
>X : any
export declare function foo(): X.bar;
>foo : () => X.bar
>X : any
>bar : X.bar

View file

@ -0,0 +1,13 @@
tests/cases/compiler/exportSpecifierReferencingOuterDeclaration3.ts(6,30): error TS2305: Module 'X' has no exported member 'bar'.
==== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration3.ts (1 errors) ====
declare module X { export interface bar { } }
declare module "m" {
module X { export interface foo { } }
export { X };
export function foo(): X.foo;
export function bar(): X.bar; // error
~~~
!!! error TS2305: Module 'X' has no exported member 'bar'.
}

View file

@ -0,0 +1,10 @@
//// [exportSpecifierReferencingOuterDeclaration3.ts]
declare module X { export interface bar { } }
declare module "m" {
module X { export interface foo { } }
export { X };
export function foo(): X.foo;
export function bar(): X.bar; // error
}
//// [exportSpecifierReferencingOuterDeclaration3.js]

View file

@ -0,0 +1,13 @@
tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_B.ts(4,34): error TS2305: Module 'X' has no exported member 'bar'.
==== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_A.ts (0 errors) ====
declare module X { export interface bar { } }
==== tests/cases/compiler/exportSpecifierReferencingOuterDeclaration2_B.ts (1 errors) ====
declare module X { export interface foo { } }
export { X };
export declare function foo(): X.foo;
export declare function bar(): X.bar; // error
~~~
!!! error TS2305: Module 'X' has no exported member 'bar'.

View file

@ -0,0 +1,13 @@
//// [tests/cases/compiler/exportSpecifierReferencingOuterDeclaration4.ts] ////
//// [exportSpecifierReferencingOuterDeclaration2_A.ts]
declare module X { export interface bar { } }
//// [exportSpecifierReferencingOuterDeclaration2_B.ts]
declare module X { export interface foo { } }
export { X };
export declare function foo(): X.foo;
export declare function bar(): X.bar; // error
//// [exportSpecifierReferencingOuterDeclaration2_A.js]
//// [exportSpecifierReferencingOuterDeclaration2_B.js]

View file

@ -0,0 +1,12 @@
declare module "m2" {
export module X {
interface I { }
}
function Y();
export { Y as X };
function Z(): X.I;
}
declare module "m2" {
function Z2(): X.I;
}

View file

@ -0,0 +1,12 @@
declare module "m2" {
module X {
interface I { }
}
function Y();
export { Y as X };
function Z(): X.I;
}
declare module "m2" {
function Z2(): X.I;
}

View file

@ -0,0 +1,5 @@
declare module X { export interface bar { } }
declare module "m" {
export { X };
export function foo(): X.bar;
}

View file

@ -0,0 +1,7 @@
// @module: commonjs
// @Filename: exportSpecifierReferencingOuterDeclaration2_A.ts
declare module X { export interface bar { } }
// @Filename: exportSpecifierReferencingOuterDeclaration2_B.ts
export { X };
export declare function foo(): X.bar;

View file

@ -0,0 +1,7 @@
declare module X { export interface bar { } }
declare module "m" {
module X { export interface foo { } }
export { X };
export function foo(): X.foo;
export function bar(): X.bar; // error
}

View file

@ -0,0 +1,9 @@
// @module: commonjs
// @Filename: exportSpecifierReferencingOuterDeclaration2_A.ts
declare module X { export interface bar { } }
// @Filename: exportSpecifierReferencingOuterDeclaration2_B.ts
declare module X { export interface foo { } }
export { X };
export declare function foo(): X.foo;
export declare function bar(): X.bar; // error