Skip to content

Commit 9657927

Browse files
feat(compiler): Automatically add @default JSDoc to @prop() declarations (#6264)
* feat: Automatically add @default JSDoc to @prop() declarations * add default values to component properties in type definitions
1 parent bbbfb45 commit 9657927

File tree

5 files changed

+123
-4
lines changed

5 files changed

+123
-4
lines changed

src/compiler/types/generate-prop-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export const generatePropTypes = (cmpMeta: d.ComponentCompilerMeta, typeImportDa
1818
cmpProp.docs.tags = [...(cmpProp.docs.tags || []), { name: 'readonly', text: '' }];
1919
doc = getTextDocs(cmpProp.docs);
2020
}
21+
if (cmpProp.defaultValue !== undefined && !doc?.match('@default')) {
22+
cmpProp.docs = cmpProp.docs || { tags: [], text: '' };
23+
cmpProp.docs.tags = [...(cmpProp.docs.tags || []), { name: 'default', text: cmpProp.defaultValue }];
24+
doc = getTextDocs(cmpProp.docs);
25+
}
2126
return {
2227
name: cmpProp.name,
2328
type: getType(cmpProp, typeImportData, cmpMeta.sourceFilePath),

src/compiler/types/tests/generate-prop-types.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,5 +189,61 @@ describe('generate-prop-types', () => {
189189

190190
expect(actualTypeInfo).toEqual(expectedTypeInfo);
191191
});
192+
193+
it('appends `@default` to jsdoc when the property has a default value', () => {
194+
const stubImportTypes = stubTypesImportData();
195+
const componentMeta = stubComponentCompilerMeta({
196+
properties: [
197+
stubComponentCompilerProperty({
198+
defaultValue: "'hello'",
199+
}),
200+
],
201+
});
202+
203+
const expectedTypeInfo: d.TypeInfo = [
204+
{
205+
jsdoc: "@default 'hello'",
206+
internal: false,
207+
name: 'propName',
208+
optional: false,
209+
required: false,
210+
type: 'UserCustomPropType',
211+
},
212+
];
213+
214+
const actualTypeInfo = generatePropTypes(componentMeta, stubImportTypes);
215+
216+
expect(actualTypeInfo).toEqual(expectedTypeInfo);
217+
});
218+
219+
it('does not duplicate `@default` in jsdoc when it is already present', () => {
220+
const stubImportTypes = stubTypesImportData();
221+
const componentMeta = stubComponentCompilerMeta({
222+
properties: [
223+
stubComponentCompilerProperty({
224+
defaultValue: "'hello'",
225+
docs: {
226+
text: '',
227+
tags: [{ name: 'default', text: "'existing default'" }],
228+
},
229+
}),
230+
],
231+
});
232+
233+
const expectedTypeInfo: d.TypeInfo = [
234+
{
235+
jsdoc: "@default 'existing default'",
236+
internal: false,
237+
name: 'propName',
238+
optional: false,
239+
required: false,
240+
type: 'UserCustomPropType',
241+
},
242+
];
243+
244+
const actualTypeInfo = generatePropTypes(componentMeta, stubImportTypes);
245+
246+
expect(actualTypeInfo).toEqual(expectedTypeInfo);
247+
});
192248
});
193249
});

