Merge pull request #7392 from Microsoft/declarationEmitFixes

Declaration emit fixes
This commit is contained in:
Mohamed Hegazy 2016-03-04 15:35:43 -08:00
commit a5354608fc
28 changed files with 739 additions and 3 deletions

View File

@ -1642,7 +1642,7 @@ namespace ts {
function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult {
// get symbol of the first identifier of the entityName
let meaning: SymbolFlags;
if (entityName.parent.kind === SyntaxKind.TypeQuery) {
if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) {
// Typeof value
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
}
@ -2429,7 +2429,7 @@ namespace ts {
return false;
default:
Debug.fail("isDeclarationVisible unknown: SyntaxKind: " + node.kind);
return false;
}
}
}
@ -16250,10 +16250,17 @@ namespace ts {
}
function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
const type = getTypeOfExpression(expr);
const type = getWidenedType(getTypeOfExpression(expr));
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
}
function writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(node));
resolveBaseTypesOfClass(classType);
const baseType = classType.resolvedBaseTypes.length ? classType.resolvedBaseTypes[0] : unknownType;
getSymbolDisplayBuilder().buildTypeDisplay(baseType, writer, enclosingDeclaration, flags);
}
function hasGlobalName(name: string): boolean {
return hasProperty(globals, name);
}
@ -16286,6 +16293,7 @@ namespace ts {
writeTypeOfDeclaration,
writeReturnTypeOfSignatureDeclaration,
writeTypeOfExpression,
writeBaseConstructorTypeOfClass,
isSymbolAccessible,
isEntityNameVisible,
getConstantValue,

View File

@ -987,6 +987,10 @@ namespace ts {
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
write("null");
}
else {
writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError;
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
}
function getHeritageClauseVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage;

View File

@ -1889,6 +1889,7 @@ namespace ts {
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult;
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant

View File

@ -0,0 +1,49 @@
//// [declarationEmit_expressionInExtends.ts]
var x: {
new<T>(s: any): Q;
}
class Q {
s: string;
}
class B extends x<string> {
}
var q: B;
q.s;
//// [declarationEmit_expressionInExtends.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var x;
var Q = (function () {
function Q() {
}
return Q;
}());
var B = (function (_super) {
__extends(B, _super);
function B() {
_super.apply(this, arguments);
}
return B;
}(x));
var q;
q.s;
//// [declarationEmit_expressionInExtends.d.ts]
declare var x: {
new <T>(s: any): Q;
};
declare class Q {
s: string;
}
declare class B extends x<string> {
}
declare var q: B;

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/declarationEmit_expressionInExtends.ts ===
var x: {
>x : Symbol(x, Decl(declarationEmit_expressionInExtends.ts, 1, 3))
new<T>(s: any): Q;
>T : Symbol(T, Decl(declarationEmit_expressionInExtends.ts, 2, 8))
>s : Symbol(s, Decl(declarationEmit_expressionInExtends.ts, 2, 11))
>Q : Symbol(Q, Decl(declarationEmit_expressionInExtends.ts, 3, 1))
}
class Q {
>Q : Symbol(Q, Decl(declarationEmit_expressionInExtends.ts, 3, 1))
s: string;
>s : Symbol(s, Decl(declarationEmit_expressionInExtends.ts, 5, 9))
}
class B extends x<string> {
>B : Symbol(B, Decl(declarationEmit_expressionInExtends.ts, 7, 1))
>x : Symbol(x, Decl(declarationEmit_expressionInExtends.ts, 1, 3))
}
var q: B;
>q : Symbol(q, Decl(declarationEmit_expressionInExtends.ts, 12, 3))
>B : Symbol(B, Decl(declarationEmit_expressionInExtends.ts, 7, 1))
q.s;
>q.s : Symbol(Q.s, Decl(declarationEmit_expressionInExtends.ts, 5, 9))
>q : Symbol(q, Decl(declarationEmit_expressionInExtends.ts, 12, 3))
>s : Symbol(Q.s, Decl(declarationEmit_expressionInExtends.ts, 5, 9))

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/declarationEmit_expressionInExtends.ts ===
var x: {
>x : new <T>(s: any) => Q
new<T>(s: any): Q;
>T : T
>s : any
>Q : Q
}
class Q {
>Q : Q
s: string;
>s : string
}
class B extends x<string> {
>B : B
>x : Q
}
var q: B;
>q : B
>B : B
q.s;
>q.s : string
>q : B
>s : string

View File

@ -0,0 +1,45 @@
//// [declarationEmit_expressionInExtends2.ts]
class C<T, U> {
x: T;
y: U;
}
function getClass<T>(c: T) {
return C;
}
class MyClass extends getClass(2) <string, number> {
}
//// [declarationEmit_expressionInExtends2.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C = (function () {
function C() {
}
return C;
}());
function getClass(c) {
return C;
}
var MyClass = (function (_super) {
__extends(MyClass, _super);
function MyClass() {
_super.apply(this, arguments);
}
return MyClass;
}(getClass(2)));
//// [declarationEmit_expressionInExtends2.d.ts]
declare class C<T, U> {
x: T;
y: U;
}
declare function getClass<T>(c: T): typeof C;
declare class MyClass extends C<string, number> {
}

