Skip to content

Commit aa40ed5

Browse files
jdlrobsonAlexej Yaroshevich
authored andcommitted
New Rule: checkParamExistence
This rule reports undocumented parameters when missing @inheritdoc, @Class or @extends statements. Closes gh-138
1 parent 1d6e20f commit aa40ed5

File tree

4 files changed

+302
-1
lines changed

4 files changed

+302
-1
lines changed

README.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,49 @@ function _f() {}
148148
/** @still-invalid */
149149
```
150150

151-
####
151+
### checkParamExistence
152+
153+
Ensures all parameters are documented.
154+
155+
Type: `Boolean`
156+
157+
Values: `true`
158+
159+
160+
#### Example
161+
162+
```js
163+
"checkParamExistence": true
164+
```
165+
166+
##### Valid
167+
168+
```js
169+
/**
170+
* @param {string} message
171+
* @return {string}
172+
*/
173+
function _f ( message ) {
174+
return true;
175+
}
176+
177+
/**
178+
* @inheritdoc
179+
*/
180+
function _f ( message ) {
181+
return true;
182+
}
183+
```
184+
185+
##### Invalid
186+
187+
```js
188+
/**
189+
* @return {string}
190+
*/
191+
function _f ( message ) {
192+
return true;
193+
}
152194

153195
### checkParamNames
154196

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module.exports = checkParamExistence;
2+
module.exports.scopes = ['function'];
3+
module.exports.options = {
4+
checkParamExistence: {allowedValues: [true]}
5+
};
6+
7+
/**
8+
* validator for check-param-existence
9+
*
10+
* @param {(FunctionDeclaration|FunctionExpression)} node
11+
* @param {Function} err
12+
*/
13+
function checkParamExistence(node, err) {
14+
if (!node.jsdoc) {
15+
return;
16+
}
17+
18+
var totalParams = 0;
19+
var excludable;
20+
var documentedParams = {};
21+
node.jsdoc.iterateByType(['param', 'arg', 'argument', 'inheritdoc', 'class', 'extends'],
22+
function(tag) {
23+
totalParams += 1;
24+
if (['inheritdoc', 'class', 'extends'].indexOf(tag.id) > -1) {
25+
excludable = true;
26+
}
27+
// set first instance at place where documentation is missing.
28+
if (['arg', 'argument', 'param'].indexOf(tag.id) > -1 && tag.name) {
29+
documentedParams[tag.name.value] = true;
30+
}
31+
});
32+
if (totalParams !== node.params.length && !excludable) {
33+
node.params.forEach(function(param) {
34+
if (!documentedParams[param.name]) {
35+
err('Function is missing documentation for parameter `' + param.name + '`.',
36+
node.loc.start);
37+
}
38+
});
39+
}
40+
}

