eslint 3.16.0 → 3.18.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 (59) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/conf/eslint-recommended.js +2 -0
  3. package/lib/ast-utils.js +3 -67
  4. package/lib/code-path-analysis/code-path-analyzer.js +2 -7
  5. package/lib/code-path-analysis/debug-helpers.js +17 -16
  6. package/lib/config/config-file.js +68 -38
  7. package/lib/eslint.js +5 -5
  8. package/lib/formatters/stylish.js +5 -4
  9. package/lib/ignored-paths.js +6 -0
  10. package/lib/internal-rules/internal-no-invalid-meta.js +2 -40
  11. package/lib/rules/array-callback-return.js +15 -5
  12. package/lib/rules/capitalized-comments.js +2 -1
  13. package/lib/rules/complexity.js +14 -8
  14. package/lib/rules/consistent-return.js +17 -10
  15. package/lib/rules/func-name-matching.js +18 -7
  16. package/lib/rules/func-names.js +20 -5
  17. package/lib/rules/keyword-spacing.js +19 -4
  18. package/lib/rules/line-comment-position.js +15 -5
  19. package/lib/rules/lines-around-comment.js +19 -0
  20. package/lib/rules/max-params.js +17 -4
  21. package/lib/rules/max-statements.js +11 -10
  22. package/lib/rules/no-compare-neg-zero.js +53 -0
  23. package/lib/rules/no-else-return.js +13 -1
  24. package/lib/rules/no-empty-function.js +9 -16
  25. package/lib/rules/no-extra-parens.js +64 -19
  26. package/lib/rules/no-extra-semi.js +13 -1
  27. package/lib/rules/no-global-assign.js +1 -1
  28. package/lib/rules/no-invalid-regexp.js +2 -1
  29. package/lib/rules/no-multiple-empty-lines.js +2 -4
  30. package/lib/rules/no-new-func.js +6 -8
  31. package/lib/rules/no-new.js +2 -6
  32. package/lib/rules/no-param-reassign.js +29 -6
  33. package/lib/rules/no-process-exit.js +2 -10
  34. package/lib/rules/no-restricted-properties.js +2 -0
  35. package/lib/rules/no-restricted-syntax.js +6 -22
  36. package/lib/rules/no-return-await.js +1 -1
  37. package/lib/rules/no-sync.js +8 -13
  38. package/lib/rules/no-unused-expressions.js +10 -1
  39. package/lib/rules/no-unused-vars.js +12 -12
  40. package/lib/rules/no-use-before-define.js +1 -1
  41. package/lib/rules/no-useless-escape.js +8 -2
  42. package/lib/rules/no-useless-return.js +13 -2
  43. package/lib/rules/nonblock-statement-body-position.js +114 -0
  44. package/lib/rules/object-shorthand.js +2 -1
  45. package/lib/rules/operator-assignment.js +1 -1
  46. package/lib/rules/padded-blocks.js +37 -28
  47. package/lib/rules/prefer-destructuring.js +1 -1
  48. package/lib/rules/semi.js +13 -1
  49. package/lib/rules/sort-vars.js +3 -5
  50. package/lib/rules/space-unary-ops.js +19 -1
  51. package/lib/rules/strict.js +8 -2
  52. package/lib/rules/yoda.js +2 -2
  53. package/lib/testers/rule-tester.js +44 -13
  54. package/lib/util/fix-tracker.js +121 -0
  55. package/lib/util/node-event-generator.js +274 -4
  56. package/lib/util/source-code-fixer.js +2 -2
  57. package/lib/util/source-code.js +99 -2
  58. package/lib/util/traverser.js +16 -25
  59. package/package.json +8 -8
