From 81164fda45756da30e7465ad7729d9d9d55ad45e Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Mon, 20 Apr 2020 14:38:33 +0800 Subject: [PATCH] fix(check-tag-names, empty-tags, require-description, require-example, require-param, require-returns) explicitly allow `inheritDoc` in all modes while only allowing `inheritdoc` in non-Closure mode; fixes #520 --- README.md | 129 ++++++++++++++++++++++++++ src/iterateJsdoc.js | 7 +- src/rules/emptyTags.js | 9 +- src/tagNames.js | 15 ++- test/rules/assertions/requireParam.js | 53 +++++++++++ 5 files changed, 207 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0df1ecfdc..6253a3b3a 100644 --- a/README.md +++ b/README.md @@ -2444,6 +2444,7 @@ function quux () { * @ignore * @implements * @inheritdoc + * @inheritDoc * @inner * @instance * @interface @@ -2519,6 +2520,7 @@ function quux (foo) {} * @ignore * @implements * @inheritdoc + * @inheritDoc * @inner * @instance * @interface @@ -2650,6 +2652,7 @@ function quux (foo) { * @ignore * @implements * @inheritdoc + * @inheritDoc * @inner * @instance * @interface @@ -2723,6 +2726,7 @@ function quux (foo) {} * @ignore * @implements * @inheritdoc + * @inheritDoc * @inner * @instance * @interface @@ -9043,6 +9047,15 @@ function quux (foo) { // Options: [{"exemptedBy":[]}] // Message: Missing JSDoc @param "foo" declaration. +/** + * @inheritdoc + */ +function quux (foo) { + +} +// Settings: {"jsdoc":{"mode":"closure"}} +// Message: Missing JSDoc @param "foo" declaration. + /** * Assign the project to a list of employees. * @param {object[]} employees - The employees who are responsible for the project. @@ -9095,6 +9108,89 @@ TestMethod(id); declare let TestFunction: (id) => void; // Options: [{"contexts":["TSFunctionType"]}] // Message: Missing JSDoc @param "id" declaration. + +/** + * A test function. + */ +let TestFunction: (id) => void; +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +/** + * A test function. + */ + function test( + processor: (id: number) => string + ) { + return processor(10); + } +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +/** + * A test function. + */ + let test = (processor: (id: number) => string) => + { + return processor(10); + } +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +class TestClass { +/** + * A class property. + */ + public Test: (id: number) => string; +} +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +class TestClass { +/** + * A class method. + */ + public TestMethod(): (id: number) => string + { + } +} +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +interface TestInterface { +/** + * An interface property. + */ + public Test: (id: number) => string; +} +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +interface TestInterface { +/** + * An interface method. + */ + public TestMethod(): (id: number) => string; +} +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +/** + * A function with return type + */ + function test(): (id: number) => string; +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. + +/** + * A function with return type + */ + let test = (): (id: number) => string => + { + return (id) => `${id}`; + } +// Options: [{"contexts":["TSFunctionType"]}] +// Message: Missing JSDoc @param "id" declaration. ```` The following patterns are not considered problems: @@ -9114,6 +9210,13 @@ function quux (foo) { } +/** + * @inheritDoc + */ +function quux (foo) { + +} + /** * @arg foo */ @@ -9461,6 +9564,32 @@ function quux (foo) { } // Options: [{"contexts":["ArrowFunctionExpression"]}] + +/** + * A function with return type + * + * @param id + */ + let test = (): (id: number) => string => + { + return (id) => `${id}`; + } +// Options: [{"contexts":["TSFunctionType"]}] + +/** @abstract */ +class base { + /** @param {boolean} arg0 */ + constructor(arg0) {} +} + +class foo extends base { + /** @inheritDoc */ + constructor(arg0) { + super(arg0); + this.arg0 = arg0; + } +} +// Settings: {"jsdoc":{"mode":"closure"}} ```` diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js index 324cef253..f05820d45 100644 --- a/src/iterateJsdoc.js +++ b/src/iterateJsdoc.js @@ -245,7 +245,12 @@ const getUtils = ( return true; } - const exemptedBy = _.get(context, 'options[0].exemptedBy', ['inheritdoc']); + const exemptedBy = _.get( + context, 'options[0].exemptedBy', [ + 'inheritDoc', + ...settings.mode === 'closure' ? [] : ['inheritdoc'], + ], + ); if (exemptedBy.length && utils.getPresentTags(exemptedBy).length) { return true; } diff --git a/src/rules/emptyTags.js b/src/rules/emptyTags.js index 3bcfe4805..f3d785248 100644 --- a/src/rules/emptyTags.js +++ b/src/rules/emptyTags.js @@ -2,11 +2,18 @@ import iterateJsdoc from '../iterateJsdoc'; const defaultEmptyTags = [ 'abstract', 'async', 'generator', 'global', 'hideconstructor', - 'ignore', 'inheritdoc', 'inner', 'instance', 'override', 'readonly', + 'ignore', 'inner', 'instance', 'override', 'readonly', + + // jsdoc doesn't use this form in its docs, but allow for compatibility with + // TypeScript which allows and Closure which requires + 'inheritDoc', ]; const emptyIfNotClosure = [ 'package', 'private', 'protected', 'public', 'static', + + // Closure doesn't allow with this casing + 'inheritdoc', ]; export default iterateJsdoc(({ diff --git a/src/tagNames.js b/src/tagNames.js index c005297bc..fe055cddc 100644 --- a/src/tagNames.js +++ b/src/tagNames.js @@ -59,6 +59,10 @@ const jsdocTags = { ignore: [], implements: [], inheritdoc: [], + + // Allowing casing distinct from jsdoc `definitions.js` (required in Closure) + inheritDoc: [], + inner: [], instance: [], interface: [], @@ -139,8 +143,14 @@ const undocumentedClosureTags = { wizaction: [], }; +const { + // eslint-disable-next-line no-unused-vars + inheritdoc, + ...typeScriptTagsNoInheritdoc +} = typeScriptTags; + const closureTags = { - ...typeScriptTags, + ...typeScriptTagsNoInheritdoc, ...undocumentedClosureTags, // From https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler @@ -158,9 +168,6 @@ const closureTags = { // With casing distinct from jsdoc `definitions.js` implicitCast: [], - // With casing distinct from jsdoc `definitions.js` - inheritDoc: [], - noalias: [], nocollapse: [], nocompile: [], diff --git a/test/rules/assertions/requireParam.js b/test/rules/assertions/requireParam.js index 119f65eac..534f10ab8 100644 --- a/test/rules/assertions/requireParam.js +++ b/test/rules/assertions/requireParam.js @@ -541,6 +541,27 @@ export default { }, ], }, + { + code: ` + /** + * @inheritdoc + */ + function quux (foo) { + + } + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc @param "foo" declaration.', + }, + ], + settings: { + jsdoc: { + mode: 'closure', + }, + }, + }, { code: ` /** @@ -1012,6 +1033,16 @@ export default { } `, }, + { + code: ` + /** + * @inheritDoc + */ + function quux (foo) { + + } + `, + }, { code: ` /** @@ -1560,5 +1591,27 @@ export default { ], parser: require.resolve('@typescript-eslint/parser'), }, + { + code: ` + /** @abstract */ + class base { + /** @param {boolean} arg0 */ + constructor(arg0) {} + } + + class foo extends base { + /** @inheritDoc */ + constructor(arg0) { + super(arg0); + this.arg0 = arg0; + } + } + `, + settings: { + jsdoc: { + mode: 'closure', + }, + }, + }, ], };