Skip to content

Commit ba8f743

Browse files
committed
Support keywords like 'public' in constructor args
1 parent 7b85d4a commit ba8f743

2 files changed

Lines changed: 89 additions & 9 deletions

File tree

lib/parse/ParameterLoader.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import type {
77
TypeNode,
88
TSIndexSignature,
99
TSTypeReference,
10+
Parameter,
1011
} from '@typescript-eslint/types/dist/ts-estree';
1112
import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
1213
import type { ClassReferenceLoaded, InterfaceLoaded } from './ClassIndex';
13-
import type { CommentData } from './CommentLoader';
14+
import type { CommentData, ConstructorCommentData } from './CommentLoader';
1415
import { CommentLoader } from './CommentLoader';
1516
import type { ConstructorData } from './ConstructorLoader';
1617
import type { TypeReferenceOverride } from './typereferenceoverride/TypeReferenceOverride';
@@ -43,18 +44,34 @@ export class ParameterLoader {
4344
// Load all constructor parameters
4445
const parameters: ParameterDataField<ParameterRangeUnresolved>[] = [];
4546
for (const field of constructor.value.params) {
46-
if (field.type === AST_NODE_TYPES.Identifier) {
47-
const commentData = constructorCommentData[field.name] || {};
48-
if (!commentData.ignored) {
49-
parameters.push(this.loadField(field, commentData));
50-
}
51-
} else {
52-
throw new Error(`Could not understand constructor parameter type ${field.type} in ${this.classLoaded.localName} at ${this.classLoaded.fileName}`);
53-
}
47+
this.loadConstructorField(parameters, constructorCommentData, field);
5448
}
5549
return { parameters };
5650
}
5751

52+
/**
53+
* Load the parameter data from the given field in a constructor.
54+
* @param parameters The array of parameters that will be appended to.
55+
* @param constructorCommentData Comment data from the constructor.
56+
* @param field The field to load.
57+
*/
58+
public loadConstructorField(
59+
parameters: ParameterDataField<ParameterRangeUnresolved>[],
60+
constructorCommentData: ConstructorCommentData,
61+
field: Parameter,
62+
): void {
63+
if (field.type === AST_NODE_TYPES.Identifier) {
64+
const commentData = constructorCommentData[field.name] || {};
65+
if (!commentData.ignored) {
66+
parameters.push(this.loadField(field, commentData));
67+
}
68+
} else if (field.type === AST_NODE_TYPES.TSParameterProperty) {
69+
this.loadConstructorField(parameters, constructorCommentData, field.parameter);
70+
} else {
71+
throw new Error(`Could not understand constructor parameter type ${field.type} in ${this.classLoaded.localName} at ${this.classLoaded.fileName}`);
72+
}
73+
}
74+
5875
/**
5976
* Load all parameter data from all fields in the given interface.
6077
* If methods are found in the interface, an error is thrown.

test/parse/ParameterLoader.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,69 @@ export class A{
209209
],
210210
});
211211
});
212+
213+
it('should handle a public field', async() => {
214+
const { constructor, parameterLoader } = await getConstructor(`
215+
export class A{
216+
constructor(public fieldA: string) {}
217+
}`);
218+
expect(parameterLoader.loadConstructorFields(constructor)).toEqual({
219+
parameters: [
220+
{
221+
type: 'field',
222+
name: 'fieldA',
223+
range: {
224+
type: 'raw',
225+
value: 'string',
226+
},
227+
required: true,
228+
unique: true,
229+
},
230+
],
231+
});
232+
});
233+
234+
it('should handle a protected field', async() => {
235+
const { constructor, parameterLoader } = await getConstructor(`
236+
export class A{
237+
constructor(protected fieldA: string) {}
238+
}`);
239+
expect(parameterLoader.loadConstructorFields(constructor)).toEqual({
240+
parameters: [
241+
{
242+
type: 'field',
243+
name: 'fieldA',
244+
range: {
245+
type: 'raw',
246+
value: 'string',
247+
},
248+
required: true,
249+
unique: true,
250+
},
251+
],
252+
});
253+
});
254+
255+
it('should handle a private field', async() => {
256+
const { constructor, parameterLoader } = await getConstructor(`
257+
export class A{
258+
constructor(private fieldA: string) {}
259+
}`);
260+
expect(parameterLoader.loadConstructorFields(constructor)).toEqual({
261+
parameters: [
262+
{
263+
type: 'field',
264+
name: 'fieldA',
265+
range: {
266+
type: 'raw',
267+
value: 'string',
268+
},
269+
required: true,
270+
unique: true,
271+
},
272+
],
273+
});
274+
});
212275
});
213276

214277
describe('loadInterfaceFields', () => {

0 commit comments

Comments
 (0)