Skip to content

Commit

Permalink
feat: optionally loosen requireParam when implements/augments/exten…
Browse files Browse the repository at this point in the history
…ds 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)
  • Loading branch information
brettz9 authored and gajus committed Dec 7, 2018
1 parent 559b287 commit 7a34bb1
Show file tree
Hide file tree
Showing 4 changed files with 654 additions and 20 deletions.
224 changes: 224 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,82 @@ function quux (foo) {

}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @implements
*/
function quux (foo) {

}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @augments
*/
function quux (foo) {

}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @extends
*/
function quux (foo) {

}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @override
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @implements
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @augments
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Message: Missing JSDoc @param "foo" declaration.

/**
* @extends
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Message: Missing JSDoc @param "foo" declaration.
```

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

}
// Settings: {"jsdoc":{"allowOverrideWithoutParam":true}}

/**
* @implements
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"allowImplementsWithoutParam":true}}

/**
* @implements
* @param foo
*/
function quux (foo) {

}

/**
* @augments
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}

/**
* @augments
* @param foo
*/
function quux (foo) {

}

/**
* @extends
*/
function quux (foo) {

}
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}

/**
* @extends
* @param foo
*/
function quux (foo) {

}

/**
* @override
*/
class A {
/**
* @param foo
*/
quux (foo) {

}
}

/**
* @override
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Settings: {"jsdoc":{"allowOverrideWithoutParam":true}}

/**
* @implements
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Settings: {"jsdoc":{"allowImplementsWithoutParam":true}}

/**
* @implements
*/
class A {
/**
* @param foo
*/
quux (foo) {

}
}

/**
* @augments
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}

/**
* @augments
*/
class A {
/**
* @param foo
*/
quux (foo) {

}
}

/**
* @extends
*/
class A {
/**
*
*/
quux (foo) {

}
}
// Settings: {"jsdoc":{"allowAugmentsExtendsWithoutParam":true}}

