diff --git a/.README/README.md b/.README/README.md index 7e210582a..871b43f2c 100644 --- a/.README/README.md +++ b/.README/README.md @@ -27,6 +27,7 @@ This table maps the rules between `eslint-plugin-jsdoc` and `jscs-jsdoc`. | [`require-param-description`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-description) | [`requireParamDescription`](https://github.com/jscs-dev/jscs-jsdoc#requireparamdescription) | | [`require-param-name`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-name) | N/A | | [`require-param-type`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-type) | [`requireParamTypes`](https://github.com/jscs-dev/jscs-jsdoc#requireparamtypes) | +| [`require-returns`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns) | [`requireReturn`](https://github.com/jscs-dev/jscs-jsdoc#requirereturn) | | [`require-returns-description`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-description) | [`requireReturnDescription`](https://github.com/jscs-dev/jscs-jsdoc#requirereturndescription) | | [`require-returns-type`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-type) | [`requireReturnTypes`](https://github.com/jscs-dev/jscs-jsdoc#requirereturntypes) | | [`valid-types`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-valid-types) | N/A | @@ -83,6 +84,7 @@ Finally, enable all of the rules that you would like to use. "jsdoc/require-param-description": 1, "jsdoc/require-param-name": 1, "jsdoc/require-param-type": 1, + "jsdoc/require-returns": 1, "jsdoc/require-returns-description": 1, "jsdoc/require-returns-type": 1, "jsdoc/valid-types": 1 diff --git a/.README/rules/require-returns.md b/.README/rules/require-returns.md new file mode 100644 index 000000000..914771d8d --- /dev/null +++ b/.README/rules/require-returns.md @@ -0,0 +1,10 @@ +### `require-returns` + +Requires returns are documented. + +||| +|---|---| +|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`| +|Tags|`returns`| + + diff --git a/src/index.js b/src/index.js index a5fc1da7c..868bff37a 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ import requireParamName from './rules/requireParamName'; import requireParam from './rules/requireParam'; import requireParamDescription from './rules/requireParamDescription'; import requireParamType from './rules/requireParamType'; +import requireReturns from './rules/requireReturns'; import requireReturnsDescription from './rules/requireReturnsDescription'; import requireReturnsType from './rules/requireReturnsType'; import validTypes from './rules/validTypes'; @@ -35,6 +36,7 @@ export default { 'jsdoc/require-param-description': 'warn', 'jsdoc/require-param-name': 'warn', 'jsdoc/require-param-type': 'warn', + 'jsdoc/require-returns': 'warn', 'jsdoc/require-returns-description': 'warn', 'jsdoc/require-returns-type': 'warn', 'jsdoc/valid-types': 'warn' @@ -56,6 +58,7 @@ export default { 'require-param-description': requireParamDescription, 'require-param-name': requireParamName, 'require-param-type': requireParamType, + 'require-returns': requireReturns, 'require-returns-description': requireReturnsDescription, 'require-returns-type': requireReturnsType, 'valid-types': validTypes diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js index 85f795d22..c29110d5f 100644 --- a/src/iterateJsdoc.js +++ b/src/iterateJsdoc.js @@ -48,6 +48,10 @@ const curryUtils = ( return jsdocUtils.getFunctionParameterNames(functionNode); }; + utils.getFunctionSourceCode = function () { + return sourceCode.getText(functionNode); + }; + utils.getJsdocParameterNamesDeep = () => { return jsdocUtils.getJsdocParameterNamesDeep(jsdoc, utils.getPreferredTagName('param')); }; diff --git a/src/rules/requireReturns.js b/src/rules/requireReturns.js new file mode 100644 index 000000000..d83dc1fdb --- /dev/null +++ b/src/rules/requireReturns.js @@ -0,0 +1,24 @@ +import _ from 'lodash'; +import iterateJsdoc from '../iterateJsdoc'; + +export default iterateJsdoc(({ + jsdoc, + report, + utils +}) => { + const targetTagName = utils.getPreferredTagName('returns'); + + const jsdocTags = _.filter(jsdoc.tags, { + tag: targetTagName + }); + + const sourcecode = utils.getFunctionSourceCode(); + + if (JSON.stringify(jsdocTags) === '[]' && sourcecode.indexOf('return') >= 1) { + report('Missing JSDoc @' + targetTagName + ' declaration.'); + } + + if (JSON.stringify(jsdocTags) !== '[]' && sourcecode.indexOf('return') < 1) { + report('Present JSDoc @' + targetTagName + ' declaration but not available return expression in function.'); + } +}); diff --git a/test/rules/assertions/requireReturns.js b/test/rules/assertions/requireReturns.js new file mode 100644 index 000000000..3feb63a05 --- /dev/null +++ b/test/rules/assertions/requireReturns.js @@ -0,0 +1,67 @@ +export default { + invalid: [ + { + code: ` + /** + * + */ + function quux (foo) { + + return foo; + } + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc @returns declaration.' + } + ] + }, + { + code: ` + /** + * + */ + function quux (foo) { + + return foo; + } + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc @return declaration.' + } + ], + settings: { + jsdoc: { + tagNamePreference: { + returns: 'return' + } + } + } + } + ], + valid: [ + { + code: ` + /** + * @returns Foo. + */ + function quux () { + + return foo; + } + ` + }, + { + code: ` + /** + * + */ + function quux () { + } + ` + } + ] +}; diff --git a/test/rules/index.js b/test/rules/index.js index 73f2d480f..bb071668a 100644 --- a/test/rules/index.js +++ b/test/rules/index.js @@ -21,6 +21,7 @@ _.forEach([ 'require-param-description', 'require-param-name', 'require-param-type', + 'require-returns', 'require-returns-description', 'require-returns-type', 'valid-types'