View File

@ -0,0 +1,30 @@
=== tests/cases/compiler/declarationEmit_expressionInExtends2.ts ===
class C<T, U> {
>C : Symbol(C, Decl(declarationEmit_expressionInExtends2.ts, 0, 0))
>T : Symbol(T, Decl(declarationEmit_expressionInExtends2.ts, 1, 8))
>U : Symbol(U, Decl(declarationEmit_expressionInExtends2.ts, 1, 10))
x: T;
>x : Symbol(x, Decl(declarationEmit_expressionInExtends2.ts, 1, 15))
>T : Symbol(T, Decl(declarationEmit_expressionInExtends2.ts, 1, 8))
y: U;
>y : Symbol(y, Decl(declarationEmit_expressionInExtends2.ts, 2, 9))
>U : Symbol(U, Decl(declarationEmit_expressionInExtends2.ts, 1, 10))
}
function getClass<T>(c: T) {
>getClass : Symbol(getClass, Decl(declarationEmit_expressionInExtends2.ts, 4, 1))
>T : Symbol(T, Decl(declarationEmit_expressionInExtends2.ts, 6, 18))
>c : Symbol(c, Decl(declarationEmit_expressionInExtends2.ts, 6, 21))
>T : Symbol(T, Decl(declarationEmit_expressionInExtends2.ts, 6, 18))
return C;
>C : Symbol(C, Decl(declarationEmit_expressionInExtends2.ts, 0, 0))
}
class MyClass extends getClass(2) <string, number> {
>MyClass : Symbol(MyClass, Decl(declarationEmit_expressionInExtends2.ts, 8, 1))
>getClass : Symbol(getClass, Decl(declarationEmit_expressionInExtends2.ts, 4, 1))
}

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/declarationEmit_expressionInExtends2.ts ===
class C<T, U> {
>C : C<T, U>
>T : T
>U : U
x: T;
>x : T
>T : T
y: U;
>y : U
>U : U
}
function getClass<T>(c: T) {
>getClass : <T>(c: T) => typeof C
>T : T
>c : T
>T : T
return C;
>C : typeof C
}
class MyClass extends getClass(2) <string, number> {
>MyClass : MyClass
>getClass(2) : C<string, number>
>getClass : <T>(c: T) => typeof C
>2 : number
}

View File

