Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 2fc02d0

Browse files
Benjamin Foxmprobst
authored andcommitted
Fix DecoratorClassVisitor to only emit ctorParameters when the class has a constructor
This more closely matches the behavior of TSC which only emits the "design:paramtypes" metadata when the class actually has a constructor function.
1 parent 6c4f962 commit 2fc02d0

File tree

3 files changed

+39
-60
lines changed

3 files changed

+39
-60
lines changed

src/class_decorator_downlevel_transformer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function insertBeforeDecoratorProperties(
100100
let insertionPoint = classMembers.findIndex(
101101
m => isNameEqual(m, 'ctorParameters') || isNameEqual(m, 'propDecorators'));
102102
if (insertionPoint === -1) {
103-
insertionPoint = classMembers.length - 1;
103+
insertionPoint = classMembers.length; // Insert at end of list
104104
}
105105
const members = [
106106
...classMembers.slice(0, insertionPoint), decoratorMetadata,
@@ -149,4 +149,4 @@ export function classDecoratorDownlevelTransformer(
149149

150150
return (sf: ts.SourceFile) => visitor(sf) as ts.SourceFile;
151151
};
152-
}
152+
}

src/decorator-annotator.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ export function shouldLower(decorator: ts.Decorator, typeChecker: ts.TypeChecker
6464
// separately for each class we encounter.
6565
export class DecoratorClassVisitor {
6666
/** Decorators on the class itself. */
67-
decorators: ts.Decorator[];
67+
private decorators: ts.Decorator[];
6868
/** The constructor parameter list and decorators on each param. */
6969
private ctorParameters: ConstructorParameter[];
7070
/** Per-method decorators. */
71-
propDecorators: Map<string, ts.Decorator[]>;
71+
private propDecorators: Map<string, ts.Decorator[]>;
7272

7373
constructor(
7474
private typeChecker: ts.TypeChecker, private rewriter: Rewriter,
@@ -249,8 +249,12 @@ export class DecoratorClassVisitor {
249249
*/
250250
emitMetadataAsStaticProperties() {
251251
const decoratorInvocations = '{type: Function, args?: any[]}[]';
252+
252253
if (this.decorators || this.ctorParameters) {
253254
this.rewriter.emit(`/** @nocollapse */\n`);
255+
}
256+
257+
if (this.ctorParameters) {
254258
// ctorParameters may contain forward references in the type: field, so wrap in a function
255259
// closure
256260
this.rewriter.emit(

test/decorator-annotator_test.ts

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,6 @@ class Foo {
120120
{ type: Test1 },
121121
{ type: Test2, args: [param,] },
122122
];
123-
/** @nocollapse */
124-
static ctorParameters: () => ({
125-
type: any;
126-
decorators?: {
127-
type: Function;
128-
args?: any[];
129-
}[];
130-
} | null)[] = () => [];
131123
}
132124
`);
133125
});
@@ -148,14 +140,6 @@ class Foo {
148140
}[] = [
149141
{ type: Test },
150142
];
151-
/** @nocollapse */
152-
static ctorParameters: () => ({
153-
type: any;
154-
decorators?: {
155-
type: Function;
156-
args?: any[];
157-
}[];
158-
} | null)[] = () => [];
159143
}
160144
`);
161145
});
@@ -177,14 +161,6 @@ class Foo {
177161
}[] = [
178162
{ type: Test },
179163
];
180-
/** @nocollapse */
181-
static ctorParameters: () => ({
182-
type: any;
183-
decorators?: {
184-
type: Function;
185-
args?: any[];
186-
}[];
187-
} | null)[] = () => [];
188164
}
189165
`);
190166
});
@@ -219,14 +195,6 @@ class Foo {
219195
{ type: Test3 },
220196
{ type: Test4, args: [param,] },
221197
];
222-
/** @nocollapse */
223-
static ctorParameters: () => ({
224-
type: any;
225-
decorators?: {
226-
type: Function;
227-
args?: any[];
228-
}[];
229-
} | null)[] = () => [];
230198
}
231199
`);
232200
});
@@ -246,14 +214,6 @@ export class Foo {
246214
}[] = [
247215
{ type: Test1 },
248216
];
249-
/** @nocollapse */
250-
static ctorParameters: () => ({
251-
type: any;
252-
decorators?: {
253-
type: Function;
254-
args?: any[];
255-
}[];
256-
} | null)[] = () => [];
257217
}
258218
`);
259219
});
@@ -282,14 +242,6 @@ export class Foo {
282242
}[] = [
283243
{ type: Test2 },
284244
];
285-
/** @nocollapse */
286-
static ctorParameters: () => ({
287-
type: any;
288-
decorators?: {
289-
type: Function;
290-
args?: any[];
291-
}[];
292-
} | null)[] = () => [];
293245
}
294246
}
295247
static decorators: {
@@ -298,14 +250,6 @@ export class Foo {
298250
}[] = [
299251
{ type: Test1 },
300252
];
301-
/** @nocollapse */
302-
static ctorParameters: () => ({
303-
type: any;
304-
decorators?: {
305-
type: Function;
306-
args?: any[];
307-
}[];
308-
} | null)[] = () => [];
309253
}
310254
`);
311255
});
@@ -321,6 +265,37 @@ class Foo {
321265
`);
322266
});
323267

268+
it('transforms empty ctors', () => {
269+
expectTranslated(`
270+
import {FakeDecorator} from 'bar';
271+
/** @Annotation */ let Test1: FakeDecorator;
272+
@Test1()
273+
class Foo {
274+
constructor() {
275+
}
276+
}`).to.equal(`import { FakeDecorator } from 'bar';
277+
/** @Annotation */ let Test1: FakeDecorator;
278+
class Foo {
279+
constructor() {
280+
}
281+
static decorators: {
282+
type: Function;
283+
args?: any[];
284+
}[] = [
285+
{ type: Test1 },
286+
];
287+
/** @nocollapse */
288+
static ctorParameters: () => ({
289+
type: any;
290+
decorators?: {
291+
type: Function;
292+
args?: any[];
293+
}[];
294+
} | null)[] = () => [];
295+
}
296+
`);
297+
});
298+
324299
it('transforms injected ctors', () => {
325300
expectTranslated(`
326301
/** @Annotation */ let Inject: Function;

0 commit comments

Comments
 (0)