eslint 4.5.0 → 4.7.1

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 (49) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/bin/eslint.js +2 -1
  3. package/conf/eslint-recommended.js +1 -0
  4. package/lib/ast-utils.js +20 -17
  5. package/lib/cli-engine.js +51 -124
  6. package/lib/code-path-analysis/code-path-analyzer.js +8 -4
  7. package/lib/code-path-analysis/code-path-segment.js +2 -1
  8. package/lib/code-path-analysis/code-path-state.js +21 -14
  9. package/lib/code-path-analysis/code-path.js +3 -2
  10. package/lib/code-path-analysis/fork-context.js +2 -1
  11. package/lib/config/autoconfig.js +2 -4
  12. package/lib/config/config-initializer.js +9 -5
  13. package/lib/config/config-ops.js +15 -15
  14. package/lib/config.js +8 -12
  15. package/lib/formatters/codeframe.js +1 -1
  16. package/lib/formatters/stylish.js +1 -1
  17. package/lib/ignored-paths.js +0 -2
  18. package/lib/linter.js +468 -638
  19. package/lib/report-translator.js +274 -0
  20. package/lib/rules/function-paren-newline.js +221 -0
  21. package/lib/rules/generator-star-spacing.js +70 -19
  22. package/lib/rules/indent-legacy.js +3 -2
  23. package/lib/rules/indent.js +15 -6
  24. package/lib/rules/key-spacing.js +2 -1
  25. package/lib/rules/newline-per-chained-call.js +20 -3
  26. package/lib/rules/no-extra-parens.js +75 -33
  27. package/lib/rules/no-invalid-this.js +2 -1
  28. package/lib/rules/no-tabs.js +1 -1
  29. package/lib/rules/no-undef-init.js +4 -0
  30. package/lib/rules/no-unmodified-loop-condition.js +1 -1
  31. package/lib/rules/no-unused-vars.js +47 -4
  32. package/lib/rules/padded-blocks.js +2 -2
  33. package/lib/rules/prefer-arrow-callback.js +1 -2
  34. package/lib/rules/quote-props.js +4 -2
  35. package/lib/rules/quotes.js +1 -2
  36. package/lib/rules/space-before-blocks.js +1 -1
  37. package/lib/rules/valid-jsdoc.js +2 -2
  38. package/lib/rules.js +48 -3
  39. package/lib/testers/rule-tester.js +27 -51
  40. package/lib/timing.js +2 -2
  41. package/lib/util/apply-disable-directives.js +131 -0
  42. package/lib/util/fix-tracker.js +1 -2
  43. package/lib/util/npm-util.js +21 -4
  44. package/lib/util/source-code-fixer.js +5 -14
  45. package/lib/util/source-code.js +3 -5
  46. package/package.json +8 -8
  47. package/lib/rule-context.js +0 -241
  48. package/lib/testers/event-generator-tester.js +0 -62
  49. package/lib/testers/test-parser.js +0 -48
@@ -159,7 +159,8 @@ class RuleTester {
159
159
 
160
160
  // we have to clone because merge uses the first argument for recipient
161
161
  lodash.cloneDeep(defaultConfig),
162
- testerConfig
162
+ testerConfig,
163
+ { rules: { "rule-tester/validate-ast": "error" } }
163
164
  );
164
165
 
165
166
  /**
@@ -306,7 +307,17 @@ class RuleTester {
306
307
  config.rules[ruleName] = 1;
307
308
  }
308
309
 
309
- linter.defineRule(ruleName, rule);
310
+ linter.defineRule(ruleName, Object.assign({}, rule, {
311
+
312
+ // Create a wrapper rule that freezes the `context` properties.
313
+ create(context) {
314
+ freezeDeeply(context.options);
315
+ freezeDeeply(context.settings);
316
+ freezeDeeply(context.parserOptions);
317
+
318
+ return (typeof rule === "function" ? rule : rule.create)(context);
319
+ }
320
+ }));
310
321
 
311
322
  const schema = validator.getRuleOptionsSchema(ruleName, linter.rules);
312
323
 
@@ -331,55 +342,20 @@ class RuleTester {
331
342
  * The goal is to check whether or not AST was modified when
332
343
  * running the rule under test.
333
344
  */