@ -0,0 +1,52 @@
tests/cases/compiler/declarationEmit_expressionInExtends3.ts(29,30): error TS4020: Extends clause of exported class 'MyClass' has or is using private name 'LocalClass'.
tests/cases/compiler/declarationEmit_expressionInExtends3.ts(37,31): error TS4020: Extends clause of exported class 'MyClass3' has or is using private name 'LocalInterface'.
==== tests/cases/compiler/declarationEmit_expressionInExtends3.ts (2 errors) ====
export class ExportedClass<T> {
x: T;
}
class LocalClass<T, U> {
x: T;
y: U;
}
export interface ExportedInterface {
x: number;
}
interface LocalInterface {
x: number;
}
function getLocalClass<T>(c: T) {
return LocalClass;
}
function getExportedClass<T>(c: T) {
return ExportedClass;
}
export class MyClass extends getLocalClass<LocalInterface>(undefined)<string, number> { // error LocalClass is inaccisible
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4020: Extends clause of exported class 'MyClass' has or is using private name 'LocalClass'.
}
export class MyClass2 extends getExportedClass<LocalInterface>(undefined)<string> { // OK
}
export class MyClass3 extends getExportedClass<LocalInterface>(undefined)<LocalInterface> { // Error LocalInterface is inaccisble
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4020: Extends clause of exported class 'MyClass3' has or is using private name 'LocalInterface'.
}
export class MyClass4 extends getExportedClass<LocalInterface>(undefined)<ExportedInterface> { // OK
}

View File

@ -0,0 +1,101 @@
//// [declarationEmit_expressionInExtends3.ts]
export class ExportedClass<T> {
x: T;
}
class LocalClass<T, U> {
x: T;
y: U;
}
export interface ExportedInterface {
x: number;
}
interface LocalInterface {
x: number;
}
function getLocalClass<T>(c: T) {
return LocalClass;
}
function getExportedClass<T>(c: T) {
return ExportedClass;
}
export class MyClass extends getLocalClass<LocalInterface>(undefined)<string, number> { // error LocalClass is inaccisible
}
export class MyClass2 extends getExportedClass<LocalInterface>(undefined)<string> { // OK
}
export class MyClass3 extends getExportedClass<LocalInterface>(undefined)<LocalInterface> { // Error LocalInterface is inaccisble
}
export class MyClass4 extends getExportedClass<LocalInterface>(undefined)<ExportedInterface> { // OK
}
//// [declarationEmit_expressionInExtends3.js]
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var ExportedClass = (function () {
function ExportedClass() {
}
return ExportedClass;
}());
exports.ExportedClass = ExportedClass;
var LocalClass = (function () {
function LocalClass() {
}
return LocalClass;
}());
function getLocalClass(c) {
return LocalClass;
}
function getExportedClass(c) {
return ExportedClass;
}
var MyClass = (function (_super) {
__extends(MyClass, _super);
function MyClass() {
_super.apply(this, arguments);
}
return MyClass;
}(getLocalClass(undefined)));
exports.MyClass = MyClass;
var MyClass2 = (function (_super) {
__extends(MyClass2, _super);
function MyClass2() {
_super.apply(this, arguments);
}
return MyClass2;
}(getExportedClass(undefined)));
exports.MyClass2 = MyClass2;
var MyClass3 = (function (_super) {
__extends(MyClass3, _super);
function MyClass3() {
_super.apply(this, arguments);
}
return MyClass3;
}(getExportedClass(undefined)));
exports.MyClass3 = MyClass3;
var MyClass4 = (function (_super) {
__extends(MyClass4, _super);
function MyClass4() {
_super.apply(this, arguments);
}
return MyClass4;
}(getExportedClass(undefined)));
exports.MyClass4 = MyClass4;

View File

