eslint 3.16.1 → 3.19.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 (86) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +1 -0
  3. package/conf/eslint-recommended.js +2 -0
  4. package/lib/ast-utils.js +3 -67
  5. package/lib/code-path-analysis/code-path-analyzer.js +2 -7
  6. package/lib/code-path-analysis/debug-helpers.js +17 -16
  7. package/lib/config/config-file.js +68 -38
  8. package/lib/config/config-rule.js +14 -10
  9. package/lib/config/plugins.js +19 -8
  10. package/lib/eslint.js +11 -10
  11. package/lib/formatters/codeframe.js +4 -9
  12. package/lib/formatters/stylish.js +5 -4
  13. package/lib/ignored-paths.js +6 -0
  14. package/lib/internal-rules/internal-no-invalid-meta.js +2 -40
  15. package/lib/rules/array-callback-return.js +15 -5
  16. package/lib/rules/arrow-body-style.js +2 -2
  17. package/lib/rules/arrow-parens.js +9 -3
  18. package/lib/rules/capitalized-comments.js +2 -1
  19. package/lib/rules/comma-dangle.js +3 -2
  20. package/lib/rules/comma-spacing.js +4 -14
  21. package/lib/rules/comma-style.js +8 -14
  22. package/lib/rules/complexity.js +14 -8
  23. package/lib/rules/consistent-return.js +17 -10
  24. package/lib/rules/curly.js +2 -2
  25. package/lib/rules/dot-notation.js +12 -6
  26. package/lib/rules/func-name-matching.js +18 -7
  27. package/lib/rules/func-names.js +20 -5
  28. package/lib/rules/keyword-spacing.js +19 -4
  29. package/lib/rules/line-comment-position.js +15 -5
  30. package/lib/rules/lines-around-comment.js +19 -0
  31. package/lib/rules/lines-around-directive.js +1 -1
  32. package/lib/rules/max-params.js +17 -4
  33. package/lib/rules/max-statements.js +11 -10
  34. package/lib/rules/new-parens.js +7 -21
  35. package/lib/rules/no-compare-neg-zero.js +53 -0
  36. package/lib/rules/no-cond-assign.js +4 -17
  37. package/lib/rules/no-else-return.js +19 -4
  38. package/lib/rules/no-empty-function.js +9 -16
  39. package/lib/rules/no-extra-parens.js +110 -121
  40. package/lib/rules/no-extra-semi.js +16 -3
  41. package/lib/rules/no-global-assign.js +1 -1
  42. package/lib/rules/no-implicit-coercion.js +21 -8
  43. package/lib/rules/no-invalid-regexp.js +2 -1
  44. package/lib/rules/no-multiple-empty-lines.js +2 -4
  45. package/lib/rules/no-native-reassign.js +1 -1
  46. package/lib/rules/no-negated-in-lhs.js +1 -1
  47. package/lib/rules/no-new-func.js +6 -8
  48. package/lib/rules/no-new.js +2 -6
  49. package/lib/rules/no-param-reassign.js +37 -7
  50. package/lib/rules/no-process-exit.js +2 -10
  51. package/lib/rules/no-restricted-properties.js +2 -0
  52. package/lib/rules/no-restricted-syntax.js +32 -21
  53. package/lib/rules/no-return-await.js +1 -1
  54. package/lib/rules/no-sequences.js +2 -2
  55. package/lib/rules/no-sync.js +8 -13
  56. package/lib/rules/no-unsafe-negation.js +1 -1
  57. package/lib/rules/no-unused-expressions.js +10 -1
  58. package/lib/rules/no-unused-vars.js +12 -12
  59. package/lib/rules/no-use-before-define.js +1 -1
  60. package/lib/rules/no-useless-computed-key.js +12 -1
  61. package/lib/rules/no-useless-escape.js +8 -2
  62. package/lib/rules/no-useless-return.js +13 -2
  63. package/lib/rules/nonblock-statement-body-position.js +114 -0
  64. package/lib/rules/object-curly-spacing.js +2 -2
  65. package/lib/rules/object-shorthand.js +10 -3
  66. package/lib/rules/operator-assignment.js +20 -3
  67. package/lib/rules/padded-blocks.js +37 -31
  68. package/lib/rules/prefer-const.js +1 -1
  69. package/lib/rules/prefer-destructuring.js +1 -1
  70. package/lib/rules/quotes.js +1 -0
  71. package/lib/rules/semi-spacing.js +2 -15
  72. package/lib/rules/semi.js +17 -13
  73. package/lib/rules/sort-vars.js +3 -5
  74. package/lib/rules/space-before-function-paren.js +53 -77
  75. package/lib/rules/space-in-parens.js +4 -8
  76. package/lib/rules/space-unary-ops.js +19 -1
  77. package/lib/rules/strict.js +8 -2
  78. package/lib/rules/yoda.js +2 -2
  79. package/lib/testers/rule-tester.js +44 -13
  80. package/lib/util/fix-tracker.js +121 -0
  81. package/lib/util/glob-util.js +1 -1
  82. package/lib/util/node-event-generator.js +274 -4
  83. package/lib/util/source-code-fixer.js +3 -9
  84. package/lib/util/source-code.js +99 -2
  85. package/lib/util/traverser.js +16 -25
  86. package/package.json +34 -34
