Skip to content

Commit

Permalink
Support an optional type annotation on export default statement
Browse files Browse the repository at this point in the history
  • Loading branch information
mhegazy committed Mar 13, 2015
1 parent 62cbe97 commit a6a8a96
Show file tree
Hide file tree
Showing 24 changed files with 172 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ module ts {
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.ExportAssignment:
if ((<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
if ((<ExportAssignment>node).expression && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
// An export default clause with an identifier exports all meanings of that identifier
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
}
Expand Down
34 changes: 26 additions & 8 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ module ts {
}

function getTargetOfExportAssignment(node: ExportAssignment): Symbol {
return resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
return node.expression && resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
}

function getTargetOfImportDeclaration(node: Declaration): Symbol {
Expand Down Expand Up @@ -622,7 +622,7 @@ module ts {
if (!links.referenced) {
links.referenced = true;
var node = getDeclarationOfAliasSymbol(symbol);
if (node.kind === SyntaxKind.ExportAssignment) {
if (node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression) {
// export default <symbol>
checkExpressionCached((<ExportAssignment>node).expression);
}
Expand Down Expand Up @@ -2061,7 +2061,16 @@ module ts {
}
// Handle export default expressions
if (declaration.kind === SyntaxKind.ExportAssignment) {
return links.type = checkExpression((<ExportAssignment>declaration).expression);
var exportAssignment = (<ExportAssignment>declaration);
if (exportAssignment.expression) {
return links.type = checkExpression(exportAssignment.expression);
}
else if (exportAssignment.type) {
return links.type = getTypeFromTypeNode(exportAssignment.type);
}
else {
return links.type = anyType;
}
}
// Handle variable, parameter or property
links.type = resolvingType;
Expand Down Expand Up @@ -10039,12 +10048,21 @@ module ts {
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
}
if (node.expression.kind === SyntaxKind.Identifier) {
markExportAsReferenced(node);
if (node.expression) {

This comment has been minimized.

Copy link
@JsonFreeman

JsonFreeman Mar 13, 2015

Contributor

What function are we in? Github doesn't show it.

This comment has been minimized.

Copy link
@mhegazy

mhegazy Mar 15, 2015

Author Contributor

getTypeOfVariableOrParameterOrProperty

This comment has been minimized.

Copy link
@JsonFreeman

JsonFreeman Mar 16, 2015

Contributor

Actually, it's checkExportAssignment

if (node.expression.kind === SyntaxKind.Identifier) {
markExportAsReferenced(node);
}
else {
checkExpressionCached(node.expression);
}
}
else {
checkExpressionCached(node.expression);
if (node.type) {
checkSourceElement(node.type);
if (!isInAmbientContext(node)) {
grammarErrorOnFirstToken(node.type, Diagnostics.Type_annotation_on_export_statements_are_only_allowed_in_ambient_module_declarations);
}
}

checkExternalModuleExports(container);
}

Expand Down Expand Up @@ -10880,7 +10898,7 @@ module ts {
}

function generateNameForExportAssignment(node: ExportAssignment) {
if (node.expression.kind !== SyntaxKind.Identifier) {
if (node.expression && node.expression.kind !== SyntaxKind.Identifier) {
assignGeneratedName(node, makeUniqueName("default"));
}
}
Expand Down
1 change: 1 addition & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ module ts {
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
Type_annotation_on_export_statements_are_only_allowed_in_ambient_module_declarations: { code: 1200, category: DiagnosticCategory.Error, key: "Type annotation on export statements are only allowed in ambient module declarations." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
Expand Down
7 changes: 6 additions & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,13 @@
},
"Unterminated Unicode escape sequence.": {
"category": "Error",
"code": 1199
"code": 1199
},
"Type annotation on export statements are only allowed in ambient module declarations.": {
"category": "Error",
"code": 1200
},

"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
Expand Down
12 changes: 9 additions & 3 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ module ts {
visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
case SyntaxKind.ExportAssignment:
return visitNodes(cbNodes, node.modifiers) ||
visitNode(cbNode, (<ExportAssignment>node).expression);
visitNode(cbNode, (<ExportAssignment>node).expression) ||
visitNode(cbNode, (<ExportAssignment>node).type);
case SyntaxKind.TemplateExpression:
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNodes, (<TemplateExpression>node).templateSpans);
case SyntaxKind.TemplateSpan:
Expand Down Expand Up @@ -4862,12 +4863,17 @@ module ts {
setModifiers(node, modifiers);
if (parseOptional(SyntaxKind.EqualsToken)) {
node.isExportEquals = true;
node.expression = parseAssignmentExpressionOrHigher();
}
else {
parseExpected(SyntaxKind.DefaultKeyword);
if (parseOptional(SyntaxKind.ColonToken)) {
node.type = parseType();
}
else {
node.expression = parseAssignmentExpressionOrHigher();
}
}
//node.exportName = parseIdentifier();
node.expression = parseAssignmentExpressionOrHigher();
parseSemicolon();
return finishNode(node);
}
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,8 @@ module ts {

export interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}

export interface FileReference extends TextRange {
Expand Down
4 changes: 4 additions & 0 deletions src/services/breakpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ module ts.BreakpointResolver {
return textSpan(node, (<ThrowStatement>node).expression);

case SyntaxKind.ExportAssignment:
if (!(<ExportAssignment>node).expression) {
return undefined;
}

// span on export = id
return textSpan(node, (<ExportAssignment>node).expression);

Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/APISample_compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,8 @@ declare module "typescript" {
type ExportSpecifier = ImportOrExportSpecifier;
interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}
interface FileReference extends TextRange {
fileName: string;
Expand Down
6 changes: 5 additions & 1 deletion tests/baselines/reference/APISample_compile.types
Original file line number Diff line number Diff line change
Expand Up @@ -2324,9 +2324,13 @@ declare module "typescript" {
isExportEquals?: boolean;
>isExportEquals : boolean

expression: Expression;
expression?: Expression;
>expression : Expression
>Expression : Expression

type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
}
interface FileReference extends TextRange {
>FileReference : FileReference
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/APISample_linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,8 @@ declare module "typescript" {
type ExportSpecifier = ImportOrExportSpecifier;
interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}
interface FileReference extends TextRange {
fileName: string;
Expand Down
6 changes: 5 additions & 1 deletion tests/baselines/reference/APISample_linter.types
Original file line number Diff line number Diff line change
Expand Up @@ -2470,9 +2470,13 @@ declare module "typescript" {
isExportEquals?: boolean;
>isExportEquals : boolean

expression: Expression;
expression?: Expression;
>expression : Expression
>Expression : Expression

type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
}
interface FileReference extends TextRange {
>FileReference : FileReference
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/APISample_transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,8 @@ declare module "typescript" {
type ExportSpecifier = ImportOrExportSpecifier;
interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}
interface FileReference extends TextRange {
fileName: string;
Expand Down
6 changes: 5 additions & 1 deletion tests/baselines/reference/APISample_transform.types
Original file line number Diff line number Diff line change
Expand Up @@ -2420,9 +2420,13 @@ declare module "typescript" {
isExportEquals?: boolean;
>isExportEquals : boolean

expression: Expression;
expression?: Expression;
>expression : Expression
>Expression : Expression

type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
}
interface FileReference extends TextRange {
>FileReference : FileReference
Expand Down
3 changes: 2 additions & 1 deletion tests/baselines/reference/APISample_watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,8 @@ declare module "typescript" {
type ExportSpecifier = ImportOrExportSpecifier;
interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}
interface FileReference extends TextRange {
fileName: string;
Expand Down
6 changes: 5 additions & 1 deletion tests/baselines/reference/APISample_watcher.types
Original file line number Diff line number Diff line change
Expand Up @@ -2593,9 +2593,13 @@ declare module "typescript" {
isExportEquals?: boolean;
>isExportEquals : boolean

expression: Expression;
expression?: Expression;
>expression : Expression
>Expression : Expression

type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
}
interface FileReference extends TextRange {
>FileReference : FileReference
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
tests/cases/compiler/exportDefaultTypeAnnoation.ts(2,18): error TS1200: Type annotation on export statements are only allowed in ambient module declarations.


==== tests/cases/compiler/exportDefaultTypeAnnoation.ts (1 errors) ====

export default : number;
~~~~~~
!!! error TS1200: Type annotation on export statements are only allowed in ambient module declarations.
6 changes: 6 additions & 0 deletions tests/baselines/reference/exportDefaultTypeAnnoation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//// [exportDefaultTypeAnnoation.ts]

export default : number;

//// [exportDefaultTypeAnnoation.js]
module.exports = ;
7 changes: 7 additions & 0 deletions tests/baselines/reference/exportDefaultTypeAnnoation2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//// [exportDefaultTypeAnnoation2.ts]

declare module "mod" {
export default : number;
}

//// [exportDefaultTypeAnnoation2.js]
6 changes: 6 additions & 0 deletions tests/baselines/reference/exportDefaultTypeAnnoation2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
=== tests/cases/compiler/exportDefaultTypeAnnoation2.ts ===

No type information for this code.declare module "mod" {
No type information for this code. export default : number;
No type information for this code.}
No type information for this code.
21 changes: 21 additions & 0 deletions tests/baselines/reference/exportDefaultTypeAnnoation3.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
tests/cases/compiler/reference1.ts(2,5): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/reference2.ts(2,5): error TS2322: Type 'number' is not assignable to type 'string'.


==== tests/cases/compiler/mod.d.ts (0 errors) ====

declare module "mod" {
export default : number;
}

==== tests/cases/compiler/reference1.ts (1 errors) ====
import d from "mod";
var s: string = d; // Error
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.

==== tests/cases/compiler/reference2.ts (1 errors) ====
import { default as d } from "mod";
var s: string = d; // Error
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
22 changes: 22 additions & 0 deletions tests/baselines/reference/exportDefaultTypeAnnoation3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [tests/cases/compiler/exportDefaultTypeAnnoation3.ts] ////

//// [mod.d.ts]

declare module "mod" {
export default : number;
}

//// [reference1.ts]
import d from "mod";
var s: string = d; // Error

//// [reference2.ts]
import { default as d } from "mod";
var s: string = d; // Error

//// [reference1.js]
var d = require("mod");
var s = d; // Error
//// [reference2.js]
var _mod = require("mod");
var s = _mod.default; // Error
4 changes: 4 additions & 0 deletions tests/cases/compiler/exportDefaultTypeAnnoation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @target: es5
// @module: commonjs

export default : number;
6 changes: 6 additions & 0 deletions tests/cases/compiler/exportDefaultTypeAnnoation2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @target: es5
// @module: commonjs

declare module "mod" {
export default : number;
}
15 changes: 15 additions & 0 deletions tests/cases/compiler/exportDefaultTypeAnnoation3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @target: es5
// @module: commonjs

// @fileName: mod.d.ts
declare module "mod" {
export default : number;
}

// @fileName: reference1.ts
import d from "mod";
var s: string = d; // Error

// @fileName: reference2.ts
import { default as d } from "mod";
var s: string = d; // Error

0 comments on commit a6a8a96

Please sign in to comment.