Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally loosen requireParam when implements/augments/extends present on tag or parent #116

Merged
merged 2 commits into from
Dec 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: add a space before ancestors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you mean a line break, right? It's at the right indent...


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