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 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() {
switch (node.kind) {
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 (!(getCombinedNodeFlags(node) & NodeFlags.Export) &&
!(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
return isDeclarationVisible(<Declaration>parent);
@ -1696,11 +1637,11 @@ module ts {
return isDeclarationVisible(<Declaration>node.parent);
// 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.NamespaceImport:
case SyntaxKind.ImportSpecifier:
return (node.name && isUsedInExportAssignment(node));
return false;
// Type parameters are always visible
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 {
while (node.kind === SyntaxKind.BindingElement) {
node = node.parent.parent;
@ -10349,6 +10318,7 @@ module ts {
isEntityNameVisible,
getConstantValue,
isUnknownIdentifier,
setDeclarationsOfIdentifierAsVisible
};
}

View file

@ -34,17 +34,18 @@ module ts {
getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic;
}
interface AliasDeclarationEmitInfo {
declaration: AnyImportSyntax;
interface ModuleElementDeclarationEmitInfo {
node: Node;
outputPos: number;
indent: number;
asynchronousOutput?: string; // If the output for alias was written asynchronously, the corresponding output
subModuleElementDeclarationEmitInfo?: ModuleElementDeclarationEmitInfo[];
isVisible?: boolean;
}
interface DeclarationEmit {
reportedDeclarationError: boolean;
aliasDeclarationEmitInfo: AliasDeclarationEmitInfo[];
moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
synchronousDeclarationOutput: string;
referencePathsOutput: string;
}
@ -365,7 +366,8 @@ module ts {
var emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
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.
// Collecting this separately because reference paths need to be first thing in the declaration file
@ -395,14 +397,14 @@ module ts {
emitSourceFile(root);
// create asynchronous output for the importDeclarations
if (aliasDeclarationEmitInfo.length) {
if (moduleElementDeclarationEmitInfo.length) {
var oldWriter = writer;
forEach(aliasDeclarationEmitInfo, aliasEmitInfo => {
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.isVisible) {
Debug.assert(aliasEmitInfo.declaration.kind === SyntaxKind.ImportDeclaration);
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
createAndSetNewTextWriterWithSymbolWriter();
Debug.assert(aliasEmitInfo.indent === 0);
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.declaration);
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
aliasEmitInfo.asynchronousOutput = writer.getText();
}
});
@ -436,7 +438,7 @@ module ts {
return {
reportedDeclarationError,
aliasDeclarationEmitInfo,
moduleElementDeclarationEmitInfo,
synchronousDeclarationOutput: writer.getText(),
referencePathsOutput,
}
@ -481,10 +483,23 @@ module ts {
decreaseIndent = newWriter.decreaseIndent;
}
function writeAsychronousImportEqualsDeclarations(anyImportSyntax: AnyImportSyntax[]) {
function writeAsynchronousModuleElements(nodes: Node[]) {
var oldWriter = writer;
forEach(anyImportSyntax, aliasToWrite => {
var aliasEmitInfo = forEach(aliasDeclarationEmitInfo, declEmitInfo => declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined);
forEach(nodes, declaration => {
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
// then we don't need to write it at this point. We will write it when we actually see its declaration
// Eg.
@ -492,19 +507,28 @@ module ts {
// 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,
// we would write alias foo declaration when we visit it since it would now be marked as visible
if (aliasEmitInfo) {
if (aliasToWrite.kind === SyntaxKind.ImportEqualsDeclaration) {
createAndSetNewTextWriterWithSymbolWriter();
for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
increaseIndent();
}
writeImportEqualsDeclaration(<ImportEqualsDeclaration>aliasToWrite);
aliasEmitInfo.asynchronousOutput = writer.getText();
}
else {
if (moduleElementEmitInfo) {
if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) {
// we have to create asynchronous output only after we have collected complete information
// 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) {
// write the aliases
if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
writeAsychronousImportEqualsDeclarations(symbolAccesibilityResult.aliasesToMakeVisible);
writeAsynchronousModuleElements(symbolAccesibilityResult.aliasesToMakeVisible);
}
}
else {
@ -719,6 +743,77 @@ module ts {
writeTextOfNode(currentSourceFile, node.exportName);
write(";");
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) {
@ -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) {
// note usage of writer. methods instead of aliases created, just to make sure we are using
// 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 {
if (namedBindings) {
if (namedBindings.kind === SyntaxKind.NamespaceImport) {
@ -858,41 +925,38 @@ module ts {
writeTextOfNode(currentSourceFile, node.name);
}
function emitModuleDeclaration(node: ModuleDeclaration) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("module ");
function writeModuleDeclaration(node: ModuleDeclaration) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("module ");
writeTextOfNode(currentSourceFile, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
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) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("type ");
writeTextOfNode(currentSourceFile, node.name);
write(" = ");
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
write(";");
writeLine();
}
function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("type ");
writeTextOfNode(currentSourceFile, node.name);
write(" = ");
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
write(";");
writeLine();
function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
return {
diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
@ -902,23 +966,21 @@ module ts {
}
}
function emitEnumDeclaration(node: EnumDeclaration) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (isConst(node)) {
write("const ")
}
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
function writeEnumDeclaration(node: EnumDeclaration) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (isConst(node)) {
write("const ")
}
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
}
function emitEnumMemberDeclaration(node: EnumMember) {
@ -1050,7 +1112,7 @@ module ts {
}
}
function emitClassDeclaration(node: ClassDeclaration) {
function writeClassDeclaration(node: ClassDeclaration) {
function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
if (constructorDeclaration) {
forEach(constructorDeclaration.parameters, param => {
@ -1061,50 +1123,46 @@ module ts {
}
}
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("class ");
writeTextOfNode(currentSourceFile, node.name);
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
var baseTypeNode = getClassBaseTypeNode(node);
if (baseTypeNode) {
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
}
emitHeritageClause(getClassImplementedTypeNodes(node), /*isImplementsList*/ true);
write(" {");
writeLine();
increaseIndent();
emitParameterProperties(getFirstConstructorWithBody(node));
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("class ");
writeTextOfNode(currentSourceFile, node.name);
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
var baseTypeNode = getClassBaseTypeNode(node);
if (baseTypeNode) {
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
}
emitHeritageClause(getClassImplementedTypeNodes(node), /*isImplementsList*/ true);
write(" {");
writeLine();
increaseIndent();
emitParameterProperties(getFirstConstructorWithBody(node));
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
}
function emitInterfaceDeclaration(node: InterfaceDeclaration) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("interface ");
writeTextOfNode(currentSourceFile, node.name);
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
}
function writeInterfaceDeclaration(node: InterfaceDeclaration) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("interface ");
writeTextOfNode(currentSourceFile, node.name);
var prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
write(" {");
writeLine();
increaseIndent();
emitLines(node.members);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
}
function emitPropertyDeclaration(node: Declaration) {
@ -1187,24 +1245,25 @@ module ts {
}
}
function emitVariableStatement(node: VariableStatement) {
var hasDeclarationWithEmit = forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
if (hasDeclarationWithEmit) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (isLet(node.declarationList)) {
write("let ");
}
else if (isConst(node.declarationList)) {
write("const ");
}
else {
write("var ");
}
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
write(";");
writeLine();
function isVariableStatementVisible(node: VariableStatement) {
return forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
}
function writeVariableStatement(node: VariableStatement) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (isLet(node.declarationList)) {
write("let ");
}
else if (isConst(node.declarationList)) {
write("const ");
}
else {
write("var ");
}
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
write(";");
writeLine();
}
function emitAccessorDeclaration(node: AccessorDeclaration) {
@ -1290,15 +1349,14 @@ module ts {
}
}
function emitFunctionDeclaration(node: FunctionLikeDeclaration) {
function writeFunctionDeclaration(node: FunctionLikeDeclaration) {
if (hasDynamicName(node)) {
return;
}
// 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
if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
!resolver.isImplementationOfOverload(node)) {
if (!resolver.isImplementationOfOverload(node)) {
emitJsDocComments(node);
if (node.kind === SyntaxKind.FunctionDeclaration) {
emitModuleElementDeclarationFlags(node);
@ -1538,11 +1596,23 @@ module ts {
function emitNode(node: Node) {
switch (node.kind) {
case SyntaxKind.Constructor:
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.MethodSignature:
return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
return writeFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.ConstructSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.IndexSignature:
@ -1550,29 +1620,13 @@ module ts {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return emitAccessorDeclaration(<AccessorDeclaration>node);
case SyntaxKind.VariableStatement:
return emitVariableStatement(<VariableStatement>node);
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
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:
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:
return emitExportAssignment(<ExportAssignment>node);
case SyntaxKind.ImportDeclaration:
return emitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.SourceFile:
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,
// or should we just not write this file like we are doing now
if (!emitDeclarationResult.reportedDeclarationError) {
var declarationOutput = emitDeclarationResult.referencePathsOutput;
// apply additions
var declarationOutput = emitDeclarationResult.referencePathsOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
}
function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) {
var appliedSyncOutputPos = 0;
forEach(emitDeclarationResult.aliasDeclarationEmitInfo, aliasEmitInfo => {
var declarationOutput = "";
// apply asynchronous additions to the synchronous output
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.asynchronousOutput) {
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
declarationOutput += aliasEmitInfo.asynchronousOutput;
declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo);
appliedSyncOutputPos = aliasEmitInfo.outputPos;
}
});
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
return declarationOutput;
}
}

View file

@ -1172,6 +1172,7 @@ module ts {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, 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;
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, 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
>Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration

View file

@ -941,6 +941,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, 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
>Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration

View file

@ -942,6 +942,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, 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
>Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>node : FunctionLikeDeclaration

View file

@ -979,6 +979,7 @@ declare module "typescript" {
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration): boolean;
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, 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
>Declaration : Declaration
setDeclarationsOfIdentifierAsVisible(node: Identifier): Node[];
>setDeclarationsOfIdentifierAsVisible : (node: Identifier) => Node[]
>node : Identifier
>Identifier : Identifier
>Node : Node
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
>isImplementationOfOverload : (node: FunctionLikeDeclaration) => boolean
>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;