@@ -5,6 +5,185 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const esquery = require("esquery");
13
+ const lodash = require("lodash");
14
+
15
+ //------------------------------------------------------------------------------
16
+ // Typedefs
17
+ //------------------------------------------------------------------------------
18
+
19
+ /**
20
+ * An object describing an AST selector
21
+ * @typedef {Object} ASTSelector
22
+ * @property {string} rawSelector The string that was parsed into this selector
23
+ * @property {boolean} isExit `true` if this should be emitted when exiting the node rather than when entering
24
+ * @property {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector
25
+ * @property {string[]|null} listenerTypes A list of node types that could possibly cause the selector to match,
26
+ * or `null` if all node types could cause a match
27
+ * @property {number} attributeCount The total number of classes, pseudo-classes, and attribute queries in this selector
28
+ * @property {number} identifierCount The total number of identifier queries in this selector
29
+ */
30
+
31
+ //------------------------------------------------------------------------------
32
+ // Helpers
33
+ //------------------------------------------------------------------------------
34
+
35
+ /**
36
+ * Gets the possible types of a selector
37
+ * @param {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector
38
+ * @returns {string[]|null} The node types that could possibly trigger this selector, or `null` if all node types could trigger it
39
+ */
40
+ function getPossibleTypes(parsedSelector) {
41
+ switch (parsedSelector.type) {
42
+ case "identifier":
43
+ return [parsedSelector.value];
44
+
45
+ case "matches": {
46
+ const typesForComponents = parsedSelector.selectors.map(getPossibleTypes);
47
+
48
+ if (typesForComponents.every(typesForComponent => typesForComponent)) {
49
+ return lodash.union.apply(null, typesForComponents);
50
+ }
51
+ return null;
52
+ }
53
+
54
+ case "compound": {
55
+ const typesForComponents = parsedSelector.selectors.map(getPossibleTypes).filter(typesForComponent => typesForComponent);
56
+
57
+ // If all of the components could match any type, then the compound could also match any type.
58
+ if (!typesForComponents.length) {
59
+ return null;
60
+ }
61
+
62
+ /*
63
+ * If at least one of the components could only match a particular type, the compound could only match
64
+ * the intersection of those types.
65
+ */
66
+ return lodash.intersection.apply(null, typesForComponents);
67
+ }
68
+
69
+ case "child":
70
+ case "descendant":
71
+ case "sibling":
72
+ case "adjacent":
73
+ return getPossibleTypes(parsedSelector.right);
74
+
75
+ default:
76
+ return null;
77
+
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Counts the number of class, pseudo-class, and attribute queries in this selector
83
+ * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior
84
+ * @returns {number} The number of class, pseudo-class, and attribute queries in this selector
85
+ */
86
+ function countClassAttributes(parsedSelector) {
87
+ switch (parsedSelector.type) {
88
+ case "child":
89
+ case "descendant":
90
+ case "sibling":
91
+ case "adjacent":
92
+ return countClassAttributes(parsedSelector.left) + countClassAttributes(parsedSelector.right);
93
+
94
+ case "compound":
95
+ case "not":
96
+ case "matches":
97
+ return parsedSelector.selectors.reduce((sum, childSelector) => sum + countClassAttributes(childSelector), 0);
98
+
99
+ case "attribute":
100
+ case "field":
101
+ case "nth-child":
102
+ case "nth-last-child":
103
+ return 1;
104
+
105
+ default:
106
+ return 0;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Counts the number of identifier queries in this selector
112
+ * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior
113
+ * @returns {number} The number of identifier queries
114
+ */
115
+ function countIdentifiers(parsedSelector) {
116
+ switch (parsedSelector.type) {
117
+ case "child":
118
+ case "descendant":
119
+ case "sibling":
120
+ case "adjacent":
121
+ return countIdentifiers(parsedSelector.left) + countIdentifiers(parsedSelector.right);
122
+
123
+ case "compound":
124
+ case "not":
125
+ case "matches":
126
+ return parsedSelector.selectors.reduce((sum, childSelector) => sum + countIdentifiers(childSelector), 0);
127
+
128
+ case "identifier":
129
+ return 1;
130
+
131
+ default:
132
+ return 0;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Compares the specificity of two selector objects, with CSS-like rules.
138
+ * @param {ASTSelector} selectorA An AST selector descriptor
139
+ * @param {ASTSelector} selectorB Another AST selector descriptor
140
+ * @returns {number}
141
+ * a value less than 0 if selectorA is less specific than selectorB
142
+ * a value greater than 0 if selectorA is more specific than selectorB
143
+ * a value less than 0 if selectorA and selectorB have the same specificity, and selectorA <= selectorB alphabetically
144
+ * a value greater than 0 if selectorA and selectorB have the same specificity, and selectorA > selectorB alphabetically
145
+ */
146
+ function compareSpecificity(selectorA, selectorB) {
147
+ return selectorA.attributeCount - selectorB.attributeCount ||
148
+ selectorA.identifierCount - selectorB.identifierCount ||
149
+ (selectorA.rawSelector <= selectorB.rawSelector ? -1 : 1);
150
+ }
151
+
152
+ /**
153
+ * Parses a raw selector string, and throws a useful error if parsing fails.
154
+ * @param {string} rawSelector A raw AST selector
155
+ * @returns {Object} An object (from esquery) describing the matching behavior of this selector
156
+ * @throws {Error} An error if the selector is invalid
157
+ */
158
+ function tryParseSelector(rawSelector) {
159
+ try {
160
+ return esquery.parse(rawSelector.replace(/:exit$/, ""));
161
+ } catch (err) {
162
+ if (typeof err.offset === "number") {
163
+ throw new Error(`Syntax error in selector "${rawSelector}" at position ${err.offset}: ${err.message}`);
164
+ }
165
+ throw err;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Parses a raw selector string, and returns the parsed selector along with specificity and type information.
171
+ * @param {string} rawSelector A raw AST selector
172
+ * @returns {ASTSelector} A selector descriptor
173
+ */
174
+ const parseSelector = lodash.memoize(rawSelector => {
175
+ const parsedSelector = tryParseSelector(rawSelector);
176
+
177
+ return {
178
+ rawSelector,
179
+ isExit: rawSelector.endsWith(":exit"),
180
+ parsedSelector,
181
+ listenerTypes: getPossibleTypes(parsedSelector),
182
+ attributeCount: countClassAttributes(parsedSelector),
183
+ identifierCount: countIdentifiers(parsedSelector)
184
+ };
185
+ });
186
+
8
187
  //------------------------------------------------------------------------------
9
188
  // Public Interface
10
189
  //------------------------------------------------------------------------------
@@ -24,10 +203,97 @@
24
203
  class NodeEventGenerator {
25
204
 
26
205
  /**
27
- * @param {EventEmitter} emitter - An event emitter which is the destination of events.
28
- */
206
+ * @param {EventEmitter} emitter - An event emitter which is the destination of events. This emitter must already
207
+ * have registered listeners for all of the events that it needs to listen for.
208
+ * @returns {NodeEventGenerator} new instance
209
+ */
29
210
  constructor(emitter) {
30
211
  this.emitter = emitter;
212
+ this.currentAncestry = [];
213
+ this.enterSelectorsByNodeType = new Map();
214
+ this.exitSelectorsByNodeType = new Map();
215
+ this.anyTypeEnterSelectors = [];
216
+ this.anyTypeExitSelectors = [];
217
+
218
+ const eventNames = typeof emitter.eventNames === "function"
219
+
220
+ // Use the built-in eventNames() function if available (Node 6+)
221
+ ? emitter.eventNames()
222
+
223
+ /*
224
+ * Otherwise, use the private _events property.
225
+ * Using a private property isn't ideal here, but this seems to
226
+ * be the best way to get a list of event names without overriding
227
+ * addEventListener, which would hurt performance. This property
228
+ * is widely used and unlikely to be removed in a future version
229
+ * (see https://github.com/nodejs/node/issues/1817). Also, future
230
+ * node versions will have eventNames() anyway.
231
+ */
232
+ : Object.keys(emitter._events); // eslint-disable-line no-underscore-dangle
233
+
234
+ eventNames.forEach(rawSelector => {
235
+ const selector = parseSelector(rawSelector);
236
+
237
+ if (selector.listenerTypes) {
238
+ selector.listenerTypes.forEach(nodeType => {
239
+ const typeMap = selector.isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType;
240
+
241
+ if (!typeMap.has(nodeType)) {
242
+ typeMap.set(nodeType, []);
243
+ }
244
+ typeMap.get(nodeType).push(selector);
245
+ });
246
+ } else {
247
+ (selector.isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors).push(selector);
248
+ }
249
+ });
250
+
251
+ this.anyTypeEnterSelectors.sort(compareSpecificity);
252
+ this.anyTypeExitSelectors.sort(compareSpecificity);
253
+ this.enterSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity));
254
+ this.exitSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity));
255
+ }
256
+
257
+ /**
258
+ * Checks a selector against a node, and emits it if it matches
259
+ * @param {ASTNode} node The node to check
260
+ * @param {ASTSelector} selector An AST selector descriptor
261
+ * @returns {void}
262
+ */
263
+ applySelector(node, selector) {
264
+ if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) {
265
+ this.emitter.emit(selector.rawSelector, node);
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Applies all appropriate selectors to a node, in specificity order
271
+ * @param {ASTNode} node The node to check
272
+ * @param {boolean} isExit `false` if the node is currently being entered, `true` if it's currently being exited
273
+ * @returns {void}
274
+ */
275
+ applySelectors(node, isExit) {
276
+ const selectorsByNodeType = (isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType).get(node.type) || [];
277
+ const anyTypeSelectors = isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors;
278
+
279
+ /*
280
+ * selectorsByNodeType and anyTypeSelectors were already sorted by specificity in the constructor.
281
+ * Iterate through each of them, applying selectors in the right order.
282
+ */
283
+ let selectorsByTypeIndex = 0;
284
+ let anyTypeSelectorsIndex = 0;
285
+
286
+ while (selectorsByTypeIndex < selectorsByNodeType.length || anyTypeSelectorsIndex < anyTypeSelectors.length) {
287
+ if (
288
+ selectorsByTypeIndex >= selectorsByNodeType.length ||
289
+ anyTypeSelectorsIndex < anyTypeSelectors.length &&
290
+ compareSpecificity(anyTypeSelectors[anyTypeSelectorsIndex], selectorsByNodeType[selectorsByTypeIndex]) < 0
291
+ ) {
292
+ this.applySelector(node, anyTypeSelectors[anyTypeSelectorsIndex++]);
293
+ } else {
294
+ this.applySelector(node, selectorsByNodeType[selectorsByTypeIndex++]);
295
+ }
296
+ }
31
297
  }
32
298
 
33
299
  /**
@@ -36,7 +302,10 @@ class NodeEventGenerator {
36
302
  * @returns {void}
37
303
  */
38
304
  enterNode(node) {
39
- this.emitter.emit(node.type, node);
305
+ if (node.parent) {
306
+ this.currentAncestry.unshift(node.parent);
307
+ }
308
+ this.applySelectors(node, false);
40
309
  }
41
310
 
42
311
  /**
@@ -45,7 +314,8 @@ class NodeEventGenerator {
45
314
  * @returns {void}
46
315
  */
47
316
  leaveNode(node) {
48
- this.emitter.emit(`${node.type}:exit`, node);
317
+ this.applySelectors(node, true);
318
+ this.currentAncestry.shift();
49
319
  }
50
320
  }
51
321
 
@@ -94,8 +94,8 @@ SourceCodeFixer.applyFixes = function(sourceCode, messages) {
94
94
  const start = fix.range[0];
95
95
  const end = fix.range[1];
96
96
 
97
- // Remain it as a problem if it's overlapped.
98
- if (lastPos >= start) {
97
+ // Remain it as a problem if it's overlapped or it's a negative range
98
+ if (lastPos >= start || start > end) {
99
99
  remainingMessages.push(problem);
100
100
  continue;
101
101
  }
@@ -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.0",
3
+ "version": "3.18.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",
@@ -78,14 +79,14 @@
78
79
  "browserify": "^12.0.1",
79
80
  "chai": "^3.5.0",
80
81
  "cheerio": "^0.19.0",
81
- "coveralls": "2.11.4",
82
+ "coveralls": "^2.11.16",
82
83
  "dateformat": "^1.0.8",
83
84
  "ejs": "^2.3.3",
84
- "eslint-plugin-node": "^2.0.0",
85
+ "eslint-plugin-eslint-plugin": "^0.7.1",
86
+ "eslint-plugin-node": "^4.1.0",
85
87
  "eslint-release": "^0.10.0",
86
88
  "esprima": "^2.4.1",
87
89
  "esprima-fb": "^15001.1001.0-dev-harmony-fb",
88
- "gh-got": "^2.2.0",
89
90
  "istanbul": "^0.4.0",
90
91
  "jsdoc": "^3.3.0-beta1",
91
92
  "karma": "^0.13.22",
@@ -94,11 +95,10 @@
94
95
  "karma-mocha-reporter": "^2.0.3",
95
96
  "karma-phantomjs-launcher": "^1.0.0",
96
97
  "leche": "^2.1.1",
97
- "linefix": "^0.1.1",
98
98
  "load-perf": "^0.2.0",
99
99
  "markdownlint": "^0.3.1",
100
100
  "mocha": "^2.4.5",
101
- "mock-fs": "^4.0.0",
101
+ "mock-fs": "^4.2.0",
102
102
  "npm-license": "^0.3.2",
103
103
  "phantomjs-prebuilt": "^2.1.7",
104
104
  "proxyquire": "^1.7.10",