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:
parent
00dc5fcce9
commit
f8351c8865
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
|
|
@ -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;
|
Loading…
Reference in a new issue