Add support for exporting imported symbols

This commit is contained in:
Anders Hejlsberg
2015-03-22 09:10:10 -07:00
parent a1525157c7
commit 20d1f73087
4 changed files with 56 additions and 38 deletions

View File

@@ -323,7 +323,7 @@ module ts {
if (!isExternalModule(<SourceFile>location)) break;
case SyntaxKind.ModuleDeclaration:
if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.ModuleMember)) {
if (!(result.flags & SymbolFlags.Alias && getDeclarationOfAliasSymbol(result).kind === SyntaxKind.ExportSpecifier)) {
if (result.flags & meaning || !(result.flags & SymbolFlags.Alias && getDeclarationOfAliasSymbol(result).kind === SyntaxKind.ExportSpecifier)) {
break loop;
}
result = undefined;
@@ -495,23 +495,6 @@ module ts {
return false;
}
// An alias symbol is created by one of the following declarations:
// import <symbol> = ...
// import <symbol> from ...
// import * as <symbol> from ...
// import { x as <symbol> } from ...
// export { x as <symbol> } from ...
// export = ...
// export default ...
function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.ImportClause && !!(<ImportClause>node).name ||
node.kind === SyntaxKind.NamespaceImport ||
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier ||
node.kind === SyntaxKind.ExportAssignment;
}
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration {
return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
}
@@ -10987,7 +10970,7 @@ module ts {
let node = getDeclarationOfAliasSymbol(symbol);
if (node) {
if (node.kind === SyntaxKind.ImportClause) {
return unescapeIdentifier(symbol.name) + ".default";
return getGeneratedNameForNode(<ImportDeclaration>node.parent) + ".default";
}
if (node.kind === SyntaxKind.ImportSpecifier) {
let moduleName = getGeneratedNameForNode(<ImportDeclaration>node.parent.parent.parent);
@@ -11012,7 +10995,7 @@ module ts {
}
function getExpressionNameSubstitution(node: Identifier): string {
let symbol = getNodeLinks(node).resolvedSymbol;
let symbol = getNodeLinks(node).resolvedSymbol || (isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined);
if (symbol) {
// Whan an identifier resolves to a parented symbol, it references an exported entity from
// another declaration of the same internal module.
@@ -11033,16 +11016,19 @@ module ts {
}
}
function isValueExportDeclaration(node: Node): boolean {
if (node.kind === SyntaxKind.ExportAssignment) {
return (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
}
if (node.kind === SyntaxKind.ExportDeclaration) {
let exportClause = (<ExportDeclaration>node).exportClause;
return exportClause && forEach(exportClause.elements, isValueExportDeclaration);
}
if (node.kind === SyntaxKind.ExportSpecifier) {
return isAliasResolvedToValue(getSymbolOfNode(node));
function isValueAliasDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return isAliasResolvedToValue(getSymbolOfNode(node));
case SyntaxKind.ExportDeclaration:
let exportClause = (<ExportDeclaration>node).exportClause;
return exportClause && forEach(exportClause.elements, isValueAliasDeclaration);
case SyntaxKind.ExportAssignment:
return (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
}
return false;
}
@@ -11187,7 +11173,7 @@ module ts {
return {
getGeneratedNameForNode,
getExpressionNameSubstitution,
isValueExportDeclaration,
isValueAliasDeclaration,
isReferencedAliasDeclaration,
getNodeCheckFlags,
isTopLevelValueImportEqualsWithEntityName,

View File

@@ -2598,7 +2598,12 @@ module ts {
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
return (<Declaration>parent).name === node;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return (<ImportOrExportSpecifier>parent).name === node || (<ImportOrExportSpecifier>parent).propertyName === node;
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.ExportAssignment:
@@ -3873,7 +3878,7 @@ module ts {
emitNodeWithoutSourceMap(specifier.name);
emitEnd(specifier.name);
write(" = ");
emitNodeWithoutSourceMap(name);
emitExpressionIdentifier(name);
write(";");
}
}
@@ -5003,6 +5008,13 @@ module ts {
return node.kind === SyntaxKind.ImportDeclaration && !(<ImportDeclaration>node).importClause;
}
function emitExportImportAssignments(node: Node) {
if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) {
emitExportMemberAssignments(<Identifier>(<Declaration>node).name);
}
forEachChild(node, emitExportImportAssignments);
}
function emitImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) {
if (contains(externalImports, node)) {
let exportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && (node.flags & NodeFlags.Export) !== 0;
@@ -5023,6 +5035,7 @@ module ts {
emitRequire(getExternalModuleName(node));
write(";");
emitEnd(node);
emitExportImportAssignments(node);
emitTrailingComments(node);
}
else {
@@ -5032,6 +5045,7 @@ module ts {
emit(namespaceDeclaration.name);
write(";");
}
emitExportImportAssignments(node);
}
}
}
@@ -5054,12 +5068,13 @@ module ts {
emit(node.moduleReference);
write(";");
emitEnd(node);
emitExportImportAssignments(node);
emitTrailingComments(node);
}
}
function emitExportDeclaration(node: ExportDeclaration) {
if (node.moduleSpecifier && (!node.exportClause || resolver.isValueExportDeclaration(node))) {
if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) {
emitStart(node);
let generatedName = resolver.getGeneratedNameForNode(node);
if (node.exportClause) {
@@ -5072,7 +5087,7 @@ module ts {
write(";");
}
for (let specifier of node.exportClause.elements) {
if (resolver.isValueExportDeclaration(specifier)) {
if (resolver.isValueAliasDeclaration(specifier)) {
writeLine();
emitStart(specifier);
emitContainingModuleName(specifier);
@@ -5104,7 +5119,7 @@ module ts {
}
function emitExportAssignment(node: ExportAssignment) {
if (!node.isExportEquals && resolver.isValueExportDeclaration(node)) {
if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
writeLine();
emitStart(node);
emitContainingModuleName(node);
@@ -5144,7 +5159,7 @@ module ts {
externalImports.push(<ExportDeclaration>node);
hasExportStars = true;
}
else if (resolver.isValueExportDeclaration(node)) {
else if (resolver.isValueAliasDeclaration(node)) {
// export { x, y } from "mod" where at least one export is a value symbol
externalImports.push(<ExportDeclaration>node);
}
@@ -5254,7 +5269,7 @@ module ts {
}
function emitExportEquals(emitAsReturn: boolean) {
if (exportEquals && resolver.isValueExportDeclaration(exportEquals)) {
if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
writeLine();
emitStart(exportEquals);
write(emitAsReturn ? "return " : "module.exports = ");

View File

@@ -1199,7 +1199,7 @@ module ts {
export interface EmitResolver {
getGeneratedNameForNode(node: Node): string;
getExpressionNameSubstitution(node: Identifier): string;
isValueExportDeclaration(node: Node): boolean;
isValueAliasDeclaration(node: Node): boolean;
isReferencedAliasDeclaration(node: Node): boolean;
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;

View File

@@ -834,6 +834,23 @@ module ts {
return false;
}
// An alias symbol is created by one of the following declarations:
// import <symbol> = ...
// import <symbol> from ...
// import * as <symbol> from ...
// import { x as <symbol> } from ...
// export { x as <symbol> } from ...
// export = ...
// export default ...
export function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.ImportClause && !!(<ImportClause>node).name ||
node.kind === SyntaxKind.NamespaceImport ||
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier ||
node.kind === SyntaxKind.ExportAssignment;
}
export function getClassBaseTypeNode(node: ClassDeclaration) {
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;