Allow export default interface. Related to issue 3792. (#16040)

* Allow export default interface. Related to issue 3792.

* Update exportDefaultAbstractClass test

* Allow default export to be a non-value for lookup purposes

* Add local usage to exportDefaultInterface test
This commit is contained in:
Mohamed Hegazy
2017-05-23 13:40:03 -07:00
committed by GitHub
parent 23b2545586
commit 5ef6192c20
10 changed files with 215 additions and 17 deletions

View File

@@ -1240,12 +1240,12 @@ namespace ts {
if (token() === SyntaxKind.ExportKeyword) {
nextToken();
if (token() === SyntaxKind.DefaultKeyword) {
return lookAhead(nextTokenIsClassOrFunctionOrAsync);
return lookAhead(nextTokenCanFollowDefaultKeyword);
}
return token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier();
}
if (token() === SyntaxKind.DefaultKeyword) {
return nextTokenIsClassOrFunctionOrAsync();
return nextTokenCanFollowDefaultKeyword();
}
if (token() === SyntaxKind.StaticKeyword) {
nextToken();
@@ -1267,9 +1267,10 @@ namespace ts {
|| isLiteralPropertyName();
}
function nextTokenIsClassOrFunctionOrAsync(): boolean {
function nextTokenCanFollowDefaultKeyword(): boolean {
nextToken();
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
token() === SyntaxKind.InterfaceKeyword ||
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
}

View File

@@ -3168,11 +3168,11 @@ namespace ts {
}
export function getLocalSymbolForExportDefault(symbol: Symbol) {
return isExportDefaultSymbol(symbol) ? symbol.valueDeclaration.localSymbol : undefined;
return isExportDefaultSymbol(symbol) ? symbol.declarations[0].localSymbol : undefined;
}
function isExportDefaultSymbol(symbol: Symbol): boolean {
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default);
return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], ModifierFlags.Default);
}
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */

View File

@@ -1,14 +1,29 @@
//// [tests/cases/compiler/exportDefaultAbstractClass.ts] ////
//// [a.ts]
export default abstract class A {}
export default abstract class A { a: number; }
class B extends A {}
new B().a.toExponential();
//// [b.ts]
import A from './a'
import A from './a';
class C extends A {}
new C().a.toExponential();
//// [a.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var A = (function () {
function A() {
@@ -16,6 +31,33 @@ var A = (function () {
return A;
}());
exports["default"] = A;
var B = (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
return B;
}(A));
new B().a.toExponential();
//// [b.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var a_1 = require("./a");
var C = (function (_super) {
__extends(C, _super);
function C() {
return _super !== null && _super.apply(this, arguments) || this;
}
return C;
}(a_1["default"]));
new C().a.toExponential();

View File

@@ -1,8 +1,31 @@
=== tests/cases/compiler/a.ts ===
export default abstract class A {}
export default abstract class A { a: number; }
>A : Symbol(A, Decl(a.ts, 0, 0))
>a : Symbol(A.a, Decl(a.ts, 0, 33))
class B extends A {}
>B : Symbol(B, Decl(a.ts, 0, 46))
>A : Symbol(A, Decl(a.ts, 0, 0))
new B().a.toExponential();
>new B().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
>new B().a : Symbol(A.a, Decl(a.ts, 0, 33))
>B : Symbol(B, Decl(a.ts, 0, 46))
>a : Symbol(A.a, Decl(a.ts, 0, 33))
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
=== tests/cases/compiler/b.ts ===
import A from './a'
import A from './a';
>A : Symbol(A, Decl(b.ts, 0, 6))
class C extends A {}
>C : Symbol(C, Decl(b.ts, 0, 20))
>A : Symbol(A, Decl(b.ts, 0, 6))
new C().a.toExponential();
>new C().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
>new C().a : Symbol(A.a, Decl(a.ts, 0, 33))
>C : Symbol(C, Decl(b.ts, 0, 20))
>a : Symbol(A.a, Decl(a.ts, 0, 33))
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))

