Skip to content

Commit 682b6bd

Browse files
kunagpalgajus
authored andcommitted
feat: add rule require-example (#35)
* feat: Add require-example rule 🎉 * test: Add require-example tests * docs: Added documentation for require-example 📝
1 parent 7e57c13 commit 682b6bd

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-0
lines changed

.README/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This table maps the rules between `eslint-plugin-jsdoc` and `jscs-jsdoc`.
1919
| [`check-types`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-types) | [`checkTypes`](https://github.com/jscs-dev/jscs-jsdoc#checktypes) |
2020
| [`newline-after-description`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-newline-after-description) | [`requireNewlineAfterDescription`](https://github.com/jscs-dev/jscs-jsdoc#requirenewlineafterdescription) and [`disallowNewlineAfterDescription`](https://github.com/jscs-dev/jscs-jsdoc#disallownewlineafterdescription) |
2121
| [`require-description-complete-sentence`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-description-complete-sentence) | [`requireDescriptionCompleteSentence`](https://github.com/jscs-dev/jscs-jsdoc#requiredescriptioncompletesentence) |
22+
| [`require-example`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-example) | N/A |
2223
| [`require-hyphen-before-param-description`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-hyphen-before-param-description) | [`requireHyphenBeforeDescription`](https://github.com/jscs-dev/jscs-jsdoc#requirehyphenbeforedescription) |
2324
| [`require-param`](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param) | [`checkParamExistence`](https://github.com/jscs-dev/jscs-jsdoc#checkparamexistence) |
2425
| [`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) |
@@ -68,6 +69,7 @@ Finally, enable all of the rules that you would like to use.
6869
"jsdoc/check-types": 1,
6970
"jsdoc/newline-after-description": 1,
7071
"jsdoc/require-description-complete-sentence": 1,
72+
"jsdoc/require-example": 1,
7173
"jsdoc/require-hyphen-before-param-description": 1,
7274
"jsdoc/require-param": 1,
7375
"jsdoc/require-param-description": 1,
@@ -123,6 +125,7 @@ Use `settings.jsdoc.additionalTagNames` to configure additional, allowed JSDoc t
123125
{"gitdown": "include", "file": "./rules/check-types.md"}
124126
{"gitdown": "include", "file": "./rules/newline-after-description.md"}
125127
{"gitdown": "include", "file": "./rules/require-description-complete-sentence.md"}
128+
{"gitdown": "include", "file": "./rules/require-example.md"}
126129
{"gitdown": "include", "file": "./rules/require-hyphen-before-param-description.md"}
127130
{"gitdown": "include", "file": "./rules/require-param.md"}
128131
{"gitdown": "include", "file": "./rules/require-param-description.md"}

.README/rules/require-example.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
### `require-example`
2+
3+
Requires that all functions have examples.
4+
5+
* All functions must have one or more `@example` tags.
6+
* Every example tag must have a non-empty description that explains the method's usage.
7+
8+
|||
9+
|---|---|
10+
|Context|`ArrowFunctionExpression`, `FunctionDeclaration`, `FunctionExpression`|
11+
|Tags|`example`|
12+
13+
<!-- assertions requireExample -->

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import checkTagNames from './rules/checkTagNames';
33
import checkTypes from './rules/checkTypes';
44
import newlineAfterDescription from './rules/newlineAfterDescription';
55
import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence';
6+
import requireExample from './rules/requireExample';
67
import requireHyphenBeforeParamDescription from './rules/requireHyphenBeforeParamDescription';
78
import requireParam from './rules/requireParam';
89
import requireParamDescription from './rules/requireParamDescription';
@@ -17,6 +18,7 @@ export default {
1718
'check-types': checkTypes,
1819
'newline-after-description': newlineAfterDescription,
1920
'require-description-complete-sentence': requireDescriptionCompleteSentence,
21+
'require-example': requireExample,
2022
'require-hyphen-before-param-description': requireHyphenBeforeParamDescription,
2123
'require-param': requireParam,
2224
'require-param-description': requireParamDescription,
@@ -30,6 +32,7 @@ export default {
3032
'check-types': 0,
3133
'newline-after-description': 0,
3234
'require-description-complete-sentence': 0,
35+
'require-example': 0,
3336
'require-hyphen-before-param-description': 0,
3437
'require-param': 0,
3538
'require-param-description': 0,

src/rules/requireExample.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import _ from 'lodash';
2+
import iterateJsdoc from '../iterateJsdoc';
3+
4+
export default iterateJsdoc(({
5+
jsdoc,
6+
report,
7+
utils
8+
}) => {
9+
const targetTagName = utils.getPreferredTagName('example');
10+
11+
const functionExamples = _.filter(jsdoc.tags, {
12+
tag: targetTagName
13+
});
14+
15+
if (_.isEmpty(functionExamples)) {
16+
return report('Missing JSDoc @' + targetTagName + ' declaration.');
17+
}
18+
19+
return _.forEach(functionExamples, (example) => {
20+
const exampleContent = _.compact((example.name + ' ' + example.description).trim().split('\n'));
21+
22+
if (_.isEmpty(exampleContent)) {
23+
report('Missing JSDoc @' + targetTagName + ' description.');
24+
}
25+
});
26+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* eslint-disable no-restricted-syntax */
2+
3+
export default {
4+
invalid: [
5+
{
6+
code: `
7+
/**
8+
*
9+
*/
10+
function quux () {
11+
12+
}
13+
`,
14+
errors: [
15+
{
16+
message: 'Missing JSDoc @example declaration.'
17+
}
18+
]
19+
},
20+
{
21+
code: `
22+
/**
23+
* @example
24+
*/
25+
function quux () {
26+
27+
}
28+
`,
29+
errors: [
30+
{
31+
message: 'Missing JSDoc @example description.'
32+
}
33+
]
34+
}
35+
],
36+
valid: [
37+
{
38+
code: `
39+
/**
40+
* @example
41+
* // arbitrary example content
42+
*/
43+
function quux () {
44+
45+
}
46+
`
47+
},
48+
{
49+
code: `
50+
/**
51+
* @example
52+
* quux(); // does something useful
53+
*/
54+
function quux () {
55+
56+
}
57+
`
58+
},
59+
{
60+
code: `
61+
/**
62+
* @example <caption>Valid usage</caption>
63+
* quux(); // does something useful
64+
*
65+
* @example <caption>Invalid usage</caption>
66+
* quux('random unwanted arg'); // results in an error
67+
*/
68+
function quux () {
69+
70+
}
71+
`
72+
}
73+
]
74+
};

test/rules/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ _.forEach([
1212
'check-types',
1313
'newline-after-description',
1414
'require-description-complete-sentence',
15+
'require-example',
1516
'require-hyphen-before-param-description',
1617
'require-param',
1718
'require-param-description',

0 commit comments

Comments
 (0)