test/end-to-end/src/components.d.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ export namespace Components {
3939
interface CmpC {
4040
}
4141
interface CmpDsd {
42+
/**
43+
* @default 0
44+
*/
4245
"initialCounter": number;
4346
}
4447
interface CmpServerVsClient {
@@ -85,6 +88,9 @@ export namespace Components {
8588
interface ImportAssets {
8689
}
8790
interface ListenCmp {
91+
/**
92+
* @default false
93+
*/
8894
"opened": boolean;
8995
}
9096
interface MethodCmp {
@@ -100,13 +106,17 @@ export namespace Components {
100106
* @returns some string
101107
*/
102108
"someMethodWithArgs": (unit: string, value: number) => Promise<string>;
109+
/**
110+
* @default 0
111+
*/
103112
"someProp": number;
104113
}
105114
interface MyCmp {
106115
/**
107116
* bar prop
108117
* @returns bar
109-
* @readonly
118+
* @readonly
119+
* @default 'bar'
110120
*/
111121
"barProp": string;
112122
/**
@@ -122,7 +132,8 @@ export namespace Components {
122132
/**
123133
* bar prop
124134
* @returns bar
125-
* @readonly
135+
* @readonly
136+
* @default 'bar'
126137
*/
127138
"barProp": string;
128139
/**
@@ -153,6 +164,9 @@ export namespace Components {
153164
interface PrerenderCmp {
154165
}
155166
interface PropCmp {
167+
/**
168+
* @default 'life preservers'
169+
*/
156170
"clothes": string;
157171
"first": string;
158172
/**
@@ -166,8 +180,14 @@ export namespace Components {
166180
"mode"?: any;
167181
}
168182
interface RuntimeDecorators {
183+
/**
184+
* @default 'basicProp'
185+
*/
169186
"basicProp": string;
170187
"decoratedGetterSetterProp": number;
188+
/**
189+
* @default -10
190+
*/
171191
"decoratedProp": number;
172192
}
173193
interface ScopedCarDetail {
@@ -625,6 +645,9 @@ declare namespace LocalJSX {
625645
interface CmpC {
626646
}
627647
interface CmpDsd {
648+
/**
649+
* @default 0
650+
*/
628651
"initialCounter"?: number;
629652
}
630653
interface CmpServerVsClient {
@@ -657,16 +680,23 @@ declare namespace LocalJSX {
657680
interface ImportAssets {
658681
}
659682
interface ListenCmp {
683+
/**
684+
* @default false
685+
*/
660686
"opened"?: boolean;
661687
}
662688
interface MethodCmp {
689+
/**
690+
* @default 0
691+
*/
663692
"someProp"?: number;
664693
}
665694
interface MyCmp {
666695
/**
667696
* bar prop
668697
* @returns bar
669-
* @readonly
698+
* @readonly
699+
* @default 'bar'
670700
*/
671701
"barProp"?: string;
672702
/**
@@ -682,7 +712,8 @@ declare namespace LocalJSX {
682712
/**
683713
* bar prop
684714
* @returns bar
685-
* @readonly
715+
* @readonly
716+
* @default 'bar'
686717
*/
687718
"barProp"?: string;
688719
/**
@@ -713,6 +744,9 @@ declare namespace LocalJSX {
713744
interface PrerenderCmp {
714745
}
715746
interface PropCmp {
747+
/**
748+
* @default 'life preservers'
749+
*/
716750
"clothes"?: string;
717751
"first"?: string;
718752
/**
@@ -726,8 +760,14 @@ declare namespace LocalJSX {
726760
"mode"?: any;
727761
}
728762
interface RuntimeDecorators {
763+
/**
764+
* @default 'basicProp'
765+
*/
729766
"basicProp"?: string;
730767
"decoratedGetterSetterProp"?: number;
768+
/**
769+
* @default -10
770+
*/
731771
"decoratedProp"?: number;
732772
}
733773
interface ScopedCarDetail {

test/wdio/src/components.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ export namespace Components {
1919
interface CmpClientShadow {
2020
}
2121
interface CmpD {
22+
/**
23+
* @default ''
24+
*/
2225
"uniqueId": string;
2326
}
2427
interface CmpScopedA {
@@ -134,6 +137,9 @@ declare namespace LocalJSX {
134137
interface CmpClientShadow {
135138
}
136139
interface CmpD {
140+
/**
141+
* @default ''
142+
*/
137143
"uniqueId"?: string;
138144
}
139145
interface CmpScopedA {

test/wdio/ts-target-props/components.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@
77
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
88
export namespace Components {
99
interface TsTargetProps {
10+
/**
11+
* @default 'basicProp'
12+
*/
1013
"basicProp": string;
1114
"decoratedGetterSetterProp": number;
15+
/**
16+
* @default -10
17+
*/
1218
"decoratedProp": number;
1319
"dynamicLifecycle": string[];
1420
}
@@ -26,8 +32,14 @@ declare global {
2632
}
2733
declare namespace LocalJSX {
2834
interface TsTargetProps {
35+
/**
36+
* @default 'basicProp'
37+
*/
2938
"basicProp"?: string;
3039
"decoratedGetterSetterProp"?: number;
40+
/**
41+
* @default -10
42+
*/
3143
"decoratedProp"?: number;
3244
"dynamicLifecycle"?: string[];
3345
}

0 commit comments

Comments
 (0)