Skip to content

Commit 7a34bb1

Browse files
brettz9gajus
authored andcommitted
feat: optionally loosen requireParam when implements/augments/extends present on tag or parent (#116)
* - Enhancement: Add new boolean options `allowImplementsWithoutParam` and `allowAugmentsExtendsWithoutParam` and apply to `requireParam` (fixes #100) * - Expand loosening brought by param checking with `is(*)AllowedWithoutParam` options to include methods whose class has the tag instead (i.e., @OverRide, @implements, @Augments, or @extends)
1 parent 559b287 commit 7a34bb1

File tree

4 files changed

+654
-20
lines changed

4 files changed

+654
-20
lines changed

README.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,82 @@ function quux (foo) {
13501350

13511351
}
13521352
// Message: Missing JSDoc @param "foo" declaration.
1353+
1354+
/**
1355+
* @implements
1356+
*/
1357+
function quux (foo) {
1358+
1359+
}
1360+
// Message: Missing JSDoc @param "foo" declaration.
1361+
1362+
/**
1363+
* @augments
1364+
*/
1365+
function quux (foo) {
1366+
1367+
}
1368+
// Message: Missing JSDoc @param "foo" declaration.
1369+
1370+
/**
1371+
* @extends
1372+
*/
1373+
function quux (foo) {
1374+
1375+
}
1376+
// Message: Missing JSDoc @param "foo" declaration.
1377+
1378+
/**
1379+
* @override
1380+
*/
1381+
class A {
1382+
/**
1383+
*
1384+
*/
1385+
quux (foo) {
1386+
1387+
}
1388+
}
1389+
// Message: Missing JSDoc @param "foo" declaration.
1390+
1391+
/**
1392+
* @implements
1393+
*/
1394+
class A {
1395+
/**
1396+
*
1397+
*/
1398+
quux (foo) {
1399+
1400+
}
1401+
}
1402+
// Message: Missing JSDoc @param "foo" declaration.
1403+
1404+
/**
1405+
* @augments
1406+
*/
1407+
class A {
1408+
/**
1409+
*
1410+
*/
1411+
quux (foo) {
1412+
1413+
}
1414+
}
1415+
// Message: Missing JSDoc @param "foo" declaration.
1416+
1417+
/**
1418+
* @extends
1419+
*/
1420+
class A {
1421+
/**
1422+
*
1423+
*/
1424+
quux (foo) {
1425+
1426+
}
1427+
}
1428+
// Message: Missing JSDoc @param "foo" declaration.
13531429
```
13541430

13551431
The following patterns are not considered problems:
@@ -1392,6 +1468,154 @@ function quux (foo) {
13921468

13931469
}
13941470
// Settings: {"jsdoc":{"allowOverrideWithoutParam":true}}
1471+
1472+
/**
1473+
* @implements
1474+
*/
1475+
function quux (foo) {
1476+
1477+
}
1478+
// Settings: {"jsdoc":{"allowImplementsWithoutParam":true}}
1479+
1480+
/**
1481+
* @implements
1482+
* @param foo
1483+
*/
1484+
function quux (foo) {
1485+
1486+
}
1487+
1488+
/**
1489+
* @augments
1490+
*/
1491+
function quux (foo) {
1492+
1493+
}
1494+
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}
1495+
1496+
/**
1497+
* @augments
1498+
* @param foo
1499+
*/
1500+
function quux (foo) {
1501+
1502+
}
1503+
1504+
/**
1505+
* @extends
1506+
*/
1507+
function quux (foo) {
1508+
1509+
}
1510+
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}
1511+
1512+
/**
1513+
* @extends
1514+
* @param foo
1515+
*/
1516+
function quux (foo) {
1517+
1518+
}
1519+
1520+
/**
1521+
* @override
1522+
*/
1523+
class A {
1524+
/**
1525+
* @param foo
1526+
*/
1527+
quux (foo) {
1528+
1529+
}
1530+
}
1531+
1532+
/**
1533+
* @override
1534+
*/
1535+
class A {
1536+
/**
1537+
*
1538+
*/
1539+
quux (foo) {
1540+
1541+
}
1542+
}
1543+
// Settings: {"jsdoc":{"allowOverrideWithoutParam":true}}
1544+
1545+
/**
1546+
* @implements
1547+
*/
1548+
class A {
1549+
/**
1550+
*
1551+
*/
1552+
quux (foo) {
1553+
1554+
}
1555+
}
1556+
// Settings: {"jsdoc":{"allowImplementsWithoutParam":true}}
1557+
1558+
/**
1559+
* @implements
1560+
*/
1561+
class A {
1562+
/**
1563+
* @param foo
1564+
*/
1565+
quux (foo) {
1566+
1567+
}
1568+
}
1569+
1570+
/**
1571+
* @augments
1572+
*/
1573+
class A {
1574+
/**
1575+
*
1576+
*/
1577+
quux (foo) {
1578+
1579+
}
1580+
}
1581+
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}
1582+
1583+
/**
1584+
* @augments
1585+
*/
1586+
class A {
1587+
/**
1588+
* @param foo
1589+
*/
1590+
quux (foo) {
1591+
1592+
}
1593+
}
1594+
1595+
/**
1596+
* @extends
1597+
*/
1598+
class A {
1599+
/**
1600+
*
1601+
*/
1602+
quux (foo) {
1603+
1604+
}
1605+
}
1606+
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}
1607+
1608+
/**
1609+
* @extends
1610+
*/
1611+
class A {
1612+
/**
1613+
* @param foo
1614+
*/
1615+
quux (foo) {
1616+
1617+
}
1618+
}
13951619
```
13961620

13971621

src/iterateJsdoc.js

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,36 @@ import _ from 'lodash';
22
import commentParser from 'comment-parser';
33
import jsdocUtils from './jsdocUtils';
44

5-
const curryUtils = (functionNode, jsdoc, tagNamePreference, additionalTagNames, allowOverrideWithoutParam) => {
5+
const parseComment = (commentNode, indent) => {
6+
// Preserve JSDoc block start/end indentation.
7+
return commentParser(indent + '/*' + commentNode.value + indent + '*/', {
8+
// @see https://github.com/yavorskiy/comment-parser/issues/21
9+
parsers: [
10+
commentParser.PARSERS.parse_tag,
11+
commentParser.PARSERS.parse_type,
12+
(str, data) => {
13+
if (_.includes(['return', 'returns'], data.tag)) {
14+
return null;
15+
}
16+
17+
return commentParser.PARSERS.parse_name(str, data);
18+
},
19+
commentParser.PARSERS.parse_description
20+
]
21+
})[0] || {};
22+
};
23+
24+
const curryUtils = (
25+
functionNode,
26+
jsdoc,
27+
tagNamePreference,
28+
additionalTagNames,
29+
allowOverrideWithoutParam,
30+
allowImplementsWithoutParam,
31+
allowAugmentsExtendsWithoutParam,
32+
ancestors,
33+
sourceCode
34+
) => {
635
const utils = {};
736

837
utils.getFunctionParameterNames = () => {
@@ -33,26 +62,36 @@ const curryUtils = (functionNode, jsdoc, tagNamePreference, additionalTagNames,
3362
return allowOverrideWithoutParam;
3463
};
3564

65+
utils.isImplementsAllowedWithoutParam = () => {
66+
return allowImplementsWithoutParam;
67+
};
68+
69+
utils.isAugmentsExtendsAllowedWithoutParam = () => {
70+
return allowAugmentsExtendsWithoutParam;
71+
};
72+
73+
utils.classHasTag = (tagName) => {
74+
const greatGrandParent = ancestors.slice(-3)[0];
75+
const greatGrandParentValue = greatGrandParent && sourceCode.getFirstToken(greatGrandParent).value;
76+
77+
if (greatGrandParentValue === 'class') {
78+
const classJsdocNode = sourceCode.getJSDocComment(greatGrandParent);
79+
const indent = _.repeat(' ', classJsdocNode.loc.start.column);
80+
const classJsdoc = parseComment(classJsdocNode, indent);
81+
82+
if (jsdocUtils.hasTag(classJsdoc, tagName)) {
83+
return true;
84+
}
85+
}
86+
87+
return false;
88+
};
89+
3690
return utils;
3791
};
3892

39-
export const parseComment = (commentNode, indent) => {
40-
// Preserve JSDoc block start/end indentation.
41-
return commentParser(indent + '/*' + commentNode.value + indent + '*/', {
42-
// @see https://github.com/yavorskiy/comment-parser/issues/21
43-
parsers: [
44-
commentParser.PARSERS.parse_tag,
45-
commentParser.PARSERS.parse_type,
46-
(str, data) => {
47-
if (_.includes(['return', 'returns'], data.tag)) {
48-
return null;
49-
}
50-
51-
return commentParser.PARSERS.parse_name(str, data);
52-
},
53-
commentParser.PARSERS.parse_description
54-
]
55-
})[0] || {};
93+
export {
94+
parseComment
5695
};
5796

5897
export default (iterator) => {
@@ -61,6 +100,8 @@ export default (iterator) => {
61100
const tagNamePreference = _.get(context, 'settings.jsdoc.tagNamePreference') || {};
62101
const additionalTagNames = _.get(context, 'settings.jsdoc.additionalTagNames') || {};
63102
const allowOverrideWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowOverrideWithoutParam'));
103+
const allowImplementsWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowImplementsWithoutParam'));
104+
const allowAugmentsExtendsWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowAugmentsExtendsWithoutParam'));
64105

65106
const checkJsdoc = (functionNode) => {
66107
const jsdocNode = sourceCode.getJSDocComment(functionNode);
@@ -69,6 +110,8 @@ export default (iterator) => {
69110
return;
70111
}
71112

113+
const ancestors = context.getAncestors();
114+
72115
const indent = _.repeat(' ', jsdocNode.loc.start.column);
73116

74117
const jsdoc = parseComment(jsdocNode, indent);
@@ -100,7 +143,17 @@ export default (iterator) => {
100143
}
101144
};
102145

103-
const utils = curryUtils(functionNode, jsdoc, tagNamePreference, additionalTagNames, allowOverrideWithoutParam);
146+
const utils = curryUtils(
147+
functionNode,
148+
jsdoc,
149+
tagNamePreference,
150+
additionalTagNames,
151+
allowOverrideWithoutParam,
152+
allowImplementsWithoutParam,
153+
allowAugmentsExtendsWithoutParam,
154+
ancestors,
155+
sourceCode
156+
);
104157

105158
iterator({
106159
context,

src/rules/requireParam.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import _ from 'lodash';
22
import iterateJsdoc from '../iterateJsdoc';
33

4+
// eslint-disable-next-line complexity
45
export default iterateJsdoc(({
56
report,
67
utils
@@ -15,7 +16,20 @@ export default iterateJsdoc(({
1516

1617
// When settings.jsdoc.allowOverrideWithoutParam is true, override implies that all documentation is inherited.
1718
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/73
18-
if (utils.hasTag('override') && utils.isOverrideAllowedWithoutParam()) {
19+
if ((utils.hasTag('override') || utils.classHasTag('override')) && utils.isOverrideAllowedWithoutParam()) {
20+
return;
21+
}
22+
23+
// When settings.jsdoc.allowImplementsWithoutParam is true, implements implies that all documentation is inherited.
24+
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/100
25+
if ((utils.hasTag('implements') || utils.classHasTag('implements')) && utils.isImplementsAllowedWithoutParam()) {
26+
return;
27+
}
28+
29+
// When settings.jsdoc.allowAugmentsExtendsWithoutParam is true, augments or extends implies that all documentation is inherited.
30+
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/100
31+
if ((utils.hasTag('augments') || utils.hasTag('extends') ||
32+
utils.classHasTag('augments') || utils.classHasTag('extends')) && utils.isAugmentsExtendsAllowedWithoutParam()) {
1933
return;
2034
}
2135

0 commit comments

Comments
 (0)