Skip to content

Commit 86e7ebb

Browse files
committed
feat: add jsdocEmptyCommentStrategy option to handle empty JSDoc comments ("keep"| "remove") "remove" is default
#243
1 parent 7fd5182 commit 86e7ebb

6 files changed

Lines changed: 136 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ Like code tags (` ```js `), header tags like `# Header`, or other Markdown featu
196196
| `jsdocSeparateReturnsFromParam` | Boolean | false | Adds a space between last `@param` and `@returns` |
197197
| `jsdocSeparateTagGroups` | Boolean | false | Adds a space between tag groups |
198198
| `jsdocPreferCodeFences` | Boolean | false | Always fence code blocks (surround them by triple backticks) |
199+
| `jsdocEmptyCommentStrategy` | ("remove","keep") | "remove" | How to handle empty JSDoc comment blocks |
199200
| `tsdoc` | Boolean | false | See [TSDoc](#tsdoc) |
200201
| `jsdocPrintWidth` | Number | undefined | If you don't set the value to `jsdocPrintWidth`, `printWidth` will be used as `jsdocPrintWidth` |
201202
| `jsdocLineWrappingStyle` | String | "greedy" | "greedy": lines wrap as soon as they reach `printWidth`. "balance": preserve existing line breaks if lines are shorter than `printWidth`, otherwise use greedy wrapping |

src/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,23 @@ const options = {
176176
default: true,
177177
description: "Format import tags",
178178
},
179+
jsdocEmptyCommentStrategy: {
180+
name: "jsdocEmptyCommentStrategy",
181+
type: "choice",
182+
choices: [
183+
{
184+
value: "remove",
185+
description: "Remove empty JSDoc comment blocks",
186+
},
187+
{
188+
value: "keep",
189+
description: "Keep empty JSDoc comment blocks",
190+
},
191+
] as ChoiceSupportOption["choices"],
192+
category: "jsdoc",
193+
default: "remove",
194+
description: "How to handle empty JSDoc comment blocks",
195+
},
179196
} as const satisfies Record<keyof JsdocOptions, SupportOption>;
180197

181198
const defaultOptions: JsdocOptions = {
@@ -200,6 +217,7 @@ const defaultOptions: JsdocOptions = {
200217
jsdocNamedImportPadding: options.jsdocNamedImportPadding.default,
201218
jsdocMergeImports: options.jsdocMergeImports.default,
202219
jsdocNamedImportLineSplitting: options.jsdocNamedImportLineSplitting.default,
220+
jsdocEmptyCommentStrategy: options.jsdocEmptyCommentStrategy.default,
203221
};
204222

205223
const parsers = {

src/parser.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const getParser = (originalParse: Parser["parse"], parserName: string) =>
4646
options = {
4747
...options,
4848
printWidth: options.jsdocPrintWidth ?? options.printWidth,
49+
jsdocEmptyCommentStrategy: options.jsdocEmptyCommentStrategy ?? "remove",
4950
};
5051

5152
const eol =
@@ -241,9 +242,11 @@ export const getParser = (originalParse: Parser["parse"], parserName: string) =>
241242
}),
242243
);
243244

244-
ast.comments = ast.comments.filter(
245-
(comment) => !(isBlockComment(comment) && !comment.value),
246-
);
245+
if (options.jsdocEmptyCommentStrategy === "remove") {
246+
ast.comments = ast.comments.filter(
247+
(comment) => !(isBlockComment(comment) && !comment.value),
248+
);
249+
}
247250

248251
return ast;
249252
};

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface JsdocOptions {
2626
jsdocNamedImportPadding: boolean;
2727
jsdocMergeImports: boolean;
2828
jsdocNamedImportLineSplitting: boolean;
29+
jsdocEmptyCommentStrategy: "remove" | "keep";
2930
}
3031

3132
export interface AllOptions extends ParserOptions, JsdocOptions {}

tests/__snapshots__/main.test.ts.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,27 @@ exports[`Block quote 2`] = `
6161
"
6262
`;
6363

64+
exports[`Empty JSDoc comment - default behavior (should remove) 1`] = `
65+
"function test() {}
66+
67+
const value = 1;
68+
69+
class MyClass {}
70+
"
71+
`;
72+
73+
exports[`Empty JSDoc comment - with jsdocEmptyCommentStrategy keep 1`] = `
74+
"/**/
75+
function test() {}
76+
77+
/**/
78+
const value = 1;
79+
80+
/**/
81+
class MyClass {}
82+
"
83+
`;
84+
6485
exports[`Empty comment 1`] = `
6586
"// Line Comment
6687
//
@@ -141,6 +162,27 @@ exports[`Long description memory leak 1`] = `
141162
"
142163
`;
143164
165+
exports[`Mixed empty and non-empty JSDoc comments - with jsdocEmptyCommentStrategy keep 1`] = `
166+
"/**/
167+
function emptyDoc() {}
168+
169+
/**
170+
* This has content
171+
*
172+
* @param {string} name
173+
*/
174+
function withContent(name) {}
175+
176+
/**/
177+
const emptyValue = 1;
178+
179+
/** @returns {number} */
180+
function withReturn() {
181+
return 42;
182+
}
183+
"
184+
`;
185+
144186
exports[`Non-jsdoc comment 1`] = `
145187
"// @type { something }
146188
/* @type { something } */

tests/main.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,74 @@ test("Empty comment", async () => {
454454
expect(result).toMatchSnapshot();
455455
});
456456

457+
test("Empty JSDoc comment - default behavior (should remove)", async () => {
458+
const result = await subject(`
459+
/**
460+
*/
461+
function test() {}
462+
463+
/** */
464+
const value = 1;
465+
466+
/**
467+
*
468+
*/
469+
class MyClass {}
470+
`);
471+
472+
expect(result).toMatchSnapshot();
473+
});
474+
475+
test("Empty JSDoc comment - with jsdocEmptyCommentStrategy keep", async () => {
476+
const result = await subject(
477+
`
478+
/**
479+
*/
480+
function test() {}
481+
482+
/** */
483+
const value = 1;
484+
485+
/**
486+
*
487+
*/
488+
class MyClass {}
489+
`,
490+
{ jsdocEmptyCommentStrategy: "keep" },
491+
);
492+
493+
expect(result).toMatchSnapshot();
494+
});
495+
496+
test("Mixed empty and non-empty JSDoc comments - with jsdocEmptyCommentStrategy keep", async () => {
497+
const result = await subject(
498+
`
499+
/**
500+
*/
501+
function emptyDoc() {}
502+
503+
/**
504+
* This has content
505+
* @param {string} name
506+
*/
507+
function withContent(name) {}
508+
509+
/** */
510+
const emptyValue = 1;
511+
512+
/**
513+
* @returns {number}
514+
*/
515+
function withReturn() {
516+
return 42;
517+
}
518+
`,
519+
{ jsdocEmptyCommentStrategy: "keep" },
520+
);
521+
522+
expect(result).toMatchSnapshot();
523+
});
524+
457525
test("Optional parameters", async () => {
458526
const result = await subject(`
459527
/**

0 commit comments

Comments
 (0)