mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-11 10:46:28 -05:00
Support for 'export *' declarations
This commit is contained in:
@@ -316,6 +316,13 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindExportDeclaration(node: ExportDeclaration) {
|
||||
if (!node.exportClause) {
|
||||
((<ExportContainer>container).exportStars || ((<ExportContainer>container).exportStars = [])).push(node);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration) {
|
||||
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
@@ -477,6 +484,9 @@ module ts {
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
bindExportDeclaration(<ExportDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.ImportClause:
|
||||
if ((<ImportClause>node).name) {
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
|
||||
@@ -179,7 +179,7 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function extendSymbol(target: Symbol, source: Symbol) {
|
||||
function mergeSymbol(target: Symbol, source: Symbol) {
|
||||
if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
|
||||
if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
|
||||
// reset flag when merging instantiated module into value module that has only const enums
|
||||
@@ -192,11 +192,11 @@ module ts {
|
||||
});
|
||||
if (source.members) {
|
||||
if (!target.members) target.members = {};
|
||||
extendSymbolTable(target.members, source.members);
|
||||
mergeSymbolTable(target.members, source.members);
|
||||
}
|
||||
if (source.exports) {
|
||||
if (!target.exports) target.exports = {};
|
||||
extendSymbolTable(target.exports, source.exports);
|
||||
mergeSymbolTable(target.exports, source.exports);
|
||||
}
|
||||
recordMergedSymbol(target, source);
|
||||
}
|
||||
@@ -222,7 +222,7 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function extendSymbolTable(target: SymbolTable, source: SymbolTable) {
|
||||
function mergeSymbolTable(target: SymbolTable, source: SymbolTable) {
|
||||
for (var id in source) {
|
||||
if (hasProperty(source, id)) {
|
||||
if (!hasProperty(target, id)) {
|
||||
@@ -233,12 +233,20 @@ module ts {
|
||||
if (!(symbol.flags & SymbolFlags.Merged)) {
|
||||
target[id] = symbol = cloneSymbol(symbol);
|
||||
}
|
||||
extendSymbol(symbol, source[id]);
|
||||
mergeSymbol(symbol, source[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extendSymbolTable(target: SymbolTable, source: SymbolTable) {
|
||||
for (var id in source) {
|
||||
if (!hasProperty(target, id)) {
|
||||
target[id] = source[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolLinks(symbol: Symbol): SymbolLinks {
|
||||
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
|
||||
if (!symbol.id) symbol.id = nextSymbolId++;
|
||||
@@ -486,7 +494,7 @@ module ts {
|
||||
if (moduleSymbol) {
|
||||
var name = specifier.propertyName || specifier.name;
|
||||
if (name.text) {
|
||||
var symbol = getSymbol(moduleSymbol.exports, name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
var symbol = getSymbol(getExportsOfSymbol(moduleSymbol), name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
if (!symbol) {
|
||||
error(name, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), declarationNameToString(name));
|
||||
return;
|
||||
@@ -587,7 +595,7 @@ module ts {
|
||||
else if (name.kind === SyntaxKind.QualifiedName) {
|
||||
var namespace = resolveEntityName(location,(<QualifiedName>name).left, SymbolFlags.Namespace);
|
||||
if (!namespace || namespace === unknownSymbol || getFullWidth((<QualifiedName>name).right) === 0) return;
|
||||
var symbol = getSymbol(namespace.exports,(<QualifiedName>name).right.text, meaning);
|
||||
var symbol = getSymbol(getExportsOfSymbol(namespace), (<QualifiedName>name).right.text, meaning);
|
||||
if (!symbol) {
|
||||
error(location, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace),
|
||||
declarationNameToString((<QualifiedName>name).right));
|
||||
@@ -708,6 +716,41 @@ module ts {
|
||||
};
|
||||
}
|
||||
|
||||
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
|
||||
return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports;
|
||||
}
|
||||
|
||||
function getExportsOfModule(symbol: Symbol): SymbolTable {
|
||||
var links = getSymbolLinks(symbol);
|
||||
return links.resolvedExports || (links.resolvedExports = getExportsForModule(symbol));
|
||||
}
|
||||
|
||||
function getExportsForModule(symbol: Symbol): SymbolTable {
|
||||
var result: SymbolTable;
|
||||
var visitedSymbols: Symbol[] = [];
|
||||
visit(symbol);
|
||||
return result;
|
||||
|
||||
function visit(symbol: Symbol) {
|
||||
if (!contains(visitedSymbols, symbol)) {
|
||||
visitedSymbols.push(symbol);
|
||||
if (!result) {
|
||||
result = symbol.exports;
|
||||
}
|
||||
else {
|
||||
extendSymbolTable(result, symbol.exports);
|
||||
}
|
||||
forEach(symbol.declarations, node => {
|
||||
if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) {
|
||||
forEach((<ExportContainer>node).exportStars, exportStar => {
|
||||
visit(resolveExternalModuleName(exportStar, exportStar.moduleSpecifier));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMergedSymbol(symbol: Symbol): Symbol {
|
||||
var merged: Symbol;
|
||||
return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
|
||||
@@ -2475,7 +2518,7 @@ module ts {
|
||||
var callSignatures: Signature[] = emptyArray;
|
||||
var constructSignatures: Signature[] = emptyArray;
|
||||
if (symbol.flags & SymbolFlags.HasExports) {
|
||||
members = symbol.exports;
|
||||
members = getExportsOfSymbol(symbol);
|
||||
}
|
||||
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
|
||||
callSignatures = getSignaturesOfSymbol(symbol);
|
||||
@@ -10468,7 +10511,7 @@ module ts {
|
||||
// Initialize global symbol table
|
||||
forEach(host.getSourceFiles(), file => {
|
||||
if (!isExternalModule(file)) {
|
||||
extendSymbolTable(globals, file.locals);
|
||||
mergeSymbolTable(globals, file.locals);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3057,11 +3057,15 @@ module ts {
|
||||
return <ModuleDeclaration>node;
|
||||
}
|
||||
|
||||
function emitContainingModuleName(node: Node) {
|
||||
var container = getContainingModule(node);
|
||||
write(container ? resolver.getGeneratedNameForNode(container) : "exports");
|
||||
}
|
||||
|
||||
function emitModuleMemberName(node: Declaration) {
|
||||
emitStart(node.name);
|
||||
if (getCombinedNodeFlags(node) & NodeFlags.Export) {
|
||||
var container = getContainingModule(node);
|
||||
write(container ? resolver.getGeneratedNameForNode(container) : "exports");
|
||||
emitContainingModuleName(node);
|
||||
write(".");
|
||||
}
|
||||
emitNode(node.name);
|
||||
@@ -3073,7 +3077,8 @@ module ts {
|
||||
forEach(exportSpecifiers[name.text], specifier => {
|
||||
writeLine();
|
||||
emitStart(specifier.name);
|
||||
write("exports.");
|
||||
emitContainingModuleName(specifier);
|
||||
write(".");
|
||||
emitNode(specifier.name);
|
||||
emitEnd(specifier.name);
|
||||
write(" = ");
|
||||
@@ -4117,27 +4122,41 @@ module ts {
|
||||
}
|
||||
|
||||
function emitExportDeclaration(node: ExportDeclaration) {
|
||||
if (node.exportClause && node.moduleSpecifier) {
|
||||
var generatedName = resolver.getGeneratedNameForNode(node);
|
||||
if (node.moduleSpecifier) {
|
||||
emitStart(node);
|
||||
var generatedName = resolver.getGeneratedNameForNode(node);
|
||||
if (compilerOptions.module !== ModuleKind.AMD) {
|
||||
write("var ");
|
||||
write(generatedName);
|
||||
write(" = ");
|
||||
emitRequire(getExternalModuleName(node));
|
||||
}
|
||||
forEach(node.exportClause.elements, specifier => {
|
||||
if (node.exportClause) {
|
||||
// export { x, y, ... }
|
||||
forEach(node.exportClause.elements, specifier => {
|
||||
writeLine();
|
||||
emitStart(specifier);
|
||||
emitContainingModuleName(specifier);
|
||||
write(".");
|
||||
emitNode(specifier.name);
|
||||
write(" = ");
|
||||
write(generatedName);
|
||||
write(".");
|
||||
emitNode(specifier.propertyName || specifier.name);
|
||||
write(";");
|
||||
emitEnd(specifier);
|
||||
});
|
||||
}
|
||||
else {
|
||||
// export *
|
||||
var tempName = createTempVariable(node).text;
|
||||
writeLine();
|
||||
emitStart(specifier);
|
||||
write("exports.");
|
||||
emitNode(specifier.name);
|
||||
write(" = ");
|
||||
write(generatedName);
|
||||
write(".");
|
||||
emitNode(specifier.propertyName || specifier.name);
|
||||
write(";");
|
||||
emitEnd(specifier);
|
||||
});
|
||||
write("for (var " + tempName + " in " + generatedName + ") if (!");
|
||||
emitContainingModuleName(node);
|
||||
write(".hasOwnProperty(" + tempName + ")) ");
|
||||
emitContainingModuleName(node);
|
||||
write("[" + tempName + "] = " + generatedName + "[" + tempName + "];");
|
||||
}
|
||||
emitEnd(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,13 +352,13 @@ module ts {
|
||||
// Specific context the parser was in when this node was created. Normally undefined.
|
||||
// Only set when the parser was in some interesting context (like async/yield).
|
||||
parserContextFlags?: ParserContextFlags;
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
}
|
||||
|
||||
export interface NodeArray<T> extends Array<T>, TextRange {
|
||||
@@ -856,7 +856,11 @@ module ts {
|
||||
members: NodeArray<EnumMember>;
|
||||
}
|
||||
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement {
|
||||
export interface ExportContainer {
|
||||
exportStars?: ExportDeclaration[]; // List of 'export *' statements (initialized by binding)
|
||||
}
|
||||
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer {
|
||||
name: Identifier | LiteralExpression;
|
||||
body: ModuleBlock | ModuleDeclaration;
|
||||
}
|
||||
@@ -934,7 +938,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration {
|
||||
export interface SourceFile extends Declaration, ExportContainer {
|
||||
statements: NodeArray<ModuleElement>;
|
||||
endOfFileToken: Node;
|
||||
|
||||
@@ -1297,6 +1301,7 @@ module ts {
|
||||
exportAssignmentChecked?: boolean; // True if export assignment was checked
|
||||
exportAssignmentSymbol?: Symbol; // Symbol exported from external module
|
||||
unionType?: UnionType; // Containing union type for union property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
}
|
||||
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
|
||||
Reference in New Issue
Block a user