Skip to content

Commit 3fe512a

Browse files
committed
Keep accessors as accessors in emitted anonymous class declarations
1 parent 56a0825 commit 3fe512a

7 files changed

Lines changed: 284 additions & 38 deletions

src/compiler/checker.ts

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ import {
465465
IntroducesNewScopeNode,
466466
isAccessExpression,
467467
isAccessor,
468+
isAccessorModifier,
468469
isAliasableExpression,
469470
isAmbientModule,
470471
isArray,
@@ -7412,26 +7413,50 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
74127413

74137414
if (propertySymbol.flags & SymbolFlags.Accessor) {
74147415
const writeType = getWriteTypeOfSymbol(propertySymbol);
7415-
if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) {
7416-
const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor)!;
7417-
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
7418-
typeElements.push(
7419-
setCommentRange(
7420-
context,
7421-
signatureToSignatureDeclarationHelper(getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7422-
getterDeclaration,
7423-
),
7424-
);
7425-
const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor)!;
7426-
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
7427-
typeElements.push(
7428-
setCommentRange(
7429-
context,
7430-
signatureToSignatureDeclarationHelper(setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7431-
setterDeclaration,
7432-
),
7433-
);
7434-
return;
7416+
if (!isErrorType(propertyType) && !isErrorType(writeType)) {
7417+
const propDeclaration = getDeclarationOfKind<PropertyDeclaration>(propertySymbol, SyntaxKind.PropertyDeclaration);
7418+
if (propertyType !== writeType || propertySymbol.parent!.flags & SymbolFlags.Class && !propDeclaration) {
7419+
const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor);
7420+
if (getterDeclaration) {
7421+
const getterSignature = getSignatureFromDeclaration(getterDeclaration);
7422+
typeElements.push(
7423+
setCommentRange(
7424+
context,
7425+
signatureToSignatureDeclarationHelper(getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7426+
getterDeclaration,
7427+
),
7428+
);
7429+
}
7430+
const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor);
7431+
if (setterDeclaration) {
7432+
const setterSignature = getSignatureFromDeclaration(setterDeclaration);
7433+
typeElements.push(
7434+
setCommentRange(
7435+
context,
7436+
signatureToSignatureDeclarationHelper(setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7437+
setterDeclaration,
7438+
),
7439+
);
7440+
}
7441+
return;
7442+
}
7443+
if (propertySymbol.parent!.flags & SymbolFlags.Class && propDeclaration && find(propDeclaration.modifiers, isAccessorModifier)) {
7444+
const fakeGetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, propertyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
7445+
typeElements.push(
7446+
setCommentRange(
7447+
context,
7448+
signatureToSignatureDeclarationHelper(fakeGetterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7449+
propDeclaration,
7450+
),
7451+
);
7452+
const setterParam = createSymbol(SymbolFlags.FunctionScopedVariable, "arg" as __String);
7453+
setterParam.links.type = writeType;
7454+
const fakeSetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, [setterParam], voidType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
7455+
typeElements.push(
7456+
signatureToSignatureDeclarationHelper(fakeSetterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7457+
);
7458+
return;
7459+
}
74357460
}
74367461
}
74377462

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
2+
3+
//// [anonymousClassAccessorsDeclarationEmit1.ts]
4+
export abstract class Base {
5+
accessor a = 1;
6+
}
7+
8+
export function middle(Super = Base) {
9+
abstract class Middle extends Super {}
10+
return Middle;
11+
}
12+
13+
class A {
14+
constructor(...args: any[]) {}
15+
}
16+
17+
export function Mixin<T extends typeof A>(Super: T) {
18+
return class B extends Super {
19+
get myName(): string {
20+
return "B";
21+
}
22+
set myName(arg: string) {}
23+
};
24+
}
25+
26+
27+
//// [anonymousClassAccessorsDeclarationEmit1.js]
28+
export class Base {
29+
accessor a = 1;
30+
}
31+
export function middle(Super = Base) {
32+
class Middle extends Super {
33+
}
34+
return Middle;
35+
}
36+
class A {
37+
constructor(...args) { }
38+
}
39+
export function Mixin(Super) {
40+
return class B extends Super {
41+
get myName() {
42+
return "B";
43+
}
44+
set myName(arg) { }
45+
};
46+
}
47+
48+
49+
//// [anonymousClassAccessorsDeclarationEmit1.d.ts]
50+
export declare abstract class Base {
51+
accessor a: number;
52+
}
53+
export declare function middle(Super?: typeof Base): abstract new () => {
54+
get a(): number;
55+
set a(arg: number);
56+
};
57+
declare class A {
58+
constructor(...args: any[]);
59+
}
60+
export declare function Mixin<T extends typeof A>(Super: T): {
61+
new (...args: any[]): {
62+
get myName(): string;
63+
set myName(arg: string);
64+
};
65+
} & T;
66+
export {};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
2+
3+
=== anonymousClassAccessorsDeclarationEmit1.ts ===
4+
export abstract class Base {
5+
>Base : Symbol(Base, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 0))
6+
7+
accessor a = 1;
8+
>a : Symbol(Base.a, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 28))
9+
}
10+
11+
export function middle(Super = Base) {
12+
>middle : Symbol(middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 2, 1))
13+
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 23))
14+
>Base : Symbol(Base, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 0, 0))
15+
16+
abstract class Middle extends Super {}
17+
>Middle : Symbol(Middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 38))
18+
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 23))
19+
20+
return Middle;
21+
>Middle : Symbol(Middle, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 4, 38))
22+
}
23+
24+
class A {
25+
>A : Symbol(A, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 7, 1))
26+
27+
constructor(...args: any[]) {}
28+
>args : Symbol(args, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 10, 14))
29+
}
30+
31+
export function Mixin<T extends typeof A>(Super: T) {
32+
>Mixin : Symbol(Mixin, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 11, 1))
33+
>T : Symbol(T, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 22))
34+
>A : Symbol(A, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 7, 1))
35+
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 42))
36+
>T : Symbol(T, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 22))
37+
38+
return class B extends Super {
39+
>B : Symbol(B, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 8))
40+
>Super : Symbol(Super, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 13, 42))
41+
42+
get myName(): string {
43+
>myName : Symbol(B.myName, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 32), Decl(anonymousClassAccessorsDeclarationEmit1.ts, 17, 5))
44+
45+
return "B";
46+
}
47+
set myName(arg: string) {}
48+
>myName : Symbol(B.myName, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 14, 32), Decl(anonymousClassAccessorsDeclarationEmit1.ts, 17, 5))
49+
>arg : Symbol(arg, Decl(anonymousClassAccessorsDeclarationEmit1.ts, 18, 15))
50+
51+
};
52+
}
53+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//// [tests/cases/conformance/declarationEmit/anonymousClassAccessorsDeclarationEmit1.ts] ////
2+
3+
=== anonymousClassAccessorsDeclarationEmit1.ts ===
4+
export abstract class Base {
5+
>Base : Base
6+
> : ^^^^
7+
8+
accessor a = 1;
9+
>a : number
10+
> : ^^^^^^
11+
>1 : 1
12+
> : ^
13+
}
14+
15+
export function middle(Super = Base) {
16+
>middle : (Super?: typeof Base) => typeof Middle
17+
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
>Super : typeof Base
19+
> : ^^^^^^^^^^^
20+
>Base : typeof Base
21+
> : ^^^^^^^^^^^
22+
23+
abstract class Middle extends Super {}
24+
>Middle : Middle
25+
> : ^^^^^^
26+
>Super : Base
27+
> : ^^^^
28+
29+
return Middle;
30+
>Middle : typeof Middle
31+
> : ^^^^^^^^^^^^^
32+
}
33+
34+
class A {
35+
>A : A
36+
> : ^
37+
38+
constructor(...args: any[]) {}
39+
>args : any[]
40+
> : ^^^^^
41+
}
42+
43+
export function Mixin<T extends typeof A>(Super: T) {
44+
>Mixin : <T extends typeof A>(Super: T) => { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
45+
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
>A : typeof A
47+
> : ^^^^^^^^
48+
>Super : T
49+
> : ^
50+
51+
return class B extends Super {
52+
>class B extends Super { get myName(): string { return "B"; } set myName(arg: string) {} } : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
53+
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
>B : { new (...args: any[]): B; prototype: Mixin<any>.B; } & T
55+
> : ^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
>Super : A
57+
> : ^
58+
59+
get myName(): string {
60+
>myName : string
61+
> : ^^^^^^
62+
63+
return "B";
64+
>"B" : "B"
65+
> : ^^^
66+
}
67+
set myName(arg: string) {}
68+
>myName : string
69+
> : ^^^^^^
70+
>arg : string
71+
> : ^^^^^^
72+
73+
};
74+
}
75+

tests/baselines/reference/autoAccessor8.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ declare class C2 {
4545
}
4646
declare function f(): {
4747
new (): {
48-
a: any;
48+
get a(): any;
49+
set a(arg: any);
4950
};
50-
b: any;
51+
get b(): any;
52+
set b(arg: any);
5153
};

tests/baselines/reference/jsDeclarationsFunctionLikeClasses2.types

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -291,16 +291,16 @@ export function Point2D(x, y) {
291291
}
292292

293293
Point2D.prototype = {
294-
>Point2D.prototype = { __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; x: number; y: number; }
295-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
296-
>Point2D.prototype : { __proto__: typeof Vec; x: number; y: number; }
297-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
294+
>Point2D.prototype = { __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
295+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
296+
>Point2D.prototype : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
297+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
298298
>Point2D : typeof Point2D
299299
> : ^^^^^^^^^^^^^^
300-
>prototype : { __proto__: typeof Vec; x: number; y: number; }
301-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
302-
>{ __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; x: number; y: number; }
303-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
300+
>prototype : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
301+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
302+
>{ __proto__: Vec, get x() { return this.storage[0]; }, /** * @param {number} x */ set x(x) { this.storage[0] = x; }, get y() { return this.storage[1]; }, /** * @param {number} y */ set y(y) { this.storage[1] = y; }} : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
303+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
304304

305305
__proto__: Vec,
306306
>__proto__ : typeof Vec
@@ -315,8 +315,8 @@ Point2D.prototype = {
315315
return this.storage[0];
316316
>this.storage[0] : any
317317
>this.storage : any
318-
>this : { __proto__: typeof Vec; x: number; y: number; }
319-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
318+
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
319+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
320320
>storage : any
321321
> : ^^^
322322
>0 : 0
@@ -337,8 +337,8 @@ Point2D.prototype = {
337337
> : ^^^^^^
338338
>this.storage[0] : any
339339
>this.storage : any
340-
>this : { __proto__: typeof Vec; x: number; y: number; }
341-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
340+
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
341+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
342342
>storage : any
343343
> : ^^^
344344
>0 : 0
@@ -354,8 +354,8 @@ Point2D.prototype = {
354354
return this.storage[1];
355355
>this.storage[1] : any
356356
>this.storage : any
357-
>this : { __proto__: typeof Vec; x: number; y: number; }
358-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
357+
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
358+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
359359
>storage : any
360360
> : ^^^
361361
>1 : 1
@@ -376,8 +376,8 @@ Point2D.prototype = {
376376
> : ^^^^^^
377377
>this.storage[1] : any
378378
>this.storage : any
379-
>this : { __proto__: typeof Vec; x: number; y: number; }
380-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
379+
>this : { __proto__: typeof Vec; get x(): number; set x(x: number); get y(): number; set y(y: number); }
380+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^^^^ ^^^^^^^^ ^^ ^^^^
381381
>storage : any
382382
> : ^^^
383383
>1 : 1
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// @strict: true
2+
// @target: esnext
3+
// @declaration: true
4+
5+
export abstract class Base {
6+
accessor a = 1;
7+
}
8+
9+
export function middle(Super = Base) {
10+
abstract class Middle extends Super {}
11+
return Middle;
12+
}
13+
14+
class A {
15+
constructor(...args: any[]) {}
16+
}
17+
18+
export function Mixin<T extends typeof A>(Super: T) {
19+
return class B extends Super {
20+
get myName(): string {
21+
return "B";
22+
}
23+
set myName(arg: string) {}
24+
};
25+
}

0 commit comments

Comments
 (0)