@ -0,0 +1,35 @@
tests/cases/compiler/declarationEmit_expressionInExtends4.ts(2,10): error TS4060: Return type of exported function has or is using private name 'D'.
tests/cases/compiler/declarationEmit_expressionInExtends4.ts(6,17): error TS2315: Type 'D' is not generic.
tests/cases/compiler/declarationEmit_expressionInExtends4.ts(10,18): error TS2304: Cannot find name 'SomeUndefinedFunction'.
tests/cases/compiler/declarationEmit_expressionInExtends4.ts(15,18): error TS2304: Cannot find name 'SomeUndefinedFunction'.
tests/cases/compiler/declarationEmit_expressionInExtends4.ts(15,18): error TS4020: Extends clause of exported class 'C3' has or is using private name 'SomeUndefinedFunction'.
==== tests/cases/compiler/declarationEmit_expressionInExtends4.ts (5 errors) ====
function getSomething() {
~~~~~~~~~~~~
!!! error TS4060: Return type of exported function has or is using private name 'D'.
return class D { }
}
class C extends getSomething()<number, string> {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2315: Type 'D' is not generic.
}
class C2 extends SomeUndefinedFunction()<number, string> {
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'SomeUndefinedFunction'.
}
class C3 extends SomeUndefinedFunction {
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'SomeUndefinedFunction'.
~~~~~~~~~~~~~~~~~~~~~
!!! error TS4020: Extends clause of exported class 'C3' has or is using private name 'SomeUndefinedFunction'.
}

View File

@ -0,0 +1,53 @@
//// [declarationEmit_expressionInExtends4.ts]
function getSomething() {
return class D { }
}
class C extends getSomething()<number, string> {
}
class C2 extends SomeUndefinedFunction()<number, string> {
}
class C3 extends SomeUndefinedFunction {
}
//// [declarationEmit_expressionInExtends4.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
function getSomething() {
return (function () {
function D() {
}
return D;
}());
}
var C = (function (_super) {
__extends(C, _super);
function C() {
_super.apply(this, arguments);
}
return C;
}(getSomething()));
var C2 = (function (_super) {
__extends(C2, _super);
function C2() {
_super.apply(this, arguments);
}
return C2;
}(SomeUndefinedFunction()));
var C3 = (function (_super) {
__extends(C3, _super);
function C3() {
_super.apply(this, arguments);
}
return C3;
}(SomeUndefinedFunction));

View File

@ -0,0 +1,26 @@
//// [declarationEmit_inferedDefaultExportType.ts]
// test.ts
export default {
foo: [],
bar: undefined,
baz: null
}
//// [declarationEmit_inferedDefaultExportType.js]
"use strict";
exports.__esModule = true;
exports["default"] = {
foo: [],
bar: undefined,
baz: null
};
//// [declarationEmit_inferedDefaultExportType.d.ts]
declare var _default: {
foo: any[];
bar: any;
baz: any;
};
export default _default;

View File

@ -0,0 +1,14 @@
=== tests/cases/compiler/declarationEmit_inferedDefaultExportType.ts ===
// test.ts
export default {
foo: [],
>foo : Symbol(foo, Decl(declarationEmit_inferedDefaultExportType.ts, 2, 16))
bar: undefined,
>bar : Symbol(bar, Decl(declarationEmit_inferedDefaultExportType.ts, 3, 10))
>undefined : Symbol(undefined)
baz: null
>baz : Symbol(baz, Decl(declarationEmit_inferedDefaultExportType.ts, 4, 17))
}

View File

@ -0,0 +1,18 @@
=== tests/cases/compiler/declarationEmit_inferedDefaultExportType.ts ===
// test.ts
export default {
>{ foo: [], bar: undefined, baz: null} : { foo: undefined[]; bar: undefined; baz: null; }
foo: [],
>foo : undefined[]
>[] : undefined[]
bar: undefined,
>bar : undefined
>undefined : undefined
baz: null
>baz : null
>null : null
}

View File

@ -0,0 +1,25 @@
//// [declarationEmit_inferedDefaultExportType2.ts]
// test.ts
export = {
foo: [],
bar: undefined,
baz: null
}
//// [declarationEmit_inferedDefaultExportType2.js]
"use strict";
module.exports = {
foo: [],
bar: undefined,
baz: null
};
//// [declarationEmit_inferedDefaultExportType2.d.ts]
declare var _default: {
foo: any[];
bar: any;
baz: any;
};
export = _default;

View File

