Set the declarations of export assignment visible on demand through dts emit

Emit those new declarations asynchronously since they are otherwise not visible
This commit is contained in:
Sheetal Nandi 2015-02-10 19:02:13 -08:00
parent 00dc5fcce9
commit f8351c8865
14 changed files with 381 additions and 248 deletions

View file

@ -1588,65 +1588,6 @@ module ts {
} }
function isDeclarationVisible(node: Declaration): boolean { function isDeclarationVisible(node: Declaration): boolean {
function getContainingExternalModule(node: Node) {
for (; node; node = node.parent) {
if (node.kind === SyntaxKind.ModuleDeclaration) {
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
return node;
}
}
else if (node.kind === SyntaxKind.SourceFile) {
return isExternalModule(<SourceFile>node) ? node : undefined;
}
}
Debug.fail("getContainingModule cant reach here");
}
function isUsedInExportAssignment(node: Node) {
// Get source File and see if it is external module and has export assigned symbol
var externalModule = getContainingExternalModule(node);
if (externalModule) {
// This is export assigned symbol node
var externalModuleSymbol = getSymbolOfNode(externalModule);
var exportAssignmentSymbol = getExportAssignmentSymbol(externalModuleSymbol);
var resolvedExportSymbol: Symbol;
var symbolOfNode = getSymbolOfNode(node);
if (isSymbolUsedInExportAssignment(symbolOfNode)) {
return true;
}
// if symbolOfNode is import declaration, resolve the symbol declaration and check
if (symbolOfNode.flags & SymbolFlags.Import) {
return isSymbolUsedInExportAssignment(resolveImport(symbolOfNode));
}
}
// Check if the symbol is used in export assignment
function isSymbolUsedInExportAssignment(symbol: Symbol) {
if (exportAssignmentSymbol === symbol) {
return true;
}
if (exportAssignmentSymbol && !!(exportAssignmentSymbol.flags & SymbolFlags.Import)) {
// if export assigned symbol is import declaration, resolve the import
resolvedExportSymbol = resolvedExportSymbol || resolveImport(exportAssignmentSymbol);
if (resolvedExportSymbol === symbol) {
return true;
}
// Container of resolvedExportSymbol is visible
return forEach(resolvedExportSymbol.declarations, (current: Node) => {
while (current) {
if (current === node) {
return true;
}
current = current.parent;
}
});
}
}
}
function determineIfDeclarationIsVisible() { function determineIfDeclarationIsVisible() {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.VariableDeclaration: case SyntaxKind.VariableDeclaration:
@ -1662,7 +1603,7 @@ module ts {
// If the node is not exported or it is not ambient module element (except import declaration) // If the node is not exported or it is not ambient module element (except import declaration)
if (!(getCombinedNodeFlags(node) & NodeFlags.Export) && if (!(getCombinedNodeFlags(node) & NodeFlags.Export) &&
!(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) { !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) {
return isGlobalSourceFile(parent) || isUsedInExportAssignment(node); return isGlobalSourceFile(parent);
} }
// Exported members/ambient module elements (exception import declaration) are visible if parent is visible // Exported members/ambient module elements (exception import declaration) are visible if parent is visible
return isDeclarationVisible(<Declaration>parent); return isDeclarationVisible(<Declaration>parent);
@ -1696,11 +1637,11 @@ module ts {
return isDeclarationVisible(<Declaration>node.parent); return isDeclarationVisible(<Declaration>node.parent);
// Default binding, import specifier and namespace import is visible // Default binding, import specifier and namespace import is visible
// only if the import declaration is exported or it is used in export assignment // only on demand so by default it is not visible
case SyntaxKind.ImportClause: case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport: case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportSpecifier:
return (node.name && isUsedInExportAssignment(node)); return false;
// Type parameters are always visible // Type parameters are always visible
case SyntaxKind.TypeParameter: case SyntaxKind.TypeParameter:
@ -1722,6 +1663,34 @@ module ts {
} }
} }
function setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[]{
if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) {
var exportSymbol = resolveName(node.parent, node.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, Diagnostics.Cannot_find_name_0, node);
var result: Node[] = [];
buildVisibleNodeList(exportSymbol.declarations);
return result;
}
function buildVisibleNodeList(declarations: Declaration[]) {
forEach(declarations, declaration => {
getNodeLinks(declaration).isVisible = true;
var resultNode = getAnyImportSyntax(declaration) || declaration;
if (!contains(result, resultNode)) {
result.push(resultNode);
}
if (isInternalModuleImportEqualsDeclaration(declaration)) {
// Add the referenced top container visible
var internalModuleReference = <Identifier | QualifiedName>(<ImportEqualsDeclaration>declaration).moduleReference;
var firstIdentifier = getFirstIdentifier(internalModuleReference);
var importSymbol = resolveName(declaration, firstIdentifier.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace,
Diagnostics.Cannot_find_name_0, firstIdentifier);
buildVisibleNodeList(importSymbol.declarations);
}
});
}
}
function getRootDeclaration(node: Node): Node { function getRootDeclaration(node: Node): Node {
while (node.kind === SyntaxKind.BindingElement) { while (node.kind === SyntaxKind.BindingElement) {
node = node.parent.parent; node = node.parent.parent;
@ -10349,6 +10318,7 @@ module ts {
isEntityNameVisible, isEntityNameVisible,
getConstantValue, getConstantValue,
isUnknownIdentifier, isUnknownIdentifier,
setDeclarationsOfIdentifierAsVisible
}; };
} }

View file

@ -34,17 +34,18 @@ module ts {
getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic;
} }
interface AliasDeclarationEmitInfo { interface ModuleElementDeclarationEmitInfo {
declaration: AnyImportSyntax; node: Node;
outputPos: number; outputPos: number;
indent: number; indent: number;
asynchronousOutput?: string; // If the output for alias was written asynchronously, the corresponding output asynchronousOutput?: string; // If the output for alias was written asynchronously, the corresponding output
subModuleElementDeclarationEmitInfo?: ModuleElementDeclarationEmitInfo[];
isVisible?: boolean; isVisible?: boolean;
} }
interface DeclarationEmit { interface DeclarationEmit {
reportedDeclarationError: boolean; reportedDeclarationError: boolean;
aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[]; moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
synchronousDeclarationOutput: string; synchronousDeclarationOutput: string;
referencePathsOutput: string; referencePathsOutput: string;
} }
@ -365,7 +366,8 @@ module ts {
var emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments; var emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
var emit = compilerOptions.stripInternal ? stripInternal : emitNode; var emit = compilerOptions.stripInternal ? stripInternal : emitNode;
var aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[] = []; var moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
var asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
// Contains the reference paths that needs to go in the declaration file. // Contains the reference paths that needs to go in the declaration file.
// Collecting this separately because reference paths need to be first thing in the declaration file // Collecting this separately because reference paths need to be first thing in the declaration file
@ -395,14 +397,14 @@ module ts {
emitSourceFile(root); emitSourceFile(root);
// create asynchronous output for the importDeclarations // create asynchronous output for the importDeclarations
if (aliasDeclarationEmitInfo.length) { if (moduleElementDeclarationEmitInfo.length) {
var oldWriter = writer; var oldWriter = writer;
forEach(aliasDeclarationEmitInfo, aliasEmitInfo => { forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.isVisible) { if (aliasEmitInfo.isVisible) {
Debug.assert(aliasEmitInfo.declaration.kind === SyntaxKind.ImportDeclaration); Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
createAndSetNewTextWriterWithSymbolWriter(); createAndSetNewTextWriterWithSymbolWriter();
Debug.assert(aliasEmitInfo.indent === 0); Debug.assert(aliasEmitInfo.indent === 0);
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.declaration); writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
aliasEmitInfo.asynchronousOutput = writer.getText(); aliasEmitInfo.asynchronousOutput = writer.getText();
} }
}); });
@ -436,7 +438,7 @@ module ts {
return { return {
reportedDeclarationError, reportedDeclarationError,
aliasDeclarationEmitInfo, moduleElementDeclarationEmitInfo,
synchronousDeclarationOutput: writer.getText(), synchronousDeclarationOutput: writer.getText(),
referencePathsOutput, referencePathsOutput,
} }
@ -481,10 +483,23 @@ module ts {
decreaseIndent = newWriter.decreaseIndent; decreaseIndent = newWriter.decreaseIndent;
} }
function writeAsychronousImportEqualsDeclarations(anyImportSyntax: AnyImportSyntax[]) { function writeAsynchronousModuleElements(nodes: Node[]) {
var oldWriter = writer; var oldWriter = writer;
forEach(anyImportSyntax, aliasToWrite => { forEach(nodes, declaration => {
var aliasEmitInfo = forEach(aliasDeclarationEmitInfo, declEmitInfo => declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined); var nodeToCheck: Node;
if (declaration.kind === SyntaxKind.VariableDeclaration) {
nodeToCheck = declaration.parent.parent;
} else if (declaration.kind === SyntaxKind.NamedImports || declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ImportClause) {
Debug.fail("We should be getting ImportDeclaration instead to write");
} else {
nodeToCheck = declaration;
}
var moduleElementEmitInfo = forEach(moduleElementDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
moduleElementEmitInfo = forEach(asynchronousSubModuleDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
}
// If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration // If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
// then we don't need to write it at this point. We will write it when we actually see its declaration // then we don't need to write it at this point. We will write it when we actually see its declaration
// Eg. // Eg.
@ -492,19 +507,28 @@ module ts {
// import foo = require("foo"); // import foo = require("foo");
// Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing, // Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing,
// we would write alias foo declaration when we visit it since it would now be marked as visible // we would write alias foo declaration when we visit it since it would now be marked as visible
if (aliasEmitInfo) { if (moduleElementEmitInfo) {
if (aliasToWrite.kind === SyntaxKind.ImportEqualsDeclaration) { if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) {
createAndSetNewTextWriterWithSymbolWriter();
for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
increaseIndent();
}
writeImportEqualsDeclaration(<ImportEqualsDeclaration>aliasToWrite);
aliasEmitInfo.asynchronousOutput = writer.getText();
}
else {
// we have to create asynchronous output only after we have collected complete information // we have to create asynchronous output only after we have collected complete information
// because it is possible to enable multiple bindings as asynchronously visible // because it is possible to enable multiple bindings as asynchronously visible
aliasEmitInfo.isVisible = true; moduleElementEmitInfo.isVisible = true;
}
else {
createAndSetNewTextWriterWithSymbolWriter();
for (var declarationIndent = moduleElementEmitInfo.indent; declarationIndent; declarationIndent--) {
increaseIndent();
}
if (nodeToCheck.kind === SyntaxKind.ModuleDeclaration) {
Debug.assert(asynchronousSubModuleDeclarationEmitInfo === undefined);
asynchronousSubModuleDeclarationEmitInfo = [];
}
writeModuleElement(nodeToCheck);
if (nodeToCheck.kind === SyntaxKind.ModuleDeclaration) {
moduleElementEmitInfo.subModuleElementDeclarationEmitInfo = asynchronousSubModuleDeclarationEmitInfo;
asynchronousSubModuleDeclarationEmitInfo = undefined;
}
moduleElementEmitInfo.asynchronousOutput = writer.getText();
} }
} }
}); });
@ -515,7 +539,7 @@ module ts {
if (symbolAccesibilityResult.accessibility === SymbolAccessibility.Accessible) { if (symbolAccesibilityResult.accessibility === SymbolAccessibility.Accessible) {
// write the aliases // write the aliases
if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) { if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
writeAsychronousImportEqualsDeclarations(symbolAccesibilityResult.aliasesToMakeVisible); writeAsynchronousModuleElements(symbolAccesibilityResult.aliasesToMakeVisible);
} }
} }
else { else {
@ -719,6 +743,77 @@ module ts {
writeTextOfNode(currentSourceFile, node.exportName); writeTextOfNode(currentSourceFile, node.exportName);
write(";"); write(";");
writeLine(); writeLine();
// Make all the declarations visible for the export name
var nodes = resolver.setDeclarationsOfIdentifierAsVisible(node.exportName);
// write each of these declarations asynchronously
writeAsynchronousModuleElements(nodes);
}
function isModuleElementVisible(node: Declaration) {
return resolver.isDeclarationVisible(node);
}
function emitModuleElement(node: Node, isModuleElementVisible: boolean) {
if (isModuleElementVisible) {
writeModuleElement(node);
}
// Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective
else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
(node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) {
if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
// Import declaration of another module that is visited async so lets put it in right spot
asynchronousSubModuleDeclarationEmitInfo.push({
node,
outputPos: writer.getTextPos(),
indent: writer.getIndent(),
isVisible
});
}
else {
var isVisible: boolean;
if (node.kind === SyntaxKind.ImportDeclaration) {
var importDeclaration = <ImportDeclaration>node;
if (importDeclaration.importClause) {
isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
}
}
moduleElementDeclarationEmitInfo.push({
node,
outputPos: writer.getTextPos(),
indent: writer.getIndent(),
isVisible
});
}
}
}
function writeModuleElement(node: Node) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
return writeFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.VariableStatement:
return writeVariableStatement(<VariableStatement>node);
case SyntaxKind.InterfaceDeclaration:
return writeInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.ClassDeclaration:
return writeClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.TypeAliasDeclaration:
return writeTypeAliasDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.EnumDeclaration:
return writeEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
return writeModuleDeclaration(<ModuleDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return writeImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ImportDeclaration:
return writeImportDeclaration(<ImportDeclaration>node);
default:
Debug.fail("Unknown symbol kind");
}
} }
function emitModuleElementDeclarationFlags(node: Node) { function emitModuleElementDeclarationFlags(node: Node) {
@ -748,19 +843,6 @@ module ts {
} }
} }
function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) {
if (resolver.isDeclarationVisible(node)) {
writeImportEqualsDeclaration(node);
}
else {
aliasDeclarationEmitInfo.push({
declaration: node,
outputPos: writer.getTextPos(),
indent: writer.getIndent(),
});
}
}
function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) { function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) {
// note usage of writer. methods instead of aliases created, just to make sure we are using // note usage of writer. methods instead of aliases created, just to make sure we are using
// correct writer especially to handle asynchronous alias writing // correct writer especially to handle asynchronous alias writing
@ -791,21 +873,6 @@ module ts {
} }
} }
function emitImportDeclaration(node: ImportDeclaration) {
if (node.importClause) {
aliasDeclarationEmitInfo.push({
declaration: node,
outputPos: writer.getTextPos(),
indent: writer.getIndent(),
isVisible: (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) ||
isVisibleNamedBinding(node.importClause.namedBindings)
});
}
else {
writeImportDeclaration(node);
}
}
function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports): boolean { function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports): boolean {
if (namedBindings) { if (namedBindings) {
if (namedBindings.kind === SyntaxKind.NamespaceImport) { if (namedBindings.kind === SyntaxKind.NamespaceImport) {
@ -858,41 +925,38 @@ module ts {
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentSourceFile, node.name);
} }
function emitModuleDeclaration(node: ModuleDeclaration) { function writeModuleDeclaration(node: ModuleDeclaration) {
if (resolver.isDeclarationVisible(node)) { emitJsDocComments(node);
emitJsDocComments(node); emitModuleElementDeclarationFlags(node);
emitModuleElementDeclarationFlags(node); write("module ");
write("module "); writeTextOfNode(currentSourceFile, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentSourceFile, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
writeTextOfNode(currentSourceFile, node.name);
}
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
write(" {");
writeLine();
increaseIndent();
emitLines((<ModuleBlock>node.body).statements);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
} }
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
write(" {");
writeLine();
increaseIndent();
emitLines((<ModuleBlock>node.body).statements);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
} }
function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
if (resolver.isDeclarationVisible(node)) { emitJsDocComments(node);
emitJsDocComments(node); emitModuleElementDeclarationFlags(node);
emitModuleElementDeclarationFlags(node); write("type ");
write("type "); writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentSourceFile, node.name); write(" = ");
write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); write(";");
write(";"); writeLine();
writeLine();
}
function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
return { return {
diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
@ -902,23 +966,21 @@ module ts {
} }
} }
function emitEnumDeclaration(node: EnumDeclaration) { function writeEnumDeclaration(node: EnumDeclaration) {
if (resolver.isDeclarationVisible(node)) { emitJsDocComments(node);
emitJsDocComments(node); emitModuleElementDeclarationFlags(node);
emitModuleElementDeclarationFlags(node); if (isConst(node)) {
if (isConst(node)) { write("const ")
write("const ")
}
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
} }
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
} }
function emitEnumMemberDeclaration(node: EnumMember) { function emitEnumMemberDeclaration(node: EnumMember) {
@ -1050,7 +1112,7 @@ module ts {
} }
} }
function emitClassDeclaration(node: ClassDeclaration) { function writeClassDeclaration(node: ClassDeclaration) {
function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) { function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
if (constructorDeclaration) { if (constructorDeclaration) {
forEach(constructorDeclaration.parameters, param => { forEach(constructorDeclaration.parameters, param => {
@ -1061,50 +1123,46 @@ module ts {
} }
} }
if (resolver.isDeclarationVisible(node)) { emitJsDocComments(node);
emitJsDocComments(node); emitModuleElementDeclarationFlags(node);
emitModuleElementDeclarationFlags(node); write("class ");
write("class "); writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentSourceFile, node.name); var prevEnclosingDeclaration = enclosingDeclaration;
var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node;
enclosingDeclaration = node; emitTypeParameters(node.typeParameters);
emitTypeParameters(node.typeParameters); var baseTypeNode = getClassBaseTypeNode(node);
var baseTypeNode = getClassBaseTypeNode(node); if (baseTypeNode) {
if (baseTypeNode) { emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
}
emitHeritageClause(getClassImplementedTypeNodes(node), /*isImplementsList*/ true);
write(" {");
writeLine();
increaseIndent();
emitParameterProperties(getFirstConstructorWithBody(node));
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
} }
emitHeritageClause(getClassImplementedTypeNodes(node), /*isImplementsList*/ true);
write(" {");
writeLine();
increaseIndent();
emitParameterProperties(getFirstConstructorWithBody(node));
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
} }
function emitInterfaceDeclaration(node: InterfaceDeclaration) { function writeInterfaceDeclaration(node: InterfaceDeclaration) {
if (resolver.isDeclarationVisible(node)) { emitJsDocComments(node);
emitJsDocComments(node); emitModuleElementDeclarationFlags(node);
emitModuleElementDeclarationFlags(node); write("interface ");
write("interface "); writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentSourceFile, node.name); var prevEnclosingDeclaration = enclosingDeclaration;
var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node;
enclosingDeclaration = node; emitTypeParameters(node.typeParameters);
emitTypeParameters(node.typeParameters); emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); write(" {");
write(" {"); writeLine();
writeLine(); increaseIndent();
increaseIndent(); emitLines(node.members);
emitLines(node.members); decreaseIndent();
decreaseIndent(); write("}");
write("}"); writeLine();
writeLine(); enclosingDeclaration = prevEnclosingDeclaration;
enclosingDeclaration = prevEnclosingDeclaration;
}
} }
function emitPropertyDeclaration(node: Declaration) { function emitPropertyDeclaration(node: Declaration) {
@ -1187,24 +1245,25 @@ module ts {
} }
} }
function emitVariableStatement(node: VariableStatement) { function isVariableStatementVisible(node: VariableStatement) {
var hasDeclarationWithEmit = forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration)); return forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
if (hasDeclarationWithEmit) { }
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node); function writeVariableStatement(node: VariableStatement) {
if (isLet(node.declarationList)) { emitJsDocComments(node);
write("let "); emitModuleElementDeclarationFlags(node);
} if (isLet(node.declarationList)) {
else if (isConst(node.declarationList)) { write("let ");
write("const ");
}
else {
write("var ");
}
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
write(";");
writeLine();
} }
else if (isConst(node.declarationList)) {
write("const ");
}
else {
write("var ");
}
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
write(";");
writeLine();
} }
function emitAccessorDeclaration(node: AccessorDeclaration) { function emitAccessorDeclaration(node: AccessorDeclaration) {
@ -1290,15 +1349,14 @@ module ts {
} }
} }
function emitFunctionDeclaration(node: FunctionLikeDeclaration) { function writeFunctionDeclaration(node: FunctionLikeDeclaration) {
if (hasDynamicName(node)) { if (hasDynamicName(node)) {
return; return;
} }
// If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting
// so no need to verify if the declaration is visible // so no need to verify if the declaration is visible
if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) && if (!resolver.isImplementationOfOverload(node)) {
!resolver.isImplementationOfOverload(node)) {
emitJsDocComments(node); emitJsDocComments(node);
if (node.kind === SyntaxKind.FunctionDeclaration) { if (node.kind === SyntaxKind.FunctionDeclaration) {
emitModuleElementDeclarationFlags(node); emitModuleElementDeclarationFlags(node);
@ -1538,11 +1596,23 @@ module ts {
function emitNode(node: Node) { function emitNode(node: Node) {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
return emitModuleElement(node, isModuleElementVisible(<Declaration>node));
case SyntaxKind.VariableStatement:
return emitModuleElement(node, isVariableStatementVisible(<VariableStatement>node));
case SyntaxKind.ImportDeclaration:
// Import declaration without import clause is visible, otherwise it is not visible
return emitModuleElement(node, /*isModuleElementVisible*/!(<ImportDeclaration>node).importClause);
case SyntaxKind.Constructor:
case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature: case SyntaxKind.MethodSignature:
return emitFunctionDeclaration(<FunctionLikeDeclaration>node); return writeFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.ConstructSignature: case SyntaxKind.ConstructSignature:
case SyntaxKind.CallSignature: case SyntaxKind.CallSignature:
case SyntaxKind.IndexSignature: case SyntaxKind.IndexSignature:
@ -1550,29 +1620,13 @@ module ts {
case SyntaxKind.GetAccessor: case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor: case SyntaxKind.SetAccessor:
return emitAccessorDeclaration(<AccessorDeclaration>node); return emitAccessorDeclaration(<AccessorDeclaration>node);
case SyntaxKind.VariableStatement:
return emitVariableStatement(<VariableStatement>node);
case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature: case SyntaxKind.PropertySignature:
return emitPropertyDeclaration(<PropertyDeclaration>node); return emitPropertyDeclaration(<PropertyDeclaration>node);
case SyntaxKind.InterfaceDeclaration:
return emitInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.ClassDeclaration:
return emitClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.TypeAliasDeclaration:
return emitTypeAliasDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.EnumMember: case SyntaxKind.EnumMember:
return emitEnumMemberDeclaration(<EnumMember>node); return emitEnumMemberDeclaration(<EnumMember>node);
case SyntaxKind.EnumDeclaration:
return emitEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
return emitModuleDeclaration(<ModuleDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return emitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ExportAssignment: case SyntaxKind.ExportAssignment:
return emitExportAssignment(<ExportAssignment>node); return emitExportAssignment(<ExportAssignment>node);
case SyntaxKind.ImportDeclaration:
return emitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.SourceFile: case SyntaxKind.SourceFile:
return emitSourceFile(<SourceFile>node); return emitSourceFile(<SourceFile>node);
} }
@ -4626,18 +4680,24 @@ module ts {
// TODO(shkamat): Should we not write any declaration file if any of them can produce error, // TODO(shkamat): Should we not write any declaration file if any of them can produce error,
// or should we just not write this file like we are doing now // or should we just not write this file like we are doing now
if (!emitDeclarationResult.reportedDeclarationError) { if (!emitDeclarationResult.reportedDeclarationError) {
var declarationOutput = emitDeclarationResult.referencePathsOutput; var declarationOutput = emitDeclarationResult.referencePathsOutput
// apply additions + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
}
function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) {
var appliedSyncOutputPos = 0; var appliedSyncOutputPos = 0;
forEach(emitDeclarationResult.aliasDeclarationEmitInfo, aliasEmitInfo => { var declarationOutput = "";
// apply asynchronous additions to the synchronous output
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.asynchronousOutput) { if (aliasEmitInfo.asynchronousOutput) {
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
declarationOutput += aliasEmitInfo.asynchronousOutput; declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo);
appliedSyncOutputPos = aliasEmitInfo.outputPos; appliedSyncOutputPos = aliasEmitInfo.outputPos;
} }
}); });
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos); declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM); return declarationOutput;
} }
} }

