diff --git a/src/rules/requireDescriptionCompleteSentence.js b/src/rules/requireDescriptionCompleteSentence.js index 262f8df83..67fedd02b 100644 --- a/src/rules/requireDescriptionCompleteSentence.js +++ b/src/rules/requireDescriptionCompleteSentence.js @@ -6,13 +6,21 @@ const extractParagraphs = (text) => { }; const extractSentences = (text) => { - return text.split(/\.\s+|\.$/).filter((sentence) => { + return text + + // Remove all {} tags. + .replace(/\{[\s\S]*?\}\s*/g, '') + .split(/[.?!:](?:\s+|$)/) + // Ignore sentences with only whitespaces. - return !/^\s*$/.test(sentence); - }).map((sentence) => { + .filter((sentence) => { + return !/^\s*$/.test(sentence); + }) + // Re-add the dot. - return sentence + '.'; - }); + .map((sentence) => { + return sentence + '.'; + }); }; const isNewLinePrecededByAPeriod = (text) => { @@ -52,7 +60,7 @@ const validateDescription = (description, report, jsdocNode, sourceCode) => { const fix = (fixer) => { let text = sourceCode.getText(jsdocNode); - if (!_.endsWith(paragraph, '.')) { + if (!/[.:?!]$/.test(paragraph)) { const line = _.last(paragraph.split('\n')); text = text.replace(line, line + '.'); @@ -75,7 +83,7 @@ const validateDescription = (description, report, jsdocNode, sourceCode) => { report('Sentence should start with an uppercase character.', fix); } - if (!/\.$/.test(paragraph)) { + if (!/[.!?]$/.test(paragraph)) { report('Sentence must end with a period.', fix); return true; @@ -102,7 +110,7 @@ export default iterateJsdoc(({ } const tags = _.filter(jsdoc.tags, (tag) => { - return _.includes(['param', 'returns'], tag.tag); + return _.includes(['param', 'arg', 'argument', 'returns', 'return'], tag.tag); }); _.some(tags, (tag) => { diff --git a/test/rules/assertions/requireDescriptionCompleteSentence.js b/test/rules/assertions/requireDescriptionCompleteSentence.js index 35a93f826..0946f3faf 100644 --- a/test/rules/assertions/requireDescriptionCompleteSentence.js +++ b/test/rules/assertions/requireDescriptionCompleteSentence.js @@ -171,6 +171,32 @@ export default { } ` }, + { + code: ` + /** + * {@see Foo.bar} buz + */ + function quux (foo) { + + } + `, + errors: [ + { + message: 'Sentence should start with an uppercase character.' + }, + { + message: 'Sentence must end with a period.' + } + ], + output: ` + /** + * {@see Foo.bar} Buz. + */ + function quux (foo) { + + } + ` + }, { code: ` /** @@ -258,6 +284,78 @@ export default { */ function longDescription (foo) { + } + ` + }, + { + code: ` + /** + * @arg {number} foo - Foo + */ + function quux (foo) { + + } + `, + errors: [ + { + message: 'Sentence must end with a period.' + } + ], + output: ` + /** + * @arg {number} foo - Foo. + */ + function quux (foo) { + + } + ` + }, + { + code: ` + /** + * @argument {number} foo - Foo + */ + function quux (foo) { + + } + `, + errors: [ + { + message: 'Sentence must end with a period.' + } + ], + output: ` + /** + * @argument {number} foo - Foo. + */ + function quux (foo) { + + } + ` + }, + { + code: ` + /** + * @return {number} foo + */ + function quux (foo) { + + } + `, + errors: [ + { + message: 'Sentence should start with an uppercase character.' + }, + { + message: 'Sentence must end with a period.' + } + ], + output: ` + /** + * @return {number} Foo. + */ + function quux (foo) { + } ` } @@ -335,6 +433,32 @@ export default { */ function quux () { + } + ` + }, + { + code: ` + /** + * Foo. {@see Math.sin}. + */ + function quux () { + + } + ` + }, + { + code: ` + /** + * Foo? + * + * Bar! + * + * Baz: + * 1. Foo. + * 2. Bar. + */ + function quux () { + } ` }