diff --git a/README.md b/README.md index aff998b88..74141281d 100644 --- a/README.md +++ b/README.md @@ -15179,6 +15179,10 @@ export function testFn1 ({ prop = { a: 1, b: 2 } }) { } // "jsdoc/require-param": ["error"|"warn", {"useDefaultObjectProperties":true}] // Message: Missing JSDoc @param "props.prop.a" declaration. + +/** Foo. */ +function foo(a, b, c) {} +// Message: Missing JSDoc @param "a" declaration. ```` The following patterns are not considered problems: diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js index 8500b3168..6ac036384 100644 --- a/src/iterateJsdoc.js +++ b/src/iterateJsdoc.js @@ -246,6 +246,23 @@ const getUtils = ( utils.seedTokens = seedTokens; + utils.emptyTokens = (tokens) => { + [ + 'start', + 'postDelimiter', + 'tag', + 'type', + 'postType', + 'postTag', + 'name', + 'postName', + 'description', + 'end', + ].forEach((prop) => { + tokens[prop] = ''; + }); + }; + utils.addLine = (sourceIndex, tokens) => { const number = (jsdoc.source[sourceIndex - 1]?.number || 0) + 1; jsdoc.source.splice(sourceIndex, 0, { @@ -300,6 +317,49 @@ const getUtils = ( }); }; + utils.makeMultiline = () => { + const {source: [{tokens}]} = jsdoc; + const {postDelimiter, description, tag, name, type} = tokens; + + let {tokens: { + postName, postTag, postType, + }} = jsdoc.source[0]; + + // Strip trailing leftovers from single line ending + if (!description) { + if (postName) { + postName = ''; + } else if (postType) { + postType = ''; + // eslint-disable-next-line max-len, no-inline-comments + } else /* istanbul ignore else -- `comment-parser` prevents empty blocks currently per https://github.com/syavorsky/comment-parser/issues/128 */ if (postTag) { + postTag = ''; + } + } + + utils.emptyTokens(tokens); + + utils.addLine(1, { + delimiter: '*', + + // If a description were present, it may have whitespace attached + // due to being at the end of the single line + description: description.trimEnd(), + name, + postDelimiter, + postName, + postTag, + postType, + start: indent + ' ', + tag, + type, + }); + utils.addLine(2, { + end: '*/', + start: indent + ' ', + }); + }; + utils.flattenRoots = (params) => { return jsdocUtils.flattenRoots(params); }; diff --git a/src/rules/multilineBlocks.js b/src/rules/multilineBlocks.js index b032d8ad7..c1d575b99 100644 --- a/src/rules/multilineBlocks.js +++ b/src/rules/multilineBlocks.js @@ -2,7 +2,6 @@ import iterateJsdoc from '../iterateJsdoc'; export default iterateJsdoc(({ context, - indent, jsdoc, utils, }) => { @@ -18,26 +17,9 @@ export default iterateJsdoc(({ } = context.options[0] || {}; const {source: [{tokens}]} = jsdoc; - const {postDelimiter, description, tag, name, type} = tokens; + const {description, tag} = tokens; const sourceLength = jsdoc.source.length; - const emptyTokens = () => { - [ - 'start', - 'postDelimiter', - 'tag', - 'type', - 'postType', - 'postTag', - 'name', - 'postName', - 'description', - 'end', - ].forEach((prop) => { - tokens[prop] = ''; - }); - }; - const isInvalidSingleLine = (tagName) => { return noSingleLineBlocks && (!tagName || @@ -50,43 +32,7 @@ export default iterateJsdoc(({ } const fixer = () => { - let {tokens: { - postName, postTag, postType, - }} = jsdoc.source[0]; - - // Strip trailing leftovers from single line ending - if (!description) { - if (postName) { - postName = ''; - } else if (postType) { - postType = ''; - // eslint-disable-next-line max-len, no-inline-comments - } else /* istanbul ignore else -- `comment-parser` prevents empty blocks currently per https://github.com/syavorsky/comment-parser/issues/128 */ if (postTag) { - postTag = ''; - } - } - - emptyTokens(); - - utils.addLine(1, { - delimiter: '*', - - // If a description were present, it may have whitespace attached - // due to being at the end of the single line - description: description.trimEnd(), - name, - postDelimiter, - postName, - postTag, - postType, - start: indent + ' ', - tag, - type, - }); - utils.addLine(2, { - end: '*/', - start: indent + ' ', - }); + utils.makeMultiline(); }; utils.reportJSDoc( @@ -104,7 +50,7 @@ export default iterateJsdoc(({ ) { const fixer = () => { const line = {...tokens}; - emptyTokens(); + utils.emptyTokens(tokens); const {tokens: {delimiter, start}} = jsdoc.source[1]; utils.addLine(1, {...line, delimiter, start}); }; diff --git a/src/rules/requireParam.js b/src/rules/requireParam.js index 7b76d0656..31e154ecf 100644 --- a/src/rules/requireParam.js +++ b/src/rules/requireParam.js @@ -293,6 +293,9 @@ export default iterateJsdoc(({ }); }; + if (missingTags.length && jsdoc.source.length === 1) { + utils.makeMultiline(); + } missingTags.forEach(({functionParameterName}) => { utils.reportJSDoc( `Missing JSDoc @${preferredTagName} "${functionParameterName}" declaration.`, diff --git a/test/rules/assertions/requireParam.js b/test/rules/assertions/requireParam.js index b8903ebb3..ae5719057 100644 --- a/test/rules/assertions/requireParam.js +++ b/test/rules/assertions/requireParam.js @@ -2224,6 +2224,32 @@ export default { sourceType: 'module', }, }, + { + code: ` + /** Foo. */ + function foo(a, b, c) {} + `, + errors: [ + { + message: 'Missing JSDoc @param "a" declaration.', + }, + { + message: 'Missing JSDoc @param "b" declaration.', + }, + { + message: 'Missing JSDoc @param "c" declaration.', + }, + ], + output: ` + /** + * Foo. + * @param a + * @param b + * @param c + */ + function foo(a, b, c) {} + `, + }, ], valid: [ {