334
- linter.reset();
335
-
336
- linter.on("Program", node => {
337
- beforeAST = cloneDeeplyExcludesParent(node);
338
- });
339
-
340
- linter.on("Program:exit", node => {
341
- afterAST = node;
342
- });
343
-
344
- // Freezes rule-context properties.
345
- const originalGet = linter.rules.get;
346
-
347
- try {
348
- linter.rules.get = function(ruleId) {
349
- const originalRule = originalGet.call(linter.rules, ruleId);
350
-
351
- if (typeof originalRule === "function") {
352
- return function(context) {
353
- Object.freeze(context);
354
- freezeDeeply(context.options);
355
- freezeDeeply(context.settings);
356
- freezeDeeply(context.parserOptions);
357
-
358
- return originalRule(context);
359
- };
360
- }
361
- return {
362
- meta: originalRule.meta,
363
- create(context) {
364
- Object.freeze(context);
365
- freezeDeeply(context.options);
366
- freezeDeeply(context.settings);
367
- freezeDeeply(context.parserOptions);
368
-
369
- return originalRule.create(context);
370
- }
371
- };
372
-
373
- };
345
+ linter.defineRule("rule-tester/validate-ast", () => ({
346
+ Program(node) {
347
+ beforeAST = cloneDeeplyExcludesParent(node);
348
+ },
349
+ "Program:exit"(node) {
350
+ afterAST = node;
351
+ }
352
+ }));
374
353
 
375
- return {
376
- messages: linter.verify(code, config, filename, true),
377
- beforeAST,
378
- afterAST: cloneDeeplyExcludesParent(afterAST)
379
- };
380
- } finally {
381
- linter.rules.get = originalGet;
382
- }
354
+ return {
355
+ messages: linter.verify(code, config, filename, true),
356
+ beforeAST,
357
+ afterAST: cloneDeeplyExcludesParent(afterAST)
358
+ };
383
359
  }
384
360
 
