eslint 4.2.0 → 4.5.0

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/bin/eslint.js +5 -4
  3. package/conf/category-list.json +2 -2
  4. package/conf/config-schema.js +3 -1
  5. package/conf/eslint-recommended.js +11 -14
  6. package/lib/config/config-file.js +5 -5
  7. package/lib/config/config-initializer.js +123 -14
  8. package/lib/config/config-validator.js +25 -1
  9. package/lib/config/plugins.js +13 -1
  10. package/lib/formatters/junit.js +2 -8
  11. package/lib/formatters/stylish.js +2 -1
  12. package/lib/linter.js +21 -13
  13. package/lib/rule-context.js +53 -41
  14. package/lib/rules/arrow-parens.js +1 -1
  15. package/lib/rules/curly.js +1 -1
  16. package/lib/rules/getter-return.js +34 -9
  17. package/lib/rules/id-blacklist.js +7 -3
  18. package/lib/rules/id-match.js +8 -4
  19. package/lib/rules/indent-legacy.js +2 -2
  20. package/lib/rules/indent.js +451 -380
  21. package/lib/rules/key-spacing.js +2 -2
  22. package/lib/rules/no-cond-assign.js +7 -3
  23. package/lib/rules/no-constant-condition.js +62 -6
  24. package/lib/rules/no-else-return.js +1 -1
  25. package/lib/rules/no-extra-parens.js +3 -1
  26. package/lib/rules/no-inner-declarations.js +8 -4
  27. package/lib/rules/no-multi-spaces.js +53 -115
  28. package/lib/rules/no-regex-spaces.js +2 -2
  29. package/lib/rules/no-restricted-globals.js +50 -9
  30. package/lib/rules/no-restricted-properties.js +19 -11
  31. package/lib/rules/no-tabs.js +8 -4
  32. package/lib/rules/no-underscore-dangle.js +28 -1
  33. package/lib/rules/object-curly-newline.js +18 -0
  34. package/lib/rules/object-curly-spacing.js +1 -1
  35. package/lib/rules/padded-blocks.js +2 -2
  36. package/lib/rules/padding-line-between-statements.js +1 -1
  37. package/lib/rules/prefer-destructuring.js +70 -32
  38. package/lib/rules/prefer-numeric-literals.js +36 -7
  39. package/lib/rules/prefer-reflect.js +8 -4
  40. package/lib/rules/prefer-template.js +2 -2
  41. package/lib/rules/space-infix-ops.js +1 -1
  42. package/lib/rules/spaced-comment.js +2 -2
  43. package/lib/rules/valid-jsdoc.js +15 -7
  44. package/lib/testers/rule-tester.js +13 -21
  45. package/lib/testers/test-parser.js +48 -0
  46. package/lib/util/npm-util.js +9 -8
  47. package/package.json +11 -6
