Skip to content

Commit 4b2dfad

Browse files
author
Alexej Yaroshevich
committed
little refactoring of jsdoc validators
1 parent c0924b6 commit 4b2dfad

3 files changed

Lines changed: 157 additions & 115 deletions

File tree

lib/rules/validate-jsdoc.js

Lines changed: 27 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
var assert = require('assert'),
1+
var assert = require('assert');
22

3-
jsDocHelpers = require('../jsdoc-helpers'),
4-
esprimaHelpers = require('../esprima-helpers');
3+
var jsDocHelpers = require('../jsdoc-helpers');
54

65
module.exports = function() {};
76

@@ -10,24 +9,15 @@ module.exports.prototype = {
109
configure: function(options) {
1110
assert(typeof options === 'object', 'jsDoc option requires object value');
1211
this._options = options;
12+
this._optionsList = Object.keys(options);
1313
},
1414

1515
getOptionName: function() {
1616
return 'jsDoc';
1717
},
1818

1919
check: function(file, errors) {
20-
var options = this._options;
21-
var lineValidators = [];
22-
23-
// create validators list
24-
if (options.checkParamNames || options.checkRedundantParams || options.requireParamTypes) {
25-
lineValidators.push(validateParamLine);
26-
}
27-
if (options.checkReturnTypes || options.checkRedundantReturns || options.checkTypes ||
28-
options.requireReturnTypes) {
29-
lineValidators.push(validateReturnsLine);
30-
}
20+
var lineValidators = this.loadLineValidators();
3121

3222
// skip if there is nothing to check
3323
if (!lineValidators.length) {
@@ -36,7 +26,10 @@ module.exports.prototype = {
3626

3727
var jsDocs = jsDocHelpers.parseComments(file.getComments());
3828

39-
file.iterateNodesByType(['FunctionDeclaration', 'FunctionExpression'], function(node) {
29+
file.iterateNodesByType([
30+
'FunctionDeclaration',
31+
'FunctionExpression'
32+
], function(node) {
4033
var jsDoc = jsDocs.node(node);
4134
if (!jsDoc) {
4235
return;
@@ -69,113 +62,32 @@ module.exports.prototype = {
6962
}
7063
});
7164

72-
/**
73-
* validator for @param
74-
* @param {{type: 'FunctionDeclaration'}|{type: 'FunctionExpression'}} node
75-
* @param {Number} line
76-
* @param {Function} err
77-
*/
78-
function validateParamLine(node, line, err) {
79-
if (line.indexOf('@param') !== 0) {
80-
return;
81-
}
82-
83-
// checking validity
84-
var match = line.match(/^@param\s+(?:{(.+?)})?\s*(\[)?([a-zA-Z0-9_\.\$]+)/);
85-
if (!match) {
86-
return err('Invalid JsDoc @param');
87-
}
88-
89-
var jsDocType = match[1];
90-
var jsDocName = match[3];
91-
var jsDocOptional = match[2] === '[';
92-
93-
// checking existance
94-
if (options.requireParamTypes && !jsDocType) {
95-
return err('Missing JsDoc @param type');
96-
}
97-
98-
var jsDocParsedType = jsDocHelpers.parse(jsDocType);
99-
if (options.checkTypes && jsDocParsedType.invalid) {
100-
return err('Invalid JsDoc type definition');
101-
}
102-
103-
// skip if there is dot in param name (object's inner param)
104-
if (jsDocName.indexOf('.') !== -1) {
105-
return;
106-
}
107-
108-
// checking redudant
109-
var param = node.params[node.jsDoc.paramIndex];
110-
if (options.checkRedundantParams && !jsDocOptional && !param) {
111-
return err('Redundant JsDoc @param');
112-
}
113-
114-
// checking name
115-
if (options.checkParamNames && jsDocName !== param.name) {
116-
return err('Invalid JsDoc @param argument name');
117-
}
65+
},
11866

119-
node.jsDoc.paramIndex++;
67+
loadLineValidators: function() {
68+
var passedOptions = this._optionsList;
69+
var validators = [];
70+
if (!passedOptions) {
71+
return validators;
12072
}
12173

122-
/**
123-
* validator for @return/@returns
124-
* @param {(FunctionDeclaration|FunctionExpression)} node
125-
* @param {Number} line
126-
* @param {Function} err
127-
*/
128-
function validateReturnsLine(node, line, err) {
129-
if (line.indexOf('@return') !== 0) {
130-
return;
131-
}
132-
133-
// checking validity
134-
var match = line.match(/^@returns?\s+(?:{(.+?)})?/);
135-
if (!match) {
136-
return err('Invalid JsDoc @returns');
137-
}
138-
139-
var jsDocType = match[1];
140-
141-
// checking existance
142-
if (options.requireReturnTypes && !jsDocType) {
143-
err('Missing JsDoc @returns type');
144-
}
145-
146-
var jsDocParsedType = jsDocHelpers.parse(jsDocType);
147-
if (options.checkTypes && jsDocParsedType.invalid) {
148-
return err('Invalid JsDoc type definition');
149-
}
150-
151-
if (!options.checkRedundantReturns && !options.checkReturnTypes) {
74+
var availableValidators = [
75+
'param',
76+
'returns'
77+
];
78+
availableValidators.forEach(function (name) {
79+
var v = require('./validate-jsdoc/' + name);
80+
if (!v.coveredOptions) {
15281
return;
15382
}
154-
155-
var returnsArgumentStatements = [];
156-
esprimaHelpers.treeIterator.iterate(node, function(n/*, parentNode, parentCollection*/) {
157-
if (n && n.type === 'ReturnStatement' && n.argument) {
158-
if (node === esprimaHelpers.closestScopeNode(n)) {
159-
returnsArgumentStatements.push(n.argument);
160-
}
83+
for (var i = 0, l = v.coveredOptions.length; i < l; i += 1) {
84+
if (passedOptions.indexOf(v.coveredOptions[i]) !== -1) {
85+
validators.push(v.bind(this));
86+
return;
16187
}
162-
});
163-
164-
// checking redundant
165-
if (options.checkRedundantReturns && !returnsArgumentStatements.length) {
166-
err('Redundant JsDoc @returns');
16788
}
89+
}.bind(this));
16890

169-
// try to check returns types
170-
if (options.checkReturnTypes && jsDocParsedType) {
171-
returnsArgumentStatements.forEach(function (argument) {
172-
if (!jsDocHelpers.match(jsDocParsedType, argument)) {
173-
err('Wrong returns value', argument.loc.start);
174-
}
175-
});
176-
}
177-
}
178-
91+
return validators;
17992
}
180-
18193
};

lib/rules/validate-jsdoc/param.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
var jsDocHelpers = require('../../jsdoc-helpers');
3+
4+
module.exports = validateParamLine;
5+
module.exports.coveredOptions = [
6+
'checkParamNames',
7+
'requireParamTypes',
8+
'checkRedundantParams',
9+
'checkTypes',
10+
];
11+
12+
/**
13+
* validator for @param
14+
* @param {{type: 'FunctionDeclaration'}|{type: 'FunctionExpression'}} node
15+
* @param {Number} line
16+
* @param {Function} err
17+
*/
18+
function validateParamLine(node, line, err) {
19+
var options = this._options;
20+
if (line.indexOf('@param') !== 0) {
21+
return;
22+
}
23+
24+
// checking validity
25+
var match = line.match(/^@param\s+(?:{(.+?)})?\s*(\[)?([a-zA-Z0-9_\.\$]+)/);
26+
if (!match) {
27+
return err('Invalid JsDoc @param');
28+
}
29+
30+
var jsDocType = match[1];
31+
var jsDocName = match[3];
32+
var jsDocOptional = match[2] === '[';
33+
34+
// checking existance
35+
if (options.requireParamTypes && !jsDocType) {
36+
return err('Missing JsDoc @param type');
37+
}
38+
39+
var jsDocParsedType = jsDocHelpers.parse(jsDocType);
40+
if (options.checkTypes && jsDocParsedType.invalid) {
41+
return err('Invalid JsDoc type definition');
42+
}
43+
44+
// skip if there is dot in param name (object's inner param)
45+
if (jsDocName.indexOf('.') !== -1) {
46+
return;
47+
}
48+
49+
// checking redudant
50+
var param = node.params[node.jsDoc.paramIndex];
51+
if (options.checkRedundantParams && !jsDocOptional && !param) {
52+
return err('Redundant JsDoc @param');
53+
}
54+
55+
// checking name
56+
if (options.checkParamNames && jsDocName !== param.name) {
57+
return err('Invalid JsDoc @param argument name');
58+
}
59+
60+
node.jsDoc.paramIndex++;
61+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
var jsDocHelpers = require('../../jsdoc-helpers');
3+
var esprimaHelpers = require('../../esprima-helpers');
4+
5+
module.exports = validateReturnsLine;
6+
module.exports.coveredOptions = [
7+
'checkReturnTypes',
8+
'requireReturnTypes',
9+
'checkRedundantReturns',
10+
'checkTypes',
11+
];
12+
13+
/**
14+
* validator for @return/@returns
15+
* @param {(FunctionDeclaration|FunctionExpression)} node
16+
* @param {Number} line
17+
* @param {Function} err
18+
*/
19+
function validateReturnsLine(node, line, err) {
20+
var options = this._options;
21+
if (line.indexOf('@return') !== 0) {
22+
return;
23+
}
24+
25+
// checking validity
26+
var match = line.match(/^@returns?\s+(?:{(.+?)})?/);
27+
if (!match) {
28+
return err('Invalid JsDoc @returns');
29+
}
30+
31+
var jsDocType = match[1];
32+
33+
// checking existance
34+
if (options.requireReturnTypes && !jsDocType) {
35+
err('Missing JsDoc @returns type');
36+
}
37+
38+
var jsDocParsedType = jsDocHelpers.parse(jsDocType);
39+
if (options.checkTypes && jsDocParsedType.invalid) {
40+
return err('Invalid JsDoc type definition');
41+
}
42+
43+
if (!options.checkRedundantReturns && !options.checkReturnTypes) {
44+
return;
45+
}
46+
47+
var returnsArgumentStatements = [];
48+
esprimaHelpers.treeIterator.iterate(node, function(n/*, parentNode, parentCollection*/) {
49+
if (n && n.type === 'ReturnStatement' && n.argument) {
50+
if (node === esprimaHelpers.closestScopeNode(n)) {
51+
returnsArgumentStatements.push(n.argument);
52+
}
53+
}
54+
});
55+
56+
// checking redundant
57+
if (options.checkRedundantReturns && !returnsArgumentStatements.length) {
58+
err('Redundant JsDoc @returns');
59+
}
60+
61+
// try to check returns types
62+
if (options.checkReturnTypes && jsDocParsedType) {
63+
returnsArgumentStatements.forEach(function (argument) {
64+
if (!jsDocHelpers.match(jsDocParsedType, argument)) {
65+
err('Wrong returns value', argument.loc.start);
66+
}
67+
});
68+
}
69+
}

0 commit comments

Comments
 (0)