Skip to content

Commit 140dfd6

Browse files
mattvotAlexej Yaroshevich
authored andcommitted
enforceExistence: rework rule, add options to suppress exporting, expressions, etc.
- Refactored configuration and added options to suppress module.export and expression function definitions - Added further tests and reconfigured configuration parsing Fixes #110 Closes gh-126
1 parent 96e9765 commit 140dfd6

File tree

2 files changed

+148
-20
lines changed

2 files changed

+148
-20
lines changed
Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,95 @@
1+
var assert = require('assert');
2+
13
module.exports = enforceExistence;
24
module.exports.scopes = ['function'];
35
module.exports.options = {
4-
enforceExistence: {allowedValues: [true, 'exceptExports']}
6+
enforceExistence: true
57
};
68

79
/**
8-
* Validator for jsdoc data existance
10+
* @param {Object} options
11+
*/
12+
enforceExistence.configure = function(options) {
13+
14+
// set default policy
15+
var policy = this._enforceExistencePolicy = {
16+
all: true,
17+
anonymous: false,
18+
exports: true,
19+
expressions: true
20+
};
21+
22+
// check options are valid
23+
var o = options.enforceExistence;
24+
assert(
25+
o === true || o === false || typeof o === 'string' || (typeof o === 'object' && Array.isArray(o.allExcept)),
26+
'jsDoc.enforceExistence rule was not configured properly'
27+
);
28+
29+
// parse options for policies
30+
if (o === false) {
31+
policy.all = false;
32+
} else if (typeof o === 'string' && o === 'exceptExports') { // backward compatible string option
33+
policy.exports = false;
34+
} else if (typeof o === 'object' && Array.isArray(o.allExcept)) {
35+
if (o.allExcept.indexOf('exports') > -1) {
36+
policy.exports = false;
37+
}
38+
if (o.allExcept.indexOf('expressions') > -1) {
39+
policy.expressions = false;
40+
}
41+
}
42+
43+
};
44+
45+
/**
46+
* Validator for jsdoc data existence
947
*
1048
* @param {(FunctionDeclaration|FunctionExpression)} node
1149
* @param {Function} err
1250
*/
1351
function enforceExistence(node, err) {
14-
var reportExports = this._options.enforceExistence !== 'exceptExports';
52+
var policy = this._enforceExistencePolicy;
1553

16-
// if function is not anonymous or in variabledeclarator or in assignmentexpression
54+
// enforce 'break-out' policies
1755
var parentNode = node.parentNode || {};
18-
var needCheck = node.id ||
19-
parentNode.type === 'VariableDeclarator' ||
20-
parentNode.type === 'Property' ||
21-
parentNode.type === 'AssignmentExpression' && parentNode.operator === '=';
22-
23-
if (!reportExports && needCheck && parentNode.type === 'AssignmentExpression') {
24-
var left = parentNode.left;
25-
if ((left.object && left.object.name) === 'module' &&
26-
(left.property && left.property.name) === 'exports') {
27-
needCheck = false;
56+
57+
if (policy.all === false) {
58+
// don't check anything
59+
return;
60+
}
61+
if (policy.anonymous === false) {
62+
if (!node.id && ['AssignmentExpression', 'VariableDeclarator', 'Property'].indexOf(parentNode.type) === -1) {
63+
// don't check anonymous functions
64+
return;
65+
}
66+
}
67+
if (policy.exports === false) {
68+
if (parentNode.type === 'AssignmentExpression') {
69+
var left = parentNode.left;
70+
if ((left.object && left.object.name) === 'module' &&
71+
(left.property && left.property.name) === 'exports') {
72+
// don't check exports functions
73+
return;
74+
}
75+
}
76+
}
77+
if (policy.expressions === false) {
78+
if (['AssignmentExpression', 'VariableDeclarator', 'Property'].indexOf(parentNode.type) > -1) {
79+
// don't check expression functions
80+
return;
2881
}
2982
}
3083

31-
// skip unless jsdoc exists and check is needed
32-
if (node.jsdoc || !needCheck) {
84+
// now clear to check for documentation
85+
if (node.jsdoc) {
86+
if (!node.jsdoc.valid) {
87+
err('Invalid jsdoc-block definition', node.jsdoc.loc);
88+
}
3389
return;
3490
}
3591

3692
// report absence
37-
err('jsdoc definition required', node.loc.start);
93+
err('Expect valid jsdoc-block definition', node.loc.start);
94+
3895
}

test/lib/rules/validate-jsdoc/enforce-existence.js

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,33 @@ describe('lib/rules/validate-jsdoc/enforce-existence', function () {
88
it('should report with undefined', function() {
99
global.expect(function() {
1010
checker.configure({enforceExistence: undefined});
11-
}).to.throws(/accepted value/i);
11+
}).to.throws(/jsDoc.enforceExistence rule was not configured properly/i);
1212
});
1313

1414
it('should report with an object', function() {
1515
global.expect(function() {
16-
checker.configure({enforceExistence: {}});
17-
}).to.throws(/accepted value/i);
16+
checker.configure({enforceExistence: {allExcept: 'something invalid'}});
17+
}).to.throws(/jsDoc.enforceExistence rule was not configured properly/i);
1818
});
1919

2020
});
2121

22+
describe('with false', function() {
23+
checker.rules({enforceExistence: false});
24+
25+
checker.cases([
26+
/* jshint ignore:start */
27+
{
28+
it: 'should not report jsdocs existence for function',
29+
code: function () {
30+
function funcName(p) {
31+
}
32+
}
33+
}
34+
/* jshint ignore:end */
35+
]);
36+
});
37+
2238
describe('with true', function() {
2339
checker.rules({enforceExistence: true});
2440

@@ -147,4 +163,59 @@ describe('lib/rules/validate-jsdoc/enforce-existence', function () {
147163
]);
148164
});
149165

166+
describe('with allExcept exports', function() {
167+
checker.rules({enforceExistence: {allExcept: ['exports']}});
168+
169+
checker.cases([
170+
/* jshint ignore:start */
171+
{
172+
it: 'should not report jsdocs existence for export functions',
173+
errors: 0,
174+
code: function () {
175+
module.exports = function () {
176+
};
177+
}
178+
}
179+
/* jshint ignore:end */
180+
]);
181+
});
182+
183+
describe('with allExcept expressions', function() {
184+
checker.rules({enforceExistence: {allExcept: ['expressions']}});
185+
186+
checker.cases([
187+
/* jshint ignore:start */
188+
{
189+
it: 'should not report jsdocs existence for expression functions',
190+
code: function () {
191+
var x = function () {
192+
};
193+
}
194+
}
195+
/* jshint ignore:end */
196+
]);
197+
});
198+
199+
describe('with allExcept exports and expressions', function() {
200+
checker.rules({enforceExistence: {allExcept: ['exports', 'expressions']}});
201+
202+
checker.cases([
203+
/* jshint ignore:start */
204+
{
205+
it: 'should not report jsdocs existence for expression functions',
206+
code: function () {
207+
var x = function () {
208+
};
209+
}
210+
}, {
211+
it: 'should not report jsdocs existence for export',
212+
code: function () {
213+
module.exports = function () {
214+
};
215+
}
216+
}
217+
/* jshint ignore:end */
218+
]);
219+
});
220+
150221
});

0 commit comments

Comments
 (0)