@@ -10,7 +10,8 @@
10
10
 
11
11
  const TokenStore = require("../token-store"),
12
12
  Traverser = require("./traverser"),
13
- astUtils = require("../ast-utils");
13
+ astUtils = require("../ast-utils"),
14
+ lodash = require("lodash");
14
15
 
15
16
  //------------------------------------------------------------------------------
16
17
  // Private
@@ -138,7 +139,26 @@ function SourceCode(text, ast) {
138
139
  * This is done to avoid each rule needing to do so separately.
139
140
  * @type string[]
140
141
  */
141
- this.lines = SourceCode.splitLines(this.text);
142
+ this.lines = [];
143
+ this.lineStartIndices = [0];
144
+
145
+ const lineEndingPattern = astUtils.createGlobalLinebreakMatcher();
146
+ let match;
147
+
148
+ /*
149
+ * Previously, this was implemented using a regex that
150
+ * matched a sequence of non-linebreak characters followed by a
151
+ * linebreak, then adding the lengths of the matches. However,
152
+ * this caused a catastrophic backtracking issue when the end
153
+ * of a file contained a large number of non-newline characters.
154
+ * To avoid this, the current implementation just matches newlines
155
+ * and uses match.index to get the correct line start indices.
156
+ */
157
+ while ((match = lineEndingPattern.exec(this.text))) {
158
+ this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1], match.index));
159
+ this.lineStartIndices.push(match.index + match[0].length);
160
+ }
161
+ this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1]));
142
162
 
143
163
  this.tokensAndComments = sortedMerge(ast.tokens, ast.comments);
144
164
 