View file

@ -1172,6 +1172,7 @@ module ts {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags; getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean; isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -910,6 +910,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags; getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean; isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -2924,6 +2924,12 @@ declare module "typescript" {
>node : Declaration >node : Declaration
>Declaration : Declaration >Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean >isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration >node : FunctionLikeDeclaration

View file

@ -941,6 +941,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags; getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean; isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -3068,6 +3068,12 @@ declare module "typescript" {
>node : Declaration >node : Declaration
>Declaration : Declaration >Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean >isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration >node : FunctionLikeDeclaration

View file

@ -942,6 +942,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags; getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean; isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -3020,6 +3020,12 @@ declare module "typescript" {
>node : Declaration >node : Declaration
>Declaration : Declaration >Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean >isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration >node : FunctionLikeDeclaration

View file

@ -979,6 +979,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags; getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean; isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -3193,6 +3193,12 @@ declare module "typescript" {
>node : Declaration >node : Declaration
>Declaration : Declaration >Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean >isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration >node : FunctionLikeDeclaration

View file

@ -0,0 +1,39 @@
//// [declarationEmitImportInExportAssignmentModule.ts]
module m {
export module c {
export class c {
}
}
import x = c;
export var a: typeof x;
}
export = m;
//// [declarationEmitImportInExportAssignmentModule.js]
var m;
(function (m) {
var c;
(function (_c) {
var c = (function () {
function c() {
}
return c;
})();
_c.c = c;
})(c = m.c || (m.c = {}));
m.a;
})(m || (m = {}));
module.exports = m;
//// [declarationEmitImportInExportAssignmentModule.d.ts]
declare module m {
module c {
class c {
}
}
import x = c;
var a: typeof x;
}
export = m;

View file

@ -0,0 +1,23 @@
=== tests/cases/compiler/declarationEmitImportInExportAssignmentModule.ts ===
module m {
>m : typeof m
export module c {
>c : typeof x
export class c {
>c : c
}
}
import x = c;
>x : typeof x
>c : typeof x
export var a: typeof x;
>a : typeof x
>x : typeof x
}
export = m;
>m : typeof m

View file

@ -0,0 +1,12 @@
// @declaration: true
// @module: commonjs
module m {
export module c {
export class c {
}
}
import x = c;
export var a: typeof x;
}
export = m;