Merge pull request #5588 from Microsoft/reexport-default-export

Reexport default export
This commit is contained in:
Nathan Shively-Sanders 2015-11-11 11:29:31 -08:00
commit c1ea85fa72
5 changed files with 113 additions and 22 deletions

View file

@ -486,9 +486,19 @@ namespace ts {
if (location.kind === SyntaxKind.SourceFile || if (location.kind === SyntaxKind.SourceFile ||
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) { (location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
// It's an external module. Because of module/namespace merging, a module's exports are in scope, // It's an external module. First see if the module has an export default and if the local
// yet we never want to treat an export specifier as putting a member in scope. Therefore, // name of that export default matches.
// if the name we find is purely an export specifier, it is not actually considered in scope. if (result = moduleExports["default"]) {
const localSymbol = getLocalSymbolForExportDefault(result);
if (localSymbol && (result.flags & meaning) && localSymbol.name === name) {
break loop;
}
result = undefined;
}
// 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: // Two things to note about this:
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol // 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 // on an export specifier is that it might find the export specifier itself, and try to
@ -502,13 +512,6 @@ namespace ts {
getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) { getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) {
break; break;
} }
result = moduleExports["default"];
const localSymbol = getLocalSymbolForExportDefault(result);
if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) {
break loop;
}
result = undefined;
} }
if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) { if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) {
@ -4201,12 +4204,12 @@ namespace ts {
// We only support expressions that are simple qualified names. For other expressions this produces undefined. // We only support expressions that are simple qualified names. For other expressions this produces undefined.
const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName : const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression : isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
undefined; undefined;
const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol; const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
const type = symbol === unknownSymbol ? unknownType : const type = symbol === unknownSymbol ? unknownType :
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) : symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) : symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
getTypeFromNonGenericTypeReference(node, symbol); getTypeFromNonGenericTypeReference(node, symbol);
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
// type reference in checkTypeReferenceOrExpressionWithTypeArguments. // type reference in checkTypeReferenceOrExpressionWithTypeArguments.
links.resolvedSymbol = symbol; links.resolvedSymbol = symbol;
@ -11446,7 +11449,7 @@ namespace ts {
// Abstract methods can't have an implementation -- in particular, they don't need one. // Abstract methods can't have an implementation -- in particular, they don't need one.
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) { !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) {
reportImplementationExpectedError(lastSeenNonAmbientDeclaration); reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
} }
@ -14380,8 +14383,8 @@ namespace ts {
if (className) { if (className) {
copySymbol(location.symbol, meaning); copySymbol(location.symbol, meaning);
} }
// fall through; this fall-through is necessary because we would like to handle // fall through; this fall-through is necessary because we would like to handle
// type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration
case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration: case SyntaxKind.InterfaceDeclaration:
// If we didn't come from static member of class or interface, // If we didn't come from static member of class or interface,
@ -14537,8 +14540,8 @@ namespace ts {
return resolveEntityName(<EntityName>entityName, meaning); return resolveEntityName(<EntityName>entityName, meaning);
} }
else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) || else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) ||
(entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) || (entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) ||
(entityName.parent.kind === SyntaxKind.JsxClosingElement)) { (entityName.parent.kind === SyntaxKind.JsxClosingElement)) {
return getJsxElementTagSymbol(<JsxOpeningLikeElement>entityName.parent); return getJsxElementTagSymbol(<JsxOpeningLikeElement>entityName.parent);
} }
else if (isExpression(entityName)) { else if (isExpression(entityName)) {
@ -14605,8 +14608,8 @@ namespace ts {
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node); : getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
} }
else if (node.parent.kind === SyntaxKind.BindingElement && else if (node.parent.kind === SyntaxKind.BindingElement &&
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
node === (<BindingElement>node.parent).propertyName) { node === (<BindingElement>node.parent).propertyName) {
const typeOfPattern = getTypeOfNode(node.parent.parent); const typeOfPattern = getTypeOfNode(node.parent.parent);
const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text); const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text);
@ -14643,7 +14646,7 @@ namespace ts {
(<ImportDeclaration>node.parent).moduleSpecifier === node)) { (<ImportDeclaration>node.parent).moduleSpecifier === node)) {
return resolveExternalModuleName(node, <LiteralExpression>node); return resolveExternalModuleName(node, <LiteralExpression>node);
} }
// Fall through // Fall through
case SyntaxKind.NumericLiteral: case SyntaxKind.NumericLiteral:
// index access // index access
@ -14839,7 +14842,7 @@ namespace ts {
if (links.isNestedRedeclaration === undefined) { if (links.isNestedRedeclaration === undefined) {
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
links.isNestedRedeclaration = isStatementWithLocals(container) && links.isNestedRedeclaration = isStatementWithLocals(container) &&
!!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
} }
return links.isNestedRedeclaration; return links.isNestedRedeclaration;
} }

View file

@ -0,0 +1,27 @@
//// [tests/cases/conformance/es6/modules/reExportDefaultExport.ts] ////
//// [m1.ts]
export default function f() {
}
export {f};
//// [m2.ts]
import foo from "./m1";
import {f} from "./m1";
f();
foo();
//// [m1.js]
function f() {
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = f;
exports.f = f;
//// [m2.js]
var m1_1 = require("./m1");
var m1_2 = require("./m1");
m1_2.f();
m1_1.default();

View file

@ -0,0 +1,22 @@
=== tests/cases/conformance/es6/modules/m1.ts ===
export default function f() {
>f : Symbol(f, Decl(m1.ts, 0, 0))
}
export {f};
>f : Symbol(f, Decl(m1.ts, 3, 8))
=== tests/cases/conformance/es6/modules/m2.ts ===
import foo from "./m1";
>foo : Symbol(foo, Decl(m2.ts, 0, 6))
import {f} from "./m1";
>f : Symbol(f, Decl(m2.ts, 1, 8))
f();
>f : Symbol(f, Decl(m2.ts, 1, 8))
foo();
>foo : Symbol(foo, Decl(m2.ts, 0, 6))

View file

@ -0,0 +1,24 @@
=== tests/cases/conformance/es6/modules/m1.ts ===
export default function f() {
>f : () => void
}
export {f};
>f : () => void
=== tests/cases/conformance/es6/modules/m2.ts ===
import foo from "./m1";
>foo : () => void
import {f} from "./m1";
>f : () => void
f();
>f() : void
>f : () => void
foo();
>foo() : void
>foo : () => void

View file

@ -0,0 +1,15 @@
// @module: commonjs
// @target: ES5
// @filename: m1.ts
export default function f() {
}
export {f};
// @filename: m2.ts
import foo from "./m1";
import {f} from "./m1";
f();
foo();