Skip to content

Commit 6b20133

Browse files
authored
feat(type-formatting): new objectFieldSeparatorOptionalLinebreak option (#1514)
1 parent dd0950b commit 6b20133

File tree

5 files changed

+149
-6
lines changed

5 files changed

+149
-6
lines changed

.README/rules/type-formatting.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ each object property-value pair.
4848

4949
Defaults to `"comma"`.
5050

51+
### `objectFieldSeparatorOptionalLinebreak`
52+
53+
Whether `objectFieldSeparator` set to `"semicolon-and-linebreak"` or
54+
`"comma-and-linebreak"` should be allowed to optionally drop the linebreak.
55+
56+
Defaults to `true`.
57+
5158
### `objectFieldIndent`
5259

5360
A string indicating the whitespace to be added on each line preceding an
@@ -82,7 +89,7 @@ Determines the spacing to add to unions (`|`). Defaults to a single space (`" "`
8289
|Tags|`param`, `property`, `returns`, `this`, `throws`, `type`, `typedef`, `yields`|
8390
|Recommended|false|
8491
|Settings|`mode`|
85-
|Options|`arrayBrackets`, `enableFixer`, `genericDot`, `objectFieldIndent`, `objectFieldQuote`, `objectFieldSeparator`, `objectFieldSeparatorTrailingPunctuation`, `propertyQuotes`, `separatorForSingleObjectField`, `stringQuotes`, `typeBracketSpacing`, `unionSpacing`|
92+
|Options|`arrayBrackets`, `enableFixer`, `genericDot`, `objectFieldIndent`, `objectFieldQuote`, `objectFieldSeparator`, `objectFieldSeparatorOptionalLinebreak`, `objectFieldSeparatorTrailingPunctuation`, `propertyQuotes`, `separatorForSingleObjectField`, `stringQuotes`, `typeBracketSpacing`, `unionSpacing`|
8693

8794
## Failing examples
8895

docs/rules/type-formatting.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ each object property-value pair.
6666

6767
Defaults to `"comma"`.
6868

69+
<a name="user-content-type-formatting-options-objectfieldseparatoroptionallinebreak"></a>
70+
<a name="type-formatting-options-objectfieldseparatoroptionallinebreak"></a>
71+
### <code>objectFieldSeparatorOptionalLinebreak</code>
72+
73+
Whether `objectFieldSeparator` set to `"semicolon-and-linebreak"` or
74+
`"comma-and-linebreak"` should be allowed to optionally drop the linebreak.
75+
76+
Defaults to `true`.
77+
6978
<a name="user-content-type-formatting-options-objectfieldindent"></a>
7079
<a name="type-formatting-options-objectfieldindent"></a>
7180
### <code>objectFieldIndent</code>
@@ -110,7 +119,7 @@ Determines the spacing to add to unions (`|`). Defaults to a single space (`" "`
110119
|Tags|`param`, `property`, `returns`, `this`, `throws`, `type`, `typedef`, `yields`|
111120
|Recommended|false|
112121
|Settings|`mode`|
113-
|Options|`arrayBrackets`, `enableFixer`, `genericDot`, `objectFieldIndent`, `objectFieldQuote`, `objectFieldSeparator`, `objectFieldSeparatorTrailingPunctuation`, `propertyQuotes`, `separatorForSingleObjectField`, `stringQuotes`, `typeBracketSpacing`, `unionSpacing`|
122+
|Options|`arrayBrackets`, `enableFixer`, `genericDot`, `objectFieldIndent`, `objectFieldQuote`, `objectFieldSeparator`, `objectFieldSeparatorOptionalLinebreak`, `objectFieldSeparatorTrailingPunctuation`, `propertyQuotes`, `separatorForSingleObjectField`, `stringQuotes`, `typeBracketSpacing`, `unionSpacing`|
114123

115124
<a name="user-content-type-formatting-failing-examples"></a>
116125
<a name="type-formatting-failing-examples"></a>
@@ -281,6 +290,21 @@ The following patterns are considered problems:
281290
*/
282291
// "jsdoc/type-formatting": ["error"|"warn", {"propertyQuotes":null}]
283292
// Message: Inconsistent null property quotes usage
293+
294+
/**
295+
* @param {{a: string, b: number}} cfg
296+
*/
297+
// "jsdoc/type-formatting": ["error"|"warn", {"objectFieldIndent":" ","objectFieldSeparator":"semicolon-and-linebreak","objectFieldSeparatorOptionalLinebreak":true}]
298+
// Message: Inconsistent semicolon-and-linebreak separator usage
299+
300+
/**
301+
* @param {{
302+
* a: string,
303+
* b: number
304+
* }} cfg
305+
*/
306+
// "jsdoc/type-formatting": ["error"|"warn", {"objectFieldIndent":" ","objectFieldSeparator":"semicolon-and-linebreak","objectFieldSeparatorOptionalLinebreak":true}]
307+
// Message: Inconsistent semicolon-and-linebreak separator usage
284308
````
285309

286310

@@ -357,5 +381,18 @@ The following patterns are not considered problems:
357381
/**
358382
* @param cfg
359383
*/
384+
385+
/**
386+
* @param {{a: string; b: number}} cfg
387+
*/
388+
// "jsdoc/type-formatting": ["error"|"warn", {"objectFieldIndent":" ","objectFieldSeparator":"semicolon-and-linebreak","objectFieldSeparatorOptionalLinebreak":true}]
389+
390+
/**
391+
* @param {{
392+
* a: string;
393+
* b: number
394+
* }} cfg
395+
*/
396+
// "jsdoc/type-formatting": ["error"|"warn", {"objectFieldIndent":" ","objectFieldSeparator":"semicolon-and-linebreak","objectFieldSeparatorOptionalLinebreak":true}]
360397
````
361398

src/rules.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ export interface Rules {
766766
objectFieldIndent?: string;
767767
objectFieldQuote?: "double" | "single" | null;
768768
objectFieldSeparator?: "comma" | "comma-and-linebreak" | "linebreak" | "semicolon" | "semicolon-and-linebreak";
769+
objectFieldSeparatorOptionalLinebreak?: boolean;
769770
objectFieldSeparatorTrailingPunctuation?: boolean;
770771
propertyQuotes?: "double" | "single" | null;
771772
separatorForSingleObjectField?: boolean;

src/rules/typeFormatting.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default iterateJsdoc(({
2222
objectFieldIndent = '',
2323
objectFieldQuote = null,
2424
objectFieldSeparator = 'comma',
25+
objectFieldSeparatorOptionalLinebreak = true,
2526
objectFieldSeparatorTrailingPunctuation = false,
2627
propertyQuotes = null,
2728
separatorForSingleObjectField = false,
@@ -232,14 +233,21 @@ export default iterateJsdoc(({
232233

233234
case 'JsdocTypeObject': {
234235
const typeNode = /** @type {import('jsdoc-type-pratt-parser').ObjectResult} */ (nde);
236+
/* c8 ignore next -- Guard */
237+
const separator = typeNode.meta.separator ?? 'comma';
235238
if (
236-
/* c8 ignore next -- Guard */
237-
(typeNode.meta.separator ?? 'comma') !== objectFieldSeparator ||
239+
(separator !== objectFieldSeparator &&
240+
(!objectFieldSeparatorOptionalLinebreak ||
241+
!(objectFieldSeparator.endsWith('-linebreak') &&
242+
objectFieldSeparator.startsWith(separator)))) ||
238243
(typeNode.meta.separatorForSingleObjectField ?? false) !== separatorForSingleObjectField ||
239-
(typeNode.meta.propertyIndent ?? '') !== objectFieldIndent ||
244+
((typeNode.meta.propertyIndent ?? '') !== objectFieldIndent &&
245+
separator.endsWith('-linebreak')) ||
240246
(typeNode.meta.trailingPunctuation ?? false) !== objectFieldSeparatorTrailingPunctuation
241247
) {
242-
typeNode.meta.separator = objectFieldSeparator;
248+
typeNode.meta.separator = objectFieldSeparatorOptionalLinebreak && !separator.endsWith('and-linebreak') ?
249+
objectFieldSeparator.replace(/-and-linebreak$/v, '') :
250+
objectFieldSeparator;
243251
typeNode.meta.separatorForSingleObjectField = separatorForSingleObjectField;
244252
typeNode.meta.propertyIndent = objectFieldIndent;
245253
typeNode.meta.trailingPunctuation = objectFieldSeparatorTrailingPunctuation;
@@ -391,6 +399,9 @@ export default iterateJsdoc(({
391399
'semicolon-and-linebreak',
392400
],
393401
},
402+
objectFieldSeparatorOptionalLinebreak: {
403+
type: 'boolean',
404+
},
394405
objectFieldSeparatorTrailingPunctuation: {
395406
type: 'boolean',
396407
},

test/rules/assertions/typeFormatting.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,62 @@ export default {
650650
*/
651651
`,
652652
},
653+
{
654+
code: `
655+
/**
656+
* @param {{a: string, b: number}} cfg
657+
*/
658+
`,
659+
errors: [
660+
{
661+
line: 3,
662+
message: 'Inconsistent semicolon-and-linebreak separator usage',
663+
},
664+
],
665+
options: [
666+
{
667+
objectFieldIndent: ' ',
668+
objectFieldSeparator: 'semicolon-and-linebreak',
669+
objectFieldSeparatorOptionalLinebreak: true,
670+
},
671+
],
672+
output: `
673+
/**
674+
* @param {{a: string; b: number}} cfg
675+
*/
676+
`,
677+
},
678+
{
679+
code: `
680+
/**
681+
* @param {{
682+
* a: string,
683+
* b: number
684+
* }} cfg
685+
*/
686+
`,
687+
errors: [
688+
{
689+
line: 3,
690+
message: 'Inconsistent semicolon-and-linebreak separator usage',
691+
},
692+
],
693+
options: [
694+
{
695+
objectFieldIndent: ' ',
696+
objectFieldSeparator: 'semicolon-and-linebreak',
697+
objectFieldSeparatorOptionalLinebreak: true,
698+
},
699+
],
700+
output: `
701+
/**
702+
* @param {{
703+
* a: string;
704+
* b: number
705+
* }} cfg
706+
*/
707+
`,
708+
},
653709
],
654710
valid: [
655711
{
@@ -800,5 +856,36 @@ export default {
800856
*/
801857
`,
802858
},
859+
{
860+
code: `
861+
/**
862+
* @param {{a: string; b: number}} cfg
863+
*/
864+
`,
865+
options: [
866+
{
867+
objectFieldIndent: ' ',
868+
objectFieldSeparator: 'semicolon-and-linebreak',
869+
objectFieldSeparatorOptionalLinebreak: true,
870+
},
871+
],
872+
},
873+
{
874+
code: `
875+
/**
876+
* @param {{
877+
* a: string;
878+
* b: number
879+
* }} cfg
880+
*/
881+
`,
882+
options: [
883+
{
884+
objectFieldIndent: ' ',
885+
objectFieldSeparator: 'semicolon-and-linebreak',
886+
objectFieldSeparatorOptionalLinebreak: true,
887+
},
888+
],
889+
},
803890
],
804891
};

0 commit comments

Comments
 (0)