/**
* @extends
*/
class A {
/**
* @param foo
*/
quux (foo) {

}
}
```


Expand Down
91 changes: 72 additions & 19 deletions src/iterateJsdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,36 @@ import _ from 'lodash';
import commentParser from 'comment-parser';
import jsdocUtils from './jsdocUtils';

const curryUtils = (functionNode, jsdoc, tagNamePreference, additionalTagNames, allowOverrideWithoutParam) => {
const parseComment = (commentNode, indent) => {
// Preserve JSDoc block start/end indentation.
return commentParser(indent + '/*' + commentNode.value + indent + '*/', {
// @see https://github.com/yavorskiy/comment-parser/issues/21
parsers: [
commentParser.PARSERS.parse_tag,
commentParser.PARSERS.parse_type,
(str, data) => {
if (_.includes(['return', 'returns'], data.tag)) {
return null;
}

return commentParser.PARSERS.parse_name(str, data);
},
commentParser.PARSERS.parse_description
]
})[0] || {};
};

const curryUtils = (
functionNode,
jsdoc,
tagNamePreference,
additionalTagNames,
allowOverrideWithoutParam,
allowImplementsWithoutParam,
allowAugmentsExtendsWithoutParam,
ancestors,
sourceCode
) => {
const utils = {};

utils.getFunctionParameterNames = () => {
Expand Down Expand Up @@ -33,26 +62,36 @@ const curryUtils = (functionNode, jsdoc, tagNamePreference, additionalTagNames,
return allowOverrideWithoutParam;
};

utils.isImplementsAllowedWithoutParam = () => {
return allowImplementsWithoutParam;
};

utils.isAugmentsExtendsAllowedWithoutParam = () => {
return allowAugmentsExtendsWithoutParam;
};

utils.classHasTag = (tagName) => {
const greatGrandParent = ancestors.slice(-3)[0];
const greatGrandParentValue = greatGrandParent && sourceCode.getFirstToken(greatGrandParent).value;

if (greatGrandParentValue === 'class') {
const classJsdocNode = sourceCode.getJSDocComment(greatGrandParent);
const indent = _.repeat(' ', classJsdocNode.loc.start.column);
const classJsdoc = parseComment(classJsdocNode, indent);

if (jsdocUtils.hasTag(classJsdoc, tagName)) {
return true;
}
}

return false;
};

return utils;
};

export const parseComment = (commentNode, indent) => {
// Preserve JSDoc block start/end indentation.
return commentParser(indent + '/*' + commentNode.value + indent + '*/', {
// @see https://github.com/yavorskiy/comment-parser/issues/21
parsers: [
commentParser.PARSERS.parse_tag,
commentParser.PARSERS.parse_type,
(str, data) => {
if (_.includes(['return', 'returns'], data.tag)) {
return null;
}

return commentParser.PARSERS.parse_name(str, data);
},
commentParser.PARSERS.parse_description
]
})[0] || {};
export {
parseComment
};

export default (iterator) => {
Expand All @@ -61,6 +100,8 @@ export default (iterator) => {
const tagNamePreference = _.get(context, 'settings.jsdoc.tagNamePreference') || {};
const additionalTagNames = _.get(context, 'settings.jsdoc.additionalTagNames') || {};
const allowOverrideWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowOverrideWithoutParam'));
const allowImplementsWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowImplementsWithoutParam'));
const allowAugmentsExtendsWithoutParam = Boolean(_.get(context, 'settings.jsdoc.allowAugmentsExtendsWithoutParam'));

const checkJsdoc = (functionNode) => {
const jsdocNode = sourceCode.getJSDocComment(functionNode);
Expand All @@ -69,6 +110,8 @@ export default (iterator) => {
return;
}

const ancestors = context.getAncestors();

const indent = _.repeat(' ', jsdocNode.loc.start.column);

const jsdoc = parseComment(jsdocNode, indent);
Expand Down Expand Up @@ -100,7 +143,17 @@ export default (iterator) => {
}
};

const utils = curryUtils(functionNode, jsdoc, tagNamePreference, additionalTagNames, allowOverrideWithoutParam);
const utils = curryUtils(
functionNode,
jsdoc,
tagNamePreference,
additionalTagNames,
allowOverrideWithoutParam,
allowImplementsWithoutParam,
allowAugmentsExtendsWithoutParam,
ancestors,
sourceCode
);

iterator({
context,
Expand Down
16 changes: 15 additions & 1 deletion src/rules/requireParam.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import _ from 'lodash';
import iterateJsdoc from '../iterateJsdoc';

// eslint-disable-next-line complexity
export default iterateJsdoc(({
report,
utils
Expand All @@ -15,7 +16,20 @@ export default iterateJsdoc(({

// When settings.jsdoc.allowOverrideWithoutParam is true, override implies that all documentation is inherited.
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/73
if (utils.hasTag('override') && utils.isOverrideAllowedWithoutParam()) {
if ((utils.hasTag('override') || utils.classHasTag('override')) && utils.isOverrideAllowedWithoutParam()) {
return;
}

// When settings.jsdoc.allowImplementsWithoutParam is true, implements implies that all documentation is inherited.
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/100
if ((utils.hasTag('implements') || utils.classHasTag('implements')) && utils.isImplementsAllowedWithoutParam()) {
return;
}

// When settings.jsdoc.allowAugmentsExtendsWithoutParam is true, augments or extends implies that all documentation is inherited.
// See https://github.com/gajus/eslint-plugin-jsdoc/issues/100
if ((utils.hasTag('augments') || utils.hasTag('extends') ||
utils.classHasTag('augments') || utils.classHasTag('extends')) && utils.isAugmentsExtendsAllowedWithoutParam()) {
return;
}

Expand Down
Loading

0 comments on commit 7a34bb1

Please sign in to comment.