@@ -312,6 +332,83 @@ SourceCode.prototype = {
312
332
  const text = this.text.slice(first.range[1], second.range[0]);
313
333
 
314
334
  return /\s/.test(text.replace(/\/\*.*?\*\//g, ""));
335
+ },
336
+
337
+ /**
338
+ * Converts a source text index into a (line, column) pair.
339
+ * @param {number} index The index of a character in a file
340
+ * @returns {Object} A {line, column} location object with a 0-indexed column
341
+ */
342
+ getLocFromIndex(index) {
343
+ if (typeof index !== "number") {
344
+ throw new TypeError("Expected `index` to be a number.");
345
+ }
346
+
347
+ if (index < 0 || index > this.text.length) {
348
+ throw new RangeError(`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`);
349
+ }
350
+
351
+ /*
352
+ * For an argument of this.text.length, return the location one "spot" past the last character
353
+ * of the file. If the last character is a linebreak, the location will be column 0 of the next
354
+ * line; otherwise, the location will be in the next column on the same line.
355
+ *
356
+ * See getIndexFromLoc for the motivation for this special case.
357
+ */
358
+ if (index === this.text.length) {
359
+ return { line: this.lines.length, column: this.lines[this.lines.length - 1].length };
360
+ }
361
+
362
+ /*
363
+ * To figure out which line rangeIndex is on, determine the last index at which rangeIndex could
364
+ * be inserted into lineIndices to keep the list sorted.
365
+ */
366
+ const lineNumber = lodash.sortedLastIndex(this.lineStartIndices, index);
367
+
368
+ return { line: lineNumber, column: index - this.lineStartIndices[lineNumber - 1] };
369
+
370
+ },
371
+
372
+ /**
373
+ * Converts a (line, column) pair into a range index.
374
+ * @param {Object} loc A line/column location
375
+ * @param {number} loc.line The line number of the location (1-indexed)
376
+ * @param {number} loc.column The column number of the location (0-indexed)
377
+ * @returns {number} The range index of the location in the file.
378
+ */
379
+ getIndexFromLoc(loc) {
380
+ if (typeof loc !== "object" || typeof loc.line !== "number" || typeof loc.column !== "number") {
381
+ throw new TypeError("Expected `loc` to be an object with numeric `line` and `column` properties.");
382
+ }
383
+
384
+ if (loc.line <= 0) {
385
+ throw new RangeError(`Line number out of range (line ${loc.line} requested). Line numbers should be 1-based.`);
386
+ }
387
+
388
+ if (loc.line > this.lineStartIndices.length) {
389
+ throw new RangeError(`Line number out of range (line ${loc.line} requested, but only ${this.lineStartIndices.length} lines present).`);
390
+ }
391
+
392
+ const lineStartIndex = this.lineStartIndices[loc.line - 1];
393
+ const lineEndIndex = loc.line === this.lineStartIndices.length ? this.text.length : this.lineStartIndices[loc.line];
394
+ const positionIndex = lineStartIndex + loc.column;
395
+
396
+ /*
397
+ * By design, getIndexFromLoc({ line: lineNum, column: 0 }) should return the start index of
398
+ * the given line, provided that the line number is valid element of this.lines. Since the
399
+ * last element of this.lines is an empty string for files with trailing newlines, add a
400
+ * special case where getting the index for the first location after the end of the file
401
+ * will return the length of the file, rather than throwing an error. This allows rules to
402
+ * use getIndexFromLoc consistently without worrying about edge cases at the end of a file.
403
+ */
404
+ if (
405
+ loc.line === this.lineStartIndices.length && positionIndex > lineEndIndex ||
406
+ loc.line < this.lineStartIndices.length && positionIndex >= lineEndIndex
407
+ ) {
408
+ throw new RangeError(`Column number out of range (column ${loc.column} requested, but the length of line ${loc.line} is ${lineEndIndex - lineStartIndex}).`);
409
+ }
410
+
411
+ return positionIndex;
315
412
  }
316
413
  };
317
414
 
@@ -14,41 +14,32 @@ const estraverse = require("estraverse");
14
14
  // Helpers
15
15
  //------------------------------------------------------------------------------
16
16
 
17
- const KEY_BLACKLIST = [
17
+ const KEY_BLACKLIST = new Set([
18
18
  "parent",
19
19
  "leadingComments",
20
20
  "trailingComments"
21
- ];
21
+ ]);
22
22
 
23
23
  /**
24
24
  * Wrapper around an estraverse controller that ensures the correct keys
25
25
  * are visited.
26
26
  * @constructor
27
27
  */
28
- function Traverser() {
29
-
30
- const controller = Object.create(new estraverse.Controller()),
31
- originalTraverse = controller.traverse;
32
-
33
- // intercept call to traverse() and add the fallback key to the visitor
34
- controller.traverse = function(node, visitor) {
28
+ class Traverser extends estraverse.Controller {
29
+ traverse(node, visitor) {
35
30
  visitor.fallback = Traverser.getKeys;
36
- return originalTraverse.call(this, node, visitor);
37
- };
38
-
39
- return controller;
31
+ return super.traverse(node, visitor);
32
+ }
33
+
34
+ /**
35
+ * Calculates the keys to use for traversal.
36
+ * @param {ASTNode} node The node to read keys from.
37
+ * @returns {string[]} An array of keys to visit on the node.
38
+ * @private
39
+ */
40
+ static getKeys(node) {
41
+ return Object.keys(node).filter(key => !KEY_BLACKLIST.has(key));
42
+ }
40
43
  }
41
44
 
42
- /**
43
- * Calculates the keys to use for traversal.
44
- * @param {ASTNode} node The node to read keys from.
45
- * @returns {string[]} An array of keys to visit on the node.
46
- * @private
47
- */
48
- Traverser.getKeys = function(node) {
49
- return Object.keys(node).filter(key => KEY_BLACKLIST.indexOf(key) === -1);
50
- };
51
-
52
45
  module.exports = Traverser;
53
-
54
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "3.16.1",
3
+ "version": "3.19.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -36,11 +36,12 @@
36
36
  "dependencies": {
37
37
  "babel-code-frame": "^6.16.0",
38
38
  "chalk": "^1.1.3",
39
- "concat-stream": "^1.4.6",
39
+ "concat-stream": "^1.5.2",
40
40
  "debug": "^2.1.1",
41
- "doctrine": "^1.2.2",
41
+ "doctrine": "^2.0.0",
42
42
  "escope": "^3.6.0",
43
43
  "espree": "^3.4.0",
44
+ "esquery": "^1.0.0",
44
45
  "estraverse": "^4.2.0",
45
46
  "esutils": "^2.0.2",
46
47
  "file-entry-cache": "^2.0.0",
@@ -70,43 +71,42 @@
70
71
  "user-home": "^2.0.0"
71
72
  },
72
73
  "devDependencies": {
73
- "babel-polyfill": "^6.9.1",
74
- "babel-preset-es2015": "^6.9.0",
74
+ "babel-polyfill": "^6.23.0",
75
+ "babel-preset-es2015": "^6.24.0",
75
76
  "babelify": "^7.3.0",
76
- "beefy": "^2.0.0",
77
- "brfs": "0.0.9",
78
- "browserify": "^12.0.1",
77
+ "beefy": "^2.1.8",
78
+ "brfs": "1.4.3",
79
+ "browserify": "^14.1.0",
79
80
  "chai": "^3.5.0",
80
- "cheerio": "^0.19.0",
81
- "coveralls": "2.11.4",
82
- "dateformat": "^1.0.8",
83
- "ejs": "^2.3.3",
84
- "eslint-plugin-node": "^2.0.0",
85
- "eslint-release": "^0.10.0",
86
- "esprima": "^2.4.1",
81
+ "cheerio": "^0.22.0",
82
+ "coveralls": "^2.12.0",
83
+ "dateformat": "^2.0.0",
84
+ "ejs": "^2.5.6",
85
+ "eslint-plugin-eslint-plugin": "^0.7.1",
86
+ "eslint-plugin-node": "^4.2.1",
87
+ "eslint-release": "^0.10.1",
88
+ "esprima": "^3.1.3",
87
89
  "esprima-fb": "^15001.1001.0-dev-harmony-fb",
88
- "gh-got": "^2.2.0",
89
- "istanbul": "^0.4.0",
90
- "jsdoc": "^3.3.0-beta1",
91
- "karma": "^0.13.22",
90
+ "istanbul": "^0.4.5",
91
+ "jsdoc": "^3.4.3",
92
+ "karma": "^1.5.0",
92
93
  "karma-babel-preprocessor": "^6.0.1",
93
- "karma-mocha": "^1.0.1",
94
- "karma-mocha-reporter": "^2.0.3",
95
- "karma-phantomjs-launcher": "^1.0.0",
96
- "leche": "^2.1.1",
97
- "linefix": "^0.1.1",
94
+ "karma-mocha": "^1.3.0",
95
+ "karma-mocha-reporter": "^2.2.2",
96
+ "karma-phantomjs-launcher": "^1.0.4",
97
+ "leche": "^2.1.2",
98
98
  "load-perf": "^0.2.0",
99
- "markdownlint": "^0.3.1",
100
- "mocha": "^2.4.5",
101
- "mock-fs": "^4.0.0",
102
- "npm-license": "^0.3.2",
103
- "phantomjs-prebuilt": "^2.1.7",
104
- "proxyquire": "^1.7.10",
105
- "semver": "^5.0.3",
106
- "shelljs-nodecli": "~0.1.0",
107
- "sinon": "^1.17.2",
99
+ "markdownlint": "^0.4.0",
100
+ "mocha": "^3.2.0",
101
+ "mock-fs": "^4.2.0",
102
+ "npm-license": "^0.3.3",
103
+ "phantomjs-prebuilt": "^2.1.14",
104
+ "proxyquire": "^1.7.11",
105
+ "semver": "^5.3.0",
106
+ "shelljs-nodecli": "~0.1.1",
107
+ "sinon": "^2.0.0",
108
108
  "temp": "^0.8.3",
109
- "through": "^2.3.6"
109
+ "through": "^2.3.8"
110
110
  },
111
111
  "keywords": [
112
112
  "ast",