mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Support for 'export default' with expressions
This commit is contained in:
+14
-18
@@ -693,9 +693,14 @@ module ts {
|
||||
// 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.exportName.text) {
|
||||
var meaning = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace;
|
||||
var exportSymbol = resolveName(node, node.exportName.text, meaning, Diagnostics.Cannot_find_name_0, node.exportName);
|
||||
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;
|
||||
}
|
||||
@@ -9537,19 +9542,6 @@ module ts {
|
||||
if (!isInAmbientContext(node) && node.name.kind === SyntaxKind.StringLiteral) {
|
||||
grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
|
||||
}
|
||||
else if (node.name.kind === SyntaxKind.Identifier && node.body.kind === SyntaxKind.ModuleBlock) {
|
||||
var statements = (<ModuleBlock>node.body).statements;
|
||||
for (var i = 0, n = statements.length; i < n; i++) {
|
||||
var statement = statements[i];
|
||||
|
||||
// TODO: AndersH: No reason to do a separate pass over the statements for this check, we should
|
||||
// just fold it into checkExportAssignment.
|
||||
if (statement.kind === SyntaxKind.ExportAssignment) {
|
||||
// Export assignments are not allowed in an internal module
|
||||
grammarErrorOnNode(statement, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
@@ -9704,11 +9696,14 @@ module ts {
|
||||
}
|
||||
|
||||
function checkExportAssignment(node: ExportAssignment) {
|
||||
if (node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.Identifier) {
|
||||
error(node, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
|
||||
return;
|
||||
}
|
||||
// Grammar checking
|
||||
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
|
||||
@@ -9906,6 +9901,7 @@ module ts {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.ExportAssignment:
|
||||
case SyntaxKind.SourceFile:
|
||||
forEachChild(node, checkFunctionExpressionBodies);
|
||||
break;
|
||||
@@ -10165,7 +10161,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
return (<ExportAssignment>nodeOnRightSide.parent).exportName === nodeOnRightSide && <ExportAssignment>nodeOnRightSide.parent;
|
||||
return (<ExportAssignment>nodeOnRightSide.parent).expression === <Node>nodeOnRightSide && <ExportAssignment>nodeOnRightSide.parent;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -700,8 +700,8 @@ module ts {
|
||||
}
|
||||
|
||||
function emitExportAssignment(node: ExportAssignment) {
|
||||
write("export = ");
|
||||
writeTextOfNode(currentSourceFile, node.exportName);
|
||||
write(node.isExportEquals ? "export = " : "export default ");
|
||||
writeTextOfNode(currentSourceFile, node.expression);
|
||||
write(";");
|
||||
writeLine();
|
||||
}
|
||||
@@ -4759,15 +4759,14 @@ 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 ");
|
||||
emitStart(exportAssignment.exportName);
|
||||
write(exportName);
|
||||
emitEnd(exportAssignment.exportName);
|
||||
emit(exportAssignment.expression);
|
||||
write(";");
|
||||
emitEnd(exportAssignment);
|
||||
}
|
||||
@@ -4780,15 +4779,14 @@ 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("module.exports = ");
|
||||
emitStart(exportAssignment.exportName);
|
||||
write(exportName);
|
||||
emitEnd(exportAssignment.exportName);
|
||||
emit(exportAssignment.expression);
|
||||
write(";");
|
||||
emitEnd(exportAssignment);
|
||||
}
|
||||
|
||||
+17
-6
@@ -278,7 +278,7 @@ module ts {
|
||||
visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return visitNodes(cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ExportAssignment>node).exportName);
|
||||
visitNode(cbNode, (<ExportAssignment>node).expression);
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNodes, (<TemplateExpression>node).templateSpans);
|
||||
case SyntaxKind.TemplateSpan:
|
||||
@@ -1500,6 +1500,10 @@ module ts {
|
||||
}
|
||||
if (token === SyntaxKind.ExportKeyword) {
|
||||
nextToken();
|
||||
if (token === SyntaxKind.DefaultKeyword) {
|
||||
nextToken();
|
||||
return token === SyntaxKind.ClassKeyword || token === SyntaxKind.FunctionKeyword;
|
||||
}
|
||||
return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.OpenBraceToken && canFollowModifier();
|
||||
}
|
||||
nextToken();
|
||||
@@ -4828,10 +4832,17 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseExportAssignmentTail(fullStart: number, modifiers: ModifiersArray): ExportAssignment {
|
||||
function parseExportAssignment(fullStart: number, modifiers: ModifiersArray): ExportAssignment {
|
||||
var node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
node.exportName = parseIdentifier();
|
||||
if (parseOptional(SyntaxKind.EqualsToken)) {
|
||||
node.isExportEquals = true;
|
||||
}
|
||||
else {
|
||||
parseExpected(SyntaxKind.DefaultKeyword);
|
||||
}
|
||||
//node.exportName = parseIdentifier();
|
||||
node.expression = parseAssignmentExpressionOrHigher();
|
||||
parseSemicolon();
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -4898,7 +4909,7 @@ module ts {
|
||||
function nextTokenCanFollowExportKeyword() {
|
||||
nextToken();
|
||||
return token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken ||
|
||||
token === SyntaxKind.OpenBraceToken || isDeclarationStart();
|
||||
token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword || isDeclarationStart();
|
||||
}
|
||||
|
||||
function nextTokenIsDeclarationStart() {
|
||||
@@ -4915,8 +4926,8 @@ module ts {
|
||||
var modifiers = parseModifiers();
|
||||
if (token === SyntaxKind.ExportKeyword) {
|
||||
nextToken();
|
||||
if (parseOptional(SyntaxKind.EqualsToken)) {
|
||||
return parseExportAssignmentTail(fullStart, modifiers);
|
||||
if (token === SyntaxKind.DefaultKeyword || token === SyntaxKind.EqualsToken) {
|
||||
return parseExportAssignment(fullStart, modifiers);
|
||||
}
|
||||
if (token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken) {
|
||||
return parseExportDeclaration(fullStart, modifiers);
|
||||
|
||||
@@ -933,7 +933,8 @@ module ts {
|
||||
export type ExportSpecifier = ImportOrExportSpecifier;
|
||||
|
||||
export interface ExportAssignment extends Statement, ModuleElement {
|
||||
exportName: Identifier;
|
||||
isExportEquals?: boolean;
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface FileReference extends TextRange {
|
||||
|
||||
@@ -174,7 +174,7 @@ module ts.BreakpointResolver {
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
// span on export = id
|
||||
return textSpan(node, (<ExportAssignment>node).exportName);
|
||||
return textSpan(node, (<ExportAssignment>node).expression);
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
// import statement without including semicolon
|
||||
|
||||
@@ -5,4 +5,4 @@ export function x(){
|
||||
|
||||
// @Filename: foo2.ts
|
||||
import foo1 = require('./foo1');
|
||||
export = foo1.x; // Error, export assignment must be identifier only
|
||||
export = foo1.x; // Ok
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// @Filename: foo1.ts
|
||||
var x = 10;
|
||||
export = typeof x; // Error
|
||||
export = typeof x; // Ok
|
||||
|
||||
// @Filename: foo2.ts
|
||||
export = "sausages"; // Error
|
||||
export = "sausages"; // Ok
|
||||
|
||||
// @Filename: foo3.ts
|
||||
export = class Foo3 {}; // Error
|
||||
export = class Foo3 {}; // Error, not an expression
|
||||
|
||||
// @Filename: foo4.ts
|
||||
export = true; // Error
|
||||
export = true; // Ok
|
||||
|
||||
// @Filename: foo5.ts
|
||||
export = undefined; // Valid. undefined is an identifier in JavaScript/TypeScript
|
||||
|
||||
// @Filename: foo6.ts
|
||||
export = void; // Error
|
||||
export = void; // Error, void operator requires an argument
|
||||
|
||||
// @Filename: foo7.ts
|
||||
export = Date || String; // Error
|
||||
export = Date || String; // Ok
|
||||
|
||||
// @Filename: foo8.ts
|
||||
export = null; // Error
|
||||
export = null; // Ok
|
||||
|
||||
|
||||
Reference in New Issue
Block a user