mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 04:17:34 -06:00
Unifying ES6 and TypeScript external modules
Export assignments are now equivalent to export of member named "default" Export assignments and exports defaults collected by binder Export * declarations collected by binder Simplified logic for marking import symbols as referenced Removed "location" parameter from resolveEntityName Improved error position reporting in resolveEntityName
This commit is contained in:
parent
84760c298f
commit
234358e6c6
@ -112,6 +112,10 @@ module ts {
|
||||
return "__new";
|
||||
case SyntaxKind.IndexSignature:
|
||||
return "__index";
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return "default";
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return "__export";
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,9 +141,9 @@ module ts {
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name, message, getDisplayName(declaration)));
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name, message, getDisplayName(node)));
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
|
||||
symbol = createSymbol(0, name);
|
||||
}
|
||||
@ -310,13 +314,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindExportDeclaration(node: ExportDeclaration) {
|
||||
if (!node.exportClause) {
|
||||
((<ExportContainer>container).exportStars || ((<ExportContainer>container).exportStars = [])).push(node);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration) {
|
||||
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
@ -478,9 +475,6 @@ module ts {
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
bindExportDeclaration(<ExportDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.ImportClause:
|
||||
if ((<ImportClause>node).name) {
|
||||
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
|
||||
@ -489,6 +483,22 @@ module ts {
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// All export * declarations are collected in an __export symbol
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.ExportStar, 0);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if ((<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes);
|
||||
}
|
||||
else {
|
||||
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
if (isExternalModule(<SourceFile>node)) {
|
||||
bindAnonymousDeclaration(<SourceFile>node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).fileName) + '"', /*isBlockScopeContainer*/ true);
|
||||
|
||||
@ -465,7 +465,8 @@ module ts {
|
||||
node.kind === SyntaxKind.ImportClause && !!(<ImportClause>node).name ||
|
||||
node.kind === SyntaxKind.NamespaceImport ||
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier;
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment;
|
||||
}
|
||||
|
||||
function getDeclarationOfImportSymbol(symbol: Symbol): Declaration {
|
||||
@ -518,7 +519,11 @@ module ts {
|
||||
function getTargetOfExportSpecifier(node: ExportSpecifier): Symbol {
|
||||
return (<ExportDeclaration>node.parent.parent).moduleSpecifier ?
|
||||
getExternalModuleMember(<ExportDeclaration>node.parent.parent, node) :
|
||||
resolveEntityName(node, node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
}
|
||||
|
||||
function getTargetOfExportAssignment(node: ExportAssignment): Symbol {
|
||||
return resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
}
|
||||
|
||||
function getTargetOfImportDeclaration(node: Declaration): Symbol {
|
||||
@ -533,6 +538,8 @@ module ts {
|
||||
return getTargetOfImportSpecifier(<ImportSpecifier>node);
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return getTargetOfExportSpecifier(<ExportSpecifier>node);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return getTargetOfExportAssignment(<ExportAssignment>node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,6 +563,31 @@ module ts {
|
||||
return links.target;
|
||||
}
|
||||
|
||||
function markExportAsReferenced(node: ImportEqualsDeclaration | ExportAssignment | ExportSpecifier) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var target = resolveImport(symbol);
|
||||
if (target && target !== unknownSymbol && target.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(target)) {
|
||||
markImportSymbolAsReferenced(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
function markImportSymbolAsReferenced(symbol: Symbol) {
|
||||
var links = getSymbolLinks(symbol);
|
||||
if (!links.referenced) {
|
||||
links.referenced = true;
|
||||
var node = getDeclarationOfImportSymbol(symbol);
|
||||
if (node.kind === SyntaxKind.ExportAssignment) {
|
||||
checkExpressionCached((<ExportAssignment>node).expression);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.ExportSpecifier) {
|
||||
checkExpressionCached((<ExportSpecifier>node).propertyName || (<ExportSpecifier>node).name);
|
||||
}
|
||||
else if (isInternalModuleImportEqualsDeclaration(node)) {
|
||||
checkExpressionCached(<Expression>(<ImportEqualsDeclaration>node).moduleReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is only for imports with entity names
|
||||
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, importDeclaration?: ImportEqualsDeclaration): Symbol {
|
||||
if (!importDeclaration) {
|
||||
@ -573,13 +605,13 @@ module ts {
|
||||
}
|
||||
// Check for case 1 and 3 in the above example
|
||||
if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) {
|
||||
return resolveEntityName(importDeclaration, entityName, SymbolFlags.Namespace);
|
||||
return resolveEntityName(entityName, SymbolFlags.Namespace);
|
||||
}
|
||||
else {
|
||||
// Case 2 in above example
|
||||
// entityName.kind could be a QualifiedName or a Missing identifier
|
||||
Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration);
|
||||
return resolveEntityName(importDeclaration, entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,28 +620,28 @@ module ts {
|
||||
}
|
||||
|
||||
// Resolves a qualified name and any involved import aliases
|
||||
function resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol {
|
||||
function resolveEntityName(name: EntityName, meaning: SymbolFlags): Symbol {
|
||||
if (getFullWidth(name) === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
var symbol = resolveName(location,(<Identifier>name).text, meaning, Diagnostics.Cannot_find_name_0, <Identifier>name);
|
||||
var symbol = resolveName(name, (<Identifier>name).text, meaning, Diagnostics.Cannot_find_name_0, <Identifier>name);
|
||||
if (!symbol) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else if (name.kind === SyntaxKind.QualifiedName) {
|
||||
var namespace = resolveEntityName(location,(<QualifiedName>name).left, SymbolFlags.Namespace);
|
||||
if (!namespace || namespace === unknownSymbol || getFullWidth((<QualifiedName>name).right) === 0) return;
|
||||
var symbol = getSymbol(getExportsOfSymbol(namespace), (<QualifiedName>name).right.text, meaning);
|
||||
var namespace = resolveEntityName((<QualifiedName>name).left, SymbolFlags.Namespace);
|
||||
if (!namespace || namespace === unknownSymbol || getFullWidth((<QualifiedName>name).right) === 0) {
|
||||
return undefined;
|
||||
}
|
||||
var right = (<QualifiedName>name).right;
|
||||
var symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
|
||||
if (!symbol) {
|
||||
error(location, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace),
|
||||
declarationNameToString((<QualifiedName>name).right));
|
||||
return;
|
||||
error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
|
||||
return symbol.flags & meaning ? symbol : resolveImport(symbol);
|
||||
}
|
||||
@ -658,6 +690,10 @@ module ts {
|
||||
error(moduleReferenceLiteral, Diagnostics.Cannot_find_external_module_0, moduleName);
|
||||
}
|
||||
|
||||
function getExportAssignmentSymbol(moduleSymbol: Symbol): Symbol {
|
||||
return moduleSymbol.exports["default"];
|
||||
}
|
||||
|
||||
function getResolvedExportAssignmentSymbol(moduleSymbol: Symbol): Symbol {
|
||||
var symbol = getExportAssignmentSymbol(moduleSymbol);
|
||||
if (symbol) {
|
||||
@ -670,64 +706,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getExportAssignmentSymbol(symbol: Symbol): Symbol {
|
||||
checkTypeOfExportAssignmentSymbol(symbol);
|
||||
return getSymbolLinks(symbol).exportAssignmentSymbol;
|
||||
}
|
||||
|
||||
function checkTypeOfExportAssignmentSymbol(containerSymbol: Symbol): void {
|
||||
var symbolLinks = getSymbolLinks(containerSymbol);
|
||||
if (!symbolLinks.exportAssignmentChecked) {
|
||||
var exportInformation = collectExportInformationForSourceFileOrModule(containerSymbol);
|
||||
if (exportInformation.exportAssignments.length) {
|
||||
if (exportInformation.exportAssignments.length > 1) {
|
||||
// TypeScript 1.0 spec (April 2014): 11.2.4
|
||||
// It is an error for an external module to contain more than one export assignment.
|
||||
forEach(exportInformation.exportAssignments, node => error(node, Diagnostics.A_module_cannot_have_more_than_one_export_assignment));
|
||||
}
|
||||
var node = exportInformation.exportAssignments[0];
|
||||
if (exportInformation.hasExportedMember) {
|
||||
// TypeScript 1.0 spec (April 2014): 11.2.3
|
||||
// If an external module contains an export assignment it is an error
|
||||
// for the external module to also contain export declarations.
|
||||
// The two types of exports are mutually exclusive.
|
||||
error(node, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
|
||||
}
|
||||
if (node.expression.kind === SyntaxKind.Identifier && (<Identifier>node.expression).text) {
|
||||
var exportSymbol = resolveName(node, (<Identifier>node.expression).text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace,
|
||||
Diagnostics.Cannot_find_name_0, <Identifier>node.expression);
|
||||
}
|
||||
else {
|
||||
var exportSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "*default*");
|
||||
exportSymbol.parent = containerSymbol;
|
||||
(<TransientSymbol>exportSymbol).type = checkExpression(node.expression);
|
||||
}
|
||||
symbolLinks.exportAssignmentSymbol = exportSymbol || unknownSymbol;
|
||||
}
|
||||
symbolLinks.exportAssignmentChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
function collectExportInformationForSourceFileOrModule(symbol: Symbol) {
|
||||
var seenExportedMember = false;
|
||||
var result: ExportAssignment[] = [];
|
||||
forEach(symbol.declarations, declaration => {
|
||||
var block = <Block>(declaration.kind === SyntaxKind.SourceFile ? declaration : (<ModuleDeclaration>declaration).body);
|
||||
forEach(block.statements, node => {
|
||||
if (node.kind === SyntaxKind.ExportAssignment) {
|
||||
result.push(<ExportAssignment>node);
|
||||
}
|
||||
else {
|
||||
seenExportedMember = seenExportedMember || (node.flags & NodeFlags.Export) !== 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
return {
|
||||
hasExportedMember: seenExportedMember,
|
||||
exportAssignments: result
|
||||
};
|
||||
}
|
||||
|
||||
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
|
||||
return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports;
|
||||
}
|
||||
@ -738,6 +716,14 @@ module ts {
|
||||
}
|
||||
|
||||
function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
|
||||
if (compilerOptions.target < ScriptTarget.ES6) {
|
||||
var defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
|
||||
if (defaultSymbol) {
|
||||
return {
|
||||
"default": defaultSymbol
|
||||
};
|
||||
}
|
||||
}
|
||||
var result: SymbolTable;
|
||||
var visitedSymbols: Symbol[] = [];
|
||||
visit(moduleSymbol);
|
||||
@ -752,13 +738,12 @@ module ts {
|
||||
}
|
||||
extendSymbolTable(result, symbol.exports);
|
||||
}
|
||||
forEach(symbol.declarations, node => {
|
||||
if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) {
|
||||
forEach((<ExportContainer>node).exportStars, exportStar => {
|
||||
visit(resolveExternalModuleName(exportStar, exportStar.moduleSpecifier));
|
||||
});
|
||||
}
|
||||
});
|
||||
var exportStars = symbol.exports["__export"];
|
||||
if (exportStars) {
|
||||
forEach(exportStars.declarations, node => {
|
||||
visit(resolveExternalModuleName(node, (<ExportDeclaration>node).moduleSpecifier));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2001,6 +1986,10 @@ module ts {
|
||||
if (declaration.kind === SyntaxKind.CatchClause) {
|
||||
return links.type = anyType;
|
||||
}
|
||||
// Handle export default expressions
|
||||
if (declaration.kind === SyntaxKind.ExportAssignment) {
|
||||
return links.type = checkExpression((<ExportAssignment>declaration).expression);
|
||||
}
|
||||
// Handle variable, parameter or property
|
||||
links.type = resolvingType;
|
||||
var type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
|
||||
@ -3055,7 +3044,7 @@ module ts {
|
||||
function getTypeFromTypeReferenceNode(node: TypeReferenceNode): Type {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
var symbol = resolveEntityName(node, node.typeName, SymbolFlags.Type);
|
||||
var symbol = resolveEntityName(node.typeName, SymbolFlags.Type);
|
||||
if (symbol) {
|
||||
var type: Type;
|
||||
if ((symbol.flags & SymbolFlags.TypeParameter) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
|
||||
@ -5001,22 +4990,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
/*Transitively mark all linked imports as referenced*/
|
||||
function markLinkedImportsAsReferenced(node: ImportEqualsDeclaration): void {
|
||||
if (node) {
|
||||
var nodeLinks = getNodeLinks(node);
|
||||
while (nodeLinks.importOnRightSide) {
|
||||
var rightSide = nodeLinks.importOnRightSide;
|
||||
nodeLinks.importOnRightSide = undefined;
|
||||
|
||||
getSymbolLinks(rightSide).referenced = true;
|
||||
Debug.assert((rightSide.flags & SymbolFlags.Import) !== 0);
|
||||
|
||||
nodeLinks = getNodeLinks(getDeclarationOfKind(rightSide, SyntaxKind.ImportEqualsDeclaration))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIdentifier(node: Identifier): Type {
|
||||
var symbol = getResolvedSymbol(node);
|
||||
|
||||
@ -5030,44 +5003,8 @@ module ts {
|
||||
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_Consider_using_a_standard_function_expression);
|
||||
}
|
||||
|
||||
if (symbol.flags & SymbolFlags.Import) {
|
||||
|
||||
//var symbolLinks = getSymbolLinks(symbol);
|
||||
//if (!symbolLinks.referenced) {
|
||||
// if (!isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveImport(symbol))) {
|
||||
// symbolLinks.referenced = true;
|
||||
// }
|
||||
//}
|
||||
|
||||
// TODO: AndersH: This needs to be simplified. In an import of the form "import x = a.b.c;" we only need
|
||||
// to resolve "a" and mark it as referenced. If "b" and/or "c" are aliases, we would be able to access them
|
||||
// unless they're exported, and in that case they're already implicitly referenced.
|
||||
|
||||
var symbolLinks = getSymbolLinks(symbol);
|
||||
if (!symbolLinks.referenced) {
|
||||
var importOrExportAssignment = getLeftSideOfImportEqualsOrExportAssignment(node);
|
||||
|
||||
// decision about whether import is referenced can be made now if
|
||||
// - import that are used anywhere except right side of import declarations
|
||||
// - imports that are used on the right side of exported import declarations
|
||||
// for other cases defer decision until the check of left side
|
||||
if (!importOrExportAssignment ||
|
||||
(importOrExportAssignment.flags & NodeFlags.Export) ||
|
||||
(importOrExportAssignment.kind === SyntaxKind.ExportAssignment)) {
|
||||
// Mark the import as referenced so that we emit it in the final .js file.
|
||||
// exception: identifiers that appear in type queries, const enums, modules that contain only const enums
|
||||
symbolLinks.referenced = !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveImport(symbol));
|
||||
}
|
||||
else {
|
||||
var nodeLinks = getNodeLinks(importOrExportAssignment);
|
||||
Debug.assert(!nodeLinks.importOnRightSide);
|
||||
nodeLinks.importOnRightSide = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolLinks.referenced) {
|
||||
markLinkedImportsAsReferenced(<ImportEqualsDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ImportEqualsDeclaration));
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Import && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveImport(symbol))) {
|
||||
markImportSymbolAsReferenced(symbol);
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node);
|
||||
@ -9081,7 +9018,7 @@ module ts {
|
||||
var staticBaseType = getTypeOfSymbol(baseType.symbol);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (baseType.symbol !== resolveEntityName(node, baseTypeNode.typeName, SymbolFlags.Value)) {
|
||||
if (baseType.symbol !== resolveEntityName(baseTypeNode.typeName, SymbolFlags.Value)) {
|
||||
error(baseTypeNode, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
|
||||
}
|
||||
|
||||
@ -9656,30 +9593,25 @@ module ts {
|
||||
|
||||
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
|
||||
checkGrammarModifiers(node);
|
||||
if (isInternalModuleImportEqualsDeclaration(node)) {
|
||||
if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
|
||||
checkImportBinding(node);
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var target = resolveImport(symbol);
|
||||
if (target !== unknownSymbol) {
|
||||
if (target.flags & SymbolFlags.Value) {
|
||||
// Target is a value symbol, check that it is not hidden by a local declaration with the same name and
|
||||
// ensure it can be evaluated as an expression
|
||||
var moduleName = getFirstIdentifier(<EntityName>node.moduleReference);
|
||||
if (resolveEntityName(node, moduleName, SymbolFlags.Value | SymbolFlags.Namespace).flags & SymbolFlags.Namespace) {
|
||||
checkExpressionOrQualifiedName(<EntityName>node.moduleReference);
|
||||
}
|
||||
else {
|
||||
error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName));
|
||||
}
|
||||
}
|
||||
if (target.flags & SymbolFlags.Type) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0);
|
||||
}
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
markExportAsReferenced(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (checkExternalImportOrExportDeclaration(node)) {
|
||||
checkImportBinding(node);
|
||||
if (isInternalModuleImportEqualsDeclaration(node)) {
|
||||
var target = resolveImport(getSymbolOfNode(node));
|
||||
if (target !== unknownSymbol) {
|
||||
if (target.flags & SymbolFlags.Value) {
|
||||
// Target is a value symbol, check that it is not hidden by a local declaration with the same name
|
||||
var moduleName = getFirstIdentifier(<EntityName>node.moduleReference);
|
||||
if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace).flags & SymbolFlags.Namespace)) {
|
||||
error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName));
|
||||
}
|
||||
}
|
||||
if (target.flags & SymbolFlags.Type) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9690,13 +9622,21 @@ module ts {
|
||||
}
|
||||
if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
|
||||
if (node.exportClause) {
|
||||
forEach(node.exportClause.elements, checkImportSymbol);
|
||||
forEach(node.exportClause.elements, checkExportSpecifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkExportSpecifier(node: ExportSpecifier) {
|
||||
checkImportSymbol(node);
|
||||
if (!(<ExportDeclaration>node.parent.parent).moduleSpecifier) {
|
||||
markExportAsReferenced(node);
|
||||
}
|
||||
}
|
||||
|
||||
function checkExportAssignment(node: ExportAssignment) {
|
||||
if (node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.Identifier) {
|
||||
var container = node.parent.kind === SyntaxKind.SourceFile ? <SourceFile>node.parent : <ModuleDeclaration>node.parent.parent;
|
||||
if (container.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>container).name.kind === SyntaxKind.Identifier) {
|
||||
error(node, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
|
||||
return;
|
||||
}
|
||||
@ -9704,12 +9644,64 @@ module ts {
|
||||
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
|
||||
}
|
||||
var container = node.parent;
|
||||
if (container.kind !== SyntaxKind.SourceFile) {
|
||||
// In a module, the immediate parent will be a block, so climb up one more parent
|
||||
container = container.parent;
|
||||
if (node.expression.kind === SyntaxKind.Identifier) {
|
||||
markExportAsReferenced(node);
|
||||
}
|
||||
else {
|
||||
checkExpressionCached(node.expression);
|
||||
}
|
||||
checkExternalModuleExports(container);
|
||||
}
|
||||
|
||||
function getModuleStatements(node: Declaration): ModuleElement[] {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
return (<SourceFile>node).statements;
|
||||
}
|
||||
if (node.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node).body.kind === SyntaxKind.ModuleBlock) {
|
||||
return (<ModuleBlock>(<ModuleDeclaration>node).body).statements;
|
||||
}
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
function hasExportedMembers(moduleSymbol: Symbol) {
|
||||
var declarations = moduleSymbol.declarations;
|
||||
for (var i = 0; i < declarations.length; i++) {
|
||||
var statements = getModuleStatements(declarations[i]);
|
||||
for (var j = 0; j < statements.length; j++) {
|
||||
var node = statements[j];
|
||||
if (node.kind === SyntaxKind.ExportDeclaration) {
|
||||
var exportClause = (<ExportDeclaration>node).exportClause;
|
||||
if (!exportClause) {
|
||||
return true;
|
||||
}
|
||||
var specifiers = exportClause.elements;
|
||||
for (var k = 0; k < specifiers.length; k++) {
|
||||
var specifier = specifiers[k];
|
||||
if (!(specifier.propertyName && specifier.name && specifier.name.text === "default")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.kind !== SyntaxKind.ExportAssignment && node.flags & NodeFlags.Export) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) {
|
||||
var moduleSymbol = getSymbolOfNode(node);
|
||||
var links = getSymbolLinks(moduleSymbol);
|
||||
if (!links.exportsChecked) {
|
||||
var defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
|
||||
if (defaultSymbol) {
|
||||
if (hasExportedMembers(moduleSymbol)) {
|
||||
var declaration = getDeclarationOfImportSymbol(defaultSymbol);
|
||||
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
|
||||
}
|
||||
}
|
||||
links.exportsChecked = true;
|
||||
}
|
||||
checkTypeOfExportAssignmentSymbol(getSymbolOfNode(container));
|
||||
}
|
||||
|
||||
function checkSourceElement(node: Node): void {
|
||||
@ -9928,13 +9920,7 @@ module ts {
|
||||
checkFunctionExpressionBodies(node);
|
||||
|
||||
if (isExternalModule(node)) {
|
||||
var symbol = getExportAssignmentSymbol(node.symbol);
|
||||
if (symbol && symbol.flags & SymbolFlags.Import) {
|
||||
// Mark the import as referenced so that we emit it in the final .js file.
|
||||
getSymbolLinks(symbol).referenced = true;
|
||||
// mark any import declarations that depend upon this import as referenced
|
||||
markLinkedImportsAsReferenced(<ImportEqualsDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ImportEqualsDeclaration))
|
||||
}
|
||||
checkExternalModuleExports(node);
|
||||
}
|
||||
|
||||
if (potentialThisCollisions.length) {
|
||||
@ -10182,7 +10168,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (entityName.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
return resolveEntityName(/*location*/ entityName.parent.parent, <Identifier>entityName,
|
||||
return resolveEntityName(<Identifier>entityName,
|
||||
/*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Import);
|
||||
}
|
||||
|
||||
@ -10207,7 +10193,7 @@ module ts {
|
||||
// Include Import in the meaning, this ensures that we do not follow aliases to where they point and instead
|
||||
// return the alias symbol.
|
||||
var meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Import;
|
||||
return resolveEntityName(entityName, <Identifier>entityName, meaning);
|
||||
return resolveEntityName(<Identifier>entityName, meaning);
|
||||
}
|
||||
else if (entityName.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
var symbol = getNodeLinks(entityName).resolvedSymbol;
|
||||
@ -10229,7 +10215,7 @@ module ts {
|
||||
// Include Import in the meaning, this ensures that we do not follow aliases to where they point and instead
|
||||
// return the alias symbol.
|
||||
meaning |= SymbolFlags.Import;
|
||||
return resolveEntityName(entityName, <EntityName>entityName, meaning);
|
||||
return resolveEntityName(<EntityName>entityName, meaning);
|
||||
}
|
||||
|
||||
// Do we want to return undefined here?
|
||||
@ -10301,7 +10287,7 @@ module ts {
|
||||
// This is necessary as an identifier in short-hand property assignment can contains two meaning:
|
||||
// property name and property value.
|
||||
if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
return resolveEntityName(location, (<ShorthandPropertyAssignment>location).name, SymbolFlags.Value);
|
||||
return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -10567,9 +10553,9 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getExportAssignmentName(node: SourceFile): string {
|
||||
var symbol = getExportAssignmentSymbol(getSymbolOfNode(node));
|
||||
return symbol && symbol !== unknownSymbol && symbolIsValue(symbol) && !isConstEnumSymbol(symbol) ? symbolToString(symbol): undefined;
|
||||
function hasExportDefaultValue(node: SourceFile): boolean {
|
||||
var symbol = getResolvedExportAssignmentSymbol(getSymbolOfNode(node));
|
||||
return symbol && symbol !== unknownSymbol && symbolIsValue(symbol) && !isConstEnumSymbol(symbol);
|
||||
}
|
||||
|
||||
function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean {
|
||||
@ -10596,11 +10582,6 @@ module ts {
|
||||
if (getSymbolLinks(symbol).referenced) {
|
||||
return true;
|
||||
}
|
||||
// logic below will answer 'true' for exported import declaration in a nested module that itself is not exported.
|
||||
// As a consequence this might cause emitting extra.
|
||||
if (node.kind === SyntaxKind.ImportEqualsDeclaration && node.flags & NodeFlags.Export && isImportResolvedToValue(symbol)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return forEachChild(node, isReferencedImportDeclaration);
|
||||
}
|
||||
@ -10676,7 +10657,7 @@ module ts {
|
||||
return {
|
||||
getGeneratedNameForNode,
|
||||
getExpressionNameSubstitution,
|
||||
getExportAssignmentName,
|
||||
hasExportDefaultValue,
|
||||
isReferencedImportDeclaration,
|
||||
getNodeCheckFlags,
|
||||
isTopLevelValueImportEqualsWithEntityName,
|
||||
|
||||
@ -1580,6 +1580,7 @@ module ts {
|
||||
var tempParameters: Identifier[];
|
||||
var externalImports: ExternalImportInfo[];
|
||||
var exportSpecifiers: Map<ExportSpecifier[]>;
|
||||
var exportDefault: ExportAssignment | ExportSpecifier;
|
||||
|
||||
/** write emitted output to disk*/
|
||||
var writeEmittedFiles = writeJavaScriptFile;
|
||||
@ -3446,7 +3447,7 @@ module ts {
|
||||
}
|
||||
|
||||
function emitExportMemberAssignments(name: Identifier) {
|
||||
if (exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
|
||||
if (!exportDefault && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
|
||||
forEach(exportSpecifiers[name.text], specifier => {
|
||||
writeLine();
|
||||
emitStart(specifier.name);
|
||||
@ -4665,13 +4666,20 @@ module ts {
|
||||
function createExternalModuleInfo(sourceFile: SourceFile) {
|
||||
externalImports = [];
|
||||
exportSpecifiers = {};
|
||||
exportDefault = undefined;
|
||||
forEach(sourceFile.statements, node => {
|
||||
if (node.kind === SyntaxKind.ExportDeclaration && !(<ExportDeclaration>node).moduleSpecifier) {
|
||||
forEach((<ExportDeclaration>node).exportClause.elements, specifier => {
|
||||
if (specifier.name.text === "default") {
|
||||
exportDefault = exportDefault || specifier;
|
||||
}
|
||||
var name = (specifier.propertyName || specifier.name).text;
|
||||
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
|
||||
});
|
||||
}
|
||||
else if (node.kind === SyntaxKind.ExportAssignment) {
|
||||
exportDefault = exportDefault || <ExportAssignment>node;
|
||||
}
|
||||
else {
|
||||
var info = createExternalImportInfo(node);
|
||||
if (info) {
|
||||
@ -4759,17 +4767,7 @@ module ts {
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
// TODO: Handle export default expressions
|
||||
var exportName = resolver.getExportAssignmentName(node);
|
||||
if (exportName) {
|
||||
writeLine();
|
||||
var exportAssignment = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignment);
|
||||
write("return ");
|
||||
emit(exportAssignment.expression);
|
||||
write(";");
|
||||
emitEnd(exportAssignment);
|
||||
}
|
||||
emitExportDefault(node, /*emitAsReturn*/ true);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("});");
|
||||
@ -4779,16 +4777,22 @@ module ts {
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
// TODO: Handle export default expressions
|
||||
var exportName = resolver.getExportAssignmentName(node);
|
||||
if (exportName) {
|
||||
emitExportDefault(node, /*emitAsReturn*/ false);
|
||||
}
|
||||
|
||||
function emitExportDefault(sourceFile: SourceFile, emitAsReturn: boolean) {
|
||||
if (exportDefault && resolver.hasExportDefaultValue(sourceFile)) {
|
||||
writeLine();
|
||||
var exportAssignment = getFirstExportAssignment(node);
|
||||
emitStart(exportAssignment);
|
||||
write("module.exports = ");
|
||||
emit(exportAssignment.expression);
|
||||
emitStart(exportDefault);
|
||||
write(emitAsReturn ? "return " : "module.exports = ");
|
||||
if (exportDefault.kind === SyntaxKind.ExportAssignment) {
|
||||
emit((<ExportAssignment>exportDefault).expression);
|
||||
}
|
||||
else {
|
||||
emit((<ExportSpecifier>exportDefault).propertyName);
|
||||
}
|
||||
write(";");
|
||||
emitEnd(exportAssignment);
|
||||
emitEnd(exportDefault);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4845,6 +4849,7 @@ module ts {
|
||||
else {
|
||||
externalImports = undefined;
|
||||
exportSpecifiers = undefined;
|
||||
exportDefault = undefined;
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
|
||||
@ -863,11 +863,7 @@ module ts {
|
||||
members: NodeArray<EnumMember>;
|
||||
}
|
||||
|
||||
export interface ExportContainer {
|
||||
exportStars?: ExportDeclaration[]; // List of 'export *' statements (initialized by binding)
|
||||
}
|
||||
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer {
|
||||
export interface ModuleDeclaration extends Declaration, ModuleElement {
|
||||
name: Identifier | LiteralExpression;
|
||||
body: ModuleBlock | ModuleDeclaration;
|
||||
}
|
||||
@ -912,7 +908,7 @@ module ts {
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
export interface ExportDeclaration extends Statement, ModuleElement {
|
||||
export interface ExportDeclaration extends Declaration, ModuleElement {
|
||||
exportClause?: NamedExports;
|
||||
moduleSpecifier?: Expression;
|
||||
}
|
||||
@ -932,7 +928,7 @@ module ts {
|
||||
export type ImportSpecifier = ImportOrExportSpecifier;
|
||||
export type ExportSpecifier = ImportOrExportSpecifier;
|
||||
|
||||
export interface ExportAssignment extends Statement, ModuleElement {
|
||||
export interface ExportAssignment extends Declaration, ModuleElement {
|
||||
isExportEquals?: boolean;
|
||||
expression: Expression;
|
||||
}
|
||||
@ -946,7 +942,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration, ExportContainer {
|
||||
export interface SourceFile extends Declaration {
|
||||
statements: NodeArray<ModuleElement>;
|
||||
endOfFileToken: Node;
|
||||
|
||||
@ -1191,7 +1187,7 @@ module ts {
|
||||
export interface EmitResolver {
|
||||
getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string;
|
||||
getExpressionNameSubstitution(node: Identifier): string;
|
||||
getExportAssignmentName(node: SourceFile): string;
|
||||
hasExportDefaultValue(node: SourceFile): boolean;
|
||||
isReferencedImportDeclaration(node: Node): boolean;
|
||||
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
|
||||
getNodeCheckFlags(node: Node): NodeCheckFlags;
|
||||
@ -1227,11 +1223,9 @@ module ts {
|
||||
Signature = 0x00020000, // Call, construct, or index signature
|
||||
TypeParameter = 0x00040000, // Type parameter
|
||||
TypeAlias = 0x00080000, // Type alias
|
||||
|
||||
// Export markers (see comment in declareModuleMember in binder)
|
||||
ExportValue = 0x00100000, // Exported value marker
|
||||
ExportType = 0x00200000, // Exported type marker
|
||||
ExportNamespace = 0x00400000, // Exported namespace marker
|
||||
ExportValue = 0x00100000, // Exported value marker (see comment in declareModuleMember in binder)
|
||||
ExportType = 0x00200000, // Exported type marker (see comment in declareModuleMember in binder)
|
||||
ExportNamespace = 0x00400000, // Exported namespace marker (see comment in declareModuleMember in binder)
|
||||
Import = 0x00800000, // Import
|
||||
Instantiated = 0x01000000, // Instantiated symbol
|
||||
Merged = 0x02000000, // Merged symbol (created during program binding)
|
||||
@ -1239,6 +1233,7 @@ module ts {
|
||||
Prototype = 0x08000000, // Prototype property (no source representation)
|
||||
UnionProperty = 0x10000000, // Property in union type
|
||||
Optional = 0x20000000, // Optional property
|
||||
ExportStar = 0x40000000, // Export * declaration
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
@ -1306,10 +1301,9 @@ module ts {
|
||||
declaredType?: Type; // Type of class, interface, enum, or type parameter
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
exportAssignmentChecked?: boolean; // True if export assignment was checked
|
||||
exportAssignmentSymbol?: Symbol; // Symbol exported from external module
|
||||
unionType?: UnionType; // Containing union type for union property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
}
|
||||
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user