@@ -20,6 +20,7 @@ const PASSTHROUGHS = [
20
20
  "getDeclaredVariables",
21
21
  "getFilename",
22
22
  "getScope",
23
+ "getSourceCode",
23
24
  "markVariableAsUsed",
24
25
 
25
26
  // DEPRECATED
@@ -58,7 +59,7 @@ const PASSTHROUGHS = [
58
59
  */
59
60
 
60
61
  //------------------------------------------------------------------------------
61
- // Rule Definition
62
+ // Module Definition
62
63
  //------------------------------------------------------------------------------
63
64
 
64
65
  /**
@@ -132,13 +133,13 @@ function getFix(descriptor, sourceCode) {
132
133
 
133
134
  /**
134
135
  * Rule context class
135
- * Acts as an abstraction layer between rules and the main eslint object.
136
+ * Acts as an abstraction layer between rules and the main linter object.
136
137
  */
137
138
  class RuleContext {
138
139
 
139
140
  /**
140
141
  * @param {string} ruleId The ID of the rule using this object.
141
- * @param {eslint} eslint The eslint object.
142
+ * @param {Linter} linter The linter object.
142
143
  * @param {number} severity The configured severity level of the rule.
143
144
  * @param {Array} options The configuration information to be added to the rule.
144
145
  * @param {Object} settings The configuration settings passed from the config file.
@@ -147,7 +148,7 @@ class RuleContext {
147
148
  * @param {Object} meta The metadata of the rule
148
149
  * @param {Object} parserServices The parser services for the rule.
149
150
  */
150
- constructor(ruleId, eslint, severity, options, settings, parserOptions, parserPath, meta, parserServices) {
151
+ constructor(ruleId, linter, severity, options, settings, parserOptions, parserPath, meta, parserServices) {
151
152
 
152
153
  // public.
153
154
  this.id = ruleId;
@@ -161,22 +162,14 @@ class RuleContext {
161
162
  this.parserServices = Object.freeze(Object.assign({}, parserServices));
162
163
 
163
164
  // private.
164
- this.eslint = eslint;
165
- this.severity = severity;
165
+ this._linter = linter;
166
+ this._severity = severity;
166
167
 
167
168
  Object.freeze(this);
168
169
  }
169
170
 
170
171
  /**
171
- * Passthrough to eslint.getSourceCode().
172
- * @returns {SourceCode} The SourceCode object for the code.
173
- */
174
- getSourceCode() {
175
- return this.eslint.getSourceCode();
176
- }
177
-
178
- /**
179
- * Passthrough to eslint.report() that automatically assigns the rule ID and severity.
172
+ * Passthrough to Linter#report() that automatically assigns the rule ID and severity.
180
173
  * @param {ASTNode|MessageDescriptor} nodeOrDescriptor The AST node related to the message or a message
181
174
  * descriptor.
182
175
  * @param {Object=} location The location of the error.
@@ -192,38 +185,57 @@ class RuleContext {
192
185
  const descriptor = nodeOrDescriptor;
193
186
  const fix = getFix(descriptor, this.getSourceCode());
194
187
 
195
- this.eslint.report(
188
+ if (descriptor.loc) {
189
+ this._linter.report(
190
+ this.id,
191
+ this._severity,
192
+ descriptor.node,
193
+ descriptor.loc,
194
+ descriptor.message,
195
+ descriptor.data,
196
+ fix,
197
+ this.meta
198
+ );
199
+ } else {
200
+ this._linter.report(
201
+ this.id,
202
+ this._severity,
203
+ descriptor.node,
204
+
205
+ /* loc not provided */
206
+ descriptor.message,
207
+ descriptor.data,
208
+ fix,
209
+ this.meta
210
+ );
211
+ }
212
+
213
+ } else {
214
+
215
+ // old style call
216
+ this._linter.report(
196
217
  this.id,
197
- this.severity,
198
- descriptor.node,
199
- descriptor.loc || descriptor.node.loc.start,
200
- descriptor.message,
201
- descriptor.data,
202
- fix,
218
+ this._severity,
219
+ nodeOrDescriptor,
220
+ location,
221
+ message,
222
+ opts,
203
223
  this.meta
204
224
  );
205
-
206
- return;
207
225
  }
208
-
209
- // old style call
210
- this.eslint.report(
211
- this.id,
212
- this.severity,
213
- nodeOrDescriptor,
214
- location,
215
- message,
216
- opts,
217
- this.meta
218
- );
219
226
  }
220
227
  }
221
228
 
222
- // Copy over passthrough methods. All functions will have 5 or fewer parameters.
223
- PASSTHROUGHS.forEach(function(name) {
224
- this[name] = function(a, b, c, d, e) {
225
- return this.eslint[name](a, b, c, d, e);
226
- };
227
- }, RuleContext.prototype);
229
+ // Copy over passthrough methods.
230
+ PASSTHROUGHS.forEach(name => {
231
+ Object.defineProperty(RuleContext.prototype, name, {
232
+ value() {
233
+ return this._linter[name].apply(this._linter, arguments);
234
+ },
235
+ configurable: true,
236
+ writable: true,
237
+ enumerable: false
238
+ });
239
+ });
228
240
 
229
241
  module.exports = RuleContext;
