eslint 6.3.0 → 6.6.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.
- package/CHANGELOG.md +126 -0
- package/README.md +11 -10
- package/bin/eslint.js +38 -12
- package/lib/cli-engine/cascading-config-array-factory.js +2 -1
- package/lib/cli-engine/cli-engine.js +11 -11
- package/lib/cli-engine/config-array/config-array.js +0 -4
- package/lib/cli-engine/config-array/config-dependency.js +2 -0
- package/lib/cli-engine/config-array/override-tester.js +4 -2
- package/lib/cli-engine/config-array-factory.js +7 -1
- package/lib/cli-engine/file-enumerator.js +5 -3
- package/lib/cli-engine/formatters/html.js +1 -0
- package/lib/cli-engine/ignored-paths.js +4 -3
- package/lib/cli-engine/lint-result-cache.js +0 -1
- package/lib/cli.js +13 -12
- package/lib/init/autoconfig.js +1 -11
- package/lib/init/config-file.js +0 -1
- package/lib/init/config-initializer.js +0 -1
- package/lib/init/config-rule.js +3 -7
- package/lib/init/npm-utils.js +1 -6
- package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
- package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
- package/lib/linter/code-path-analysis/code-path-state.js +40 -81
- package/lib/linter/code-path-analysis/code-path.js +10 -11
- package/lib/linter/code-path-analysis/debug-helpers.js +9 -13
- package/lib/linter/code-path-analysis/fork-context.js +23 -34
- package/lib/linter/code-path-analysis/id-generator.js +2 -2
- package/lib/linter/linter.js +121 -96
- package/lib/linter/node-event-generator.js +3 -2
- package/lib/options.js +6 -0
- package/lib/rule-tester/rule-tester.js +7 -10
- package/lib/rules/accessor-pairs.js +59 -19
- package/lib/rules/array-bracket-newline.js +12 -15
- package/lib/rules/array-bracket-spacing.js +12 -12
- package/lib/rules/array-callback-return.js +6 -11
- package/lib/rules/array-element-newline.js +5 -8
- package/lib/rules/arrow-parens.js +0 -1
- package/lib/rules/block-scoped-var.js +3 -3
- package/lib/rules/block-spacing.js +4 -4
- package/lib/rules/capitalized-comments.js +2 -9
- package/lib/rules/class-methods-use-this.js +3 -3
- package/lib/rules/comma-dangle.js +15 -23
- package/lib/rules/comma-spacing.js +1 -1
- package/lib/rules/computed-property-spacing.js +28 -11
- package/lib/rules/consistent-return.js +4 -5
- package/lib/rules/consistent-this.js +5 -5
- package/lib/rules/constructor-super.js +14 -16
- package/lib/rules/curly.js +3 -5
- package/lib/rules/default-param-last.js +62 -0
- package/lib/rules/dot-location.js +11 -12
- package/lib/rules/eqeqeq.js +7 -19
- package/lib/rules/func-names.js +6 -6
- package/lib/rules/function-call-argument-newline.js +5 -5
- package/lib/rules/generator-star-spacing.js +4 -9
- package/lib/rules/getter-return.js +4 -7
- package/lib/rules/indent-legacy.js +1 -1
- package/lib/rules/indent.js +46 -8
- package/lib/rules/index.js +3 -0
- package/lib/rules/init-declarations.js +2 -2
- package/lib/rules/jsx-quotes.js +1 -1
- package/lib/rules/keyword-spacing.js +32 -56
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/max-len.js +0 -5
- package/lib/rules/max-statements-per-line.js +3 -7
- package/lib/rules/multiline-ternary.js +3 -3
- package/lib/rules/new-parens.js +5 -1
- package/lib/rules/newline-after-var.js +6 -7
- package/lib/rules/newline-before-return.js +8 -9
- package/lib/rules/newline-per-chained-call.js +2 -4
- package/lib/rules/no-class-assign.js +2 -2
- package/lib/rules/no-compare-neg-zero.js +1 -2
- package/lib/rules/no-confusing-arrow.js +2 -2
- package/lib/rules/no-console.js +4 -8
- package/lib/rules/no-const-assign.js +1 -1
- package/lib/rules/no-dupe-args.js +1 -1
- package/lib/rules/no-dupe-class-members.js +3 -4
- package/lib/rules/no-dupe-keys.js +6 -5
- package/lib/rules/no-duplicate-imports.js +14 -18
- package/lib/rules/no-else-return.js +0 -8
- package/lib/rules/no-empty-function.js +2 -4
- package/lib/rules/no-eval.js +10 -18
- package/lib/rules/no-ex-assign.js +1 -1
- package/lib/rules/no-extra-bind.js +12 -13
- package/lib/rules/no-extra-boolean-cast.js +1 -3
- package/lib/rules/no-extra-label.js +13 -10
- package/lib/rules/no-extra-parens.js +32 -17
- package/lib/rules/no-extra-semi.js +5 -6
- package/lib/rules/no-fallthrough.js +6 -6
- package/lib/rules/no-func-assign.js +3 -3
- package/lib/rules/no-global-assign.js +4 -4
- package/lib/rules/no-implicit-coercion.js +10 -10
- package/lib/rules/no-implied-eval.js +0 -1
- package/lib/rules/no-import-assign.js +238 -0
- package/lib/rules/no-invalid-this.js +1 -3
- package/lib/rules/no-labels.js +3 -6
- package/lib/rules/no-lone-blocks.js +7 -2
- package/lib/rules/no-loop-func.js +6 -11
- package/lib/rules/no-magic-numbers.js +6 -6
- package/lib/rules/no-misleading-character-class.js +14 -7
- package/lib/rules/no-mixed-operators.js +13 -22
- package/lib/rules/no-mixed-requires.js +0 -1
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-native-reassign.js +4 -4
- package/lib/rules/no-obj-calls.js +29 -9
- package/lib/rules/no-octal-escape.js +14 -8
- package/lib/rules/no-param-reassign.js +28 -7
- package/lib/rules/no-redeclare.js +1 -1
- package/lib/rules/no-regex-spaces.js +105 -45
- package/lib/rules/no-restricted-imports.js +11 -11
- package/lib/rules/no-self-assign.js +18 -18
- package/lib/rules/no-sequences.js +5 -5
- package/lib/rules/no-shadow.js +1 -4
- package/lib/rules/no-tabs.js +8 -2
- package/lib/rules/no-this-before-super.js +12 -13
- package/lib/rules/no-trailing-spaces.js +19 -7
- package/lib/rules/no-undef-init.js +7 -1
- package/lib/rules/no-unmodified-loop-condition.js +16 -29
- package/lib/rules/no-unneeded-ternary.js +3 -3
- package/lib/rules/no-unreachable.js +7 -7
- package/lib/rules/no-unsafe-finally.js +4 -7
- package/lib/rules/no-unsafe-negation.js +34 -19
- package/lib/rules/no-unused-expressions.js +11 -7
- package/lib/rules/no-unused-labels.js +3 -6
- package/lib/rules/no-unused-vars.js +22 -29
- package/lib/rules/no-use-before-define.js +10 -15
- package/lib/rules/no-useless-call.js +4 -4
- package/lib/rules/no-useless-concat.js +4 -4
- package/lib/rules/no-useless-constructor.js +14 -22
- package/lib/rules/no-useless-escape.js +3 -5
- package/lib/rules/no-useless-rename.js +32 -20
- package/lib/rules/no-useless-return.js +11 -17
- package/lib/rules/no-var.js +12 -25
- package/lib/rules/no-warning-comments.js +0 -1
- package/lib/rules/no-whitespace-before-property.js +3 -3
- package/lib/rules/object-curly-newline.js +7 -10
- package/lib/rules/object-curly-spacing.js +14 -15
- package/lib/rules/object-shorthand.js +36 -10
- package/lib/rules/one-var-declaration-per-line.js +2 -2
- package/lib/rules/operator-assignment.js +22 -1
- package/lib/rules/padded-blocks.js +1 -1
- package/lib/rules/padding-line-between-statements.js +0 -16
- package/lib/rules/prefer-arrow-callback.js +6 -6
- package/lib/rules/prefer-const.js +13 -21
- package/lib/rules/prefer-destructuring.js +1 -7
- package/lib/rules/prefer-named-capture-group.js +3 -16
- package/lib/rules/prefer-numeric-literals.js +35 -3
- package/lib/rules/prefer-object-spread.js +7 -7
- package/lib/rules/prefer-regex-literals.js +125 -0
- package/lib/rules/prefer-rest-params.js +3 -6
- package/lib/rules/prefer-spread.js +4 -4
- package/lib/rules/prefer-template.js +5 -6
- package/lib/rules/quote-props.js +1 -1
- package/lib/rules/quotes.js +11 -6
- package/lib/rules/radix.js +5 -10
- package/lib/rules/require-await.js +2 -5
- package/lib/rules/require-yield.js +2 -2
- package/lib/rules/rest-spread-spacing.js +1 -1
- package/lib/rules/sort-imports.js +3 -4
- package/lib/rules/sort-keys.js +1 -3
- package/lib/rules/space-before-blocks.js +1 -2
- package/lib/rules/space-before-function-paren.js +12 -1
- package/lib/rules/space-in-parens.js +81 -75
- package/lib/rules/space-infix-ops.js +5 -5
- package/lib/rules/spaced-comment.js +15 -18
- package/lib/rules/strict.js +2 -4
- package/lib/rules/symbol-description.js +1 -2
- package/lib/rules/template-curly-spacing.js +2 -2
- package/lib/rules/use-isnan.js +104 -6
- package/lib/rules/utils/ast-utils.js +53 -81
- package/lib/rules/utils/fix-tracker.js +0 -6
- package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
- package/lib/rules/vars-on-top.js +11 -11
- package/lib/shared/config-ops.js +2 -2
- package/lib/shared/logging.js +2 -0
- package/lib/shared/runtime-info.js +163 -0
- package/lib/shared/traverser.js +2 -0
- package/lib/source-code/source-code.js +11 -12
- package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/backward-token-cursor.js +5 -5
- package/lib/source-code/token-store/cursors.js +17 -19
- package/lib/source-code/token-store/decorative-cursor.js +1 -1
- package/lib/source-code/token-store/filter-cursor.js +2 -2
- package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/forward-token-cursor.js +5 -5
- package/lib/source-code/token-store/index.js +86 -92
- package/lib/source-code/token-store/limit-cursor.js +2 -2
- package/lib/source-code/token-store/padded-token-cursor.js +7 -7
- package/lib/source-code/token-store/skip-cursor.js +2 -2
- package/lib/source-code/token-store/utils.js +9 -13
- package/package.json +8 -5
package/lib/linter/linter.js
CHANGED
@@ -292,10 +292,15 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
292
292
|
if (!match) {
|
293
293
|
return;
|
294
294
|
}
|
295
|
-
const
|
295
|
+
const directiveText = match[1];
|
296
|
+
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText);
|
296
297
|
|
297
|
-
if (
|
298
|
-
|
298
|
+
if (comment.type === "Line" && !lineCommentSupported) {
|
299
|
+
return;
|
300
|
+
}
|
301
|
+
|
302
|
+
if (warnInlineConfig) {
|
303
|
+
const kind = comment.type === "Block" ? `/*${directiveText}*/` : `//${directiveText}`;
|
299
304
|
|
300
305
|
problems.push(createLintingProblem({
|
301
306
|
ruleId: null,
|
@@ -306,108 +311,101 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|
306
311
|
return;
|
307
312
|
}
|
308
313
|
|
309
|
-
|
310
|
-
|
314
|
+
if (lineCommentSupported && comment.loc.start.line !== comment.loc.end.line) {
|
315
|
+
const message = `${directiveText} comment should not span multiple lines.`;
|
311
316
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
+
problems.push(createLintingProblem({
|
318
|
+
ruleId: null,
|
319
|
+
message,
|
320
|
+
loc: comment.loc
|
321
|
+
}));
|
322
|
+
return;
|
323
|
+
}
|
317
324
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
325
|
+
const directiveValue = trimmedCommentText.slice(match.index + directiveText.length);
|
326
|
+
|
327
|
+
switch (directiveText) {
|
328
|
+
case "eslint-disable":
|
329
|
+
case "eslint-enable":
|
330
|
+
case "eslint-disable-next-line":
|
331
|
+
case "eslint-disable-line": {
|
332
|
+
const directiveType = directiveText.slice("eslint-".length);
|
333
|
+
const options = { type: directiveType, loc: comment.loc, value: directiveValue, ruleMapper };
|
334
|
+
const { directives, directiveProblems } = createDisableDirectives(options);
|
335
|
+
|
336
|
+
disableDirectives.push(...directives);
|
337
|
+
problems.push(...directiveProblems);
|
338
|
+
break;
|
323
339
|
}
|
324
|
-
} else if (comment.type === "Block") {
|
325
|
-
switch (match[1]) {
|
326
|
-
case "exported":
|
327
|
-
Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
|
328
|
-
break;
|
329
340
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
341
|
+
case "exported":
|
342
|
+
Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
|
343
|
+
break;
|
344
|
+
|
345
|
+
case "globals":
|
346
|
+
case "global":
|
347
|
+
for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
|
348
|
+
let normalizedValue;
|
349
|
+
|
350
|
+
try {
|
351
|
+
normalizedValue = ConfigOps.normalizeConfigGlobal(value);
|
352
|
+
} catch (err) {
|
353
|
+
problems.push(createLintingProblem({
|
354
|
+
ruleId: null,
|
355
|
+
loc: comment.loc,
|
356
|
+
message: err.message
|
357
|
+
}));
|
358
|
+
continue;
|
359
|
+
}
|
360
|
+
|
361
|
+
if (enabledGlobals[id]) {
|
362
|
+
enabledGlobals[id].comments.push(comment);
|
363
|
+
enabledGlobals[id].value = normalizedValue;
|
364
|
+
} else {
|
365
|
+
enabledGlobals[id] = {
|
366
|
+
comments: [comment],
|
367
|
+
value: normalizedValue
|
368
|
+
};
|
369
|
+
}
|
370
|
+
}
|
371
|
+
break;
|
372
|
+
|
373
|
+
case "eslint": {
|
374
|
+
const parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc);
|
375
|
+
|
376
|
+
if (parseResult.success) {
|
377
|
+
Object.keys(parseResult.config).forEach(name => {
|
378
|
+
const rule = ruleMapper(name);
|
379
|
+
const ruleValue = parseResult.config[name];
|
380
|
+
|
381
|
+
if (rule === null) {
|
382
|
+
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
|
383
|
+
return;
|
384
|
+
}
|
334
385
|
|
335
386
|
try {
|
336
|
-
|
387
|
+
validator.validateRuleOptions(rule, name, ruleValue);
|
337
388
|
} catch (err) {
|
338
389
|
problems.push(createLintingProblem({
|
339
|
-
ruleId:
|
340
|
-
|
341
|
-
|
390
|
+
ruleId: name,
|
391
|
+
message: err.message,
|
392
|
+
loc: comment.loc
|
342
393
|
}));
|
343
|
-
continue;
|
344
|
-
}
|
345
394
|
|
346
|
-
|
347
|
-
|
348
|
-
enabledGlobals[id].value = normalizedValue;
|
349
|
-
} else {
|
350
|
-
enabledGlobals[id] = {
|
351
|
-
comments: [comment],
|
352
|
-
value: normalizedValue
|
353
|
-
};
|
395
|
+
// do not apply the config, if found invalid options.
|
396
|
+
return;
|
354
397
|
}
|
355
|
-
}
|
356
|
-
break;
|
357
|
-
|
358
|
-
case "eslint-disable":
|
359
|
-
directiveType = "disable";
|
360
|
-
break;
|
361
|
-
|
362
|
-
case "eslint-enable":
|
363
|
-
directiveType = "enable";
|
364
|
-
break;
|
365
|
-
|
366
|
-
case "eslint": {
|
367
|
-
const parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc);
|
368
|
-
|
369
|
-
if (parseResult.success) {
|
370
|
-
Object.keys(parseResult.config).forEach(name => {
|
371
|
-
const rule = ruleMapper(name);
|
372
|
-
const ruleValue = parseResult.config[name];
|
373
|
-
|
374
|
-
if (rule === null) {
|
375
|
-
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
|
376
|
-
return;
|
377
|
-
}
|
378
|
-
|
379
|
-
try {
|
380
|
-
validator.validateRuleOptions(rule, name, ruleValue);
|
381
|
-
} catch (err) {
|
382
|
-
problems.push(createLintingProblem({
|
383
|
-
ruleId: name,
|
384
|
-
message: err.message,
|
385
|
-
loc: comment.loc
|
386
|
-
}));
|
387
|
-
|
388
|
-
// do not apply the config, if found invalid options.
|
389
|
-
return;
|
390
|
-
}
|
391
|
-
|
392
|
-
configuredRules[name] = ruleValue;
|
393
|
-
});
|
394
|
-
} else {
|
395
|
-
problems.push(parseResult.error);
|
396
|
-
}
|
397
398
|
|
398
|
-
|
399
|
+
configuredRules[name] = ruleValue;
|
400
|
+
});
|
401
|
+
} else {
|
402
|
+
problems.push(parseResult.error);
|
399
403
|
}
|
400
404
|
|
401
|
-
|
405
|
+
break;
|
402
406
|
}
|
403
|
-
}
|
404
|
-
|
405
|
-
if (directiveType !== "") {
|
406
|
-
const options = { type: directiveType, loc: comment.loc, value: directiveValue, ruleMapper };
|
407
|
-
const { directives, directiveProblems } = createDisableDirectives(options);
|
408
407
|
|
409
|
-
|
410
|
-
problems.push(...directiveProblems);
|
408
|
+
// no default
|
411
409
|
}
|
412
410
|
});
|
413
411
|
|
@@ -438,7 +436,7 @@ const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//gu;
|
|
438
436
|
|
439
437
|
/**
|
440
438
|
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
|
441
|
-
* @param {string} text
|
439
|
+
* @param {string} text A source code text to check.
|
442
440
|
* @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
|
443
441
|
*/
|
444
442
|
function findEslintEnv(text) {
|
@@ -472,7 +470,6 @@ function normalizeFilename(filename) {
|
|
472
470
|
return index === -1 ? filename : parts.slice(index).join(path.sep);
|
473
471
|
}
|
474
472
|
|
475
|
-
// eslint-disable-next-line valid-jsdoc
|
476
473
|
/**
|
477
474
|
* Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
|
478
475
|
* consistent shape.
|
@@ -556,8 +553,7 @@ function resolveGlobals(providedGlobals, enabledEnvironments) {
|
|
556
553
|
|
557
554
|
/**
|
558
555
|
* Strips Unicode BOM from a given text.
|
559
|
-
*
|
560
|
-
* @param {string} text - A text to strip.
|
556
|
+
* @param {string} text A text to strip.
|
561
557
|
* @returns {string} The stripped text.
|
562
558
|
*/
|
563
559
|
function stripUnicodeBOM(text) {
|
@@ -670,6 +666,8 @@ function parse(text, parser, providedParserOptions, filePath) {
|
|
670
666
|
// If the message includes a leading line number, strip it:
|
671
667
|
const message = `Parsing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`;
|
672
668
|
|
669
|
+
debug("%s\n%s", message, ex.stack);
|
670
|
+
|
673
671
|
return {
|
674
672
|
success: false,
|
675
673
|
error: {
|
@@ -814,9 +812,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
814
812
|
* @param {Object} settings The settings that were enabled in the config
|
815
813
|
* @param {string} filename The reported filename of the code
|
816
814
|
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
815
|
+
* @param {string | undefined} cwd cwd of the cli
|
817
816
|
* @returns {Problem[]} An array of reported problems
|
818
817
|
*/
|
819
|
-
function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes) {
|
818
|
+
function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd) {
|
820
819
|
const emitter = createEmitter();
|
821
820
|
const nodeQueue = [];
|
822
821
|
let currentNode = sourceCode.ast;
|
@@ -843,6 +842,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|
843
842
|
{
|
844
843
|
getAncestors: () => getAncestors(currentNode),
|
845
844
|
getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
|
845
|
+
getCwd: () => cwd,
|
846
846
|
getFilename: () => filename,
|
847
847
|
getScope: () => getScope(sourceCode.scopeManager, currentNode),
|
848
848
|
getSourceCode: () => sourceCode,
|
@@ -989,6 +989,24 @@ function getRule(slots, ruleId) {
|
|
989
989
|
);
|
990
990
|
}
|
991
991
|
|
992
|
+
/**
|
993
|
+
* Normalize the value of the cwd
|
994
|
+
* @param {string | undefined} cwd raw value of the cwd, path to a directory that should be considered as the current working directory, can be undefined.
|
995
|
+
* @returns {string | undefined} normalized cwd
|
996
|
+
*/
|
997
|
+
function normalizeCwd(cwd) {
|
998
|
+
if (cwd) {
|
999
|
+
return cwd;
|
1000
|
+
}
|
1001
|
+
if (typeof process === "object") {
|
1002
|
+
return process.cwd();
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
// It's more explicit to assign the undefined
|
1006
|
+
// eslint-disable-next-line no-undefined
|
1007
|
+
return undefined;
|
1008
|
+
}
|
1009
|
+
|
992
1010
|
/**
|
993
1011
|
* The map to store private data.
|
994
1012
|
* @type {WeakMap<Linter, LinterInternalSlots>}
|
@@ -1005,8 +1023,14 @@ const internalSlotsMap = new WeakMap();
|
|
1005
1023
|
*/
|
1006
1024
|
class Linter {
|
1007
1025
|
|
1008
|
-
|
1026
|
+
/**
|
1027
|
+
* Initialize the Linter.
|
1028
|
+
* @param {Object} [config] the config object
|
1029
|
+
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1030
|
+
*/
|
1031
|
+
constructor({ cwd } = {}) {
|
1009
1032
|
internalSlotsMap.set(this, {
|
1033
|
+
cwd: normalizeCwd(cwd),
|
1010
1034
|
lastConfigArray: null,
|
1011
1035
|
lastSourceCode: null,
|
1012
1036
|
parserMap: new Map([["espree", espree]]),
|
@@ -1138,7 +1162,8 @@ class Linter {
|
|
1138
1162
|
parserName,
|
1139
1163
|
settings,
|
1140
1164
|
options.filename,
|
1141
|
-
options.disableFixes
|
1165
|
+
options.disableFixes,
|
1166
|
+
slots.cwd
|
1142
1167
|
);
|
1143
1168
|
} catch (err) {
|
1144
1169
|
err.message += `\nOccurred while linting ${options.filename}`;
|
@@ -202,6 +202,7 @@ const parseSelector = lodash.memoize(rawSelector => {
|
|
202
202
|
*/
|
203
203
|
class NodeEventGenerator {
|
204
204
|
|
205
|
+
// eslint-disable-next-line jsdoc/require-description
|
205
206
|
/**
|
206
207
|
* @param {SafeEmitter} emitter
|
207
208
|
* An SafeEmitter which is the destination of events. This emitter must already
|
@@ -286,7 +287,7 @@ class NodeEventGenerator {
|
|
286
287
|
|
287
288
|
/**
|
288
289
|
* Emits an event of entering AST node.
|
289
|
-
* @param {ASTNode} node
|
290
|
+
* @param {ASTNode} node A node which was entered.
|
290
291
|
* @returns {void}
|
291
292
|
*/
|
292
293
|
enterNode(node) {
|
@@ -298,7 +299,7 @@ class NodeEventGenerator {
|
|
298
299
|
|
299
300
|
/**
|
300
301
|
* Emits an event of leaving AST node.
|
301
|
-
* @param {ASTNode} node
|
302
|
+
* @param {ASTNode} node A node which was left.
|
302
303
|
* @returns {void}
|
303
304
|
*/
|
304
305
|
leaveNode(node) {
|
package/lib/options.js
CHANGED
@@ -224,6 +224,12 @@ module.exports = optionator({
|
|
224
224
|
default: "false",
|
225
225
|
description: "Run config initialization wizard"
|
226
226
|
},
|
227
|
+
{
|
228
|
+
option: "env-info",
|
229
|
+
type: "Boolean",
|
230
|
+
default: "false",
|
231
|
+
description: "Output execution environment information"
|
232
|
+
},
|
227
233
|
{
|
228
234
|
option: "debug",
|
229
235
|
type: "Boolean",
|
@@ -78,8 +78,7 @@ const hasOwnProperty = Function.call.bind(Object.hasOwnProperty);
|
|
78
78
|
/**
|
79
79
|
* Clones a given value deeply.
|
80
80
|
* Note: This ignores `parent` property.
|
81
|
-
*
|
82
|
-
* @param {any} x - A value to clone.
|
81
|
+
* @param {any} x A value to clone.
|
83
82
|
* @returns {any} A cloned value.
|
84
83
|
*/
|
85
84
|
function cloneDeeplyExcludesParent(x) {
|
@@ -104,8 +103,7 @@ function cloneDeeplyExcludesParent(x) {
|
|
104
103
|
|
105
104
|
/**
|
106
105
|
* Freezes a given value deeply.
|
107
|
-
*
|
108
|
-
* @param {any} x - A value to freeze.
|
106
|
+
* @param {any} x A value to freeze.
|
109
107
|
* @returns {void}
|
110
108
|
*/
|
111
109
|
function freezeDeeply(x) {
|
@@ -130,7 +128,7 @@ function freezeDeeply(x) {
|
|
130
128
|
*/
|
131
129
|
function sanitize(text) {
|
132
130
|
return text.replace(
|
133
|
-
/[\u0000-\
|
131
|
+
/[\u0000-\u0009|\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
|
134
132
|
c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
|
135
133
|
);
|
136
134
|
}
|
@@ -146,8 +144,8 @@ const IT = Symbol("it");
|
|
146
144
|
/**
|
147
145
|
* This is `it` default handler if `it` don't exist.
|
148
146
|
* @this {Mocha}
|
149
|
-
* @param {string} text
|
150
|
-
* @param {Function} method
|
147
|
+
* @param {string} text The description of the test case.
|
148
|
+
* @param {Function} method The logic of the test case.
|
151
149
|
* @returns {any} Returned value of `method`.
|
152
150
|
*/
|
153
151
|
function itDefaultHandler(text, method) {
|
@@ -164,8 +162,8 @@ function itDefaultHandler(text, method) {
|
|
164
162
|
/**
|
165
163
|
* This is `describe` default handler if `describe` don't exist.
|
166
164
|
* @this {Mocha}
|
167
|
-
* @param {string} text
|
168
|
-
* @param {Function} method
|
165
|
+
* @param {string} text The description of the test case.
|
166
|
+
* @param {Function} method The logic of the test case.
|
169
167
|
* @returns {any} Returned value of `method`.
|
170
168
|
*/
|
171
169
|
function describeDefaultHandler(text, method) {
|
@@ -177,7 +175,6 @@ class RuleTester {
|
|
177
175
|
/**
|
178
176
|
* Creates a new instance of RuleTester.
|
179
177
|
* @param {Object} [testerConfig] Optional, extra configuration for the tester
|
180
|
-
* @constructor
|
181
178
|
*/
|
182
179
|
constructor(testerConfig) {
|
183
180
|
|
@@ -79,7 +79,7 @@ function areEqualKeys(left, right) {
|
|
79
79
|
|
80
80
|
/**
|
81
81
|
* Checks whether or not a given node is of an accessor kind ('get' or 'set').
|
82
|
-
* @param {ASTNode} node
|
82
|
+
* @param {ASTNode} node A node to check.
|
83
83
|
* @returns {boolean} `true` if the node is of an accessor kind.
|
84
84
|
*/
|
85
85
|
function isAccessorKind(node) {
|
@@ -88,8 +88,8 @@ function isAccessorKind(node) {
|
|
88
88
|
|
89
89
|
/**
|
90
90
|
* Checks whether or not a given node is an `Identifier` node which was named a given name.
|
91
|
-
* @param {ASTNode} node
|
92
|
-
* @param {string} name
|
91
|
+
* @param {ASTNode} node A node to check.
|
92
|
+
* @param {string} name An expected name of the node.
|
93
93
|
* @returns {boolean} `true` if the node is an `Identifier` node which was named as expected.
|
94
94
|
*/
|
95
95
|
function isIdentifier(node, name) {
|
@@ -98,10 +98,10 @@ function isIdentifier(node, name) {
|
|
98
98
|
|
99
99
|
/**
|
100
100
|
* Checks whether or not a given node is an argument of a specified method call.
|
101
|
-
* @param {ASTNode} node
|
102
|
-
* @param {number} index
|
103
|
-
* @param {string} object
|
104
|
-
* @param {string} property
|
101
|
+
* @param {ASTNode} node A node to check.
|
102
|
+
* @param {number} index An expected index of the node in arguments.
|
103
|
+
* @param {string} object An expected name of the object of the method.
|
104
|
+
* @param {string} property An expected name of the method.
|
105
105
|
* @returns {boolean} `true` if the node is an argument of the specified method call.
|
106
106
|
*/
|
107
107
|
function isArgumentOfMethodCall(node, index, object, property) {
|
@@ -119,7 +119,7 @@ function isArgumentOfMethodCall(node, index, object, property) {
|
|
119
119
|
|
120
120
|
/**
|
121
121
|
* Checks whether or not a given node is a property descriptor.
|
122
|
-
* @param {ASTNode} node
|
122
|
+
* @param {ASTNode} node A node to check.
|
123
123
|
* @returns {boolean} `true` if the node is a property descriptor.
|
124
124
|
*/
|
125
125
|
function isPropertyDescriptor(node) {
|
@@ -152,7 +152,7 @@ module.exports = {
|
|
152
152
|
type: "suggestion",
|
153
153
|
|
154
154
|
docs: {
|
155
|
-
description: "enforce getter and setter pairs in objects",
|
155
|
+
description: "enforce getter and setter pairs in objects and classes",
|
156
156
|
category: "Best Practices",
|
157
157
|
recommended: false,
|
158
158
|
url: "https://eslint.org/docs/rules/accessor-pairs"
|
@@ -168,6 +168,10 @@ module.exports = {
|
|
168
168
|
setWithoutGet: {
|
169
169
|
type: "boolean",
|
170
170
|
default: true
|
171
|
+
},
|
172
|
+
enforceForClassMembers: {
|
173
|
+
type: "boolean",
|
174
|
+
default: false
|
171
175
|
}
|
172
176
|
},
|
173
177
|
additionalProperties: false
|
@@ -177,13 +181,16 @@ module.exports = {
|
|
177
181
|
missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.",
|
178
182
|
missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.",
|
179
183
|
missingGetterInObjectLiteral: "Getter is not present for {{ name }}.",
|
180
|
-
missingSetterInObjectLiteral: "Setter is not present for {{ name }}."
|
184
|
+
missingSetterInObjectLiteral: "Setter is not present for {{ name }}.",
|
185
|
+
missingGetterInClass: "Getter is not present for class {{ name }}.",
|
186
|
+
missingSetterInClass: "Setter is not present for class {{ name }}."
|
181
187
|
}
|
182
188
|
},
|
183
189
|
create(context) {
|
184
190
|
const config = context.options[0] || {};
|
185
191
|
const checkGetWithoutSet = config.getWithoutSet === true;
|
186
192
|
const checkSetWithoutGet = config.setWithoutGet !== false;
|
193
|
+
const enforceForClassMembers = config.enforceForClassMembers === true;
|
187
194
|
const sourceCode = context.getSourceCode();
|
188
195
|
|
189
196
|
/**
|
@@ -201,6 +208,13 @@ module.exports = {
|
|
201
208
|
loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
|
202
209
|
data: { name: astUtils.getFunctionNameWithKind(node.value) }
|
203
210
|
});
|
211
|
+
} else if (node.type === "MethodDefinition") {
|
212
|
+
context.report({
|
213
|
+
node,
|
214
|
+
messageId: `${messageKind}InClass`,
|
215
|
+
loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
|
216
|
+
data: { name: astUtils.getFunctionNameWithKind(node.value) }
|
217
|
+
});
|
204
218
|
} else {
|
205
219
|
context.report({
|
206
220
|
node,
|
@@ -313,15 +327,41 @@ module.exports = {
|
|
313
327
|
}
|
314
328
|
}
|
315
329
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
330
|
+
/**
|
331
|
+
* Checks the given object expression as an object literal and as a possible property descriptor.
|
332
|
+
* @param {ASTNode} node `ObjectExpression` node to check.
|
333
|
+
* @returns {void}
|
334
|
+
* @private
|
335
|
+
*/
|
336
|
+
function checkObjectExpression(node) {
|
337
|
+
checkObjectLiteral(node);
|
338
|
+
if (isPropertyDescriptor(node)) {
|
339
|
+
checkPropertyDescriptor(node);
|
324
340
|
}
|
325
|
-
}
|
341
|
+
}
|
342
|
+
|
343
|
+
/**
|
344
|
+
* Checks the given class body.
|
345
|
+
* @param {ASTNode} node `ClassBody` node to check.
|
346
|
+
* @returns {void}
|
347
|
+
* @private
|
348
|
+
*/
|
349
|
+
function checkClassBody(node) {
|
350
|
+
const methodDefinitions = node.body.filter(m => m.type === "MethodDefinition");
|
351
|
+
|
352
|
+
checkList(methodDefinitions.filter(m => m.static));
|
353
|
+
checkList(methodDefinitions.filter(m => !m.static));
|
354
|
+
}
|
355
|
+
|
356
|
+
const listeners = {};
|
357
|
+
|
358
|
+
if (checkSetWithoutGet || checkGetWithoutSet) {
|
359
|
+
listeners.ObjectExpression = checkObjectExpression;
|
360
|
+
if (enforceForClassMembers) {
|
361
|
+
listeners.ClassBody = checkClassBody;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
return listeners;
|
326
366
|
}
|
327
367
|
};
|
@@ -65,8 +65,7 @@ module.exports = {
|
|
65
65
|
|
66
66
|
/**
|
67
67
|
* Normalizes a given option value.
|
68
|
-
*
|
69
|
-
* @param {string|Object|undefined} option - An option value to parse.
|
68
|
+
* @param {string|Object|undefined} option An option value to parse.
|
70
69
|
* @returns {{multiline: boolean, minItems: number}} Normalized option object.
|
71
70
|
*/
|
72
71
|
function normalizeOptionValue(option) {
|
@@ -97,8 +96,7 @@ module.exports = {
|
|
97
96
|
|
98
97
|
/**
|
99
98
|
* Normalizes a given option value.
|
100
|
-
*
|
101
|
-
* @param {string|Object|undefined} options - An option value to parse.
|
99
|
+
* @param {string|Object|undefined} options An option value to parse.
|
102
100
|
* @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
|
103
101
|
*/
|
104
102
|
function normalizeOptions(options) {
|
@@ -109,8 +107,8 @@ module.exports = {
|
|
109
107
|
|
110
108
|
/**
|
111
109
|
* Reports that there shouldn't be a linebreak after the first token
|
112
|
-
* @param {ASTNode} node
|
113
|
-
* @param {Token} token
|
110
|
+
* @param {ASTNode} node The node to report in the event of an error.
|
111
|
+
* @param {Token} token The token to use for the report.
|
114
112
|
* @returns {void}
|
115
113
|
*/
|
116
114
|
function reportNoBeginningLinebreak(node, token) {
|
@@ -132,8 +130,8 @@ module.exports = {
|
|
132
130
|
|
133
131
|
/**
|
134
132
|
* Reports that there shouldn't be a linebreak before the last token
|
135
|
-
* @param {ASTNode} node
|
136
|
-
* @param {Token} token
|
133
|
+
* @param {ASTNode} node The node to report in the event of an error.
|
134
|
+
* @param {Token} token The token to use for the report.
|
137
135
|
* @returns {void}
|
138
136
|
*/
|
139
137
|
function reportNoEndingLinebreak(node, token) {
|
@@ -155,8 +153,8 @@ module.exports = {
|
|
155
153
|
|
156
154
|
/**
|
157
155
|
* Reports that there should be a linebreak after the first token
|
158
|
-
* @param {ASTNode} node
|
159
|
-
* @param {Token} token
|
156
|
+
* @param {ASTNode} node The node to report in the event of an error.
|
157
|
+
* @param {Token} token The token to use for the report.
|
160
158
|
* @returns {void}
|
161
159
|
*/
|
162
160
|
function reportRequiredBeginningLinebreak(node, token) {
|
@@ -172,8 +170,8 @@ module.exports = {
|
|
172
170
|
|
173
171
|
/**
|
174
172
|
* Reports that there should be a linebreak before the last token
|
175
|
-
* @param {ASTNode} node
|
176
|
-
* @param {Token} token
|
173
|
+
* @param {ASTNode} node The node to report in the event of an error.
|
174
|
+
* @param {Token} token The token to use for the report.
|
177
175
|
* @returns {void}
|
178
176
|
*/
|
179
177
|
function reportRequiredEndingLinebreak(node, token) {
|
@@ -189,8 +187,7 @@ module.exports = {
|
|
189
187
|
|
190
188
|
/**
|
191
189
|
* Reports a given node if it violated this rule.
|
192
|
-
*
|
193
|
-
* @param {ASTNode} node - A node to check. This is an ArrayExpression node or an ArrayPattern node.
|
190
|
+
* @param {ASTNode} node A node to check. This is an ArrayExpression node or an ArrayPattern node.
|
194
191
|
* @returns {void}
|
195
192
|
*/
|
196
193
|
function check(node) {
|
@@ -219,7 +216,7 @@ module.exports = {
|
|
219
216
|
) ||
|
220
217
|
(
|
221
218
|
options.consistent &&
|
222
|
-
|
219
|
+
openBracket.loc.end.line !== first.loc.start.line
|
223
220
|
)
|
224
221
|
);
|
225
222
|
|