eslint 0.5.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -8
- package/conf/environments.json +29 -12
- package/conf/eslint.json +7 -0
- package/lib/cli.js +21 -12
- package/lib/config.js +36 -13
- package/lib/eslint.js +218 -63
- package/lib/formatters/checkstyle.js +4 -6
- package/lib/formatters/compact.js +2 -5
- package/lib/formatters/junit.js +2 -5
- package/lib/formatters/stylish.js +2 -1
- package/lib/formatters/tap.js +3 -6
- package/lib/load-rules.js +3 -1
- package/lib/options.js +56 -47
- package/lib/rules/block-scoped-var.js +38 -4
- package/lib/rules/brace-style.js +6 -2
- package/lib/rules/default-case.js +64 -0
- package/lib/rules/eqeqeq.js +4 -0
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/no-comma-dangle.js +1 -1
- package/lib/rules/no-constant-condition.js +2 -1
- package/lib/rules/no-delete-var.js +1 -1
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-extend-native.js +6 -2
- package/lib/rules/no-extra-parens.js +68 -33
- package/lib/rules/no-extra-strict.js +1 -1
- package/lib/rules/no-fallthrough.js +8 -0
- package/lib/rules/no-inner-declarations.js +70 -0
- package/lib/rules/no-invalid-regexp.js +2 -2
- package/lib/rules/no-lonely-if.js +28 -0
- package/lib/rules/no-mixed-requires.js +1 -1
- package/lib/rules/no-new-require.js +23 -0
- package/lib/rules/no-redeclare.js +4 -1
- package/lib/rules/no-restricted-modules.js +72 -0
- package/lib/rules/no-sequences.js +92 -0
- package/lib/rules/no-shadow-restricted-names.js +4 -2
- package/lib/rules/no-shadow.js +1 -1
- package/lib/rules/no-spaced-func.js +5 -3
- package/lib/rules/no-sparse-arrays.js +1 -3
- package/lib/rules/no-unused-vars.js +10 -4
- package/lib/rules/no-use-before-define.js +11 -2
- package/lib/rules/semi.js +11 -3
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-after-keywords.js +64 -0
- package/lib/rules/space-infix-ops.js +11 -9
- package/lib/rules/space-return-throw-case.js +11 -3
- package/lib/rules/space-unary-word-ops.js +3 -2
- package/lib/rules/valid-jsdoc.js +18 -3
- package/package.json +8 -5
@@ -0,0 +1,23 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to disallow use of new operator with the `require` function
|
3
|
+
* @author Wil Moore III
|
4
|
+
*/
|
5
|
+
|
6
|
+
//------------------------------------------------------------------------------
|
7
|
+
// Rule Definition
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
module.exports = function(context) {
|
11
|
+
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
return {
|
15
|
+
|
16
|
+
"NewExpression": function(node) {
|
17
|
+
if (node.callee.type === "Identifier" && node.callee.name === "require") {
|
18
|
+
context.report(node, "Unexpected use of new with require.");
|
19
|
+
}
|
20
|
+
}
|
21
|
+
};
|
22
|
+
|
23
|
+
};
|
@@ -16,7 +16,10 @@ module.exports = function(context) {
|
|
16
16
|
|
17
17
|
scope.variables.forEach(function(variable) {
|
18
18
|
if (variable.identifiers && variable.identifiers.length > 1) {
|
19
|
-
variable.identifiers.sort(function(a, b) {
|
19
|
+
variable.identifiers.sort(function(a, b) {
|
20
|
+
return a.range[1] - b.range[1];
|
21
|
+
});
|
22
|
+
|
20
23
|
for (var i = 1, l = variable.identifiers.length; i < l; i++) {
|
21
24
|
context.report(variable.identifiers[i], "{{a}} is already defined", {a: variable.name});
|
22
25
|
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Restrict usage of specified node modules.
|
3
|
+
* @author Christian Schulz
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Rule Definition
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = function (context) {
|
12
|
+
// trim restricted module names
|
13
|
+
var restrictedModules = context.options;
|
14
|
+
|
15
|
+
// if no modules are restricted we don't need to check the CallExpressions
|
16
|
+
if (restrictedModules.length === 0) {
|
17
|
+
return {};
|
18
|
+
}
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Function to check if a node is a string literal.
|
22
|
+
* @param {ASTNode} node The node to check.
|
23
|
+
* @returns {boolean} If the node is a string literal.
|
24
|
+
*/
|
25
|
+
function isString(node) {
|
26
|
+
return node && node.type === "Literal" && typeof node.value === "string";
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Function to check if a node is a require call.
|
31
|
+
* @param {ASTNode} node The node to check.
|
32
|
+
* @returns {boolean} If the node is a require call.
|
33
|
+
*/
|
34
|
+
function isRequireCall(node) {
|
35
|
+
return node.callee.type === "Identifier" && node.callee.name === "require";
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Function to check if a node has an argument that is an restricted module and return its name.
|
40
|
+
* @param {ASTNode} node The node to check
|
41
|
+
* @returns {undefined|String} restricted module name or undefined if node argument isn't restricted.
|
42
|
+
*/
|
43
|
+
function getRestrictedModuleName(node) {
|
44
|
+
var moduleName;
|
45
|
+
|
46
|
+
// node has arguments and first argument is string
|
47
|
+
if (node.arguments.length && isString(node.arguments[0])) {
|
48
|
+
var argumentValue = node.arguments[0].value.trim();
|
49
|
+
|
50
|
+
// check if argument value is in restricted modules array
|
51
|
+
if (restrictedModules.indexOf(argumentValue) !== -1) {
|
52
|
+
moduleName = argumentValue;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
return moduleName;
|
57
|
+
}
|
58
|
+
|
59
|
+
return {
|
60
|
+
"CallExpression": function (node) {
|
61
|
+
if (isRequireCall(node)) {
|
62
|
+
var restrictedModuleName = getRestrictedModuleName(node);
|
63
|
+
|
64
|
+
if (restrictedModuleName) {
|
65
|
+
context.report(node, "'{{moduleName}}' module is restricted from being used.", {
|
66
|
+
moduleName: restrictedModuleName
|
67
|
+
});
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
};
|
72
|
+
};
|
@@ -0,0 +1,92 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to flag use of comma operator
|
3
|
+
* @author Brandon Mills
|
4
|
+
*/
|
5
|
+
|
6
|
+
//------------------------------------------------------------------------------
|
7
|
+
// Rule Definition
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
module.exports = function(context) {
|
11
|
+
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Parts of the grammar that are required to have parens.
|
16
|
+
*/
|
17
|
+
var parenthesized = {
|
18
|
+
"DoWhileStatement": "test",
|
19
|
+
"IfStatement": "test",
|
20
|
+
"SwitchStatement": "discriminant",
|
21
|
+
"WhileStatement": "test",
|
22
|
+
"WithStatement": "object"
|
23
|
+
|
24
|
+
// Omitting CallExpression - commas are parsed as argument separators
|
25
|
+
// Omitting NewExpression - commas are parsed as argument separators
|
26
|
+
// Omitting ForInStatement - parts aren't individually parenthesised
|
27
|
+
// Omitting ForStatement - parts aren't individually parenthesised
|
28
|
+
};
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Determines whether a node is required by the grammar to be wrapped in
|
32
|
+
* parens, e.g. the test of an if statement.
|
33
|
+
* @param {ASTNode} node - The AST node
|
34
|
+
* @returns {boolean} True if parens around node belong to parent node.
|
35
|
+
*/
|
36
|
+
function requiresExtraParens(node) {
|
37
|
+
return node.parent && parenthesized[node.parent.type] !== undefined &&
|
38
|
+
node === node.parent[parenthesized[node.parent.type]];
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Check if a node is wrapped in parens.
|
43
|
+
* @param {ASTNode} node - The AST node
|
44
|
+
* @returns {boolean} True if the node has a paren on each side.
|
45
|
+
*/
|
46
|
+
function isParenthesised(node) {
|
47
|
+
var previousToken = context.getTokenBefore(node),
|
48
|
+
nextToken = context.getTokenAfter(node);
|
49
|
+
|
50
|
+
return previousToken && nextToken &&
|
51
|
+
previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
|
52
|
+
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Check if a node is wrapped in two levels of parens.
|
57
|
+
* @param {ASTNode} node - The AST node
|
58
|
+
* @returns {boolean} True if two parens surround the node on each side.
|
59
|
+
*/
|
60
|
+
function isParenthesisedTwice(node) {
|
61
|
+
var previousToken = context.getTokenBefore(node, 1),
|
62
|
+
nextToken = context.getTokenAfter(node, 1);
|
63
|
+
|
64
|
+
return isParenthesised(node) && previousToken && nextToken &&
|
65
|
+
previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
|
66
|
+
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
|
67
|
+
}
|
68
|
+
|
69
|
+
return {
|
70
|
+
"SequenceExpression": function(node) {
|
71
|
+
// Always allow sequences in for statement update
|
72
|
+
if (node.parent.type === "ForStatement" &&
|
73
|
+
(node === node.parent.init || node === node.parent.update)) {
|
74
|
+
return;
|
75
|
+
}
|
76
|
+
|
77
|
+
// Wrapping a sequence in extra parens indicates intent
|
78
|
+
if (requiresExtraParens(node)) {
|
79
|
+
if (isParenthesisedTwice(node)) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
} else {
|
83
|
+
if (isParenthesised(node)) {
|
84
|
+
return;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
context.report(node, "Unexpected use of comma operator.");
|
89
|
+
}
|
90
|
+
};
|
91
|
+
|
92
|
+
};
|
@@ -13,7 +13,7 @@ module.exports = function(context) {
|
|
13
13
|
var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"];
|
14
14
|
|
15
15
|
function checkForViolation(id) {
|
16
|
-
if(RESTRICTED.indexOf(id.name) > -1) {
|
16
|
+
if (RESTRICTED.indexOf(id.name) > -1) {
|
17
17
|
context.report(id, "Shadowing of global property \"" + id.name + "\".");
|
18
18
|
}
|
19
19
|
}
|
@@ -23,7 +23,9 @@ module.exports = function(context) {
|
|
23
23
|
checkForViolation(node.id);
|
24
24
|
},
|
25
25
|
"FunctionExpression": function(node) {
|
26
|
-
if(node.id) {
|
26
|
+
if (node.id) {
|
27
|
+
checkForViolation(node.id);
|
28
|
+
}
|
27
29
|
[].map.call(node.params, checkForViolation);
|
28
30
|
},
|
29
31
|
"FunctionDeclaration": function(node) {
|
package/lib/rules/no-shadow.js
CHANGED
@@ -15,7 +15,7 @@ module.exports = function(context) {
|
|
15
15
|
var i, token, hasArgumentList = false, numOpen = 0;
|
16
16
|
|
17
17
|
// start at the end of the token stream; skip over argument list contents
|
18
|
-
for(i = tokens.length - 1; i >= 0; --i) {
|
18
|
+
for (i = tokens.length - 1; i >= 0; --i) {
|
19
19
|
token = tokens[i];
|
20
20
|
if (token.value === "(") {
|
21
21
|
--numOpen;
|
@@ -36,11 +36,13 @@ module.exports = function(context) {
|
|
36
36
|
callee = tokens[openParenIndex - 1];
|
37
37
|
|
38
38
|
// openParenIndex will be undefined for a NewExpression with no argument list
|
39
|
-
if (!openParenIndex) {
|
39
|
+
if (!openParenIndex) {
|
40
|
+
return;
|
41
|
+
}
|
40
42
|
|
41
43
|
// look for a space between the callee and the open paren
|
42
44
|
if (callee.range[1] !== openParen.range[0]) {
|
43
|
-
context.report(node, "
|
45
|
+
context.report(node, "Unexpected space between function name and paren.");
|
44
46
|
}
|
45
47
|
}
|
46
48
|
|
@@ -19,9 +19,7 @@ module.exports = function(context) {
|
|
19
19
|
|
20
20
|
"ArrayExpression": function(node) {
|
21
21
|
|
22
|
-
var emptySpot = node.elements.
|
23
|
-
return value === null;
|
24
|
-
});
|
22
|
+
var emptySpot = node.elements.indexOf(null) > -1;
|
25
23
|
|
26
24
|
if (emptySpot) {
|
27
25
|
context.report(node, "Unexpected comma in middle of array.");
|
@@ -12,9 +12,10 @@
|
|
12
12
|
module.exports = function(context) {
|
13
13
|
|
14
14
|
var config = {
|
15
|
-
vars: "
|
15
|
+
vars: "all",
|
16
16
|
args: "after-used"
|
17
17
|
};
|
18
|
+
|
18
19
|
if (context.options[0]) {
|
19
20
|
if (typeof(context.options[0]) === "string") {
|
20
21
|
config.vars = context.options[0];
|
@@ -27,6 +28,7 @@ module.exports = function(context) {
|
|
27
28
|
var allowUnusedGlobals = (config.vars !== "all"),
|
28
29
|
variables = {};
|
29
30
|
|
31
|
+
|
30
32
|
function lookupVariableName(name) {
|
31
33
|
|
32
34
|
// Convoluted check in case name is "hasOwnProperty"
|
@@ -40,9 +42,7 @@ module.exports = function(context) {
|
|
40
42
|
var candidates = lookupVariableName(variable.name);
|
41
43
|
if (candidates) {
|
42
44
|
return candidates.filter(function (candidate) {
|
43
|
-
return variable.identifiers.
|
44
|
-
return candidate.node === identifier;
|
45
|
-
});
|
45
|
+
return variable.identifiers.indexOf(candidate.node) > -1;
|
46
46
|
})[0];
|
47
47
|
}
|
48
48
|
return candidates;
|
@@ -101,6 +101,12 @@ module.exports = function(context) {
|
|
101
101
|
return lookupVariable(scopeVariable[0]);
|
102
102
|
}
|
103
103
|
|
104
|
+
/**
|
105
|
+
* Determines if the given node represents a function.
|
106
|
+
* @param {ASTNode} node The node to check.
|
107
|
+
* @returns {boolean} True if the node represents a function, false if not.
|
108
|
+
* @private
|
109
|
+
*/
|
104
110
|
function isFunction(node) {
|
105
111
|
return node && node.type && (node.type === "FunctionDeclaration" || node.type === "FunctionExpression");
|
106
112
|
}
|
@@ -3,6 +3,12 @@
|
|
3
3
|
* @author Ilya Volodin
|
4
4
|
*/
|
5
5
|
|
6
|
+
//------------------------------------------------------------------------------
|
7
|
+
// Constants
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
var NO_FUNC = "nofunc";
|
11
|
+
|
6
12
|
//------------------------------------------------------------------------------
|
7
13
|
// Rule Definition
|
8
14
|
//------------------------------------------------------------------------------
|
@@ -26,10 +32,13 @@ module.exports = function(context) {
|
|
26
32
|
|
27
33
|
function findVariables() {
|
28
34
|
var scope = context.getScope();
|
35
|
+
var typeOption = context.options[0];
|
29
36
|
|
30
37
|
function checkLocationAndReport(reference, declaration) {
|
31
|
-
if (declaration.
|
32
|
-
|
38
|
+
if (typeOption !== NO_FUNC || declaration.defs[0].type !== "FunctionName") {
|
39
|
+
if (declaration.identifiers[0].range[1] > reference.identifier.range[1]) {
|
40
|
+
context.report(reference.identifier, "{{a}} was used before it was defined", {a: reference.identifier.name});
|
41
|
+
}
|
33
42
|
}
|
34
43
|
}
|
35
44
|
|
package/lib/rules/semi.js
CHANGED
@@ -9,6 +9,8 @@
|
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
module.exports = function(context) {
|
11
11
|
|
12
|
+
var OPT_OUT_PATTERN = /[\[\(\/\+\-]/;
|
13
|
+
|
12
14
|
var always = context.options[0] !== "never";
|
13
15
|
|
14
16
|
//--------------------------------------------------------------------------
|
@@ -21,7 +23,8 @@ module.exports = function(context) {
|
|
21
23
|
* @returns {void}
|
22
24
|
*/
|
23
25
|
function checkForSemicolon(node) {
|
24
|
-
var lastToken = context.getLastToken(node)
|
26
|
+
var lastToken = context.getLastToken(node),
|
27
|
+
nextToken = context.getTokenAfter(node);
|
25
28
|
|
26
29
|
if (always) {
|
27
30
|
if (lastToken.type !== "Punctuator" || lastToken.value !== ";") {
|
@@ -29,7 +32,11 @@ module.exports = function(context) {
|
|
29
32
|
}
|
30
33
|
} else {
|
31
34
|
if (lastToken.type === "Punctuator" && lastToken.value === ";") {
|
32
|
-
|
35
|
+
|
36
|
+
if (!nextToken || !(OPT_OUT_PATTERN.test(nextToken.value))) {
|
37
|
+
context.report(node, node.loc.end, "Extra semicolon.");
|
38
|
+
}
|
39
|
+
|
33
40
|
}
|
34
41
|
}
|
35
42
|
}
|
@@ -69,7 +76,8 @@ module.exports = function(context) {
|
|
69
76
|
|
70
77
|
if (!always) {
|
71
78
|
nextToken = context.getTokenAfter(node) || context.getLastToken(node);
|
72
|
-
|
79
|
+
|
80
|
+
if (!(OPT_OUT_PATTERN.test(nextToken.value))) {
|
73
81
|
context.report(node, "Extra semicolon.");
|
74
82
|
}
|
75
83
|
}
|
package/lib/rules/sort-vars.js
CHANGED
@@ -14,7 +14,7 @@ module.exports = function(context) {
|
|
14
14
|
return {
|
15
15
|
"VariableDeclaration": function(node) {
|
16
16
|
node.declarations.reduce(function(memo, decl) {
|
17
|
-
if(decl.id.name < memo.id.name) {
|
17
|
+
if (decl.id.name < memo.id.name) {
|
18
18
|
context.report(decl, "Variables within the same declaration block should be sorted alphabetically");
|
19
19
|
return memo;
|
20
20
|
} else {
|
@@ -0,0 +1,64 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to enforce the number of spaces after certain keywords
|
3
|
+
* @author Nick Fisher
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Rule Definition
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = function(context) {
|
12
|
+
|
13
|
+
// unless the first option is `"never"`, then a space is required
|
14
|
+
var requiresSpace = context.options[0] !== "never";
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Check if the separation of two adjacent tokens meets the spacing rules, and report a problem if not.
|
18
|
+
*
|
19
|
+
* @param {ASTNode} node The node to which the potential problem belongs.
|
20
|
+
* @param {Token} left The first token.
|
21
|
+
* @param {Token} right The second token
|
22
|
+
* @returns {void}
|
23
|
+
*/
|
24
|
+
function checkTokens(node, left, right) {
|
25
|
+
var hasSpace = left.range[1] < right.range[0],
|
26
|
+
value = left.value;
|
27
|
+
|
28
|
+
if (hasSpace !== requiresSpace) {
|
29
|
+
context.report(node, "Keyword \"{{value}}\" must {{not}}be followed by whitespace.", {
|
30
|
+
value: value,
|
31
|
+
not: requiresSpace ? "" : "not "
|
32
|
+
});
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Check if the given node (`if`, `for`, `while`, etc), has the correct spacing after it.
|
38
|
+
* @param {ASTNode} node The node to check.
|
39
|
+
* @returns {void}
|
40
|
+
*/
|
41
|
+
function check(node) {
|
42
|
+
var tokens = context.getFirstTokens(node, 2);
|
43
|
+
checkTokens(node, tokens[0], tokens[1]);
|
44
|
+
|
45
|
+
// check the `else` of an `if`.
|
46
|
+
if (tokens[0].value === "if" && node.alternate) {
|
47
|
+
checkTokens(node.alternate, context.getTokenBefore(node.alternate), context.getFirstToken(node.alternate));
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
return {
|
52
|
+
"IfStatement": check,
|
53
|
+
"ForStatement": check,
|
54
|
+
"ForOfStatement": check,
|
55
|
+
"ForInStatement": check,
|
56
|
+
"WhileStatement": check,
|
57
|
+
"DoWhileStatement": check,
|
58
|
+
"SwitchStatement": check,
|
59
|
+
"TryStatement": check,
|
60
|
+
"CatchStatement": check,
|
61
|
+
"WithStatement": check
|
62
|
+
};
|
63
|
+
};
|
64
|
+
|
@@ -19,9 +19,9 @@ module.exports = function(context) {
|
|
19
19
|
|
20
20
|
function isSpaced(left, right) {
|
21
21
|
var op, tokens = context.getTokens({range: [left.range[1], right.range[0]]}, 1, 1);
|
22
|
-
for(var i = 1, l = tokens.length - 1; i < l; ++i) {
|
22
|
+
for (var i = 1, l = tokens.length - 1; i < l; ++i) {
|
23
23
|
op = tokens[i];
|
24
|
-
if(
|
24
|
+
if (
|
25
25
|
op.type === "Punctuator" &&
|
26
26
|
OPERATORS.indexOf(op.value) >= 0 &&
|
27
27
|
(tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
|
@@ -34,9 +34,9 @@ module.exports = function(context) {
|
|
34
34
|
|
35
35
|
function isRightSpaced(left, right) {
|
36
36
|
var op, tokens = context.getTokens({range: [left.range[1], right.range[0]]}, 1, 1);
|
37
|
-
for(var i = 1, l = tokens.length - 1; i < l; ++i) {
|
37
|
+
for (var i = 1, l = tokens.length - 1; i < l; ++i) {
|
38
38
|
op = tokens[i];
|
39
|
-
if(
|
39
|
+
if (
|
40
40
|
op.type === "Punctuator" &&
|
41
41
|
OPERATORS.indexOf(op.value) >= 0 &&
|
42
42
|
op.range[1] >= tokens[i + 1].range[0]
|
@@ -52,12 +52,14 @@ module.exports = function(context) {
|
|
52
52
|
}
|
53
53
|
|
54
54
|
function checkBinary(node) {
|
55
|
-
if(!isSpaced(node.left, node.right)) {
|
55
|
+
if (!isSpaced(node.left, node.right)) {
|
56
|
+
report(node);
|
57
|
+
}
|
56
58
|
}
|
57
59
|
|
58
60
|
function checkSequence(node) {
|
59
|
-
for(var i = 0, l = node.expressions.length - 1; i < l; ++i) {
|
60
|
-
if(!isRightSpaced(node.expressions[i], node.expressions[i + 1])) {
|
61
|
+
for (var i = 0, l = node.expressions.length - 1; i < l; ++i) {
|
62
|
+
if (!isRightSpaced(node.expressions[i], node.expressions[i + 1])) {
|
61
63
|
report(node);
|
62
64
|
break;
|
63
65
|
}
|
@@ -65,13 +67,13 @@ module.exports = function(context) {
|
|
65
67
|
}
|
66
68
|
|
67
69
|
function checkConditional(node) {
|
68
|
-
if(!isSpaced(node.test, node.consequent) || !isSpaced(node.consequent, node.alternate)) {
|
70
|
+
if (!isSpaced(node.test, node.consequent) || !isSpaced(node.consequent, node.alternate)) {
|
69
71
|
report(node);
|
70
72
|
}
|
71
73
|
}
|
72
74
|
|
73
75
|
function checkVar(node) {
|
74
|
-
if(node.init && !isSpaced(node.id, node.init)) {
|
76
|
+
if (node.init && !isSpaced(node.id, node.init)) {
|
75
77
|
report(node);
|
76
78
|
}
|
77
79
|
}
|
@@ -14,14 +14,22 @@ module.exports = function(context) {
|
|
14
14
|
var tokens = context.getFirstTokens(node, 2),
|
15
15
|
value = tokens[0].value;
|
16
16
|
|
17
|
-
if(tokens[0].range[1] >= tokens[1].range[0]) {
|
17
|
+
if (tokens[0].range[1] >= tokens[1].range[0]) {
|
18
18
|
context.report(node, "Keyword \"" + value + "\" must be followed by whitespace.");
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
22
|
return {
|
23
|
-
"ReturnStatement": function(node) {
|
24
|
-
|
23
|
+
"ReturnStatement": function(node) {
|
24
|
+
if (node.argument) {
|
25
|
+
check(node);
|
26
|
+
}
|
27
|
+
},
|
28
|
+
"SwitchCase": function(node) {
|
29
|
+
if (node.test) {
|
30
|
+
check(node);
|
31
|
+
}
|
32
|
+
},
|
25
33
|
"ThrowStatement": check
|
26
34
|
};
|
27
35
|
|
@@ -13,14 +13,15 @@ module.exports = function(context) {
|
|
13
13
|
function check(node) {
|
14
14
|
var tokens;
|
15
15
|
tokens = context.getFirstTokens(node, 2);
|
16
|
-
if(tokens[0].range[1] >= tokens[1].range[0]) {
|
17
|
-
switch(tokens[0].value) {
|
16
|
+
if (tokens[0].range[1] >= tokens[1].range[0]) {
|
17
|
+
switch (tokens[0].value) {
|
18
18
|
case "delete":
|
19
19
|
case "new":
|
20
20
|
case "typeof":
|
21
21
|
case "void":
|
22
22
|
context.report(node, "Unary word operator \"" + tokens[0].value + "\" must be followed by whitespace.");
|
23
23
|
break;
|
24
|
+
// no default
|
24
25
|
}
|
25
26
|
}
|
26
27
|
}
|
package/lib/rules/valid-jsdoc.js
CHANGED
@@ -18,7 +18,10 @@ module.exports = function(context) {
|
|
18
18
|
|
19
19
|
var options = context.options[0] || {},
|
20
20
|
prefer = options.prefer || {},
|
21
|
-
|
21
|
+
|
22
|
+
// these both default to true, so you have to explicitly make them false
|
23
|
+
requireReturn = options.requireReturn === false ? false : true,
|
24
|
+
requireParamDescription = options.requireParamDescription === false ? false : true;
|
22
25
|
|
23
26
|
//--------------------------------------------------------------------------
|
24
27
|
// Helpers
|
@@ -27,11 +30,21 @@ module.exports = function(context) {
|
|
27
30
|
// Using a stack to store if a function returns or not (handling nested functions)
|
28
31
|
var fns = [];
|
29
32
|
|
30
|
-
|
33
|
+
/**
|
34
|
+
* When parsing a new function, store it in our function stack.
|
35
|
+
* @returns {void}
|
36
|
+
* @private
|
37
|
+
*/
|
31
38
|
function startFunction() {
|
32
39
|
fns.push({returnPresent: false});
|
33
40
|
}
|
34
41
|
|
42
|
+
/**
|
43
|
+
* Indicate that return has been found in the current function.
|
44
|
+
* @param {ASTNode} node The return node.
|
45
|
+
* @returns {void}
|
46
|
+
* @private
|
47
|
+
*/
|
35
48
|
function addReturn(node) {
|
36
49
|
var functionState = fns[fns.length - 1];
|
37
50
|
|
@@ -44,6 +57,7 @@ module.exports = function(context) {
|
|
44
57
|
* Validate the JSDoc node and output warnings if anything is wrong.
|
45
58
|
* @param {ASTNode} node The AST node to check.
|
46
59
|
* @returns {void}
|
60
|
+
* @private
|
47
61
|
*/
|
48
62
|
function checkJSDoc(node) {
|
49
63
|
var jsdocNode = context.getJSDocComment(node),
|
@@ -82,7 +96,7 @@ module.exports = function(context) {
|
|
82
96
|
context.report(jsdocNode, "Missing JSDoc parameter type for '{{name}}'.", { name: tag.name });
|
83
97
|
}
|
84
98
|
|
85
|
-
if (!tag.description) {
|
99
|
+
if (!tag.description && requireParamDescription) {
|
86
100
|
context.report(jsdocNode, "Missing JSDoc parameter description for '{{name}}'.", { name: tag.name });
|
87
101
|
}
|
88
102
|
|
@@ -115,6 +129,7 @@ module.exports = function(context) {
|
|
115
129
|
hasConstructor = true;
|
116
130
|
break;
|
117
131
|
|
132
|
+
// no default
|
118
133
|
}
|
119
134
|
|
120
135
|
// check tag preferences
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.6.2",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An Esprima-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -32,9 +32,9 @@
|
|
32
32
|
"homepage": "http://eslint.org",
|
33
33
|
"bugs": "https://github.com/eslint/eslint/issues/",
|
34
34
|
"dependencies": {
|
35
|
-
"optionator": "
|
35
|
+
"optionator": "^0.4.0",
|
36
36
|
"estraverse": "~1.3.0",
|
37
|
-
"esprima": "
|
37
|
+
"esprima": "^1.2.0",
|
38
38
|
"escope": "~1.0.0",
|
39
39
|
"glob": "~3.2.7",
|
40
40
|
"text-table": "~0.2.0",
|
@@ -55,7 +55,7 @@
|
|
55
55
|
"browserify": "~3.20.0",
|
56
56
|
"mocha-phantomjs": "~3.3.1",
|
57
57
|
"phantomjs": "~1.9.2-6",
|
58
|
-
"eslint-tester": "
|
58
|
+
"eslint-tester": "^0.1.0",
|
59
59
|
"brfs": "0.0.9",
|
60
60
|
"through": "~2.3.4",
|
61
61
|
"beefy": "~1.0.0",
|
@@ -68,5 +68,8 @@
|
|
68
68
|
"ecmascript"
|
69
69
|
],
|
70
70
|
"preferGlobal": true,
|
71
|
-
"license": "MIT"
|
71
|
+
"license": "MIT",
|
72
|
+
"engines": {
|
73
|
+
"node": ">=0.10"
|
74
|
+
}
|
72
75
|
}
|