Skip to content

Commit afcf5db

Browse files
committed
Initial support for default imports/exports, see #98
Does not implement combinations like 'import theDefault, *' yet
1 parent 27e54ed commit afcf5db

23 files changed

+5875
-51
lines changed

lib/lint/base.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@
3939
"no-debugger": {
4040
"severity": "error"
4141
},
42-
"no-default-export": {
43-
"severity": "error"
44-
},
4542
"no-duplicate-super": {
4643
"severity": "error"
4744
},

src/ast.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export enum NodeKind {
6767
DO,
6868
EMPTY,
6969
EXPORT,
70+
EXPORTDEFAULT,
7071
EXPORTIMPORT,
7172
EXPRESSION,
7273
FOR,
@@ -701,6 +702,16 @@ export abstract class Node {
701702
return stmt;
702703
}
703704

705+
static createExportDefaultStatement(
706+
declaration: DeclarationStatement,
707+
range: Range
708+
): ExportDefaultStatement {
709+
var stmt = new ExportDefaultStatement();
710+
stmt.declaration = declaration;
711+
stmt.range = range;
712+
return stmt;
713+
}
714+
704715
static createExportImportStatement(
705716
name: IdentifierExpression,
706717
externalName: IdentifierExpression,
@@ -1775,6 +1786,14 @@ export class ExportStatement extends Statement {
17751786
isDeclare: bool;
17761787
}
17771788

1789+
/** Represents an `export default` statement. */
1790+
export class ExportDefaultStatement extends Statement {
1791+
kind = NodeKind.EXPORTDEFAULT;
1792+
1793+
/** Declaration being exported as default. */
1794+
declaration: DeclarationStatement;
1795+
}
1796+
17781797
/** Represents an expression that is used as a statement. */
17791798
export class ExpressionStatement extends Statement {
17801799
kind = NodeKind.EXPRESSION;

src/compiler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ import {
156156

157157
nodeIsConstantValue,
158158
findDecorator,
159-
isTypeOmitted
159+
isTypeOmitted,
160+
ExportDefaultStatement
160161
} from "./ast";
161162

162163
import {
@@ -1619,6 +1620,9 @@ export class Compiler extends DiagnosticEmitter {
16191620
// === Statements ===============================================================================
16201621

16211622
compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void {
1623+
if (statement.kind == NodeKind.EXPORTDEFAULT) {
1624+
statement = (<ExportDefaultStatement>statement).declaration;
1625+
}
16221626
switch (statement.kind) {
16231627
case NodeKind.CLASSDECLARATION: {
16241628
let memberStatements = (<ClassDeclaration>statement).members;

src/diagnosticMessages.generated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export enum DiagnosticCode {
6666
Type_expected = 1110,
6767
A_default_clause_cannot_appear_more_than_once_in_a_switch_statement = 1113,
6868
Duplicate_label_0 = 1114,
69+
An_export_assignment_cannot_have_modifiers = 1120,
6970
Octal_literals_are_not_allowed_in_strict_mode = 1121,
7071
Digit_expected = 1124,
7172
Hexadecimal_digit_expected = 1125,
@@ -204,6 +205,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
204205
case 1110: return "Type expected.";
205206
case 1113: return "A 'default' clause cannot appear more than once in a 'switch' statement.";
206207
case 1114: return "Duplicate label '{0}'.";
208+
case 1120: return "An export assignment cannot have modifiers.";
207209
case 1121: return "Octal literals are not allowed in strict mode.";
208210
case 1124: return "Digit expected.";
209211
case 1125: return "Hexadecimal digit expected.";

src/diagnosticMessages.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"Type expected.": 1110,
6060
"A 'default' clause cannot appear more than once in a 'switch' statement.": 1113,
6161
"Duplicate label '{0}'.": 1114,
62+
"An export assignment cannot have modifiers.": 1120,
6263
"Octal literals are not allowed in strict mode.": 1121,
6364
"Digit expected.": 1124,
6465
"Hexadecimal digit expected.": 1125,

src/extra/ast.ts

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
EmptyStatement,
5353
ExportImportStatement,
5454
ExportStatement,
55+
ExportDefaultStatement,
5556
ExpressionStatement,
5657
ForStatement,
5758
IfStatement,
@@ -230,6 +231,10 @@ export class ASTBuilder {
230231
this.visitExportStatement(<ExportStatement>node);
231232
break;
232233
}
234+
case NodeKind.EXPORTDEFAULT: {
235+
this.visitExportDefaultStatement(<ExportDefaultStatement>node);
236+
break;
237+
}
233238
case NodeKind.EXPORTIMPORT: {
234239
this.visitExportImportStatement(<ExportImportStatement>node);
235240
break;
@@ -851,15 +856,19 @@ export class ASTBuilder {
851856
}
852857
}
853858

854-
visitClassDeclaration(node: ClassDeclaration): void {
859+
visitClassDeclaration(node: ClassDeclaration, isDefault: bool = false): void {
855860
var decorators = node.decorators;
856861
if (decorators) {
857862
for (let i = 0, k = decorators.length; i < k; ++i) {
858863
this.serializeDecorator(decorators[i]);
859864
}
860865
}
861-
this.serializeExternalModifiers(node);
862866
var sb = this.sb;
867+
if (isDefault) {
868+
sb.push("export default ");
869+
} else {
870+
this.serializeExternalModifiers(node);
871+
}
863872
if (node.is(CommonFlags.ABSTRACT)) sb.push("abstract ");
864873
if (node.name.text.length) {
865874
sb.push("class ");
@@ -931,9 +940,13 @@ export class ASTBuilder {
931940
visitEmptyStatement(node: EmptyStatement): void {
932941
}
933942

934-
visitEnumDeclaration(node: EnumDeclaration): void {
943+
visitEnumDeclaration(node: EnumDeclaration, isDefault: bool = false): void {
935944
var sb = this.sb;
936-
this.serializeExternalModifiers(node);
945+
if (isDefault) {
946+
sb.push("export default ");
947+
} else {
948+
this.serializeExternalModifiers(node);
949+
}
937950
if (node.is(CommonFlags.CONST)) sb.push("const ");
938951
sb.push("enum ");
939952
this.visitIdentifierExpression(node.name);
@@ -1011,6 +1024,33 @@ export class ASTBuilder {
10111024
sb.push(";");
10121025
}
10131026

1027+
visitExportDefaultStatement(node: ExportDefaultStatement): void {
1028+
var declaration = node.declaration;
1029+
switch (declaration.kind) {
1030+
case NodeKind.ENUMDECLARATION: {
1031+
this.visitEnumDeclaration(<EnumDeclaration>declaration, true);
1032+
break;
1033+
}
1034+
case NodeKind.FUNCTIONDECLARATION: {
1035+
this.visitFunctionDeclaration(<FunctionDeclaration>declaration, true);
1036+
break;
1037+
}
1038+
case NodeKind.CLASSDECLARATION: {
1039+
this.visitClassDeclaration(<ClassDeclaration>declaration, true);
1040+
break;
1041+
}
1042+
case NodeKind.INTERFACEDECLARATION: {
1043+
this.visitInterfaceDeclaration(<InterfaceDeclaration>declaration, true);
1044+
break;
1045+
}
1046+
case NodeKind.NAMESPACEDECLARATION: {
1047+
this.visitNamespaceDeclaration(<NamespaceDeclaration>declaration, true);
1048+
break;
1049+
}
1050+
default: assert(false);
1051+
}
1052+
}
1053+
10141054
visitExpressionStatement(node: ExpressionStatement): void {
10151055
this.visitNode(node.expression);
10161056
}
@@ -1065,16 +1105,20 @@ export class ASTBuilder {
10651105
this.visitNode(node.statement);
10661106
}
10671107

1068-
visitFunctionDeclaration(node: FunctionDeclaration): void {
1108+
visitFunctionDeclaration(node: FunctionDeclaration, isDefault: bool = false): void {
10691109
var sb = this.sb;
10701110
var decorators = node.decorators;
10711111
if (decorators) {
10721112
for (let i = 0, k = decorators.length; i < k; ++i) {
10731113
this.serializeDecorator(decorators[i]);
10741114
}
10751115
}
1076-
this.serializeExternalModifiers(node);
1077-
this.serializeAccessModifiers(node);
1116+
if (isDefault) {
1117+
sb.push("export default ");
1118+
} else {
1119+
this.serializeExternalModifiers(node);
1120+
this.serializeAccessModifiers(node);
1121+
}
10781122
if (node.name.text.length) {
10791123
sb.push("function ");
10801124
} else {
@@ -1230,15 +1274,19 @@ export class ASTBuilder {
12301274
this.visitTypeNode(node.valueType);
12311275
}
12321276

1233-
visitInterfaceDeclaration(node: InterfaceDeclaration): void {
1277+
visitInterfaceDeclaration(node: InterfaceDeclaration, isDefault: bool = false): void {
12341278
var decorators = node.decorators;
12351279
if (decorators) {
12361280
for (let i = 0, k = decorators.length; i < k; ++i) {
12371281
this.serializeDecorator(decorators[i]);
12381282
}
12391283
}
1240-
this.serializeExternalModifiers(node);
12411284
var sb = this.sb;
1285+
if (isDefault) {
1286+
sb.push("export default ");
1287+
} else {
1288+
this.serializeExternalModifiers(node);
1289+
}
12421290
sb.push("interface ");
12431291
this.visitIdentifierExpression(node.name);
12441292
var typeParameters = node.typeParameters;
@@ -1284,15 +1332,19 @@ export class ASTBuilder {
12841332
this.visitFunctionCommon(node);
12851333
}
12861334

1287-
visitNamespaceDeclaration(node: NamespaceDeclaration): void {
1335+
visitNamespaceDeclaration(node: NamespaceDeclaration, isDefault: bool = false): void {
12881336
var decorators = node.decorators;
12891337
if (decorators) {
12901338
for (let i = 0, k = decorators.length; i < k; ++i) {
12911339
this.serializeDecorator(decorators[i]);
12921340
}
12931341
}
1294-
this.serializeExternalModifiers(node);
12951342
var sb = this.sb;
1343+
if (isDefault) {
1344+
sb.push("export default ");
1345+
} else {
1346+
this.serializeExternalModifiers(node);
1347+
}
12961348
sb.push("namespace ");
12971349
this.visitIdentifierExpression(node.name);
12981350
var members = node.members;

0 commit comments

Comments
 (0)