@@ -71,7 +71,7 @@ module.exports = {
71
71
  // https://github.com/eslint/eslint/issues/8834
72
72
  const closingParenToken = sourceCode.getTokenAfter(paramToken, astUtils.isClosingParenToken);
73
73
  const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
74
- const shouldAddSpaceForAsync = asyncToken && (asyncToken.end === firstTokenOfParam.start);
74
+ const shouldAddSpaceForAsync = asyncToken && (asyncToken.range[1] === firstTokenOfParam.range[0]);
75
75
 
76
76
  return fixer.replaceTextRange([
77
77
  firstTokenOfParam.range[0],
@@ -238,7 +238,7 @@ module.exports = {
238
238
  // `do while` expressions sometimes need a space to be inserted after `do`.
239
239
  // e.g. `do{foo()} while (bar)` should be corrected to `do foo() while (bar)`
240
240
  const needsPrecedingSpace = node.type === "DoWhileStatement" &&
241
- sourceCode.getTokenBefore(bodyNode).end === bodyNode.start &&
241
+ sourceCode.getTokenBefore(bodyNode).range[1] === bodyNode.range[0] &&
242
242
  !astUtils.canTokensBeAdjacent("do", sourceCode.getFirstToken(bodyNode, { skip: 1 }));
243
243
 
244
244
  const openingBracket = sourceCode.getFirstToken(bodyNode);
@@ -14,6 +14,7 @@ const astUtils = require("../ast-utils");
14
14
  //------------------------------------------------------------------------------
15
15
  // Helpers
16
16
  //------------------------------------------------------------------------------
17
+ const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
17
18
 
18
19
  /**
19
20
  * Checks a given code path segment is reachable.
@@ -101,22 +102,45 @@ module.exports = {
101
102
  }
102
103
  }
103
104
 
105
+ /** Checks whether a node means a getter function.
106
+ * @param {ASTNode} node - a node to check.
107
+ * @returns {boolean} if node means a getter, return true; else return false.
108
+ */
109
+ function isGetter(node) {
110
+ const parent = node.parent;
111
+
112
+ if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") {
113
+ if (parent.kind === "get") {
114
+ return true;
115
+ }
116
+ if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {
117
+
118
+ // Object.defineProperty()
119
+ if (parent.parent.parent.type === "CallExpression" &&
120
+ astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
121
+ return true;
122
+ }
123
+
124
+ // Object.defineProperties()
125
+ if (parent.parent.parent.type === "Property" &&
126
+ parent.parent.parent.parent.type === "ObjectExpression" &&
127
+ parent.parent.parent.parent.parent.type === "CallExpression" &&
128
+ astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee) === "defineProperties") {
129
+ return true;
130
+ }
131
+ }
132
+ }
133
+ return false;
134
+ }
104
135
  return {
105
136
 
106
137
  // Stacks this function's information.
107
138
  onCodePathStart(codePath, node) {
108
- const parent = node.parent;
109
-
110
139
  funcInfo = {
111
140
  upper: funcInfo,
112
141
  codePath,
113
142
  hasReturn: false,
114
- shouldCheck:
115
- node.type === "FunctionExpression" &&
116
- node.body.type === "BlockStatement" &&
117
-
118
- // check if it is a "getter", or a method named "get".
119
- (parent.kind === "get" || astUtils.getStaticPropertyName(parent) === "get"),
143
+ shouldCheck: isGetter(node),
120
144
  node
121
145
  };
122
146
  },
@@ -145,7 +169,8 @@ module.exports = {
145
169
  },
146
170
 
147
171
  // Reports a given function if the last path is reachable.
148
- "FunctionExpression:exit": checkLastSegment
172
+ "FunctionExpression:exit": checkLastSegment,
173
+ "ArrowFunctionExpression:exit": checkLastSegment
149
174
  };
150
175
  }
151
176
  };
@@ -67,9 +67,13 @@ module.exports = {
67
67
  * @private
68
68
  */
69
69
  function report(node) {
70
- context.report({ node, message: "Identifier '{{name}}' is blacklisted.", data: {
71
- name: node.name
72
- } });
70
+ context.report({
71
+ node,
72
+ message: "Identifier '{{name}}' is blacklisted.",
73
+ data: {
74
+ name: node.name
75
+ }
76
+ });
73
77
  }
74
78
 
75
79
  return {
@@ -75,10 +75,14 @@ module.exports = {
75
75
  * @private
76
76
  */
77
77
  function report(node) {
78
- context.report({ node, message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", data: {
79
- name: node.name,
80
- pattern
81
- } });
78
+ context.report({
79
+ node,
80
+ message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.",
81
+ data: {
82
+ name: node.name,
83
+ pattern
84
+ }
85
+ });
82
86
  }
83
87
 
84
88
  return {
@@ -729,7 +729,7 @@ module.exports = {
729
729
  if (!parentVarNode || parentVarNode.loc.start.line !== node.loc.start.line) {
730
730
  if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
731
731
  if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
732
- nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
732
+ nodeIndent += (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
733
733
  } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") {
734
734
  const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements;
735
735
 
@@ -765,7 +765,7 @@ module.exports = {
765
765
  }
766
766
  }
767
767
  } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
768
- nodeIndent = nodeIndent + indentSize;
768
+ nodeIndent += indentSize;
769
769
  }
770
770
 
771
771
  checkFirstNodeLineIndent(node, nodeIndent);