lib/rules/validate-jsdoc/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var assert = require('assert');
33
var validatorsByName = module.exports = {
44
checkTypes: require('./check-types'),
55

6+
checkParamExistence: require('./check-param-existence'),
67
checkParamNames: require('./check-param-names'),
78
checkRedundantParams: require('./check-redundant-params'),
89
requireParamTypes: require('./require-param-types'),
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
describe('lib/rules/validate-jsdoc/check-param-existence', function() {
2+
var checker = global.checker({
3+
plugins: ['./lib/index']
4+
});
5+
6+
describe('not configured', function() {
7+
8+
it('should report with undefined', function() {
9+
global.expect(function() {
10+
checker.configure({checkParamExistence: undefined});
11+
}).to.throws(/accepted value/i);
12+
});
13+
14+
it('should report with an object', function() {
15+
global.expect(function() {
16+
checker.configure({checkParamExistence: {}});
17+
}).to.throws(/accepted value/i);
18+
});
19+
20+
});
21+
22+
describe('checkParams compatability', function() {
23+
checker.rules({checkParamExistence: true, checkParamNames: true});
24+
25+
checker.cases([
26+
/* jshint ignore:start */
27+
/* jscs:disable */
28+
{
29+
it: 'should report when a parameter is omitted',
30+
code: function () {
31+
Cls.prototype = {
32+
/**
33+
* @param xxx
34+
*/
35+
run: function(xxx, zzz) {
36+
}
37+
};
38+
},
39+
errors: [
40+
{message: 'Function is missing documentation for parameter `zzz`.',
41+
line: 5, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
42+
]
43+
},
44+
{
45+
it: 'should report when the documentation of a parameter is skipped as well as complain about order.',
46+
code: function () {
47+
Cls.prototype = {
48+
/**
49+
* @param {Object} xxx
50+
* @param {String} aaa
51+
*/
52+
run: function(xxx, zzz, aaa) {
53+
}
54+
};
55+
},
56+
errors: [
57+
{message: 'Parameter aaa is out of order',
58+
line: 4, column: 23, filename: 'input', fixed: undefined, rule: 'jsDoc' },
59+
{message: 'Function is missing documentation for parameter `zzz`.',
60+
line: 6, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
61+
]
62+
},
63+
{
64+
it: 'should report when the documentation of a parameter is forgotten.',
65+
code: function () {
66+
Cls.prototype = {
67+
/**
68+
* @param {Object} xxx
69+
* @param {String} zzz
70+
*/
71+
run: function(xxx, zzz, aaa) {
72+
}
73+
};
74+
},
75+
errors: [
76+
{message: 'Function is missing documentation for parameter `aaa`.',
77+
line: 6, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
78+
]
79+
}
80+
// jscs:enable
81+
/* jshint ignore:end */
82+
]);
83+
});
84+
85+
describe('with true', function() {
86+
checker.rules({checkParamExistence: true});
87+
88+
checker.cases([
89+
/* jshint ignore:start */
90+
/* jscs:disable */
91+
{
92+
it: 'should report when a parameter is omitted',
93+
code: function () {
94+
Cls.prototype = {
95+
/**
96+
* @param xxx
97+
*/
98+
run: function(xxx, zzz) {
99+
}
100+
};
101+
},
102+
errors: [
103+
{message: 'Function is missing documentation for parameter `zzz`.',
104+
line: 5, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
105+
]
106+
},
107+
{
108+
it: 'should report when an argument is omitted',
109+
code: function () {
110+
Cls.prototype = {
111+
/**
112+
* @argument xxx
113+
*/
114+
run: function(xxx, zzz) {
115+
}
116+
};
117+
},
118+
errors: [
119+
{message: 'Function is missing documentation for parameter `zzz`.',
120+
line: 5, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
121+
]
122+
},
123+
{
124+
it: 'should report when an arg is omitted',
125+
code: function () {
126+
Cls.prototype = {
127+
/**
128+
* @arg xxx
129+
*/
130+
run: function(xxx, zzz) {
131+
}
132+
};
133+
},
134+
errors: [
135+
{message: 'Function is missing documentation for parameter `zzz`.',
136+
line: 5, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
137+
]
138+
},
139+
{
140+
it: 'should report when the documentation of a parameter is skipped.',
141+
code: function () {
142+
Cls.prototype = {
143+
/**
144+
* @param {Object} xxx
145+
* @param {String} aaa
146+
*/
147+
run: function(xxx, zzz, aaa) {
148+
}
149+
};
150+
},
151+
errors: [
152+
{message: 'Function is missing documentation for parameter `zzz`.',
153+
line: 6, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
154+
]
155+
},
156+
{
157+
it: 'should complain twice when more than one parameter missed.',
158+
code: function () {
159+
Cls.prototype = {
160+
/**
161+
* @param {Object} xxx
162+
* @param {String} aaa
163+
* @param {String} fff
164+
*/
165+
run: function(xxx, zzz, aaa, ggg, fff) {
166+
}
167+
};
168+
},
169+
errors: [
170+
{message: 'Function is missing documentation for parameter `zzz`.',
171+
line: 7, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' },
172+
{message: 'Function is missing documentation for parameter `ggg`.',
173+
line: 7, column: 9, filename: 'input', fixed: undefined, rule: 'jsDoc' }
174+
]
175+
},
176+
{
177+
it: 'should not complain at all when an inheritdoc is present even if a parameter is documented.',
178+
code: function () {
179+
Cls.prototype = {
180+
/**
181+
* @inheritdoc
182+
* @param {String} xxx
183+
*/
184+
run: function(xxx, zzz, aaa, ggg, fff) {
185+
}
186+
};
187+
},
188+
errors: []
189+
},
190+
{
191+
it: 'should not complain at all when an inheritdoc is present.',
192+
code: function () {
193+
Cls.prototype = {
194+
/**
195+
* @inheritdoc
196+
*/
197+
run: function(xxx, zzz, aaa, ggg, fff) {
198+
}
199+
};
200+
},
201+
errors: []
202+
},
203+
{
204+
it: 'should not complain on classes.',
205+
code: function () {
206+
/**
207+
* @class Foo
208+
*/
209+
function Cls( foo, bar ) {
210+
}
211+
},
212+
errors: []
213+
}
214+
// jscs:enable
215+
/* jshint ignore:end */
216+
]);
217+
});
218+
});

0 commit comments

Comments
 (0)