Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f56b697

Browse files
committed
feat(require-jsdoc): add exemptOverloadedImplementations option
1 parent 20ce7e4 commit f56b697

File tree

4 files changed

+251
-0
lines changed

4 files changed

+251
-0
lines changed

‎.README/rules/require-jsdoc.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,18 @@ empty string.
117117

118118
If `true`, will skip above uncommented overloaded functions to check
119119
for a comment block (e.g., at the top of a set of overloaded functions).
120+
121+
If `false`, will force each overloaded function to be checked for a
122+
comment block.
123+
120124
Defaults to `true`.
121125

126+
### `exemptOverloadedImplementations`
127+
128+
If set to `true` will avoid checking an overloaded function's implementation.
129+
130+
Defaults to `false`.
131+
122132
## Context and settings
123133

124134
|||

‎docs/rules/require-jsdoc.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* [`minLineCount`](#user-content-require-jsdoc-options-minlinecount)
1717
* [`fixerMessage`](#user-content-require-jsdoc-options-fixermessage)
1818
* [`skipInterveningOverloadedDeclarations`](#user-content-require-jsdoc-options-skipinterveningoverloadeddeclarations)
19+
* [`exemptOverloadedImplementations`](#user-content-require-jsdoc-options-exemptoverloadedimplementations)
1920
* [Context and settings](#user-content-require-jsdoc-context-and-settings)
2021
* [Failing examples](#user-content-require-jsdoc-failing-examples)
2122
* [Passing examples](#user-content-require-jsdoc-passing-examples)
@@ -164,8 +165,20 @@ empty string.
164165

165166
If `true`, will skip above uncommented overloaded functions to check
166167
for a comment block (e.g., at the top of a set of overloaded functions).
168+
169+
If `false`, will force each overloaded function to be checked for a
170+
comment block.
171+
167172
Defaults to `true`.
168173

174+
<a name="user-content-require-jsdoc-options-exemptoverloadedimplementations"></a>
175+
<a name="require-jsdoc-options-exemptoverloadedimplementations"></a>
176+
### <code>exemptOverloadedImplementations</code>
177+
178+
If set to `true` will avoid checking an overloaded function's implementation.
179+
180+
Defaults to `false`.
181+
169182
<a name="user-content-require-jsdoc-context-and-settings"></a>
170183
<a name="require-jsdoc-context-and-settings"></a>
171184
## Context and settings
@@ -1076,6 +1089,20 @@ function myFunction(foo: string): void;
10761089
function myFunction(foo?: string) {}
10771090
// "jsdoc/require-jsdoc": ["error"|"warn", {"skipInterveningOverloadedDeclarations":false}]
10781091
// Message: Missing JSDoc comment.
1092+
1093+
/**
1094+
* Test function with param.
1095+
* @param foo - Test param.
1096+
*/
1097+
function myFunction(foo: string): void;
1098+
function myFunction(): void;
1099+
/**
1100+
* Function implementation
1101+
* @param foo
1102+
*/
1103+
function myFunction(foo?: string) {}
1104+
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["TSDeclareFunction"],"exemptOverloadedImplementations":false,"skipInterveningOverloadedDeclarations":false}]
1105+
// Message: Missing JSDoc comment.
10791106
````
10801107

10811108

@@ -2007,5 +2034,40 @@ function myFunction(foo: string): void;
20072034
*/
20082035
function myFunction(): void;
20092036
function myFunction(foo?: string) {}
2037+
2038+
/**
2039+
* Test function with param.
2040+
* @param foo - Test param.
2041+
*/
2042+
function myFunction(foo: string): void;
2043+
/**
2044+
* Test function without param.
2045+
*/
2046+
function myFunction(): void;
2047+
function myFunction(foo?: string) {}
2048+
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["TSDeclareFunction"],"exemptOverloadedImplementations":true,"skipInterveningOverloadedDeclarations":false}]
2049+
2050+
/**
2051+
* Test function with param.
2052+
* @param foo - Test param.
2053+
*/
2054+
export function myFunction(foo: string): void;
2055+
/**
2056+
* Test function without param.
2057+
*/
2058+
export function myFunction(): void;
2059+
export function myFunction(foo?: string) {}
2060+
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["TSDeclareFunction"],"exemptOverloadedImplementations":true,"skipInterveningOverloadedDeclarations":false}]
2061+
2062+
/**
2063+
*
2064+
*/
2065+
const quux = () => {
2066+
/**
2067+
*
2068+
*/
2069+
function myFunction(foo?: string) {}
2070+
};
2071+
// "jsdoc/require-jsdoc": ["error"|"warn", {"exemptOverloadedImplementations":true,"require":{"ArrowFunctionExpression":true}}]
20102072
````
20112073

‎src/rules/requireJsdoc.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ const OPTIONS_SCHEMA = {
104104
default: false,
105105
type: 'boolean',
106106
},
107+
exemptOverloadedImplementations: {
108+
default: false,
109+
type: 'boolean',
110+
},
107111
fixerMessage: {
108112
default: '',
109113
type: 'string',
@@ -307,6 +311,7 @@ const getOption = (context, baseObject, option, key) => {
307311
* exemptEmptyConstructors: boolean,
308312
* exemptEmptyFunctions: boolean,
309313
* skipInterveningOverloadedDeclarations: boolean,
314+
* exemptOverloadedImplementations: boolean,
310315
* fixerMessage: string,
311316
* minLineCount: undefined|import('../iterateJsdoc.js').Integer,
312317
* publicOnly: boolean|{[key: string]: boolean|undefined}
@@ -319,6 +324,7 @@ const getOptions = (context, settings) => {
319324
enableFixer = true,
320325
exemptEmptyConstructors = true,
321326
exemptEmptyFunctions = false,
327+
exemptOverloadedImplementations = false,
322328
fixerMessage = '',
323329
minLineCount = undefined,
324330
publicOnly,
@@ -330,6 +336,7 @@ const getOptions = (context, settings) => {
330336
enableFixer,
331337
exemptEmptyConstructors,
332338
exemptEmptyFunctions,
339+
exemptOverloadedImplementations,
333340
fixerMessage,
334341
minLineCount,
335342
publicOnly: ((baseObj) => {
@@ -396,6 +403,48 @@ const getOptions = (context, settings) => {
396403
};
397404
};
398405

406+
/**
407+
* @param {ESLintOrTSNode} node
408+
*/
409+
const isFunctionWithOverload = (node) => {
410+
if (node.type !== 'FunctionDeclaration') {
411+
return false;
412+
}
413+
414+
let parent;
415+
let child;
416+
417+
if (node.parent?.type === 'Program') {
418+
parent = node.parent;
419+
child = node;
420+
} else if (node.parent?.type === 'ExportNamedDeclaration' &&
421+
node.parent?.parent.type === 'Program') {
422+
parent = node.parent?.parent;
423+
child = node.parent;
424+
}
425+
426+
if (!child || !parent) {
427+
return false;
428+
}
429+
430+
const functionName = node.id.name;
431+
432+
const idx = parent.body.indexOf(child);
433+
const prevSibling = parent.body[idx - 1];
434+
435+
return (
436+
// @ts-expect-error Should be ok
437+
(prevSibling?.type === 'TSDeclareFunction' &&
438+
// @ts-expect-error Should be ok
439+
functionName === prevSibling.id.name) ||
440+
(prevSibling?.type === 'ExportNamedDeclaration' &&
441+
// @ts-expect-error Should be ok
442+
prevSibling.declaration?.type === 'TSDeclareFunction' &&
443+
// @ts-expect-error Should be ok
444+
prevSibling.declaration?.id?.name === functionName)
445+
);
446+
};
447+
399448
/** @type {import('eslint').Rule.RuleModule} */
400449
export default {
401450
create (context) {
@@ -415,6 +464,7 @@ export default {
415464
enableFixer,
416465
exemptEmptyConstructors,
417466
exemptEmptyFunctions,
467+
exemptOverloadedImplementations,
418468
fixerMessage,
419469
minLineCount,
420470
require: requireOption,
@@ -484,6 +534,10 @@ export default {
484534
}
485535
}
486536

537+
if (exemptOverloadedImplementations && isFunctionWithOverload(node)) {
538+
return;
539+
}
540+
487541
const jsDocNode = getJSDocComment(
488542
sourceCode, node, settings, {
489543
checkOverloads: skipInterveningOverloadedDeclarations,

‎test/rules/assertions/requireJsdoc.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,6 +4382,55 @@ function quux (foo) {
43824382
function myFunction(foo?: string) {}
43834383
`,
43844384
},
4385+
{
4386+
code: `
4387+
/**
4388+
* Test function with param.
4389+
* @param foo - Test param.
4390+
*/
4391+
function myFunction(foo: string): void;
4392+
function myFunction(): void;
4393+
/**
4394+
* Function implementation
4395+
* @param foo
4396+
*/
4397+
function myFunction(foo?: string) {}
4398+
`,
4399+
errors: [
4400+
{
4401+
line: 7,
4402+
message: 'Missing JSDoc comment.',
4403+
},
4404+
],
4405+
languageOptions: {
4406+
parser: typescriptEslintParser,
4407+
},
4408+
options: [
4409+
{
4410+
contexts: [
4411+
'TSDeclareFunction',
4412+
],
4413+
exemptOverloadedImplementations: false,
4414+
skipInterveningOverloadedDeclarations: false,
4415+
},
4416+
],
4417+
output: `
4418+
/**
4419+
* Test function with param.
4420+
* @param foo - Test param.
4421+
*/
4422+
function myFunction(foo: string): void;
4423+
/**
4424+
*
4425+
*/
4426+
function myFunction(): void;
4427+
/**
4428+
* Function implementation
4429+
* @param foo
4430+
*/
4431+
function myFunction(foo?: string) {}
4432+
`,
4433+
},
43854434
],
43864435
valid: [
43874436
{
@@ -6579,5 +6628,81 @@ function quux (foo) {
65796628
parser: typescriptEslintParser,
65806629
},
65816630
},
6631+
{
6632+
code: `
6633+
/**
6634+
* Test function with param.
6635+
* @param foo - Test param.
6636+
*/
6637+
function myFunction(foo: string): void;
6638+
/**
6639+
* Test function without param.
6640+
*/
6641+
function myFunction(): void;
6642+
function myFunction(foo?: string) {}
6643+
`,
6644+
languageOptions: {
6645+
parser: typescriptEslintParser,
6646+
},
6647+
options: [
6648+
{
6649+
contexts: [
6650+
'TSDeclareFunction',
6651+
],
6652+
exemptOverloadedImplementations: true,
6653+
skipInterveningOverloadedDeclarations: false,
6654+
},
6655+
],
6656+
},
6657+
{
6658+
code: `
6659+
/**
6660+
* Test function with param.
6661+
* @param foo - Test param.
6662+
*/
6663+
export function myFunction(foo: string): void;
6664+
/**
6665+
* Test function without param.
6666+
*/
6667+
export function myFunction(): void;
6668+
export function myFunction(foo?: string) {}
6669+
`,
6670+
languageOptions: {
6671+
parser: typescriptEslintParser,
6672+
},
6673+
options: [
6674+
{
6675+
contexts: [
6676+
'TSDeclareFunction',
6677+
],
6678+
exemptOverloadedImplementations: true,
6679+
skipInterveningOverloadedDeclarations: false,
6680+
},
6681+
],
6682+
},
6683+
{
6684+
code: `
6685+
/**
6686+
*
6687+
*/
6688+
const quux = () => {
6689+
/**
6690+
*
6691+
*/
6692+
function myFunction(foo?: string) {}
6693+
};
6694+
`,
6695+
languageOptions: {
6696+
parser: typescriptEslintParser,
6697+
},
6698+
options: [
6699+
{
6700+
exemptOverloadedImplementations: true,
6701+
require: {
6702+
ArrowFunctionExpression: true,
6703+
},
6704+
},
6705+
],
6706+
},
65826707
],
65836708
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /