eslint 6.0.0-alpha.1 → 6.0.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 (246) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +28 -21
  3. package/bin/eslint.js +2 -2
  4. package/conf/config-schema.js +38 -31
  5. package/conf/environments.js +1 -1
  6. package/conf/eslint-all.js +2 -2
  7. package/conf/eslint-recommended.js +1 -1
  8. package/lib/api.js +7 -3
  9. package/lib/cli-engine/cascading-config-array-factory.js +20 -8
  10. package/lib/{cli-engine.js → cli-engine/cli-engine.js} +44 -21
  11. package/lib/cli-engine/config-array/config-array.js +7 -8
  12. package/lib/cli-engine/config-array/config-dependency.js +2 -2
  13. package/lib/cli-engine/config-array/extracted-config.js +3 -3
  14. package/lib/cli-engine/config-array/override-tester.js +11 -1
  15. package/lib/cli-engine/config-array-factory.js +75 -65
  16. package/lib/cli-engine/file-enumerator.js +14 -6
  17. package/lib/{formatters → cli-engine/formatters}/checkstyle.js +1 -1
  18. package/lib/{formatters → cli-engine/formatters}/codeframe.js +0 -0
  19. package/lib/{formatters → cli-engine/formatters}/compact.js +0 -0
  20. package/lib/{formatters → cli-engine/formatters}/html-template-message.html +0 -0
  21. package/lib/{formatters → cli-engine/formatters}/html-template-page.html +0 -0
  22. package/lib/{formatters → cli-engine/formatters}/html-template-result.html +0 -0
  23. package/lib/{formatters → cli-engine/formatters}/html.js +0 -0
  24. package/lib/{formatters → cli-engine/formatters}/jslint-xml.js +1 -1
  25. package/lib/{formatters → cli-engine/formatters}/json-with-metadata.js +0 -0
  26. package/lib/{formatters → cli-engine/formatters}/json.js +0 -0
  27. package/lib/{formatters → cli-engine/formatters}/junit.js +15 -3
  28. package/lib/{formatters → cli-engine/formatters}/stylish.js +0 -0
  29. package/lib/{formatters → cli-engine/formatters}/table.js +0 -0
  30. package/lib/{formatters → cli-engine/formatters}/tap.js +0 -0
  31. package/lib/{formatters → cli-engine/formatters}/unix.js +0 -0
  32. package/lib/{formatters → cli-engine/formatters}/visualstudio.js +0 -0
  33. package/lib/{util → cli-engine}/hash.js +0 -0
  34. package/lib/{util → cli-engine}/ignored-paths.js +6 -1
  35. package/lib/cli-engine/index.js +7 -0
  36. package/lib/{util → cli-engine}/lint-result-cache.js +0 -0
  37. package/lib/{load-rules.js → cli-engine/load-rules.js} +0 -0
  38. package/lib/{util → cli-engine}/naming.js +0 -0
  39. package/lib/{util → cli-engine}/xml-escape.js +0 -0
  40. package/lib/cli.js +3 -3
  41. package/lib/{config → init}/autoconfig.js +3 -3
  42. package/lib/{config → init}/config-file.js +0 -0
  43. package/lib/{config → init}/config-initializer.js +6 -6
  44. package/lib/{config → init}/config-rule.js +8 -2
  45. package/lib/{util → init}/npm-utils.js +1 -1
  46. package/lib/{util → init}/source-code-utils.js +16 -1
  47. package/lib/{util → linter}/apply-disable-directives.js +0 -0
  48. package/lib/{code-path-analysis → linter/code-path-analysis}/code-path-analyzer.js +19 -6
  49. package/lib/{code-path-analysis → linter/code-path-analysis}/code-path-segment.js +0 -0
  50. package/lib/{code-path-analysis → linter/code-path-analysis}/code-path-state.js +0 -0
  51. package/lib/{code-path-analysis → linter/code-path-analysis}/code-path.js +0 -0
  52. package/lib/{code-path-analysis → linter/code-path-analysis}/debug-helpers.js +0 -0
  53. package/lib/{code-path-analysis → linter/code-path-analysis}/fork-context.js +0 -0
  54. package/lib/{code-path-analysis → linter/code-path-analysis}/id-generator.js +0 -0
  55. package/lib/{util → linter}/config-comment-parser.js +1 -1
  56. package/lib/linter/index.js +13 -0
  57. package/lib/{util → linter}/interpolate.js +0 -0
  58. package/lib/{linter.js → linter/linter.js} +298 -152
  59. package/lib/{util → linter}/node-event-generator.js +7 -5
  60. package/lib/{util → linter}/report-translator.js +0 -0
  61. package/lib/{util → linter}/rule-fixer.js +0 -0
  62. package/lib/{rules.js → linter/rules.js} +3 -29
  63. package/lib/{util → linter}/safe-emitter.js +0 -0
  64. package/lib/{util → linter}/source-code-fixer.js +0 -0
  65. package/lib/{util → linter}/timing.js +1 -1
  66. package/lib/rule-tester/index.js +5 -0
  67. package/lib/{testers → rule-tester}/rule-tester.js +43 -15
  68. package/lib/rules/array-bracket-newline.js +1 -1
  69. package/lib/rules/array-bracket-spacing.js +1 -1
  70. package/lib/rules/array-callback-return.js +1 -1
  71. package/lib/rules/array-element-newline.js +1 -1
  72. package/lib/rules/arrow-body-style.js +1 -1
  73. package/lib/rules/arrow-parens.js +22 -1
  74. package/lib/rules/arrow-spacing.js +1 -1
  75. package/lib/rules/block-spacing.js +1 -1
  76. package/lib/rules/brace-style.js +1 -1
  77. package/lib/rules/capitalized-comments.js +2 -2
  78. package/lib/rules/comma-dangle.js +1 -1
  79. package/lib/rules/comma-spacing.js +1 -1
  80. package/lib/rules/comma-style.js +1 -1
  81. package/lib/rules/complexity.js +3 -3
  82. package/lib/rules/computed-property-spacing.js +1 -1
  83. package/lib/rules/consistent-return.js +1 -1
  84. package/lib/rules/curly.js +1 -1
  85. package/lib/rules/dot-location.js +1 -1
  86. package/lib/rules/dot-notation.js +2 -2
  87. package/lib/rules/eqeqeq.js +1 -1
  88. package/lib/rules/func-call-spacing.js +1 -1
  89. package/lib/rules/func-name-matching.js +1 -1
  90. package/lib/rules/func-names.js +1 -1
  91. package/lib/rules/function-paren-newline.js +1 -1
  92. package/lib/rules/getter-return.js +1 -1
  93. package/lib/rules/implicit-arrow-linebreak.js +1 -1
  94. package/lib/rules/indent-legacy.js +1 -1
  95. package/lib/rules/indent.js +1 -1
  96. package/lib/rules/index.js +281 -0
  97. package/lib/rules/jsx-quotes.js +1 -1
  98. package/lib/rules/key-spacing.js +1 -1
  99. package/lib/rules/keyword-spacing.js +2 -2
  100. package/lib/rules/line-comment-position.js +1 -1
  101. package/lib/rules/linebreak-style.js +1 -1
  102. package/lib/rules/lines-around-comment.js +1 -1
  103. package/lib/rules/lines-around-directive.js +1 -1
  104. package/lib/rules/lines-between-class-members.js +1 -1
  105. package/lib/rules/max-classes-per-file.js +2 -1
  106. package/lib/rules/max-depth.js +2 -2
  107. package/lib/rules/max-len.js +11 -4
  108. package/lib/rules/max-lines-per-function.js +4 -2
  109. package/lib/rules/max-lines.js +2 -2
  110. package/lib/rules/max-params.js +1 -1
  111. package/lib/rules/max-statements-per-line.js +1 -1
  112. package/lib/rules/max-statements.js +1 -1
  113. package/lib/rules/multiline-comment-style.js +3 -2
  114. package/lib/rules/multiline-ternary.js +1 -1
  115. package/lib/rules/new-parens.js +43 -11
  116. package/lib/rules/newline-after-var.js +1 -1
  117. package/lib/rules/newline-per-chained-call.js +1 -1
  118. package/lib/rules/no-alert.js +1 -1
  119. package/lib/rules/no-catch-shadow.js +1 -1
  120. package/lib/rules/no-class-assign.js +1 -1
  121. package/lib/rules/no-cond-assign.js +1 -1
  122. package/lib/rules/no-confusing-arrow.js +1 -1
  123. package/lib/rules/no-console.js +1 -1
  124. package/lib/rules/no-const-assign.js +1 -1
  125. package/lib/rules/no-div-regex.js +9 -1
  126. package/lib/rules/no-dupe-keys.js +1 -1
  127. package/lib/rules/no-else-return.js +129 -2
  128. package/lib/rules/no-empty-function.js +1 -1
  129. package/lib/rules/no-empty.js +1 -1
  130. package/lib/rules/no-eval.js +1 -1
  131. package/lib/rules/no-ex-assign.js +1 -1
  132. package/lib/rules/no-extend-native.js +1 -1
  133. package/lib/rules/no-extra-bind.js +1 -1
  134. package/lib/rules/no-extra-boolean-cast.js +1 -1
  135. package/lib/rules/no-extra-label.js +1 -1
  136. package/lib/rules/no-extra-parens.js +1 -1
  137. package/lib/rules/no-extra-semi.js +2 -2
  138. package/lib/rules/no-floating-decimal.js +1 -1
  139. package/lib/rules/no-func-assign.js +1 -1
  140. package/lib/rules/no-implicit-coercion.js +1 -1
  141. package/lib/rules/no-inline-comments.js +1 -1
  142. package/lib/rules/no-invalid-this.js +1 -1
  143. package/lib/rules/no-irregular-whitespace.js +1 -1
  144. package/lib/rules/no-label-var.js +1 -1
  145. package/lib/rules/no-labels.js +1 -1
  146. package/lib/rules/no-misleading-character-class.js +1 -1
  147. package/lib/rules/no-mixed-operators.js +1 -1
  148. package/lib/rules/no-multi-spaces.js +1 -1
  149. package/lib/rules/no-multi-str.js +1 -1
  150. package/lib/rules/no-octal.js +1 -1
  151. package/lib/rules/no-redeclare.js +1 -1
  152. package/lib/rules/no-regex-spaces.js +1 -1
  153. package/lib/rules/no-restricted-imports.js +18 -14
  154. package/lib/rules/no-restricted-properties.js +1 -1
  155. package/lib/rules/no-return-assign.js +1 -1
  156. package/lib/rules/no-return-await.js +1 -1
  157. package/lib/rules/no-self-assign.js +1 -1
  158. package/lib/rules/no-sequences.js +1 -1
  159. package/lib/rules/no-shadow.js +1 -1
  160. package/lib/rules/no-this-before-super.js +1 -1
  161. package/lib/rules/no-throw-literal.js +1 -1
  162. package/lib/rules/no-trailing-spaces.js +1 -1
  163. package/lib/rules/no-undef-init.js +1 -1
  164. package/lib/rules/no-unexpected-multiline.js +1 -1
  165. package/lib/rules/no-unmodified-loop-condition.js +2 -2
  166. package/lib/rules/no-unneeded-ternary.js +1 -1
  167. package/lib/rules/no-unsafe-negation.js +1 -1
  168. package/lib/rules/no-unused-vars.js +1 -1
  169. package/lib/rules/no-useless-call.js +1 -1
  170. package/lib/rules/no-useless-computed-key.js +1 -1
  171. package/lib/rules/no-useless-concat.js +1 -1
  172. package/lib/rules/no-useless-escape.js +7 -2
  173. package/lib/rules/no-useless-return.js +2 -2
  174. package/lib/rules/no-var.js +15 -2
  175. package/lib/rules/no-warning-comments.js +1 -1
  176. package/lib/rules/no-whitespace-before-property.js +1 -1
  177. package/lib/rules/object-curly-newline.js +1 -1
  178. package/lib/rules/object-curly-spacing.js +1 -1
  179. package/lib/rules/object-shorthand.js +1 -1
  180. package/lib/rules/operator-assignment.js +1 -1
  181. package/lib/rules/operator-linebreak.js +1 -1
  182. package/lib/rules/padded-blocks.js +1 -1
  183. package/lib/rules/padding-line-between-statements.js +1 -1
  184. package/lib/rules/prefer-const.js +1 -1
  185. package/lib/rules/prefer-object-spread.js +1 -1
  186. package/lib/rules/prefer-promise-reject-errors.js +1 -1
  187. package/lib/rules/prefer-spread.js +1 -1
  188. package/lib/rules/prefer-template.js +1 -1
  189. package/lib/rules/quote-props.js +1 -1
  190. package/lib/rules/quotes.js +1 -1
  191. package/lib/rules/radix.js +1 -1
  192. package/lib/rules/require-atomic-updates.js +63 -84
  193. package/lib/rules/require-await.js +1 -1
  194. package/lib/rules/semi-spacing.js +1 -1
  195. package/lib/rules/semi-style.js +1 -1
  196. package/lib/rules/semi.js +2 -2
  197. package/lib/rules/sort-keys.js +12 -4
  198. package/lib/rules/space-before-blocks.js +1 -1
  199. package/lib/rules/space-before-function-paren.js +1 -1
  200. package/lib/rules/space-in-parens.js +1 -1
  201. package/lib/rules/space-unary-ops.js +1 -1
  202. package/lib/rules/spaced-comment.js +1 -1
  203. package/lib/rules/strict.js +1 -1
  204. package/lib/rules/switch-colon-spacing.js +1 -1
  205. package/lib/rules/symbol-description.js +1 -1
  206. package/lib/rules/template-curly-spacing.js +1 -1
  207. package/lib/{util → rules/utils}/ast-utils.js +8 -27
  208. package/lib/{util → rules/utils}/fix-tracker.js +1 -1
  209. package/lib/{util → rules/utils}/keywords.js +0 -0
  210. package/lib/{util → rules/utils}/lazy-loading-rule-map.js +0 -0
  211. package/lib/{util → rules/utils}/patterns/letters.js +0 -0
  212. package/lib/{util → rules/utils}/unicode/index.js +0 -0
  213. package/lib/{util → rules/utils}/unicode/is-combining-character.js +0 -0
  214. package/lib/{util → rules/utils}/unicode/is-emoji-modifier.js +0 -0
  215. package/lib/{util → rules/utils}/unicode/is-regional-indicator-symbol.js +0 -0
  216. package/lib/{util → rules/utils}/unicode/is-surrogate-pair.js +0 -0
  217. package/lib/rules/valid-typeof.js +1 -1
  218. package/lib/rules/wrap-iife.js +1 -1
  219. package/lib/rules/yoda.js +1 -1
  220. package/lib/{util → shared}/ajv.js +0 -0
  221. package/lib/shared/ast-utils.js +29 -0
  222. package/lib/{config → shared}/config-ops.js +0 -0
  223. package/lib/{config → shared}/config-validator.js +22 -7
  224. package/lib/{util → shared}/logging.js +0 -0
  225. package/lib/{util → shared}/relative-module-resolver.js +10 -3
  226. package/lib/{util → shared}/traverser.js +0 -0
  227. package/lib/{util → shared}/types.js +4 -0
  228. package/lib/source-code/index.js +5 -0
  229. package/lib/{util → source-code}/source-code.js +10 -8
  230. package/lib/{token-store → source-code/token-store}/backward-token-comment-cursor.js +0 -0
  231. package/lib/{token-store → source-code/token-store}/backward-token-cursor.js +0 -0
  232. package/lib/{token-store → source-code/token-store}/cursor.js +0 -0
  233. package/lib/{token-store → source-code/token-store}/cursors.js +0 -0
  234. package/lib/{token-store → source-code/token-store}/decorative-cursor.js +0 -0
  235. package/lib/{token-store → source-code/token-store}/filter-cursor.js +0 -0
  236. package/lib/{token-store → source-code/token-store}/forward-token-comment-cursor.js +0 -0
  237. package/lib/{token-store → source-code/token-store}/forward-token-cursor.js +0 -0
  238. package/lib/{token-store → source-code/token-store}/index.js +3 -3
  239. package/lib/{token-store → source-code/token-store}/limit-cursor.js +0 -0
  240. package/lib/{token-store → source-code/token-store}/padded-token-cursor.js +0 -0
  241. package/lib/{token-store → source-code/token-store}/skip-cursor.js +0 -0
  242. package/lib/{token-store → source-code/token-store}/utils.js +0 -0
  243. package/messages/extend-config-missing.txt +2 -0
  244. package/messages/print-config-with-directory-path.txt +2 -0
  245. package/package.json +8 -11
  246. package/lib/built-in-rules-index.js +0 -281
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @fileoverview Main Linter Class
3
3
  * @author Gyandeep Singh
4
+ * @author aladdin-add
4
5
  */
5
6
 
6
7
  "use strict";
@@ -9,44 +10,49 @@
9
10
  // Requirements
10
11
  //------------------------------------------------------------------------------
11
12
 
12
- const path = require("path"),
13
+ const
14
+ path = require("path"),
13
15
  eslintScope = require("eslint-scope"),
14
16
  evk = require("eslint-visitor-keys"),
15
17
  espree = require("espree"),
16
18
  lodash = require("lodash"),
19
+ BuiltInEnvironments = require("../../conf/environments"),
20
+ pkg = require("../../package.json"),
21
+ astUtils = require("../shared/ast-utils"),
22
+ ConfigOps = require("../shared/config-ops"),
23
+ validator = require("../shared/config-validator"),
24
+ Traverser = require("../shared/traverser"),
25
+ { SourceCode } = require("../source-code"),
17
26
  CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
18
- ConfigOps = require("./config/config-ops"),
19
- validator = require("./config/config-validator"),
20
- BuiltInEnvironments = require("../conf/environments"),
21
- applyDisableDirectives = require("./util/apply-disable-directives"),
22
- createEmitter = require("./util/safe-emitter"),
23
- NodeEventGenerator = require("./util/node-event-generator"),
24
- SourceCode = require("./util/source-code"),
25
- Traverser = require("./util/traverser"),
26
- createReportTranslator = require("./util/report-translator"),
27
+ applyDisableDirectives = require("./apply-disable-directives"),
28
+ ConfigCommentParser = require("./config-comment-parser"),
29
+ NodeEventGenerator = require("./node-event-generator"),
30
+ createReportTranslator = require("./report-translator"),
27
31
  Rules = require("./rules"),
28
- timing = require("./util/timing"),
29
- ConfigCommentParser = require("./util/config-comment-parser"),
30
- astUtils = require("./util/ast-utils"),
31
- pkg = require("../package.json"),
32
- SourceCodeFixer = require("./util/source-code-fixer");
32
+ createEmitter = require("./safe-emitter"),
33
+ SourceCodeFixer = require("./source-code-fixer"),
34
+ timing = require("./timing"),
35
+ ruleReplacements = require("../../conf/replacements.json");
33
36
 
34
37
  const debug = require("debug")("eslint:linter");
35
38
  const MAX_AUTOFIX_PASSES = 10;
36
39
  const DEFAULT_PARSER_NAME = "espree";
37
40
  const commentParser = new ConfigCommentParser();
41
+ const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } };
38
42
 
39
43
  //------------------------------------------------------------------------------
40
44
  // Typedefs
41
45
  //------------------------------------------------------------------------------
42
46
 
43
- /** @typedef {InstanceType<import("./cli-engine/config-array")["ConfigArray"]>} ConfigArray */
44
- /** @typedef {import("./util/types").ConfigData} ConfigData */
45
- /** @typedef {import("./util/types").Environment} Environment */
46
- /** @typedef {import("./util/types").GlobalConf} GlobalConf */
47
- /** @typedef {import("./util/types").LintMessage} LintMessage */
48
- /** @typedef {import("./util/types").ParserOptions} ParserOptions */
49
- /** @typedef {import("./util/types").Rule} Rule */
47
+ /** @typedef {InstanceType<import("../cli-engine/config-array")["ConfigArray"]>} ConfigArray */
48
+ /** @typedef {InstanceType<import("../cli-engine/config-array")["ExtractedConfig"]>} ExtractedConfig */
49
+ /** @typedef {import("../shared/types").ConfigData} ConfigData */
50
+ /** @typedef {import("../shared/types").Environment} Environment */
51
+ /** @typedef {import("../shared/types").GlobalConf} GlobalConf */
52
+ /** @typedef {import("../shared/types").LintMessage} LintMessage */
53
+ /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
54
+ /** @typedef {import("../shared/types").Processor} Processor */
55
+ /** @typedef {import("../shared/types").Rule} Rule */
50
56
 
51
57
  /**
52
58
  * @typedef {Object} DisableDirective
@@ -65,6 +71,38 @@ const commentParser = new ConfigCommentParser();
65
71
  * @property {Rules} ruleMap The loaded rules.
66
72
  */
67
73
 
74
+ /**
75
+ * @typedef {Object} VerifyOptions
76
+ * @property {boolean} [allowInlineConfig] Allow/disallow inline comments' ability
77
+ * to change config once it is set. Defaults to true if not supplied.
78
+ * Useful if you want to validate JS without comments overriding rules.
79
+ * @property {boolean} [disableFixes] if `true` then the linter doesn't make `fix`
80
+ * properties into the lint result.
81
+ * @property {string} [filename] the filename of the source code.
82
+ * @property {boolean} [reportUnusedDisableDirectives] Adds reported errors for
83
+ * unused `eslint-disable` directives.
84
+ */
85
+
86
+ /**
87
+ * @typedef {Object} ProcessorOptions
88
+ * @property {(filename:string, text:string) => boolean} [filterCodeBlock] the
89
+ * predicate function that selects adopt code blocks.
90
+ * @property {Processor["postprocess"]} [postprocess] postprocessor for report
91
+ * messages. If provided, this should accept an array of the message lists
92
+ * for each code block returned from the preprocessor, apply a mapping to
93
+ * the messages as appropriate, and return a one-dimensional array of
94
+ * messages.
95
+ * @property {Processor["preprocess"]} [preprocess] preprocessor for source text.
96
+ * If provided, this should accept a string of source text, and return an
97
+ * array of code blocks to lint.
98
+ */
99
+
100
+ /**
101
+ * @typedef {Object} FixOptions
102
+ * @property {boolean | ((message: LintMessage) => boolean)} [fix] Determines
103
+ * whether fixes should be applied.
104
+ */
105
+
68
106
  //------------------------------------------------------------------------------
69
107
  // Helpers
70
108
  //------------------------------------------------------------------------------
@@ -145,19 +183,71 @@ function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, ena
145
183
  });
146
184
  }
147
185
 
186
+ /**
187
+ * creates a missing-rule message.
188
+ * @param {string} ruleId the ruleId to create
189
+ * @returns {string} created error message
190
+ * @private
191
+ */
192
+ function createMissingRuleMessage(ruleId) {
193
+ return Object.prototype.hasOwnProperty.call(ruleReplacements.rules, ruleId)
194
+ ? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
195
+ : `Definition for rule '${ruleId}' was not found.`;
196
+ }
197
+
198
+ /**
199
+ * creates a linting problem
200
+ * @param {Object} options to create linting error
201
+ * @param {string} options.ruleId the ruleId to report
202
+ * @param {Object} options.loc the loc to report
203
+ * @param {string} options.message the error message to report
204
+ * @returns {Problem} created problem, returns a missing-rule problem if only provided ruleId.
205
+ * @private
206
+ */
207
+ function createLintingProblem(options) {
208
+ const { ruleId, loc = DEFAULT_ERROR_LOC, message = createMissingRuleMessage(options.ruleId) } = options;
209
+
210
+ return {
211
+ ruleId,
212
+ message,
213
+ line: loc.start.line,
214
+ column: loc.start.column + 1,
215
+ endLine: loc.end.line,
216
+ endColumn: loc.end.column + 1,
217
+ severity: 2,
218
+ nodeType: null
219
+ };
220
+ }
221
+
148
222
  /**
149
223
  * Creates a collection of disable directives from a comment
150
- * @param {("disable"|"enable"|"disable-line"|"disable-next-line")} type The type of directive comment
151
- * @param {{line: number, column: number}} loc The 0-based location of the comment token
152
- * @param {string} value The value after the directive in the comment
224
+ * @param {Object} options to create disable directives
225
+ * @param {("disable"|"enable"|"disable-line"|"disable-next-line")} options.type The type of directive comment
226
+ * @param {{line: number, column: number}} options.loc The 0-based location of the comment token
227
+ * @param {string} options.value The value after the directive in the comment
153
228
  * comment specified no specific rules, so it applies to all rules (e.g. `eslint-disable`)
154
- * @returns {DisableDirective[]} Directives from the comment
229
+ * @param {function(string): {create: Function}} options.ruleMapper A map from rule IDs to defined rules
230
+ * @returns {Object} Directives and problems from the comment
155
231
  */
156
- function createDisableDirectives(type, loc, value) {
232
+ function createDisableDirectives(options) {
233
+ const { type, loc, value, ruleMapper } = options;
157
234
  const ruleIds = Object.keys(commentParser.parseListConfig(value));
158
235
  const directiveRules = ruleIds.length ? ruleIds : [null];
236
+ const result = {
237
+ directives: [], // valid disable directives
238
+ directiveProblems: [] // problems in directives
239
+ };
240
+
241
+ for (const ruleId of directiveRules) {
159
242
 
160
- return directiveRules.map(ruleId => ({ type, line: loc.line, column: loc.column + 1, ruleId }));
243
+ // push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
244
+ if (ruleId === null || ruleMapper(ruleId) !== null) {
245
+ result.directives.push({ type, line: loc.start.line, column: loc.start.column + 1, ruleId });
246
+ } else {
247
+ result.directiveProblems.push(createLintingProblem({ ruleId, loc }));
248
+ }
249
+ }
250
+ return result;
161
251
  }
162
252
 
163
253
  /**
@@ -186,23 +276,19 @@ function getDirectiveComments(filename, ast, ruleMapper) {
186
276
  }
187
277
 
188
278
  const directiveValue = trimmedCommentText.slice(match.index + match[1].length);
279
+ let directiveType = "";
189
280
 
190
281
  if (/^eslint-disable-(next-)?line$/u.test(match[1])) {
191
282
  if (comment.loc.start.line === comment.loc.end.line) {
192
- const directiveType = match[1].slice("eslint-".length);
193
-
194
- disableDirectives.push(...createDisableDirectives(directiveType, comment.loc.start, directiveValue));
283
+ directiveType = match[1].slice("eslint-".length);
195
284
  } else {
196
- problems.push({
285
+ const message = `${match[1]} comment should not span multiple lines.`;
286
+
287
+ problems.push(createLintingProblem({
197
288
  ruleId: null,
198
- severity: 2,
199
- message: `${match[1]} comment should not span multiple lines.`,
200
- line: comment.loc.start.line,
201
- column: comment.loc.start.column + 1,
202
- endLine: comment.loc.end.line,
203
- endColumn: comment.loc.end.column + 1,
204
- nodeType: null
205
- });
289
+ message,
290
+ loc: comment.loc
291
+ }));
206
292
  }
207
293
  } else if (comment.type === "Block") {
208
294
  switch (match[1]) {
@@ -218,16 +304,11 @@ function getDirectiveComments(filename, ast, ruleMapper) {
218
304
  try {
219
305
  normalizedValue = ConfigOps.normalizeConfigGlobal(value);
220
306
  } catch (err) {
221
- problems.push({
307
+ problems.push(createLintingProblem({
222
308
  ruleId: null,
223
- severity: 2,
224
- message: err.message,
225
- line: comment.loc.start.line,
226
- column: comment.loc.start.column + 1,
227
- endLine: comment.loc.end.line,
228
- endColumn: comment.loc.end.column + 1,
229
- nodeType: null
230
- });
309
+ loc: comment.loc,
310
+ message: err.message
311
+ }));
231
312
  continue;
232
313
  }
233
314
 
@@ -244,11 +325,11 @@ function getDirectiveComments(filename, ast, ruleMapper) {
244
325
  break;
245
326
 
246
327
  case "eslint-disable":
247
- disableDirectives.push(...createDisableDirectives("disable", comment.loc.start, directiveValue));
328
+ directiveType = "disable";
248
329
  break;
249
330
 
250
331
  case "eslint-enable":
251
- disableDirectives.push(...createDisableDirectives("enable", comment.loc.start, directiveValue));
332
+ directiveType = "enable";
252
333
  break;
253
334
 
254
335
  case "eslint": {
@@ -256,22 +337,27 @@ function getDirectiveComments(filename, ast, ruleMapper) {
256
337
 
257
338
  if (parseResult.success) {
258
339
  Object.keys(parseResult.config).forEach(name => {
340
+ const rule = ruleMapper(name);
259
341
  const ruleValue = parseResult.config[name];
260
342
 
343
+ if (rule === null) {
344
+ problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
345
+ return;
346
+ }
347
+
261
348
  try {
262
- validator.validateRuleOptions(ruleMapper(name), name, ruleValue);
349
+ validator.validateRuleOptions(rule, name, ruleValue);
263
350
  } catch (err) {
264
- problems.push({
351
+ problems.push(createLintingProblem({
265
352
  ruleId: name,
266
- severity: 2,
267
353
  message: err.message,
268
- line: comment.loc.start.line,
269
- column: comment.loc.start.column + 1,
270
- endLine: comment.loc.end.line,
271
- endColumn: comment.loc.end.column + 1,
272
- nodeType: null
273
- });
354
+ loc: comment.loc
355
+ }));
356
+
357
+ // do not apply the config, if found invalid options.
358
+ return;
274
359
  }
360
+
275
361
  configuredRules[name] = ruleValue;
276
362
  });
277
363
  } else {
@@ -284,6 +370,14 @@ function getDirectiveComments(filename, ast, ruleMapper) {
284
370
  // no default
285
371
  }
286
372
  }
373
+
374
+ if (directiveType !== "") {
375
+ const options = { type: directiveType, loc: comment.loc, value: directiveValue, ruleMapper };
376
+ const { directives, directiveProblems } = createDisableDirectives(options);
377
+
378
+ disableDirectives.push(...directives);
379
+ problems.push(...directiveProblems);
380
+ }
287
381
  });
288
382
 
289
383
  return {
@@ -328,21 +422,37 @@ function findEslintEnv(text) {
328
422
  return retv;
329
423
  }
330
424
 
425
+ /**
426
+ * Convert "/path/to/<text>" to "<text>".
427
+ * `CLIEngine#executeOnText()` method gives "/path/to/<text>" if the filename
428
+ * was omitted because `configArray.extractConfig()` requires an absolute path.
429
+ * But the linter should pass `<text>` to `RuleContext#getFilename()` in that
430
+ * case.
431
+ * Also, code blocks can have their virtual filename. If the parent filename was
432
+ * `<text>`, the virtual filename is `<text>/0_foo.js` or something like (i.e.,
433
+ * it's not an absolute path).
434
+ * @param {string} filename The filename to normalize.
435
+ * @returns {string} The normalized filename.
436
+ */
437
+ function normalizeFilename(filename) {
438
+ const parts = filename.split(path.sep);
439
+ const index = parts.lastIndexOf("<text>");
440
+
441
+ return index === -1 ? filename : parts.slice(index).join(path.sep);
442
+ }
443
+
331
444
  /**
332
445
  * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
333
446
  * consistent shape.
334
- * @param {(string|{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean})} providedOptions Options
335
- * @returns {{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean}} Normalized options
447
+ * @param {VerifyOptions} providedOptions Options
448
+ * @returns {Required<VerifyOptions>} Normalized options
336
449
  */
337
450
  function normalizeVerifyOptions(providedOptions) {
338
- const isObjectOptions = typeof providedOptions === "object";
339
- const providedFilename = isObjectOptions ? providedOptions.filename : providedOptions;
340
-
341
451
  return {
342
- filename: typeof providedFilename === "string" ? providedFilename : "<input>",
343
- allowInlineConfig: !isObjectOptions || providedOptions.allowInlineConfig !== false,
344
- reportUnusedDisableDirectives: isObjectOptions && !!providedOptions.reportUnusedDisableDirectives,
345
- disableFixes: Boolean(providedOptions && providedOptions.disableFixes)
452
+ filename: normalizeFilename(providedOptions.filename || "<input>"),
453
+ allowInlineConfig: providedOptions.allowInlineConfig !== false,
454
+ reportUnusedDisableDirectives: Boolean(providedOptions.reportUnusedDisableDirectives),
455
+ disableFixes: Boolean(providedOptions.disableFixes)
346
456
  };
347
457
  }
348
458
 
@@ -460,7 +570,7 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
460
570
  * @private
461
571
  */
462
572
  function parse(text, parser, providedParserOptions, filePath) {
463
- const textToParse = stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, (match, captured) => `//${captured}`);
573
+ const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => `//${captured}`);
464
574
  const parserOptions = Object.assign({}, providedParserOptions, {
465
575
  loc: true,
466
576
  range: true,
@@ -700,11 +810,18 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
700
810
  Object.keys(configuredRules).forEach(ruleId => {
701
811
  const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
702
812
 
813
+ // not load disabled rules
703
814
  if (severity === 0) {
704
815
  return;
705
816
  }
706
817
 
707
818
  const rule = ruleMapper(ruleId);
819
+
820
+ if (rule === null) {
821
+ lintingProblems.push(createLintingProblem({ ruleId }));
822
+ return;
823
+ }
824
+
708
825
  const messageIds = rule.meta && rule.meta.messages;
709
826
  let reportTranslator = null;
710
827
  const ruleContext = Object.freeze(
@@ -778,6 +895,22 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
778
895
  return lintingProblems;
779
896
  }
780
897
 
898
+ /**
899
+ * Ensure the source code to be a string.
900
+ * @param {string|SourceCode} textOrSourceCode The text or source code object.
901
+ * @returns {string} The source code text.
902
+ */
903
+ function ensureText(textOrSourceCode) {
904
+ if (typeof textOrSourceCode === "object") {
905
+ const { hasBOM, text } = textOrSourceCode;
906
+ const bom = hasBOM ? "\uFEFF" : "";
907
+
908
+ return bom + text;
909
+ }
910
+
911
+ return String(textOrSourceCode);
912
+ }
913
+
781
914
  /**
782
915
  * Get an environment.
783
916
  * @param {LinterInternalSlots} slots The internal slots of Linter.
@@ -796,13 +929,11 @@ function getEnv(slots, envId) {
796
929
  * Get a rule.
797
930
  * @param {LinterInternalSlots} slots The internal slots of Linter.
798
931
  * @param {string} ruleId The rule ID to get.
799
- * @returns {Rule} The rule.
932
+ * @returns {Rule|null} The rule.
800
933
  */
801
934
  function getRule(slots, ruleId) {
802
935
  return (
803
936
  (slots.lastConfigArray && slots.lastConfigArray.pluginRules.get(ruleId)) ||
804
-
805
- // This returns the stub for missing rules if the rule does not exist.
806
937
  slots.ruleMap.get(ruleId)
807
938
  );
808
939
  }
@@ -847,19 +978,13 @@ class Linter {
847
978
  * Same as linter.verify, except without support for processors.
848
979
  * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
849
980
  * @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
850
- * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked.
851
- * If this is not set, the filename will default to '<input>' in the rule context. If
852
- * an object, then it has "filename", "saveState", and "allowInlineConfig" properties.
853
- * @param {boolean} [filenameOrOptions.allowInlineConfig=true] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied.
854
- * Useful if you want to validate JS without comments overriding rules.
855
- * @param {boolean} [filenameOrOptions.reportUnusedDisableDirectives=false] Adds reported errors for unused
856
- * eslint-disable directives
981
+ * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
857
982
  * @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
858
983
  */
859
- _verifyWithoutProcessors(textOrSourceCode, providedConfig, filenameOrOptions) {
984
+ _verifyWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
860
985
  const slots = internalSlotsMap.get(this);
861
986
  const config = providedConfig || {};
862
- const options = normalizeVerifyOptions(filenameOrOptions);
987
+ const options = normalizeVerifyOptions(providedOptions);
863
988
  let text;
864
989
 
865
990
  // evaluate arguments
@@ -991,91 +1116,121 @@ class Linter {
991
1116
  * Verifies the text against the rules specified by the second argument.
992
1117
  * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
993
1118
  * @param {ConfigData|ConfigArray} config An ESLintConfig instance to configure everything.
994
- * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked.
1119
+ * @param {(string|(VerifyOptions&ProcessorOptions))} [filenameOrOptions] The optional filename of the file being checked.
995
1120
  * If this is not set, the filename will default to '<input>' in the rule context. If
996
- * an object, then it has "filename", "saveState", and "allowInlineConfig" properties.
997
- * @param {boolean} [filenameOrOptions.allowInlineConfig] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied.
998
- * Useful if you want to validate JS without comments overriding rules.
999
- * @param {function(string): string[]} [filenameOrOptions.preprocess] preprocessor for source text. If provided,
1000
- * this should accept a string of source text, and return an array of code blocks to lint.
1001
- * @param {function(Array<LintMessage[]>): LintMessage[]} [filenameOrOptions.postprocess] postprocessor for report messages. If provided,
1002
- * this should accept an array of the message lists for each code block returned from the preprocessor,
1003
- * apply a mapping to the messages as appropriate, and return a one-dimensional array of messages
1121
+ * an object, then it has "filename", "allowInlineConfig", and some properties.
1004
1122
  * @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
1005
1123
  */
1006
1124
  verify(textOrSourceCode, config, filenameOrOptions) {
1125
+ debug("Verify");
1126
+ const options = typeof filenameOrOptions === "string"
1127
+ ? { filename: filenameOrOptions }
1128
+ : filenameOrOptions || {};
1129
+
1130
+ // CLIEngine passes a `ConfigArray` object.
1007
1131
  if (config && typeof config.extractConfig === "function") {
1008
- return this._verifyWithConfigArray(
1009
- textOrSourceCode,
1010
- config,
1011
- typeof filenameOrOptions === "string"
1012
- ? { filename: filenameOrOptions }
1013
- : filenameOrOptions || {}
1014
- );
1132
+ return this._verifyWithConfigArray(textOrSourceCode, config, options);
1015
1133
  }
1016
1134
 
1017
- const preprocess = filenameOrOptions && filenameOrOptions.preprocess || (rawText => [rawText]);
1018
- const postprocess = filenameOrOptions && filenameOrOptions.postprocess || lodash.flatten;
1019
-
1020
- return postprocess(
1021
- preprocess(textOrSourceCode).map(
1022
- textBlock => this._verifyWithoutProcessors(textBlock, config, filenameOrOptions)
1023
- )
1024
- );
1135
+ /*
1136
+ * `Linter` doesn't support `overrides` property in configuration.
1137
+ * So we cannot apply multiple processors.
1138
+ */
1139
+ if (options.preprocess || options.postprocess) {
1140
+ return this._verifyWithProcessor(textOrSourceCode, config, options);
1141
+ }
1142
+ return this._verifyWithoutProcessors(textOrSourceCode, config, options);
1025
1143
  }
1026
1144
 
1027
1145
  /**
1028
1146
  * Verify a given code with `ConfigArray`.
1029
- * @param {string} text The source code string.
1147
+ * @param {string|SourceCode} textOrSourceCode The source code.
1030
1148
  * @param {ConfigArray} configArray The config array.
1031
- * @param {Object} providedOptions The options.
1149
+ * @param {VerifyOptions&ProcessorOptions} options The options.
1032
1150
  * @returns {LintMessage[]} The found problems.
1033
1151
  */
1034
- _verifyWithConfigArray(text, configArray, providedOptions) {
1035
- debug("Verify with ConfigArray");
1152
+ _verifyWithConfigArray(textOrSourceCode, configArray, options) {
1153
+ debug("With ConfigArray: %s", options.filename);
1036
1154
 
1037
1155
  // Store the config array in order to get plugin envs and rules later.
1038
1156
  internalSlotsMap.get(this).lastConfigArray = configArray;
1039
1157
 
1040
- /*
1041
- * TODO: implement https://github.com/eslint/rfcs/tree/master/designs/2018-processors-improvements here.
1042
- */
1043
-
1044
1158
  // Extract the final config for this file.
1045
- const config = configArray.extractConfig(providedOptions.filename);
1159
+ const config = configArray.extractConfig(options.filename);
1160
+ const processor =
1161
+ config.processor &&
1162
+ configArray.pluginProcessors.get(config.processor);
1046
1163
 
1047
- /*
1048
- * Convert "/path/to/<text>" to "<text>".
1049
- * `CLIEngine#executeOnText()` method gives "/path/to/<text>" if the
1050
- * filename was omitted because `configArray.extractConfig()` requires
1051
- * an absolute path. But linter should pass `<text>` to
1052
- * `RuleContext#getFilename()` in that case.
1053
- */
1054
- const filename = path.basename(providedOptions.filename) === "<text>"
1055
- ? "<text>"
1056
- : providedOptions.filename;
1057
-
1058
- // Make options.
1059
- const options = {
1060
- ...providedOptions,
1061
- filename
1062
- };
1164
+ // Verify.
1165
+ if (processor) {
1166
+ debug("Apply the processor: %o", config.processor);
1167
+ const { preprocess, postprocess, supportsAutofix } = processor;
1168
+ const disableFixes = options.disableFixes || !supportsAutofix;
1063
1169
 
1064
- // Apply processor.
1065
- if (config.processor) {
1066
- const processor = configArray.pluginProcessors.get(config.processor);
1170
+ return this._verifyWithProcessor(
1171
+ textOrSourceCode,
1172
+ config,
1173
+ { ...options, disableFixes, postprocess, preprocess },
1174
+ configArray
1175
+ );
1176
+ }
1177
+ return this._verifyWithoutProcessors(textOrSourceCode, config, options);
1178
+ }
1067
1179
 
1068
- options.preprocess = processor.preprocess;
1069
- options.postprocess = processor.postprocess;
1070
- if (!processor.supportsAutofix) {
1180
+ /**
1181
+ * Verify with a processor.
1182
+ * @param {string|SourceCode} textOrSourceCode The source code.
1183
+ * @param {ConfigData|ExtractedConfig} config The config array.
1184
+ * @param {VerifyOptions&ProcessorOptions} options The options.
1185
+ * @param {ConfigArray} [configForRecursive] The `CofnigArray` object to apply multiple processors recursively.
1186
+ * @returns {LintMessage[]} The found problems.
1187
+ */
1188
+ _verifyWithProcessor(textOrSourceCode, config, options, configForRecursive) {
1189
+ const filename = options.filename || "<input>";
1190
+ const filenameToExpose = normalizeFilename(filename);
1191
+ const text = ensureText(textOrSourceCode);
1192
+ const preprocess = options.preprocess || (rawText => [rawText]);
1193
+ const postprocess = options.postprocess || lodash.flatten;
1194
+ const filterCodeBlock =
1195
+ options.filterCodeBlock ||
1196
+ (blockFilename => blockFilename.endsWith(".js"));
1197
+ const originalExtname = path.extname(filename);
1198
+ const messageLists = preprocess(text, filenameToExpose).map((block, i) => {
1199
+ debug("A code block was found: %o", block.filename || "(unnamed)");
1200
+
1201
+ // Keep the legacy behavior.
1202
+ if (typeof block === "string") {
1203
+ return this._verifyWithoutProcessors(block, config, options);
1204
+ }
1205
+
1206
+ const blockText = block.text;
1207
+ const blockName = path.join(filename, `${i}_${block.filename}`);
1071
1208
 
1072
- // Use `disableFixes` of https://github.com/eslint/rfcs/tree/master/designs/2018-processors-improvements
1073
- options.disableFixes = true;
1209
+ // Skip this block if filtered.
1210
+ if (!filterCodeBlock(blockName, blockText)) {
1211
+ debug("This code block was skipped.");
1212
+ return [];
1074
1213
  }
1075
- }
1076
1214
 
1077
- // Verify.
1078
- return this.verify(text, config, options);
1215
+ // Resolve configuration again if the file extension was changed.
1216
+ if (configForRecursive && path.extname(blockName) !== originalExtname) {
1217
+ debug("Resolving configuration again because the file extension was changed.");
1218
+ return this._verifyWithConfigArray(
1219
+ blockText,
1220
+ configForRecursive,
1221
+ { ...options, filename: blockName }
1222
+ );
1223
+ }
1224
+
1225
+ // Does lint.
1226
+ return this._verifyWithoutProcessors(
1227
+ blockText,
1228
+ config,
1229
+ { ...options, filename: blockName }
1230
+ );
1231
+ });
1232
+
1233
+ return postprocess(messageLists, filenameToExpose);
1079
1234
  }
1080
1235
 
1081
1236
  /**
@@ -1138,16 +1293,7 @@ class Linter {
1138
1293
  * have been applied.
1139
1294
  * @param {string} text The source text to apply fixes to.
1140
1295
  * @param {ConfigData|ConfigArray} config The ESLint config object to use.
1141
- * @param {Object} options The ESLint options object to use.
1142
- * @param {string} options.filename The filename from which the text was read.
1143
- * @param {boolean} options.allowInlineConfig Flag indicating if inline comments
1144
- * should be allowed.
1145
- * @param {boolean|Function} options.fix Determines whether fixes should be applied
1146
- * @param {Function} options.preprocess preprocessor for source text. If provided, this should
1147
- * accept a string of source text, and return an array of code blocks to lint.
1148
- * @param {Function} options.postprocess postprocessor for report messages. If provided,
1149
- * this should accept an array of the message lists for each code block returned from the preprocessor,
1150
- * apply a mapping to the messages as appropriate, and return a one-dimensional array of messages
1296
+ * @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
1151
1297
  * @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
1152
1298
  * SourceCodeFixer.
1153
1299
  */