mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix #3810: Handel expressions in extends clauses
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user