Support for ES6 export declarations (except export default and export *)

This commit is contained in:
Anders Hejlsberg
2015-02-12 18:05:02 -08:00
parent 3b39e9f4a1
commit 79be0a7d26
7 changed files with 293 additions and 133 deletions

View File

@@ -15,11 +15,11 @@ module ts {
if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.TypeAliasDeclaration) {
return ModuleInstanceState.NonInstantiated;
}
// 2. const enum declarations don't make module instantiated
// 2. const enum declarations
else if (isConstEnumDeclaration(node)) {
return ModuleInstanceState.ConstEnumOnly;
}
// 3. non - exported import declarations
// 3. non-exported import declarations
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(node.flags & NodeFlags.Export)) {
return ModuleInstanceState.NonInstantiated;
}
@@ -185,42 +185,39 @@ module ts {
}
function declareModuleMember(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
// Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
// ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
// on it. There are 2 main reasons:
//
// 1. We treat locals and exports of the same name as mutually exclusive within a container.
// That means the binder will issue a Duplicate Identifier error if you mix locals and exports
// with the same name in the same container.
// TODO: Make this a more specific error and decouple it from the exclusion logic.
// 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol,
// but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
// when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
var exportKind = 0;
if (symbolKind & SymbolFlags.Value) {
exportKind |= SymbolFlags.ExportValue;
var hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
if (symbolKind & SymbolFlags.Import) {
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
}
else {
declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
}
}
if (symbolKind & SymbolFlags.Type) {
exportKind |= SymbolFlags.ExportType;
}
if (symbolKind & SymbolFlags.Namespace) {
exportKind |= SymbolFlags.ExportNamespace;
}
if (getCombinedNodeFlags(node) & NodeFlags.Export ||
(node.kind !== SyntaxKind.ImportDeclaration && node.kind !== SyntaxKind.ImportEqualsDeclaration && isAmbientContext(container))) {
if (exportKind) {
else {
// Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
// ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
// on it. There are 2 main reasons:
//
// 1. We treat locals and exports of the same name as mutually exclusive within a container.
// That means the binder will issue a Duplicate Identifier error if you mix locals and exports
// with the same name in the same container.
// TODO: Make this a more specific error and decouple it from the exclusion logic.
// 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol,
// but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
// when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
if (hasExportModifier || isAmbientContext(container)) {
var exportKind = (symbolKind & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
(symbolKind & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
(symbolKind & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
node.localSymbol = local;
}
else {
declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
}
}
else {
declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
}
}
// All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function
@@ -477,6 +474,7 @@ module ts {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.ImportClause:

View File

@@ -446,7 +446,8 @@ module ts {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.ImportClause && !!(<ImportClause>node).name ||
node.kind === SyntaxKind.NamespaceImport ||
node.kind === SyntaxKind.ImportSpecifier;
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier;
}
function getDeclarationOfImportSymbol(symbol: Symbol): Declaration {
@@ -477,10 +478,10 @@ module ts {
return resolveExternalModuleName(node, (<ImportDeclaration>node.parent.parent).moduleSpecifier);
}
function getTargetOfImportSpecifier(node: ImportSpecifier): Symbol {
var moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent.parent.parent).moduleSpecifier);
function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration, specifier: ImportOrExportSpecifier): Symbol {
var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
if (moduleSymbol) {
var name = node.propertyName || node.name;
var name = specifier.propertyName || specifier.name;
if (name.text) {
var symbol = getSymbol(moduleSymbol.exports, name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
if (!symbol) {
@@ -492,6 +493,16 @@ module ts {
}
}
function getTargetOfImportSpecifier(node: ImportSpecifier): Symbol {
return getExternalModuleMember(<ImportDeclaration>node.parent.parent.parent, node);
}
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);
}
function getTargetOfImportDeclaration(node: Declaration): Symbol {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
@@ -502,6 +513,8 @@ module ts {
return getTargetOfNamespaceImport(<NamespaceImport>node);
case SyntaxKind.ImportSpecifier:
return getTargetOfImportSpecifier(<ImportSpecifier>node);
case SyntaxKind.ExportSpecifier:
return getTargetOfExportSpecifier(<ExportSpecifier>node);
}
}
@@ -9346,7 +9359,7 @@ module ts {
}
function checkExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration): boolean {
var moduleName = getImportedModuleName(node);
var moduleName = getExternalModuleName(node);
if (getFullWidth(moduleName) !== 0 && moduleName.kind !== SyntaxKind.StringLiteral) {
error(moduleName, Diagnostics.String_literal_expected);
return false;
@@ -10174,6 +10187,9 @@ module ts {
case SyntaxKind.ImportDeclaration:
generateNameForImportDeclaration(<ImportDeclaration>node);
break;
case SyntaxKind.ExportDeclaration:
generateNameForExportDeclaration(<ExportDeclaration>node);
break;
case SyntaxKind.SourceFile:
case SyntaxKind.ModuleBlock:
forEach((<SourceFile | ModuleBlock>node).statements, generateNames);
@@ -10219,17 +10235,27 @@ module ts {
}
}
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
var expr = getExternalModuleName(node);
var baseName = expr.kind === SyntaxKind.StringLiteral ?
escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
assignGeneratedName(node, makeUniqueName(baseName));
}
function generateNameForImportDeclaration(node: ImportDeclaration) {
if (node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === SyntaxKind.NamedImports) {
var expr = getImportedModuleName(node);
var baseName = expr.kind === SyntaxKind.StringLiteral ?
escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
assignGeneratedName(node, makeUniqueName(baseName));
generateNameForImportOrExportDeclaration(node);
}
}
function generateNameForExportDeclaration(node: ExportDeclaration) {
if (node.moduleSpecifier) {
generateNameForImportOrExportDeclaration(node);
}
}
}
function getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration) {
function getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration) {
var links = getNodeLinks(node);
if (!links.generatedName) {
getGeneratedNamesForSourceFile(getSourceFile(node));
@@ -11322,6 +11348,7 @@ module ts {
if (node.kind === SyntaxKind.InterfaceDeclaration ||
node.kind === SyntaxKind.ImportDeclaration ||
node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.ExportDeclaration ||
node.kind === SyntaxKind.ExportAssignment ||
(node.flags & NodeFlags.Ambient)) {

View File

@@ -17,7 +17,7 @@ module ts {
}
interface ExternalImportInfo {
importNode: ImportDeclaration | ImportEqualsDeclaration;
rootNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration;
declarationNode?: ImportEqualsDeclaration | ImportClause | NamespaceImport;
namedImports?: NamedImports;
}
@@ -1568,6 +1568,7 @@ module ts {
var tempVariables: Identifier[];
var tempParameters: Identifier[];
var externalImports: ExternalImportInfo[];
var exportSpecifiers: Map<ExportSpecifier>;
/** write emitted output to disk*/
var writeEmittedFiles = writeJavaScriptFile;
@@ -3067,6 +3068,20 @@ module ts {
emitEnd(node.name);
}
function emitExportMemberAssignment(name: Identifier) {
if (exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
var exportName = exportSpecifiers[name.text].name;
writeLine();
emitStart(exportName);
write("exports.");
emitNode(exportName);
emitEnd(exportName);
write(" = ");
emitNode(name);
write(";");
}
}
function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, value?: Expression) {
var emitCount = 0;
// An exported declaration is actually emitted as an assignment (to a property on the module object), so
@@ -3299,6 +3314,16 @@ module ts {
}
}
function emitExportVariableAssignments(node: VariableDeclaration | BindingElement) {
var name = (<VariableLikeDeclaration>node).name;
if (name.kind === SyntaxKind.Identifier) {
emitExportMemberAssignment(<Identifier>name);
}
else if (isBindingPattern(name)) {
forEach((<BindingPattern>name).elements, emitExportVariableAssignments);
}
}
function emitVariableStatement(node: VariableStatement) {
if (!(node.flags & NodeFlags.Export)) {
if (isLet(node.declarationList)) {
@@ -3313,6 +3338,9 @@ module ts {
}
emitCommaList(node.declarationList.declarations);
write(";");
if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) {
forEach(node.declarationList.declarations, emitExportVariableAssignments);
}
}
function emitParameter(node: ParameterDeclaration) {
@@ -3437,6 +3465,9 @@ module ts {
emit(node.name);
}
emitSignatureAndBody(node);
if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile) {
emitExportMemberAssignment((<FunctionDeclaration>node).name);
}
if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
emitTrailingComments(node);
}
@@ -3773,6 +3804,9 @@ module ts {
emitEnd(node);
write(";");
}
if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) {
emitExportMemberAssignment(node.name);
}
function emitConstructorOfClass() {
var saveTempCount = tempCount;
@@ -3899,6 +3933,9 @@ module ts {
emitEnd(node);
write(";");
}
if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) {
emitExportMemberAssignment(node.name);
}
}
function emitEnumMember(node: EnumMember) {
@@ -3997,6 +4034,9 @@ module ts {
emitModuleMemberName(node);
write(" = {}));");
emitEnd(node);
if (languageVersion < ScriptTarget.ES6 && node.name.kind === SyntaxKind.Identifier && node.parent === currentSourceFile) {
emitExportMemberAssignment(<Identifier>node.name);
}
}
function emitRequire(moduleName: Expression) {
@@ -4013,13 +4053,6 @@ module ts {
}
}
function emitImportAssignment(node: Declaration, moduleName: Expression) {
if (!(node.flags & NodeFlags.Export)) write("var ");
emitModuleMemberName(<Declaration>node);
write(" = ");
emitRequire(moduleName);
}
function emitImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) {
var info = getExternalImportInfo(node);
if (info) {
@@ -4028,7 +4061,7 @@ module ts {
if (compilerOptions.module !== ModuleKind.AMD) {
emitLeadingComments(node);
emitStart(node);
var moduleName = getImportedModuleName(node);
var moduleName = getExternalModuleName(node);
if (declarationNode) {
if (!(declarationNode.flags & NodeFlags.Export)) write("var ");
emitModuleMemberName(declarationNode);
@@ -4082,11 +4115,35 @@ module ts {
}
}
function emitExportDeclaration(node: ExportDeclaration) {
if (node.exportClause && node.moduleSpecifier) {
var generatedName = resolver.getGeneratedNameForNode(node);
emitStart(node);
write("var ");
write(generatedName);
write(" = ");
emitRequire(getExternalModuleName(node));
forEach(node.exportClause.elements, specifier => {
writeLine();
emitStart(specifier);
write("exports.");
emitNode(specifier.name);
write(" = ");
write(generatedName);
write(".");
emitNode(specifier.propertyName || specifier.name);
write(";");
emitEnd(specifier);
});
emitEnd(node);
}
}
function createExternalImportInfo(node: Node): ExternalImportInfo {
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
return {
importNode: <ImportEqualsDeclaration>node,
rootNode: <ImportEqualsDeclaration>node,
declarationNode: <ImportEqualsDeclaration>node
};
}
@@ -4096,35 +4153,50 @@ module ts {
if (importClause) {
if (importClause.name) {
return {
importNode: <ImportDeclaration>node,
rootNode: <ImportDeclaration>node,
declarationNode: importClause
};
}
if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
return {
importNode: <ImportDeclaration>node,
rootNode: <ImportDeclaration>node,
declarationNode: <NamespaceImport>importClause.namedBindings
};
}
return {
importNode: <ImportDeclaration>node,
rootNode: <ImportDeclaration>node,
namedImports: <NamedImports>importClause.namedBindings,
localName: resolver.getGeneratedNameForNode(<ImportDeclaration>node)
};
}
return {
importNode: <ImportDeclaration>node
rootNode: <ImportDeclaration>node
}
}
else if (node.kind === SyntaxKind.ExportDeclaration) {
if ((<ExportDeclaration>node).moduleSpecifier) {
return {
rootNode: <ExportDeclaration>node,
};
}
}
}
function createExternalImports(sourceFile: SourceFile) {
function createExternalModuleInfo(sourceFile: SourceFile) {
externalImports = [];
exportSpecifiers = {};
forEach(sourceFile.statements, node => {
var info = createExternalImportInfo(node);
if (info) {
if ((!info.declarationNode && !info.namedImports) || resolver.isReferencedImportDeclaration(node)) {
externalImports.push(info);
if (node.kind === SyntaxKind.ExportDeclaration && !(<ExportDeclaration>node).moduleSpecifier) {
forEach((<ExportDeclaration>node).exportClause.elements, e => {
exportSpecifiers[(e.propertyName || e.name).text] = e;
});
}
else {
var info = createExternalImportInfo(node);
if (info) {
if ((!info.declarationNode && !info.namedImports) || resolver.isReferencedImportDeclaration(node)) {
externalImports.push(info);
}
}
}
});
@@ -4134,7 +4206,7 @@ module ts {
if (externalImports) {
for (var i = 0; i < externalImports.length; i++) {
var info = externalImports[i];
if (info.importNode === node) {
if (info.rootNode === node) {
return info;
}
}
@@ -4158,7 +4230,7 @@ module ts {
write("[\"require\", \"exports\"");
forEach(externalImports, info => {
write(", ");
var moduleName = getImportedModuleName(info.importNode);
var moduleName = getExternalModuleName(info.rootNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
emitLiteral(<LiteralExpression>moduleName);
}
@@ -4178,7 +4250,7 @@ module ts {
emit(info.declarationNode.name);
}
else {
write(resolver.getGeneratedNameForNode(<ImportDeclaration>info.importNode));
write(resolver.getGeneratedNameForNode(<ImportDeclaration | ExportDeclaration>info.rootNode));
}
});
write(") {");
@@ -4263,7 +4335,7 @@ module ts {
extendsEmitted = true;
}
if (isExternalModule(node)) {
createExternalImports(node);
createExternalModuleInfo(node);
if (compilerOptions.module === ModuleKind.AMD) {
emitAMDModule(node, startIndex);
}
@@ -4272,6 +4344,8 @@ module ts {
}
}
else {
externalImports = undefined;
exportSpecifiers = undefined;
emitCaptureThisForNodeIfNecessary(node);
emitLinesStartingAt(node.statements, startIndex);
emitTempDeclarations(/*newLine*/ true);
@@ -4474,6 +4548,8 @@ module ts {
return emitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return emitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ExportDeclaration:
return emitExportDeclaration(<ExportDeclaration>node);
case SyntaxKind.SourceFile:
return emitSourceFile(<SourceFile>node);
}

View File

@@ -261,10 +261,16 @@ module ts {
case SyntaxKind.NamespaceImport:
return visitNode(cbNode, (<NamespaceImport>node).name);
case SyntaxKind.NamedImports:
return visitNodes(cbNodes, (<NamedImports>node).elements);
case SyntaxKind.NamedExports:
return visitNodes(cbNodes, (<NamedImportsOrExports>node).elements);
case SyntaxKind.ExportDeclaration:
return visitNodes(cbNodes, node.modifiers) ||
visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
case SyntaxKind.ImportSpecifier:
return visitNode(cbNode, (<ImportSpecifier>node).propertyName) ||
visitNode(cbNode, (<ImportSpecifier>node).name);
case SyntaxKind.ExportSpecifier:
return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
case SyntaxKind.ExportAssignment:
return visitNodes(cbNodes, node.modifiers) ||
visitNode(cbNode, (<ExportAssignment>node).exportName);
@@ -282,28 +288,28 @@ module ts {
}
const enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
BlockStatements, // Statements in block
SwitchClauses, // Clauses in switch statement
SwitchClauseStatements, // Statements in switch clause
TypeMembers, // Members in interface or type literal
ClassMembers, // Members in class declaration
EnumMembers, // Members in enum declaration
TypeReferences, // Type references in extends or implements clause
VariableDeclarations, // Variable declarations in variable statement
ObjectBindingElements, // Binding elements in object binding list
ArrayBindingElements, // Binding elements in array binding list
ArgumentExpressions, // Expressions in argument list
ObjectLiteralMembers, // Members in object literal
ArrayLiteralMembers, // Members in array literal
Parameters, // Parameters in parameter list
TypeParameters, // Type parameters in type parameter list
TypeArguments, // Type arguments in type argument list
TupleElementTypes, // Element types in tuple element type list
HeritageClauses, // Heritage clauses for a class or interface declaration.
ImportSpecifiers, // Named import clause's import specifier list
Count // Number of parsing contexts
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
BlockStatements, // Statements in block
SwitchClauses, // Clauses in switch statement
SwitchClauseStatements, // Statements in switch clause
TypeMembers, // Members in interface or type literal
ClassMembers, // Members in class declaration
EnumMembers, // Members in enum declaration
TypeReferences, // Type references in extends or implements clause
VariableDeclarations, // Variable declarations in variable statement
ObjectBindingElements, // Binding elements in object binding list
ArrayBindingElements, // Binding elements in array binding list
ArgumentExpressions, // Expressions in argument list
ObjectLiteralMembers, // Members in object literal
ArrayLiteralMembers, // Members in array literal
Parameters, // Parameters in parameter list
TypeParameters, // Type parameters in type parameter list
TypeArguments, // Type arguments in type argument list
TupleElementTypes, // Element types in tuple element type list
HeritageClauses, // Heritage clauses for a class or interface declaration.
ImportOrExportSpecifiers, // Named import clause's import specifier list
Count // Number of parsing contexts
}
const enum Tristate {
@@ -314,27 +320,27 @@ module ts {
function parsingContextErrors(context: ParsingContext): DiagnosticMessage {
switch (context) {
case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.BlockStatements: return Diagnostics.Statement_expected;
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
case ParsingContext.TypeReferences: return Diagnostics.Type_reference_expected;
case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected;
case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected;
case ParsingContext.ImportSpecifiers: return Diagnostics.Identifier_expected;
case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.BlockStatements: return Diagnostics.Statement_expected;
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
case ParsingContext.TypeReferences: return Diagnostics.Type_reference_expected;
case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected;
case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected;
case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected;
}
};
@@ -1481,7 +1487,10 @@ module ts {
// 'const' is only a modifier if followed by 'enum'.
return nextToken() === SyntaxKind.EnumKeyword;
}
if (token === SyntaxKind.ExportKeyword) {
nextToken();
return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.OpenBraceToken && canFollowModifier();
}
nextToken();
return canFollowModifier();
}
@@ -1541,7 +1550,7 @@ module ts {
return token === SyntaxKind.CommaToken || isStartOfType();
case ParsingContext.HeritageClauses:
return isHeritageClause();
case ParsingContext.ImportSpecifiers:
case ParsingContext.ImportOrExportSpecifiers:
return isIdentifierOrKeyword();
}
@@ -1579,7 +1588,7 @@ module ts {
case ParsingContext.EnumMembers:
case ParsingContext.ObjectLiteralMembers:
case ParsingContext.ObjectBindingElements:
case ParsingContext.ImportSpecifiers:
case ParsingContext.ImportOrExportSpecifiers:
return token === SyntaxKind.CloseBraceToken;
case ParsingContext.SwitchClauseStatements:
return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
@@ -4671,7 +4680,7 @@ module ts {
// parse namespace or named imports
if (!importClause.name ||
parseOptional(SyntaxKind.CommaToken)) {
importClause.namedBindings = token === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImports();
importClause.namedBindings = token === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
}
return finishNode(importClause);
@@ -4715,8 +4724,8 @@ module ts {
return finishNode(namespaceImport);
}
function parseNamedImports(): NamedImports {
var namedImports = <NamedImports>createNode(SyntaxKind.NamedImports);
function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports {
var node = <NamedImports>createNode(kind);
// NamedImports:
// { }
@@ -4726,12 +4735,22 @@ module ts {
// ImportsList:
// ImportSpecifier
// ImportsList, ImportSpecifier
namedImports.elements = parseBracketedList(ParsingContext.ImportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken);
return finishNode(namedImports);
node.elements = parseBracketedList(ParsingContext.ImportOrExportSpecifiers,
kind === SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier,
SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken);
return finishNode(node);
}
function parseImportSpecifier(): ImportSpecifier {
var node = <ImportSpecifier>createNode(SyntaxKind.ImportSpecifier);
function parseExportSpecifier() {
return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier);
}
function parseImportSpecifier() {
return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier);
}
function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier {
var node = <ImportSpecifier>createNode(kind);
// ImportSpecifier:
// ImportedBinding
// IdentifierName as ImportedBinding
@@ -4759,6 +4778,23 @@ module ts {
return finishNode(node);
}
function parseExportDeclaration(fullStart: number, modifiers: ModifiersArray): ExportDeclaration {
var node = <ExportDeclaration>createNode(SyntaxKind.ExportDeclaration, fullStart);
setModifiers(node, modifiers);
if (parseOptional(SyntaxKind.AsteriskToken)) {
parseExpected(SyntaxKind.FromKeyword);
node.moduleSpecifier = parseModuleSpecifier();
}
else {
node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
if (parseOptional(SyntaxKind.FromKeyword)) {
node.moduleSpecifier = parseModuleSpecifier();
}
}
parseSemicolon();
return finishNode(node);
}
function parseExportAssignmentTail(fullStart: number, modifiers: ModifiersArray): ExportAssignment {
var node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment, fullStart);
setModifiers(node, modifiers);
@@ -4795,7 +4831,7 @@ module ts {
return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral);
case SyntaxKind.ExportKeyword:
// Check for export assignment or modifier on source element
return lookAhead(nextTokenIsEqualsTokenOrDeclarationStart);
return lookAhead(nextTokenCanFollowExportKeyword);
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
@@ -4826,9 +4862,10 @@ module ts {
token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken;
}
function nextTokenIsEqualsTokenOrDeclarationStart() {
function nextTokenCanFollowExportKeyword() {
nextToken();
return token === SyntaxKind.EqualsToken || isDeclarationStart();
return token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken || isDeclarationStart();
}
function nextTokenIsDeclarationStart() {
@@ -4848,6 +4885,9 @@ module ts {
if (parseOptional(SyntaxKind.EqualsToken)) {
return parseExportAssignmentTail(fullStart, modifiers);
}
if (token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken) {
return parseExportDeclaration(fullStart, modifiers);
}
}
switch (token) {
@@ -4952,8 +4992,9 @@ module ts {
sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
node.flags & NodeFlags.Export
|| node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference
|| node.kind === SyntaxKind.ExportAssignment
|| node.kind === SyntaxKind.ImportDeclaration
|| node.kind === SyntaxKind.ExportAssignment
|| node.kind === SyntaxKind.ExportDeclaration
? node
: undefined);
}

View File

@@ -351,8 +351,8 @@ module ts {
function processImportedModules(file: SourceFile, basePath: string) {
forEach(file.statements, node => {
if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) {
var moduleNameExpr = getImportedModuleName(node);
if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.ExportDeclaration) {
var moduleNameExpr = getExternalModuleName(node);
if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) {
var moduleNameText = (<LiteralExpression>moduleNameExpr).text;
if (moduleNameText) {

View File

@@ -231,12 +231,15 @@ module ts {
ModuleDeclaration,
ModuleBlock,
ImportEqualsDeclaration,
ExportAssignment,
ImportDeclaration,
ImportClause,
NamespaceImport,
NamedImports,
ImportSpecifier,
ExportAssignment,
ExportDeclaration,
NamedExports,
ExportSpecifier,
// Module references
ExternalModuleReference,
@@ -898,15 +901,26 @@ module ts {
name: Identifier;
}
export interface NamedImports extends Node {
elements: NodeArray<ImportSpecifier>;
export interface ExportDeclaration extends Statement, ModuleElement {
exportClause?: NamedExports;
moduleSpecifier?: Expression;
}
export interface ImportSpecifier extends Declaration {
propertyName?: Identifier; // Property name to be imported from module
name: Identifier; // element name to be imported in the scope
export interface NamedImportsOrExports extends Node {
elements: NodeArray<ImportOrExportSpecifier>;
}
export type NamedImports = NamedImportsOrExports;
export type NamedExports = NamedImportsOrExports;
export interface ImportOrExportSpecifier extends Declaration {
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}
export type ImportSpecifier = ImportOrExportSpecifier;
export type ExportSpecifier = ImportOrExportSpecifier;
export interface ExportAssignment extends Statement, ModuleElement {
exportName: Identifier;
}
@@ -1163,7 +1177,7 @@ module ts {
}
export interface EmitResolver {
getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string;
getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string;
getExpressionNameSubstitution(node: Identifier): string;
getExportAssignmentName(node: SourceFile): string;
isReferencedImportDeclaration(node: Node): boolean;

View File

@@ -603,7 +603,7 @@ module ts {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}
export function getImportedModuleName(node: Node): Expression {
export function getExternalModuleName(node: Node): Expression {
if (node.kind === SyntaxKind.ImportDeclaration) {
return (<ImportDeclaration>node).moduleSpecifier;
}
@@ -613,6 +613,9 @@ module ts {
return (<ExternalModuleReference>reference).expression;
}
}
if (node.kind === SyntaxKind.ExportDeclaration) {
return (<ExportDeclaration>node).moduleSpecifier;
}
}
export function hasDotDotDotToken(node: Node) {
@@ -695,6 +698,7 @@ module ts {
case SyntaxKind.ImportClause:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ExportSpecifier:
return true;
}
return false;