eslint 1.9.0 → 1.10.3
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 +1 -1
- package/bin/eslint.js +1 -2
- package/lib/ast-utils.js +22 -1
- package/lib/cli-engine.js +15 -7
- package/lib/cli.js +2 -1
- package/lib/config/config-file.js +440 -0
- package/lib/config/config-initializer.js +241 -0
- package/lib/config/config-ops.js +186 -0
- package/lib/{config-validator.js → config/config-validator.js} +10 -2
- package/lib/config.js +39 -183
- package/lib/eslint.js +49 -41
- package/lib/file-finder.js +34 -15
- package/lib/ignored-paths.js +1 -1
- package/lib/options.js +7 -1
- package/lib/rules/block-spacing.js +7 -2
- package/lib/rules/brace-style.js +3 -1
- package/lib/rules/comma-spacing.js +25 -66
- package/lib/rules/consistent-this.js +25 -29
- package/lib/rules/curly.js +37 -7
- package/lib/rules/eqeqeq.js +17 -2
- package/lib/rules/id-length.js +2 -2
- package/lib/rules/indent.js +7 -10
- package/lib/rules/lines-around-comment.js +32 -12
- package/lib/rules/new-cap.js +11 -1
- package/lib/rules/no-alert.js +2 -3
- package/lib/rules/no-catch-shadow.js +7 -13
- package/lib/rules/no-extend-native.js +1 -2
- package/lib/rules/no-fallthrough.js +1 -2
- package/lib/rules/no-implicit-coercion.js +19 -0
- package/lib/rules/no-label-var.js +9 -23
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-sequences.js +2 -1
- package/lib/rules/no-shadow.js +31 -58
- package/lib/rules/no-spaced-func.js +16 -12
- package/lib/rules/no-undef-init.js +5 -3
- package/lib/rules/no-undef.js +10 -13
- package/lib/rules/no-use-before-define.js +7 -21
- package/lib/rules/operator-linebreak.js +3 -2
- package/lib/rules/quotes.js +34 -15
- package/lib/rules/require-jsdoc.js +61 -2
- package/lib/rules/space-after-keywords.js +2 -0
- package/lib/rules/space-before-function-paren.js +5 -26
- package/lib/rules/space-before-keywords.js +5 -2
- package/lib/rules/spaced-comment.js +1 -3
- package/lib/rules/valid-jsdoc.js +8 -4
- package/lib/rules/vars-on-top.js +2 -2
- package/lib/testers/rule-tester.js +48 -7
- package/lib/util/source-code.js +4 -0
- package/lib/util.js +0 -92
- package/package.json +4 -6
- package/lib/config-initializer.js +0 -146
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
var astUtils = require("../ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -18,32 +24,12 @@ module.exports = function(context) {
|
|
18
24
|
/**
|
19
25
|
* Check if the identifier is present inside current scope
|
20
26
|
* @param {object} scope current scope
|
21
|
-
* @param {
|
27
|
+
* @param {string} name To evaluate
|
22
28
|
* @returns {boolean} True if its present
|
23
29
|
* @private
|
24
30
|
*/
|
25
|
-
function findIdentifier(scope,
|
26
|
-
|
27
|
-
|
28
|
-
scope.variables.forEach(function(variable) {
|
29
|
-
if (variable.name === identifier) {
|
30
|
-
found = true;
|
31
|
-
}
|
32
|
-
});
|
33
|
-
|
34
|
-
scope.references.forEach(function(reference) {
|
35
|
-
if (reference.identifier.name === identifier) {
|
36
|
-
found = true;
|
37
|
-
}
|
38
|
-
});
|
39
|
-
|
40
|
-
// If we have not found the identifier in this scope, check the parent
|
41
|
-
// scope.
|
42
|
-
if (scope.upper && !found) {
|
43
|
-
return findIdentifier(scope.upper, identifier);
|
44
|
-
}
|
45
|
-
|
46
|
-
return found;
|
31
|
+
function findIdentifier(scope, name) {
|
32
|
+
return astUtils.getVariableByName(scope, name) !== null;
|
47
33
|
}
|
48
34
|
|
49
35
|
//--------------------------------------------------------------------------
|
@@ -88,7 +88,7 @@ module.exports = function(context) {
|
|
88
88
|
// within the file, not at the end
|
89
89
|
if (blankCounter >= max) {
|
90
90
|
context.report(node, location,
|
91
|
-
"More than " + max + " blank lines not allowed.");
|
91
|
+
"More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed.");
|
92
92
|
}
|
93
93
|
} else {
|
94
94
|
// inside the last blank lines
|
@@ -85,7 +85,8 @@ module.exports = function(context) {
|
|
85
85
|
}
|
86
86
|
}
|
87
87
|
|
88
|
-
context.
|
88
|
+
var child = context.getTokenAfter(node.expressions[0]);
|
89
|
+
context.report(node, child.loc.start, "Unexpected use of comma operator.");
|
89
90
|
}
|
90
91
|
};
|
91
92
|
|
package/lib/rules/no-shadow.js
CHANGED
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Requirements
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
var astUtils = require("../ast-utils");
|
14
|
+
|
9
15
|
//------------------------------------------------------------------------------
|
10
16
|
// Rule Definition
|
11
17
|
//------------------------------------------------------------------------------
|
@@ -99,70 +105,37 @@ module.exports = function(context) {
|
|
99
105
|
);
|
100
106
|
}
|
101
107
|
|
102
|
-
/**
|
103
|
-
* Checks if a variable is contained in the list of given scope variables.
|
104
|
-
* @param {Object} variable The variable to check.
|
105
|
-
* @param {Array} scopeVars The scope variables to look for.
|
106
|
-
* @returns {boolean} Whether or not the variable is contains in the list of scope variables.
|
107
|
-
*/
|
108
|
-
function isContainedInScopeVars(variable, scopeVars) {
|
109
|
-
return scopeVars.some(function(scopeVar) {
|
110
|
-
return (
|
111
|
-
(scopeVar.identifiers.length > 0 || (options.builtinGlobals && "writeable" in scopeVar)) &&
|
112
|
-
variable.name === scopeVar.name &&
|
113
|
-
!isDuplicatedClassNameVariable(scopeVar) &&
|
114
|
-
!isOnInitializer(variable, scopeVar) &&
|
115
|
-
!(options.hoist !== "all" && isInTdz(variable, scopeVar))
|
116
|
-
);
|
117
|
-
});
|
118
|
-
}
|
119
|
-
|
120
|
-
/**
|
121
|
-
* Checks if the given variables are shadowed in the given scope.
|
122
|
-
* @param {Array} variables The variables to look for
|
123
|
-
* @param {Object} scope The scope to be checked.
|
124
|
-
* @returns {Array} Variables which are not declared in the given scope.
|
125
|
-
*/
|
126
|
-
function checkShadowsInScope(variables, scope) {
|
127
|
-
|
128
|
-
var passedVars = [];
|
129
|
-
|
130
|
-
variables.forEach(function(variable) {
|
131
|
-
// "arguments" is a special case that has no identifiers (#1759)
|
132
|
-
if (variable.identifiers.length > 0 && isContainedInScopeVars(variable, scope.variables)) {
|
133
|
-
context.report(
|
134
|
-
variable.identifiers[0],
|
135
|
-
"\"{{name}}\" is already declared in the upper scope.",
|
136
|
-
{name: variable.name});
|
137
|
-
} else {
|
138
|
-
passedVars.push(variable);
|
139
|
-
}
|
140
|
-
});
|
141
|
-
|
142
|
-
return passedVars;
|
143
|
-
}
|
144
|
-
|
145
108
|
/**
|
146
109
|
* Checks the current context for shadowed variables.
|
147
110
|
* @param {Scope} scope - Fixme
|
148
111
|
* @returns {void}
|
149
112
|
*/
|
150
113
|
function checkForShadows(scope) {
|
151
|
-
var variables = scope.variables
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
114
|
+
var variables = scope.variables;
|
115
|
+
for (var i = 0; i < variables.length; ++i) {
|
116
|
+
var variable = variables[i];
|
117
|
+
|
118
|
+
// Skips "arguments" or variables of a class name in the class scope of ClassDeclaration.
|
119
|
+
if (variable.identifiers.length === 0 ||
|
120
|
+
isDuplicatedClassNameVariable(variable) ||
|
121
|
+
isAllowed(variable)
|
122
|
+
) {
|
123
|
+
continue;
|
124
|
+
}
|
125
|
+
|
126
|
+
// Gets shadowed variable.
|
127
|
+
var shadowed = astUtils.getVariableByName(scope.upper, variable.name);
|
128
|
+
if (shadowed &&
|
129
|
+
(shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) &&
|
130
|
+
!isOnInitializer(variable, shadowed) &&
|
131
|
+
!(options.hoist !== "all" && isInTdz(variable, shadowed))
|
132
|
+
) {
|
133
|
+
context.report({
|
134
|
+
node: variable.identifiers[0],
|
135
|
+
message: "\"{{name}}\" is already declared in the upper scope.",
|
136
|
+
data: variable
|
137
|
+
});
|
138
|
+
}
|
166
139
|
}
|
167
140
|
}
|
168
141
|
|
@@ -21,26 +21,30 @@ module.exports = function(context) {
|
|
21
21
|
*/
|
22
22
|
function detectOpenSpaces(node) {
|
23
23
|
var lastCalleeToken = sourceCode.getLastToken(node.callee),
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
while (
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
prevToken = lastCalleeToken,
|
25
|
+
parenToken = sourceCode.getTokenAfter(lastCalleeToken);
|
26
|
+
|
27
|
+
// advances to an open parenthesis.
|
28
|
+
while (
|
29
|
+
parenToken &&
|
30
|
+
parenToken.range[1] < node.range[1] &&
|
31
|
+
parenToken.value !== "("
|
32
|
+
) {
|
33
|
+
prevToken = parenToken;
|
34
|
+
parenToken = sourceCode.getTokenAfter(parenToken);
|
34
35
|
}
|
35
36
|
|
36
37
|
// look for a space between the callee and the open paren
|
37
|
-
if (
|
38
|
+
if (parenToken &&
|
39
|
+
parenToken.range[1] < node.range[1] &&
|
40
|
+
sourceCode.isSpaceBetweenTokens(prevToken, parenToken)
|
41
|
+
) {
|
38
42
|
context.report({
|
39
43
|
node: node,
|
40
44
|
loc: lastCalleeToken.loc.start,
|
41
45
|
message: "Unexpected space between function name and paren.",
|
42
46
|
fix: function(fixer) {
|
43
|
-
return fixer.removeRange([
|
47
|
+
return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
|
44
48
|
}
|
45
49
|
});
|
46
50
|
}
|
@@ -1,6 +1,8 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to flag when initializing to undefined
|
3
3
|
* @author Ilya Volodin
|
4
|
+
* @copyright 2013 Ilya Volodin. All rights reserved.
|
5
|
+
* See LICENSE in root directory for full license.
|
4
6
|
*/
|
5
7
|
|
6
8
|
"use strict";
|
@@ -14,10 +16,10 @@ module.exports = function(context) {
|
|
14
16
|
return {
|
15
17
|
|
16
18
|
"VariableDeclarator": function(node) {
|
17
|
-
var name = node.id.name
|
18
|
-
|
19
|
+
var name = node.id.name,
|
20
|
+
init = node.init && node.init.name;
|
19
21
|
|
20
|
-
if (init === "undefined") {
|
22
|
+
if (init === "undefined" && node.parent.kind !== "const") {
|
21
23
|
context.report(node, "It's not necessary to initialize '{{name}}' to undefined.", { name: name });
|
22
24
|
}
|
23
25
|
}
|
package/lib/rules/no-undef.js
CHANGED
@@ -10,12 +10,14 @@
|
|
10
10
|
// Requirements
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
|
-
|
13
|
+
var astUtils = require("../ast-utils");
|
14
14
|
|
15
15
|
//------------------------------------------------------------------------------
|
16
16
|
// Helpers
|
17
17
|
//------------------------------------------------------------------------------
|
18
18
|
|
19
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
20
|
+
|
19
21
|
/**
|
20
22
|
* Check if a variable is an implicit declaration
|
21
23
|
* @param {ASTNode} variable node to evaluate
|
@@ -35,18 +37,13 @@ function isImplicitGlobal(variable) {
|
|
35
37
|
* @returns {Variable} The variable, or null if ref refers to an undeclared variable.
|
36
38
|
*/
|
37
39
|
function getDeclaredGlobalVariable(scope, ref) {
|
38
|
-
var
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
}
|
46
|
-
}
|
47
|
-
return false;
|
48
|
-
});
|
49
|
-
return declaredGlobal;
|
40
|
+
var variable = astUtils.getVariableByName(scope, ref.identifier.name);
|
41
|
+
|
42
|
+
// If it's an implicit global, it must have a `writeable` field (indicating it was declared)
|
43
|
+
if (variable && (!isImplicitGlobal(variable) || hasOwnProperty.call(variable, "writeable"))) {
|
44
|
+
return variable;
|
45
|
+
}
|
46
|
+
return null;
|
50
47
|
}
|
51
48
|
|
52
49
|
/**
|
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Requirements
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
var astUtils = require("../ast-utils");
|
14
|
+
|
9
15
|
//------------------------------------------------------------------------------
|
10
16
|
// Constants
|
11
17
|
//------------------------------------------------------------------------------
|
@@ -18,26 +24,6 @@ var NO_FUNC = "nofunc";
|
|
18
24
|
|
19
25
|
module.exports = function(context) {
|
20
26
|
|
21
|
-
/**
|
22
|
-
* Finds variable declarations in a given scope.
|
23
|
-
* @param {string} name The variable name to find.
|
24
|
-
* @param {Scope} scope The scope to search in.
|
25
|
-
* @returns {Object} The variable declaration object.
|
26
|
-
* @private
|
27
|
-
*/
|
28
|
-
function findDeclaration(name, scope) {
|
29
|
-
// try searching in the current scope first
|
30
|
-
for (var i = 0, l = scope.variables.length; i < l; i++) {
|
31
|
-
if (scope.variables[i].name === name) {
|
32
|
-
return scope.variables[i];
|
33
|
-
}
|
34
|
-
}
|
35
|
-
// check if there's upper scope and call recursivly till we find the variable
|
36
|
-
if (scope.upper) {
|
37
|
-
return findDeclaration(name, scope.upper);
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
27
|
/**
|
42
28
|
* Finds and validates all variables in a given scope.
|
43
29
|
* @param {Scope} scope The scope object.
|
@@ -68,7 +54,7 @@ module.exports = function(context) {
|
|
68
54
|
if (reference.resolved && reference.resolved.identifiers.length > 0) {
|
69
55
|
checkLocationAndReport(reference, reference.resolved);
|
70
56
|
} else {
|
71
|
-
var declaration =
|
57
|
+
var declaration = astUtils.getVariableByName(scope, reference.identifier.name);
|
72
58
|
// if there're no identifiers, this is a global environment variable
|
73
59
|
if (declaration && declaration.identifiers.length !== 0) {
|
74
60
|
checkLocationAndReport(reference, declaration);
|
@@ -6,7 +6,8 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
-
var
|
9
|
+
var assign = require("object-assign"),
|
10
|
+
astUtils = require("../ast-utils");
|
10
11
|
|
11
12
|
//------------------------------------------------------------------------------
|
12
13
|
// Rule Definition
|
@@ -17,7 +18,7 @@ module.exports = function(context) {
|
|
17
18
|
var usedDefaultGlobal = !context.options[0];
|
18
19
|
var globalStyle = context.options[0] || "after";
|
19
20
|
var options = context.options[1] || {};
|
20
|
-
var styleOverrides = options.overrides
|
21
|
+
var styleOverrides = options.overrides ? assign({}, options.overrides) : {};
|
21
22
|
|
22
23
|
if (usedDefaultGlobal && !styleOverrides["?"]) {
|
23
24
|
styleOverrides["?"] = "before";
|
package/lib/rules/quotes.js
CHANGED
@@ -11,9 +11,7 @@
|
|
11
11
|
// Requirements
|
12
12
|
//------------------------------------------------------------------------------
|
13
13
|
|
14
|
-
var astUtils = require("../ast-utils")
|
15
|
-
toSingleQuotes = require("to-single-quotes"),
|
16
|
-
toDoubleQuotes = require("to-double-quotes");
|
14
|
+
var astUtils = require("../ast-utils");
|
17
15
|
|
18
16
|
//------------------------------------------------------------------------------
|
19
17
|
// Constants
|
@@ -23,27 +21,48 @@ var QUOTE_SETTINGS = {
|
|
23
21
|
"double": {
|
24
22
|
quote: "\"",
|
25
23
|
alternateQuote: "'",
|
26
|
-
description: "doublequote"
|
27
|
-
convert: function(str) {
|
28
|
-
return toDoubleQuotes(str);
|
29
|
-
}
|
24
|
+
description: "doublequote"
|
30
25
|
},
|
31
26
|
"single": {
|
32
27
|
quote: "'",
|
33
28
|
alternateQuote: "\"",
|
34
|
-
description: "singlequote"
|
35
|
-
convert: function(str) {
|
36
|
-
return toSingleQuotes(str);
|
37
|
-
}
|
29
|
+
description: "singlequote"
|
38
30
|
},
|
39
31
|
"backtick": {
|
40
32
|
quote: "`",
|
41
33
|
alternateQuote: "\"",
|
42
|
-
description: "backtick"
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
description: "backtick"
|
35
|
+
}
|
36
|
+
};
|
37
|
+
/**
|
38
|
+
* Switches quoting of javascript string between ' " and `
|
39
|
+
* escaping and unescaping as necessary.
|
40
|
+
* Only escaping of the minimal set of characters is changed.
|
41
|
+
* Note: escaping of newlines when switching from backtick to other quotes is not handled.
|
42
|
+
* @param {string} str - A string to convert.
|
43
|
+
* @returns {string} The string with changed quotes.
|
44
|
+
* @private
|
45
|
+
*/
|
46
|
+
QUOTE_SETTINGS.double.convert =
|
47
|
+
QUOTE_SETTINGS.single.convert =
|
48
|
+
QUOTE_SETTINGS.backtick.convert = function(str) {
|
49
|
+
var newQuote = this.quote;
|
50
|
+
var oldQuote = str[0];
|
51
|
+
if (newQuote === oldQuote) {
|
52
|
+
return str;
|
46
53
|
}
|
54
|
+
return newQuote + str.slice(1, -1).replace(/\\(\${|\r\n?|\n|.)|["'`]|\${|(\r\n?|\n)/g, function(match, escaped, newline) {
|
55
|
+
if (escaped === oldQuote || oldQuote === "`" && escaped === "${") {
|
56
|
+
return escaped; // unescape
|
57
|
+
}
|
58
|
+
if (match === newQuote || newQuote === "`" && match === "${") {
|
59
|
+
return "\\" + match; // escape
|
60
|
+
}
|
61
|
+
if (newline && oldQuote === "`") {
|
62
|
+
return "\\n"; // escape newlines
|
63
|
+
}
|
64
|
+
return match;
|
65
|
+
}) + newQuote;
|
47
66
|
};
|
48
67
|
|
49
68
|
var AVOID_ESCAPE = "avoid-escape",
|
@@ -5,8 +5,16 @@
|
|
5
5
|
*/
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
var assign = require("object-assign");
|
9
|
+
|
8
10
|
module.exports = function(context) {
|
9
11
|
var source = context.getSourceCode();
|
12
|
+
var DEFAULT_OPTIONS = {
|
13
|
+
"FunctionDeclaration": true,
|
14
|
+
"MethodDefinition": false,
|
15
|
+
"ClassDeclaration": false
|
16
|
+
};
|
17
|
+
var options = assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {});
|
10
18
|
|
11
19
|
/**
|
12
20
|
* Report the error message
|
@@ -17,6 +25,21 @@ module.exports = function(context) {
|
|
17
25
|
context.report(node, "Missing JSDoc comment.");
|
18
26
|
}
|
19
27
|
|
28
|
+
/**
|
29
|
+
* Check if the jsdoc comment is present for class methods
|
30
|
+
* @param {ASTNode} node node to examine
|
31
|
+
* @returns {void}
|
32
|
+
*/
|
33
|
+
function checkClassMethodJsDoc(node) {
|
34
|
+
if (node.parent.type === "MethodDefinition") {
|
35
|
+
var jsdocComment = source.getJSDocComment(node);
|
36
|
+
|
37
|
+
if (!jsdocComment) {
|
38
|
+
report(node);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
20
43
|
/**
|
21
44
|
* Check if the jsdoc comment is present or not.
|
22
45
|
* @param {ASTNode} node node to examine
|
@@ -31,8 +54,44 @@ module.exports = function(context) {
|
|
31
54
|
}
|
32
55
|
|
33
56
|
return {
|
34
|
-
"FunctionDeclaration":
|
57
|
+
"FunctionDeclaration": function(node) {
|
58
|
+
if (options.FunctionDeclaration) {
|
59
|
+
checkJsDoc(node);
|
60
|
+
}
|
61
|
+
},
|
62
|
+
"FunctionExpression": function(node) {
|
63
|
+
if (options.MethodDefinition) {
|
64
|
+
checkClassMethodJsDoc(node);
|
65
|
+
}
|
66
|
+
},
|
67
|
+
"ClassDeclaration": function(node) {
|
68
|
+
if (options.ClassDeclaration) {
|
69
|
+
checkJsDoc(node);
|
70
|
+
}
|
71
|
+
}
|
35
72
|
};
|
36
73
|
};
|
37
74
|
|
38
|
-
module.exports.schema = [
|
75
|
+
module.exports.schema = [
|
76
|
+
{
|
77
|
+
"type": "object",
|
78
|
+
"properties": {
|
79
|
+
"require": {
|
80
|
+
"type": "object",
|
81
|
+
"properties": {
|
82
|
+
"ClassDeclaration": {
|
83
|
+
"type": "boolean"
|
84
|
+
},
|
85
|
+
"MethodDefinition": {
|
86
|
+
"type": "boolean"
|
87
|
+
},
|
88
|
+
"FunctionDeclaration": {
|
89
|
+
"type": "boolean"
|
90
|
+
}
|
91
|
+
},
|
92
|
+
"additionalProperties": false
|
93
|
+
}
|
94
|
+
},
|
95
|
+
"additionalProperties": false
|
96
|
+
}
|
97
|
+
];
|
@@ -33,6 +33,7 @@ module.exports = function(context) {
|
|
33
33
|
if (hasSpace !== requiresSpace) {
|
34
34
|
context.report({
|
35
35
|
node: node,
|
36
|
+
loc: left.loc.end,
|
36
37
|
message: "Keyword \"{{value}}\" must {{not}}be followed by whitespace.",
|
37
38
|
data: {
|
38
39
|
value: value,
|
@@ -49,6 +50,7 @@ module.exports = function(context) {
|
|
49
50
|
} else if (left.loc.end.line !== right.loc.start.line) {
|
50
51
|
context.report({
|
51
52
|
node: node,
|
53
|
+
loc: left.loc.end,
|
52
54
|
message: "Keyword \"{{value}}\" must not be followed by a newline.",
|
53
55
|
data: {
|
54
56
|
value: value
|
@@ -37,7 +37,7 @@ module.exports = function(context) {
|
|
37
37
|
return true;
|
38
38
|
}
|
39
39
|
|
40
|
-
parent =
|
40
|
+
parent = node.parent;
|
41
41
|
return parent.type === "MethodDefinition" ||
|
42
42
|
(parent.type === "Property" &&
|
43
43
|
(
|
@@ -55,7 +55,6 @@ module.exports = function(context) {
|
|
55
55
|
*/
|
56
56
|
function validateSpacingBeforeParentheses(node) {
|
57
57
|
var isNamed = isNamedFunction(node),
|
58
|
-
tokens,
|
59
58
|
leftToken,
|
60
59
|
rightToken,
|
61
60
|
location;
|
@@ -64,31 +63,11 @@ module.exports = function(context) {
|
|
64
63
|
return;
|
65
64
|
}
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
if (node.id) {
|
71
|
-
leftToken = tokens[2];
|
72
|
-
rightToken = tokens[3];
|
73
|
-
} else {
|
74
|
-
// Object methods are named but don't have an id
|
75
|
-
leftToken = context.getTokenBefore(node);
|
76
|
-
rightToken = tokens[0];
|
77
|
-
}
|
78
|
-
} else if (isNamed) {
|
79
|
-
if (node.id) {
|
80
|
-
leftToken = tokens[1];
|
81
|
-
rightToken = tokens[2];
|
82
|
-
} else {
|
83
|
-
// Object methods are named but don't have an id
|
84
|
-
leftToken = context.getTokenBefore(node);
|
85
|
-
rightToken = tokens[0];
|
86
|
-
}
|
87
|
-
} else {
|
88
|
-
leftToken = tokens[0];
|
89
|
-
rightToken = tokens[1];
|
66
|
+
rightToken = sourceCode.getFirstToken(node);
|
67
|
+
while (rightToken.value !== "(") {
|
68
|
+
rightToken = sourceCode.getTokenAfter(rightToken);
|
90
69
|
}
|
91
|
-
|
70
|
+
leftToken = context.getTokenBefore(rightToken);
|
92
71
|
location = leftToken.loc.end;
|
93
72
|
|
94
73
|
if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
|
@@ -134,7 +134,10 @@ module.exports = function(context) {
|
|
134
134
|
check(node);
|
135
135
|
// else
|
136
136
|
if (node.alternate) {
|
137
|
-
|
137
|
+
var tokens = context.getTokensBefore(node.alternate, 2);
|
138
|
+
if (tokens[0].value === "}") {
|
139
|
+
check(tokens[1], { requireSpace: SPACE_REQUIRED });
|
140
|
+
}
|
138
141
|
}
|
139
142
|
},
|
140
143
|
"ForStatement": check,
|
@@ -185,7 +188,7 @@ module.exports = function(context) {
|
|
185
188
|
return;
|
186
189
|
}
|
187
190
|
|
188
|
-
checkTokens(node, left, right, { allowedPrecedingChars: [ "(", "{" ] });
|
191
|
+
checkTokens(node, left, right, { allowedPrecedingChars: [ "(", "{", "[" ] });
|
189
192
|
},
|
190
193
|
"YieldExpression": function(node) {
|
191
194
|
check(node, { allowedPrecedingChars: [ "(", "{" ] });
|
@@ -41,9 +41,7 @@ function escapeAndRepeat(s) {
|
|
41
41
|
* @returns {string[]} A marker list.
|
42
42
|
*/
|
43
43
|
function parseMarkersOption(markers) {
|
44
|
-
|
45
|
-
markers = [];
|
46
|
-
}
|
44
|
+
markers = markers ? markers.slice(0) : [];
|
47
45
|
|
48
46
|
// `*` is a marker for JSDoc comments.
|
49
47
|
if (markers.indexOf("*") === -1) {
|
package/lib/rules/valid-jsdoc.js
CHANGED
@@ -24,7 +24,8 @@ module.exports = function(context) {
|
|
24
24
|
// these both default to true, so you have to explicitly make them false
|
25
25
|
requireReturn = options.requireReturn !== false,
|
26
26
|
requireParamDescription = options.requireParamDescription !== false,
|
27
|
-
requireReturnDescription = options.requireReturnDescription !== false
|
27
|
+
requireReturnDescription = options.requireReturnDescription !== false,
|
28
|
+
requireReturnType = options.requireReturnType !== false;
|
28
29
|
|
29
30
|
//--------------------------------------------------------------------------
|
30
31
|
// Helpers
|
@@ -77,7 +78,7 @@ module.exports = function(context) {
|
|
77
78
|
* @private
|
78
79
|
*/
|
79
80
|
function isValidReturnType(tag) {
|
80
|
-
return tag.type.name === "void" || tag.type.type === "UndefinedLiteral";
|
81
|
+
return tag.type === null || tag.type.name === "void" || tag.type.type === "UndefinedLiteral";
|
81
82
|
}
|
82
83
|
|
83
84
|
/**
|
@@ -141,10 +142,10 @@ module.exports = function(context) {
|
|
141
142
|
case "returns":
|
142
143
|
hasReturns = true;
|
143
144
|
|
144
|
-
if (!requireReturn && !functionData.returnPresent && tag.type
|
145
|
+
if (!requireReturn && !functionData.returnPresent && (tag.type === null || !isValidReturnType(tag))) {
|
145
146
|
context.report(jsdocNode, "Unexpected @" + tag.title + " tag; function has no return statement.");
|
146
147
|
} else {
|
147
|
-
if (!tag.type) {
|
148
|
+
if (requireReturnType && !tag.type) {
|
148
149
|
context.report(jsdocNode, "Missing JSDoc return type.");
|
149
150
|
}
|
150
151
|
|
@@ -258,6 +259,9 @@ module.exports.schema = [
|
|
258
259
|
},
|
259
260
|
"matchDescription": {
|
260
261
|
"type": "string"
|
262
|
+
},
|
263
|
+
"requireReturnType": {
|
264
|
+
"type": "boolean"
|
261
265
|
}
|
262
266
|
},
|
263
267
|
"additionalProperties": false
|