View File

@@ -1,8 +1,35 @@
=== tests/cases/compiler/a.ts ===
export default abstract class A {}
export default abstract class A { a: number; }
>A : A
>a : number
class B extends A {}
>B : B
>A : A
new B().a.toExponential();
>new B().a.toExponential() : string
>new B().a.toExponential : (fractionDigits?: number) => string
>new B().a : number
>new B() : B
>B : typeof B
>a : number
>toExponential : (fractionDigits?: number) => string
=== tests/cases/compiler/b.ts ===
import A from './a'
import A from './a';
>A : typeof A
class C extends A {}
>C : C
>A : A
new C().a.toExponential();
>new C().a.toExponential() : string
>new C().a.toExponential : (fractionDigits?: number) => string
>new C().a : number
>new C() : C
>C : typeof C
>a : number
>toExponential : (fractionDigits?: number) => string

View File

@@ -0,0 +1,24 @@
//// [tests/cases/compiler/exportDefaultInterface.ts] ////
//// [a.ts]
export default interface A { value: number; }
var a: A;
a.value.toExponential();
//// [b.ts]
import A from './a';
var a: A;
a.value.toExponential();
//// [a.js]
"use strict";
exports.__esModule = true;
var a;
a.value.toExponential();
//// [b.js]
"use strict";
exports.__esModule = true;
var a;
a.value.toExponential();

View File

@@ -0,0 +1,31 @@
=== tests/cases/compiler/a.ts ===
export default interface A { value: number; }
>A : Symbol(A, Decl(a.ts, 0, 0))
>value : Symbol(A.value, Decl(a.ts, 0, 28))
var a: A;
>a : Symbol(a, Decl(a.ts, 2, 3))
>A : Symbol(A, Decl(a.ts, 0, 0))
a.value.toExponential();
>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
>a.value : Symbol(A.value, Decl(a.ts, 0, 28))
>a : Symbol(a, Decl(a.ts, 2, 3))
>value : Symbol(A.value, Decl(a.ts, 0, 28))
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
=== tests/cases/compiler/b.ts ===
import A from './a';
>A : Symbol(A, Decl(b.ts, 0, 6))
var a: A;
>a : Symbol(a, Decl(b.ts, 2, 3))
>A : Symbol(A, Decl(b.ts, 0, 6))
a.value.toExponential();
>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
>a.value : Symbol(A.value, Decl(a.ts, 0, 28))
>a : Symbol(a, Decl(b.ts, 2, 3))
>value : Symbol(A.value, Decl(a.ts, 0, 28))
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))

View File

@@ -0,0 +1,33 @@
=== tests/cases/compiler/a.ts ===
export default interface A { value: number; }
>A : A
>value : number
var a: A;
>a : A
>A : A
a.value.toExponential();
>a.value.toExponential() : string
>a.value.toExponential : (fractionDigits?: number) => string
>a.value : number
>a : A
>value : number
>toExponential : (fractionDigits?: number) => string
=== tests/cases/compiler/b.ts ===
import A from './a';
>A : any
var a: A;
>a : A
>A : A
a.value.toExponential();
>a.value.toExponential() : string
>a.value.toExponential : (fractionDigits?: number) => string
>a.value : number
>a : A
>value : number
>toExponential : (fractionDigits?: number) => string

View File

@@ -1,5 +1,11 @@
// @filename: a.ts
export default abstract class A {}
// @filename: b.ts
import A from './a'
// @Filename: a.ts
export default abstract class A { a: number; }
class B extends A {}
new B().a.toExponential();
// @Filename: b.ts
import A from './a';
class C extends A {}
new C().a.toExponential();

View File

@@ -0,0 +1,11 @@
// @Filename: a.ts
export default interface A { value: number; }
var a: A;
a.value.toExponential();
// @Filename: b.ts
import A from './a';
var a: A;
a.value.toExponential();