Fix #3810: Handel expressions in extends clauses

This commit is contained in:
Mohamed Hegazy
2016-03-03 22:35:30 -08:00
parent c98c763243
commit 3bb2c57264
10 changed files with 331 additions and 0 deletions
+10
View File
@@ -16244,6 +16244,15 @@ namespace ts {
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[0];
if (baseType) {
getSymbolDisplayBuilder().buildTypeDisplay(baseType, writer, enclosingDeclaration, flags);
}
}
function hasGlobalName(name: string): boolean {
return hasProperty(globals, name);
}
@@ -16276,6 +16285,7 @@ namespace ts {
writeTypeOfDeclaration,
writeReturnTypeOfSignatureDeclaration,
writeTypeOfExpression,
writeBaseConstructorTypeOfClass,
isSymbolAccessible,
isEntityNameVisible,
getConstantValue,
+4
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;
+1
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
@@ -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> {
}
@@ -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))
}
@@ -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
}
@@ -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
}
@@ -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;
@@ -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> {
}
@@ -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
}