@ -0,0 +1,14 @@
=== tests/cases/compiler/declarationEmit_inferedDefaultExportType2.ts ===
// test.ts
export = {
foo: [],
>foo : Symbol(foo, Decl(declarationEmit_inferedDefaultExportType2.ts, 2, 10))
bar: undefined,
>bar : Symbol(bar, Decl(declarationEmit_inferedDefaultExportType2.ts, 3, 10))
>undefined : Symbol(undefined)
baz: null
>baz : Symbol(baz, Decl(declarationEmit_inferedDefaultExportType2.ts, 4, 17))
}

View File

@ -0,0 +1,18 @@
=== tests/cases/compiler/declarationEmit_inferedDefaultExportType2.ts ===
// test.ts
export = {
>{ foo: [], bar: undefined, baz: null} : { foo: undefined[]; bar: undefined; baz: null; }
foo: [],
>foo : undefined[]
>[] : undefined[]
bar: undefined,
>bar : undefined
>undefined : undefined
baz: null
>baz : null
>null : null
}

View File

@ -0,0 +1,19 @@
tests/cases/compiler/declarationEmit_invalidExport.ts(3,3): error TS7027: Unreachable code detected.
tests/cases/compiler/declarationEmit_invalidExport.ts(5,30): error TS4081: Exported type alias 'MyClass' has or is using private name 'myClass'.
tests/cases/compiler/declarationEmit_invalidExport.ts(6,1): error TS1128: Declaration or statement expected.
==== tests/cases/compiler/declarationEmit_invalidExport.ts (3 errors) ====
if (false) {
export var myClass = 0;
~~~~~~
!!! error TS7027: Unreachable code detected.
}
export type MyClass = typeof myClass;
~~~~~~~
!!! error TS4081: Exported type alias 'MyClass' has or is using private name 'myClass'.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,14 @@
//// [declarationEmit_invalidExport.ts]
if (false) {
export var myClass = 0;
}
export type MyClass = typeof myClass;
}
//// [declarationEmit_invalidExport.js]
"use strict";
if (false) {
exports.myClass = 0;
}

View File

@ -0,0 +1,15 @@
// @declaration: true
var x: {
new<T>(s: any): Q;
}
class Q {
s: string;
}
class B extends x<string> {
}
var q: B;
q.s;

View File

@ -0,0 +1,13 @@
// @declaration: true
class C<T, U> {
x: T;
y: U;
}
function getClass<T>(c: T) {
return C;
}
class MyClass extends getClass(2) <string, number> {
}

View File

@ -0,0 +1,43 @@
// @declaration: true
export class ExportedClass<T> {
x: T;
}
class LocalClass<T, U> {
x: T;
y: U;
}
export interface ExportedInterface {
x: number;
}
interface LocalInterface {
x: number;
}
function getLocalClass<T>(c: T) {
return LocalClass;
}
function getExportedClass<T>(c: T) {
return ExportedClass;
}
export class MyClass extends getLocalClass<LocalInterface>(undefined)<string, number> { // error LocalClass is inaccisible
}
export class MyClass2 extends getExportedClass<LocalInterface>(undefined)<string> { // OK
}
export class MyClass3 extends getExportedClass<LocalInterface>(undefined)<LocalInterface> { // Error LocalInterface is inaccisble
}
export class MyClass4 extends getExportedClass<LocalInterface>(undefined)<ExportedInterface> { // OK
}

View File

@ -0,0 +1,18 @@
// @declaration: true
function getSomething() {
return class D { }
}
class C extends getSomething()<number, string> {
}
class C2 extends SomeUndefinedFunction()<number, string> {
}
class C3 extends SomeUndefinedFunction {
}

View File

@ -0,0 +1,9 @@
// @declaration: true
// @module: commonjs
// test.ts
export default {
foo: [],
bar: undefined,
baz: null
}

View File

@ -0,0 +1,9 @@
// @declaration: true
// @module: commonjs
// test.ts
export = {
foo: [],
bar: undefined,
baz: null
}

View File

@ -0,0 +1,7 @@
// @declaration: true
if (false) {
export var myClass = 0;
}
export type MyClass = typeof myClass;
}