385
361
  /**
@@ -519,7 +495,7 @@ class RuleTester {
519
495
  "Expected no autofixes to be suggested"
520
496
  );
521
497
  } else {
522
- const fixResult = SourceCodeFixer.applyFixes(linter.getSourceCode(), messages);
498
+ const fixResult = SourceCodeFixer.applyFixes(item.code, messages);
523
499
 
524
500
  assert.equal(fixResult.output, item.output, "Output is incorrect.");
525
501
  }
package/lib/timing.js CHANGED
@@ -84,11 +84,11 @@ function display(data) {
84
84
  }
85
85
  });
86
86
 
87
- const table = rows.map(row =>
87
+ const table = rows.map(row => (
88
88
  row
89
89
  .map((cell, index) => ALIGN[index](cell, widths[index]))
90
90
  .join(" | ")
91
- );
91
+ ));
92
92
 
93
93
  table.splice(1, 0, widths.map((w, index) => {
94
94
  if (index !== 0 && index !== widths.length - 1) {
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @fileoverview A module that filters reported problems based on `eslint-disable` and `eslint-enable` comments
3
+ * @author Teddy Katz
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const lodash = require("lodash");
9
+
10
+ /**
11
+ * Compares the locations of two objects in a source file
12
+ * @param {{line: number, column: number}} itemA The first object
13
+ * @param {{line: number, column: number}} itemB The second object
14
+ * @returns {number} A value less than 1 if itemA appears before itemB in the source file, greater than 1 if
15
+ * itemA appears after itemB in the source file, or 0 if itemA and itemB have the same location.
16
+ */
17
+ function compareLocations(itemA, itemB) {
18
+ return itemA.line - itemB.line || itemA.column - itemB.column;
19
+ }
20
+
21
+ /**
22
+ * This is the same as the exported function, except that it doesn't handle disable-line and disable-next-line directives.
23
+ * @param {Object} options options (see the exported function)
24
+ * @returns {Problem[]} Filtered problems (see the exported function)
25
+ */
26
+ function applyDirectives(options) {
27
+ const problems = [];
28
+ let nextDirectiveIndex = 0;
29
+ let globalDisableActive = false;
30
+
31
+ // disabledRules is only used when there is no active global /* eslint-disable */ comment.
32
+ const disabledRules = new Set();
33
+
34
+ // enabledRules is only used when there is an active global /* eslint-disable */ comment.
35
+ const enabledRules = new Set();
36
+
37
+ for (const problem of options.problems) {
38
+ while (
39
+ nextDirectiveIndex < options.directives.length &&
40
+ compareLocations(options.directives[nextDirectiveIndex], problem) <= 0
41
+ ) {
42
+ const directive = options.directives[nextDirectiveIndex++];
43
+
44
+ switch (directive.type) {
45
+ case "disable":
46
+ if (directive.ruleId === null) {
47
+ globalDisableActive = true;
48
+ enabledRules.clear();
49
+ } else if (globalDisableActive) {
50
+ enabledRules.delete(directive.ruleId);
51
+ } else {
52
+ disabledRules.add(directive.ruleId);
53
+ }
54
+ break;
55
+
56
+ case "enable":
57
+ if (directive.ruleId === null) {
58
+ globalDisableActive = false;
59
+ disabledRules.clear();
60
+ } else if (globalDisableActive) {
61
+ enabledRules.add(directive.ruleId);
62
+ } else {
63
+ disabledRules.delete(directive.ruleId);
64
+ }
65
+ break;
66
+
67
+ // no default
68
+ }
69
+ }
70
+
71
+ if (
72
+ globalDisableActive && enabledRules.has(problem.ruleId) ||
73
+ !globalDisableActive && !disabledRules.has(problem.ruleId)
74
+ ) {
75
+ problems.push(problem);
76
+ }
77
+ }
78
+
79
+ return problems;
80
+ }
81
+
82
+ /**
83
+ * Given a list of directive comments (i.e. metadata about eslint-disable and eslint-enable comments) and a list
84
+ * of reported problems, determines which problems should be reported.
85
+ * @param {Object} options Information about directives and problems
86
+ * @param {{
87
+ * type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
88
+ * ruleId: (string|null),
89
+ * line: number,
90
+ * column: number
91
+ * }} options.directives Directive comments found in the file, with one-based columns.
92
+ * Two directive comments can only have the same location if they also have the same type (e.g. a single eslint-disable
93
+ * comment for two different rules is represented as two directives).
94
+ * @param {{ruleId: (string|null), line: number, column: number}[]} options.problems
95
+ * A list of problems reported by rules, sorted by increasing location in the file, with one-based columns.
96
+ * @returns {{ruleId: (string|null), line: number, column: number}[]}
97
+ * A list of reported problems that were not disabled by the directive comments.
98
+ */
99
+ module.exports = options => {
100
+ const blockDirectives = options.directives
101
+ .filter(directive => directive.type === "disable" || directive.type === "enable")
102
+ .sort(compareLocations);
103
+
104
+ const lineDirectives = lodash.flatMap(options.directives, directive => {
105
+ switch (directive.type) {
106
+ case "disable":
107
+ case "enable":
108
+ return [];
109
+
110
+ case "disable-line":
111
+ return [
112
+ { type: "disable", line: directive.line, column: 1, ruleId: directive.ruleId },
113
+ { type: "enable", line: directive.line + 1, column: 0, ruleId: directive.ruleId }
114
+ ];
115
+
116
+ case "disable-next-line":
117
+ return [
118
+ { type: "disable", line: directive.line + 1, column: 1, ruleId: directive.ruleId },
119
+ { type: "enable", line: directive.line + 2, column: 0, ruleId: directive.ruleId }
120
+ ];
121
+
122
+ default:
123
+ throw new TypeError(`Unrecognized directive type '${directive.type}'`);
124
+ }
125
+ }).sort(compareLocations);
126
+
127
+ const problemsAfterBlockDirectives = applyDirectives({ problems: options.problems, directives: blockDirectives });
128
+ const problemsAfterLineDirectives = applyDirectives({ problems: problemsAfterBlockDirectives, directives: lineDirectives });
129
+
130
+ return problemsAfterLineDirectives.sort(compareLocations);
131
+ };
@@ -57,8 +57,7 @@ class FixTracker {
57
57
  retainEnclosingFunction(node) {
58
58
  const functionNode = astUtils.getUpperFunction(node);
59
59
 
60
- return this.retainRange(
61
- functionNode ? functionNode.range : this.sourceCode.ast.range);
60
+ return this.retainRange(functionNode ? functionNode.range : this.sourceCode.ast.range);
62
61
  }
63
62
 
64
63
  /**
@@ -53,22 +53,39 @@ function installSyncSaveDev(packages) {
53
53
  if (!Array.isArray(packages)) {
54
54
  packages = [packages];
55
55
  }
56
- spawn.sync("npm", ["i", "--save-dev"].concat(packages), { stdio: "inherit" });
56
+ const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packages),
57
+ { stdio: "inherit" });
58
+ const error = npmProcess.error;
59
+
60
+ if (error && error.code === "ENOENT") {
61
+ const pluralS = packages.length > 1 ? "s" : "";
62
+
63
+ log.error(`Could not execute npm. Please install the following package${pluralS} with your package manager of choice: ${packages.join(", ")}`);
64
+ }
57
65
  }
58
66
 
59
67
  /**
60
68
  * Fetch `peerDependencies` of the given package by `npm show` command.
61
69
  * @param {string} packageName The package name to fetch peerDependencies.
62
- * @returns {Object} Gotten peerDependencies.
70
+ * @returns {Object} Gotten peerDependencies. Returns null if npm was not found.
63
71
  */
64
72
  function fetchPeerDependencies(packageName) {
65
- const fetchedText = spawn.sync(
73
+ const npmProcess = spawn.sync(
66
74
  "npm",
67
75
  ["show", "--json", packageName, "peerDependencies"],
68
76
  { encoding: "utf8" }
69
- ).stdout.trim();
77
+ );
78
+
79
+ const error = npmProcess.error;
80
+
81
+ if (error && error.code === "ENOENT") {
82
+ return null;
83
+ }
84
+ const fetchedText = npmProcess.stdout.trim();
70
85
 
71
86
  return JSON.parse(fetchedText || "{}");
87
+
88
+
72
89
  }
73
90
 
74
91
  /**
@@ -53,37 +53,28 @@ function SourceCodeFixer() {
53
53
  /**
54
54
  * Applies the fixes specified by the messages to the given text. Tries to be
55
55
  * smart about the fixes and won't apply fixes over the same area in the text.
56
- * @param {SourceCode} sourceCode The source code to apply the changes to.
56
+ * @param {string} sourceText The text to apply the changes to.
57
57
  * @param {Message[]} messages The array of messages reported by ESLint.
58
58
  * @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed
59
59
  * @returns {Object} An object containing the fixed text and any unfixed messages.
60
60
  */
61
- SourceCodeFixer.applyFixes = function(sourceCode, messages, shouldFix) {
61
+ SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) {
62
62
  debug("Applying fixes");
63
63
 
64
- if (!sourceCode) {
65
- debug("No source code to fix");
66
- return {
67
- fixed: false,
68
- messages,
69
- output: ""
70
- };
71
- }
72
-
73
64
  if (shouldFix === false) {
74
65
  debug("shouldFix parameter was false, not attempting fixes");
75
66
  return {
76
67
  fixed: false,
77
68
  messages,
78
- output: sourceCode.text
69
+ output: sourceText
79
70
  };
80
71
  }
81
72
 
82
73
  // clone the array
83
74
  const remainingMessages = [],
84
75
  fixes = [],
85
- bom = (sourceCode.hasBOM ? BOM : ""),
86
- text = sourceCode.text;
76
+ bom = sourceText.startsWith(BOM) ? BOM : "",
77
+ text = bom ? sourceText.slice(1) : sourceText;
87
78
  let lastPos = Number.NEGATIVE_INFINITY,
88
79
  output = bom;
89
80
 
@@ -349,15 +349,13 @@ class SourceCode extends TokenStore {
349
349
  * @returns {ASTNode} The node if found or null if not found.
350
350
  */
351
351
  getNodeByRangeIndex(index) {
352
- let result = null,
353
- resultParent = null;
352
+ let result = null;
354
353
  const traverser = new Traverser();
355
354
 
356
355
  traverser.traverse(this.ast, {
357
- enter(node, parent) {
356
+ enter(node) {
358
357
  if (node.range[0] <= index && index < node.range[1]) {
359
358
  result = node;
360
- resultParent = parent;
361
359
  } else {
362
360
  this.skip();
363
361
  }
@@ -369,7 +367,7 @@ class SourceCode extends TokenStore {
369
367
  }
370
368
  });
371
369
 
372
- return result ? Object.assign({ parent: resultParent }, result) : null;
370
+ return result;
373
371
  }
374
372
 
375
373
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "4.5.0",
3
+ "version": "4.7.1",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -40,10 +40,10 @@
40
40
  "chalk": "^2.1.0",
41
41
  "concat-stream": "^1.6.0",
42
42
  "cross-spawn": "^5.1.0",
43
- "debug": "^2.6.8",
43
+ "debug": "^3.0.1",
44
44
  "doctrine": "^2.0.0",
45
45
  "eslint-scope": "^3.7.1",
46
- "espree": "^3.5.0",
46
+ "espree": "^3.5.1",
47
47
  "esquery": "^1.0.0",
48
48
  "estraverse": "^4.2.0",
49
49
  "esutils": "^2.0.2",
@@ -64,7 +64,7 @@
64
64
  "natural-compare": "^1.4.0",
65
65
  "optionator": "^0.8.2",
66
66
  "path-is-inside": "^1.0.2",
67
- "pluralize": "^4.0.0",
67
+ "pluralize": "^7.0.0",
68
68
  "progress": "^2.0.0",
69
69
  "require-uncached": "^1.0.3",
70
70
  "semver": "^5.3.0",
@@ -85,11 +85,11 @@
85
85
  "coveralls": "^2.13.1",
86
86
  "dateformat": "^2.0.0",
87
87
  "ejs": "^2.5.6",
88
- "eslint-plugin-eslint-plugin": "^0.8.0",
88
+ "eslint-plugin-eslint-plugin": "^1.2.0",
89
89
  "eslint-plugin-node": "^5.1.0",
90
90
  "eslint-release": "^0.10.1",
91
91
  "eslump": "1.6.0",
92
- "esprima": "^3.1.3",
92
+ "esprima": "^4.0.0",
93
93
  "esprima-fb": "^15001.1001.0-dev-harmony-fb",
94
94
  "istanbul": "^0.4.5",
95
95
  "jsdoc": "^3.4.3",
@@ -100,7 +100,7 @@
100
100
  "karma-phantomjs-launcher": "^1.0.4",
101
101
  "leche": "^2.1.2",
102
102
  "load-perf": "^0.2.0",
103
- "markdownlint": "^0.5.0",
103
+ "markdownlint": "^0.6.1",
104
104
  "mocha": "^3.4.2",
105
105
  "mock-fs": "^4.3.0",
106
106
  "npm-license": "^0.3.3",
@@ -108,7 +108,7 @@
108
108
  "proxyquire": "^1.8.0",
109
109
  "shelljs": "^0.7.7",
110
110
  "shelljs-nodecli": "~0.1.1",
111
- "sinon": "^2.3.2",
111
+ "sinon": "^3.2.1",
112
112
  "temp": "^0.8.3",
113
113
  "through": "^2.3.8"
114
114
  },
@@ -1,241 +0,0 @@
1
- /**
2
- * @fileoverview RuleContext utility for rules
3
- * @author Nicholas C. Zakas
4
- */
5
- "use strict";
6
-
7
- //------------------------------------------------------------------------------
8
- // Requirements
9
- //------------------------------------------------------------------------------
10
-
11
- const assert = require("assert");
12
- const ruleFixer = require("./util/rule-fixer");
13
-
14
- //------------------------------------------------------------------------------
15
- // Constants
16
- //------------------------------------------------------------------------------
17
-
18
- const PASSTHROUGHS = [
19
- "getAncestors",
20
- "getDeclaredVariables",
21
- "getFilename",
22
- "getScope",
23
- "getSourceCode",
24
- "markVariableAsUsed",
25
-
26
- // DEPRECATED
27
- "getAllComments",
28
- "getComments",
29
- "getFirstToken",
30
- "getFirstTokens",
31
- "getJSDocComment",
32
- "getLastToken",
33
- "getLastTokens",
34
- "getNodeByRangeIndex",
35
- "getSource",
36
- "getSourceLines",
37
- "getTokenAfter",
38
- "getTokenBefore",
39
- "getTokenByRangeStart",
40
- "getTokens",
41
- "getTokensAfter",
42
- "getTokensBefore",
43
- "getTokensBetween"
44
- ];
45
-
46
- //------------------------------------------------------------------------------
47
- // Typedefs
48
- //------------------------------------------------------------------------------
49
-
50
- /**
51
- * An error message description
52
- * @typedef {Object} MessageDescriptor
53
- * @property {string} nodeType The type of node.
54
- * @property {Location} loc The location of the problem.
55
- * @property {string} message The problem message.
56
- * @property {Object} [data] Optional data to use to fill in placeholders in the
57
- * message.
58
- * @property {Function} fix The function to call that creates a fix command.
59
- */
60
-
61
- //------------------------------------------------------------------------------
62
- // Module Definition
63
- //------------------------------------------------------------------------------
64
-
65
- /**
66
- * Compares items in a fixes array by range.
67
- * @param {Fix} a The first message.
68
- * @param {Fix} b The second message.
69
- * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal.
70
- * @private
71
- */
72
- function compareFixesByRange(a, b) {
73
- return a.range[0] - b.range[0] || a.range[1] - b.range[1];
74
- }
75
-
76
- /**
77
- * Merges the given fixes array into one.
78
- * @param {Fix[]} fixes The fixes to merge.
79
- * @param {SourceCode} sourceCode The source code object to get the text between fixes.
80
- * @returns {void}
81
- */
82
- function mergeFixes(fixes, sourceCode) {
83
- if (fixes.length === 0) {
84
- return null;
85
- }
86
- if (fixes.length === 1) {
87
- return fixes[0];
88
- }
89
-
90
- fixes.sort(compareFixesByRange);
91
-
92
- const originalText = sourceCode.text;
93
- const start = fixes[0].range[0];
94
- const end = fixes[fixes.length - 1].range[1];
95
- let text = "";
96
- let lastPos = Number.MIN_SAFE_INTEGER;
97
-
98
- for (const fix of fixes) {
99
- assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report.");
100
-
101
- if (fix.range[0] >= 0) {
102
- text += originalText.slice(Math.max(0, start, lastPos), fix.range[0]);
103
- }
104
- text += fix.text;
105
- lastPos = fix.range[1];
106
- }
107
- text += originalText.slice(Math.max(0, start, lastPos), end);
108
-
109
- return { range: [start, end], text };
110
- }
111
-
112
- /**
113
- * Gets one fix object from the given descriptor.
114
- * If the descriptor retrieves multiple fixes, this merges those to one.
115
- * @param {Object} descriptor The report descriptor.
116
- * @param {SourceCode} sourceCode The source code object to get text between fixes.
117
- * @returns {Fix} The got fix object.
118
- */
119
- function getFix(descriptor, sourceCode) {
120
- if (typeof descriptor.fix !== "function") {
121
- return null;
122
- }
123
-
124
- // @type {null | Fix | Fix[] | IterableIterator<Fix>}
125
- const fix = descriptor.fix(ruleFixer);
126
-
127
- // Merge to one.
128
- if (fix && Symbol.iterator in fix) {
129
- return mergeFixes(Array.from(fix), sourceCode);
130
- }
131
- return fix;
132
- }
133
-
134
- /**
135
- * Rule context class
136
- * Acts as an abstraction layer between rules and the main linter object.
137
- */
138
- class RuleContext {
139
-
140
- /**
141
- * @param {string} ruleId The ID of the rule using this object.
142
- * @param {Linter} linter The linter object.
143
- * @param {number} severity The configured severity level of the rule.
144
- * @param {Array} options The configuration information to be added to the rule.
145
- * @param {Object} settings The configuration settings passed from the config file.
146
- * @param {Object} parserOptions The parserOptions settings passed from the config file.
147
- * @param {Object} parserPath The parser setting passed from the config file.
148
- * @param {Object} meta The metadata of the rule
149
- * @param {Object} parserServices The parser services for the rule.
150
- */
151
- constructor(ruleId, linter, severity, options, settings, parserOptions, parserPath, meta, parserServices) {
152
-
153
- // public.
154
- this.id = ruleId;
155
- this.options = options;
156
- this.settings = settings;
157
- this.parserOptions = parserOptions;
158
- this.parserPath = parserPath;
159
- this.meta = meta;
160
-
161
- // create a separate copy and freeze it (it's not nice to freeze other people's objects)
162
- this.parserServices = Object.freeze(Object.assign({}, parserServices));
163
-
164
- // private.
165
- this._linter = linter;
166
- this._severity = severity;
167
-
168
- Object.freeze(this);
169
- }
170
-
171
- /**
172
- * Passthrough to Linter#report() that automatically assigns the rule ID and severity.
173
- * @param {ASTNode|MessageDescriptor} nodeOrDescriptor The AST node related to the message or a message
174
- * descriptor.
175
- * @param {Object=} location The location of the error.
176
- * @param {string} message The message to display to the user.
177
- * @param {Object} opts Optional template data which produces a formatted message
178
- * with symbols being replaced by this object's values.
179
- * @returns {void}
180
- */
181
- report(nodeOrDescriptor, location, message, opts) {
182
-
183
- // check to see if it's a new style call
184
- if (arguments.length === 1) {
185
- const descriptor = nodeOrDescriptor;
186
- const fix = getFix(descriptor, this.getSourceCode());
187
-
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(
217
- this.id,
218
- this._severity,
219
- nodeOrDescriptor,
220
- location,
221
- message,
222
- opts,
223
- this.meta
224
- );
225
- }
226
- }
227
- }
228
-
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
- });
240
-
241
- module.exports = RuleContext;