Skip to content

Commit b5a78ff

Browse files
yeonjuanbrettz9
authored andcommitted
feat: allow empty line between jsdoc and jscode (#353)
feat(*): have doc block retrieval allow or require additional preceding empty lines via min/max line setting API
1 parent 6c18637 commit b5a78ff

File tree

6 files changed

+207
-8
lines changed

6 files changed

+207
-8
lines changed

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4757,6 +4757,32 @@ Accepts one optional options object with the following optional keys.
47574757
The following patterns are considered problems:
47584758

47594759
````js
4760+
/**
4761+
* @func myFunction
4762+
*/
4763+
function myFunction() {
4764+
4765+
}
4766+
// Settings: {"jsdoc":{"maxLines":3,"minLines":2}}
4767+
// Message: Missing JSDoc comment.
4768+
4769+
/**
4770+
* @func myFunction
4771+
*/
4772+
4773+
4774+
function myFunction() {
4775+
4776+
}
4777+
// Settings: {"jsdoc":{"maxLines":2}}
4778+
// Message: Missing JSDoc comment.
4779+
4780+
/** @func myFunction */ function myFunction() {
4781+
4782+
}
4783+
// Settings: {"jsdoc":{"minLines":1}}
4784+
// Message: Missing JSDoc comment.
4785+
47604786
export var test = function () {
47614787

47624788
};
@@ -5181,6 +5207,39 @@ Object.keys(this.options.rules || {}).forEach(function(name) {}.bind(this));
51815207
var object = { name: 'key'};
51825208
Object.keys(object).forEach(function() {})
51835209

5210+
/**
5211+
* @func myFunction
5212+
*/
5213+
5214+
function myFunction() {
5215+
5216+
}
5217+
// Settings: {"jsdoc":{"maxLines":2,"minLines":0}}
5218+
5219+
/**
5220+
* @func myFunction
5221+
*/
5222+
5223+
5224+
function myFunction() {
5225+
5226+
}
5227+
// Settings: {"jsdoc":{"maxLines":3,"minLines":0}}
5228+
5229+
/** @func myFunction */ function myFunction() {
5230+
5231+
}
5232+
// Settings: {"jsdoc":{"maxLines":0,"minLines":0}}
5233+
5234+
/**
5235+
* @func myFunction
5236+
*/
5237+
5238+
function myFunction() {
5239+
5240+
}
5241+
// Settings: {"jsdoc":{"maxLines":3,"minLines":2}}
5242+
51845243
function myFunction() {}
51855244
// Options: [{"require":{"ClassDeclaration":true,"FunctionDeclaration":false,"MethodDefinition":true}}]
51865245

src/eslint/getJSDocComment.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ const looksLikeExport = function (astNode) {
3232
*
3333
* @param {SourceCode} sourceCode The ESLint SourceCode
3434
* @param {ASTNode} node The AST node to get the comment for.
35+
* @param {object} settings The settings in context
3536
* @returns {Token|null} The Block comment token containing the JSDoc comment
3637
* for the given node or null if not found.
3738
* @public
3839
* @deprecated
3940
*/
40-
const getJSDocComment = function (sourceCode, node) {
41+
const getJSDocComment = function (sourceCode, node, settings) {
4142
/**
4243
* Checks for the presence of a JSDoc comment for the given node and returns it.
4344
*
@@ -48,13 +49,14 @@ const getJSDocComment = function (sourceCode, node) {
4849
*/
4950
const findJSDocComment = (astNode) => {
5051
const tokenBefore = sourceCode.getTokenBefore(astNode, {includeComments: true});
51-
52+
const {minLines, maxLines} = settings;
5253
if (
5354
tokenBefore &&
5455
isCommentToken(tokenBefore) &&
5556
tokenBefore.type === 'Block' &&
5657
tokenBefore.value.charAt(0) === '*' &&
57-
astNode.loc.start.line - tokenBefore.loc.end.line <= 1
58+
astNode.loc.start.line - tokenBefore.loc.end.line >= minLines &&
59+
astNode.loc.start.line - tokenBefore.loc.end.line <= maxLines
5860
) {
5961
return tokenBefore;
6062
}

src/iterateJsdoc.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ const getUtils = (
6868
tagNamePreference,
6969
overrideReplacesDocs,
7070
implementsReplacesDocs,
71-
augmentsExtendsReplacesDocs
71+
augmentsExtendsReplacesDocs,
72+
maxLines,
73+
minLines
7274
},
7375
report,
7476
context
@@ -246,7 +248,10 @@ const getUtils = (
246248

247249
utils.getClassJsdoc = () => {
248250
const classNode = utils.getClassNode();
249-
const classJsdocNode = getJSDocComment(sourceCode, classNode);
251+
const classJsdocNode = getJSDocComment(sourceCode, classNode, {
252+
maxLines,
253+
minLines
254+
});
250255

251256
if (classJsdocNode) {
252257
const indent = ' '.repeat(classJsdocNode.loc.start.column);
@@ -302,6 +307,8 @@ const getSettings = (context) => {
302307

303308
// All rules
304309
settings.ignorePrivate = Boolean(_.get(context, 'settings.jsdoc.ignorePrivate'));
310+
settings.minLines = Number(_.get(context, 'settings.jsdoc.minLines', 0));
311+
settings.maxLines = Number(_.get(context, 'settings.jsdoc.maxLines', 1));
305312

306313
// `check-tag-names` and many returns/param rules
307314
settings.tagNamePreference = _.get(context, 'settings.jsdoc.tagNamePreference') || {};
@@ -418,6 +425,7 @@ const iterateAllJsdocs = (iterator, ruleConfig) => {
418425
};
419426

420427
export {
428+
getSettings,
421429
parseComment
422430
};
423431

@@ -461,7 +469,7 @@ export default function iterateJsdoc (iterator, ruleConfig) {
461469
const settings = getSettings(context);
462470

463471
const checkJsdoc = (node) => {
464-
const jsdocNode = getJSDocComment(sourceCode, node);
472+
const jsdocNode = getJSDocComment(sourceCode, node, settings);
465473

466474
if (!jsdocNode) {
467475
return;

src/rules/requireJsdoc.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import jsdocUtils from '../jsdocUtils';
33
import exportParser from '../exportParser';
44
import getJSDocComment from '../eslint/getJSDocComment';
55
import warnRemovedSettings from '../warnRemovedSettings';
6+
import {getSettings} from '../iterateJsdoc';
67

78
const OPTIONS_SCHEMA = {
89
additionalProperties: false,
@@ -141,8 +142,10 @@ export default {
141142

142143
const {require: requireOption, publicOnly, exemptEmptyFunctions} = getOptions(context);
143144

145+
const settings = getSettings(context);
146+
144147
const checkJsDoc = (node) => {
145-
const jsDocNode = getJSDocComment(sourceCode, node);
148+
const jsDocNode = getJSDocComment(sourceCode, node, settings);
146149

147150
if (jsDocNode) {
148151
return;

test/eslint/getJSDocComment.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
RuleTester
33
} from 'eslint';
44
import getJSDocComment from '../../src/eslint/getJSDocComment';
5+
import {getSettings} from '../../src/iterateJsdoc';
56

67
/* eslint-disable sort-keys */
78
const rule = {
@@ -13,10 +14,11 @@ const rule = {
1314
},
1415
create (context) {
1516
const sourceCode = context.getSourceCode();
17+
const settings = getSettings(context);
1618

1719
return {
1820
ObjectExpression: (node) => {
19-
const comment = getJSDocComment(sourceCode, node);
21+
const comment = getJSDocComment(sourceCode, node, settings);
2022
if (comment !== null) {
2123
return;
2224
}

test/rules/assertions/requireJsdoc.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,66 @@
44

55
export default {
66
invalid: [
7+
{
8+
code: `
9+
/**
10+
* @func myFunction
11+
*/
12+
function myFunction() {
13+
14+
}
15+
`,
16+
errors: [
17+
{
18+
message: 'Missing JSDoc comment.'
19+
}
20+
],
21+
settings: {
22+
jsdoc: {
23+
maxLines: 3,
24+
minLines: 2
25+
}
26+
}
27+
},
28+
{
29+
code: `
30+
/**
31+
* @func myFunction
32+
*/
33+
34+
35+
function myFunction() {
36+
37+
}
38+
`,
39+
errors: [
40+
{
41+
message: 'Missing JSDoc comment.'
42+
}
43+
],
44+
settings: {
45+
jsdoc: {
46+
maxLines: 2
47+
}
48+
}
49+
},
50+
{
51+
code: `
52+
/** @func myFunction */ function myFunction() {
53+
54+
}
55+
`,
56+
errors: [
57+
{
58+
message: 'Missing JSDoc comment.'
59+
}
60+
],
61+
settings: {
62+
jsdoc: {
63+
minLines: 1
64+
}
65+
}
66+
},
767
{
868
code: `
969
export var test = function () {
@@ -1130,6 +1190,71 @@ export default {
11301190
Object.keys(object).forEach(function() {})
11311191
`
11321192
},
1193+
{
1194+
code: `
1195+
/**
1196+
* @func myFunction
1197+
*/
1198+
1199+
function myFunction() {
1200+
1201+
}
1202+
`,
1203+
settings: {
1204+
jsdoc: {
1205+
maxLines: 2,
1206+
minLines: 0
1207+
}
1208+
}
1209+
},
1210+
{
1211+
code: `
1212+
/**
1213+
* @func myFunction
1214+
*/
1215+
1216+
1217+
function myFunction() {
1218+
1219+
}
1220+
`,
1221+
settings: {
1222+
jsdoc: {
1223+
maxLines: 3,
1224+
minLines: 0
1225+
}
1226+
}
1227+
},
1228+
{
1229+
code: `
1230+
/** @func myFunction */ function myFunction() {
1231+
1232+
}
1233+
`,
1234+
settings: {
1235+
jsdoc: {
1236+
maxLines: 0,
1237+
minLines: 0
1238+
}
1239+
}
1240+
},
1241+
{
1242+
code: `
1243+
/**
1244+
* @func myFunction
1245+
*/
1246+
1247+
function myFunction() {
1248+
1249+
}
1250+
`,
1251+
settings: {
1252+
jsdoc: {
1253+
maxLines: 3,
1254+
minLines: 2
1255+
}
1256+
}
1257+
},
11331258
{
11341259
code: 'function myFunction() {}',
11351260
options: [{

0 commit comments

Comments
 (0)