eslint 8.56.0 → 9.0.0-alpha.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.
- package/README.md +7 -2
- package/conf/ecma-version.js +16 -0
- package/conf/rule-type-list.json +3 -1
- package/lib/api.js +1 -1
- package/lib/cli-engine/cli-engine.js +14 -3
- package/lib/cli-engine/formatters/formatters-meta.json +1 -29
- package/lib/cli-engine/lint-result-cache.js +2 -2
- package/lib/cli.js +46 -25
- package/lib/config/default-config.js +3 -0
- package/lib/config/flat-config-array.js +0 -20
- package/lib/config/flat-config-helpers.js +41 -20
- package/lib/config/flat-config-schema.js +35 -25
- package/lib/config/rule-validator.js +27 -4
- package/lib/eslint/eslint-helpers.js +32 -12
- package/lib/eslint/eslint.js +856 -373
- package/lib/eslint/index.js +2 -2
- package/lib/eslint/legacy-eslint.js +722 -0
- package/lib/linter/apply-disable-directives.js +35 -7
- package/lib/linter/code-path-analysis/code-path.js +5 -19
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/config-comment-parser.js +8 -11
- package/lib/linter/linter.js +196 -100
- package/lib/linter/report-translator.js +2 -2
- package/lib/linter/rules.js +6 -15
- package/lib/linter/source-code-fixer.js +1 -1
- package/lib/options.js +9 -1
- package/lib/rule-tester/rule-tester.js +234 -291
- package/lib/rules/array-bracket-newline.js +1 -1
- package/lib/rules/array-bracket-spacing.js +1 -1
- package/lib/rules/block-scoped-var.js +1 -1
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/comma-dangle.js +1 -1
- package/lib/rules/comma-style.js +2 -2
- package/lib/rules/complexity.js +1 -1
- package/lib/rules/constructor-super.js +1 -1
- package/lib/rules/default-case.js +1 -1
- package/lib/rules/eol-last.js +2 -2
- package/lib/rules/function-paren-newline.js +2 -2
- package/lib/rules/indent-legacy.js +5 -5
- package/lib/rules/indent.js +5 -5
- package/lib/rules/index.js +1 -2
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/line-comment-position.js +1 -1
- package/lib/rules/lines-around-directive.js +2 -2
- package/lib/rules/max-depth.js +1 -1
- package/lib/rules/max-len.js +3 -3
- package/lib/rules/max-lines.js +3 -3
- package/lib/rules/max-nested-callbacks.js +1 -1
- package/lib/rules/max-params.js +1 -1
- package/lib/rules/max-statements.js +1 -1
- package/lib/rules/multiline-comment-style.js +7 -7
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-before-return.js +1 -1
- package/lib/rules/no-constant-binary-expression.js +6 -6
- package/lib/rules/no-constructor-return.js +2 -2
- package/lib/rules/no-dupe-class-members.js +2 -2
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-function.js +2 -2
- package/lib/rules/no-empty-static-block.js +1 -1
- package/lib/rules/no-extra-semi.js +1 -1
- package/lib/rules/no-fallthrough.js +1 -1
- package/lib/rules/no-implicit-coercion.js +17 -1
- package/lib/rules/no-inner-declarations.js +23 -2
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-lone-blocks.js +2 -2
- package/lib/rules/no-loss-of-precision.js +1 -1
- package/lib/rules/no-misleading-character-class.js +174 -65
- package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-new-native-nonconstructor.js +1 -1
- package/lib/rules/no-new-symbol.js +8 -1
- package/lib/rules/no-restricted-globals.js +1 -1
- package/lib/rules/no-restricted-imports.js +2 -2
- package/lib/rules/no-restricted-modules.js +2 -2
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sequences.js +1 -0
- package/lib/rules/no-trailing-spaces.js +2 -3
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-unsafe-optional-chaining.js +1 -1
- package/lib/rules/no-unused-private-class-members.js +1 -1
- package/lib/rules/no-unused-vars.js +6 -8
- package/lib/rules/no-useless-assignment.js +566 -0
- package/lib/rules/no-useless-backreference.js +1 -1
- package/lib/rules/object-curly-spacing.js +3 -3
- package/lib/rules/object-property-newline.js +1 -1
- package/lib/rules/one-var.js +5 -5
- package/lib/rules/padded-blocks.js +7 -7
- package/lib/rules/prefer-arrow-callback.js +3 -3
- package/lib/rules/prefer-reflect.js +1 -1
- package/lib/rules/prefer-regex-literals.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/radix.js +2 -2
- package/lib/rules/semi-style.js +1 -1
- package/lib/rules/sort-imports.js +1 -1
- package/lib/rules/sort-keys.js +1 -1
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-unary-ops.js +1 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/utils/ast-utils.js +7 -7
- package/lib/rules/yield-star-spacing.js +1 -1
- package/lib/shared/types.js +1 -1
- package/lib/source-code/source-code.js +5 -83
- package/lib/source-code/token-store/index.js +2 -2
- package/lib/unsupported-api.js +3 -5
- package/package.json +12 -14
- package/conf/config-schema.js +0 -93
- package/lib/cli-engine/formatters/checkstyle.js +0 -60
- package/lib/cli-engine/formatters/compact.js +0 -60
- package/lib/cli-engine/formatters/jslint-xml.js +0 -41
- package/lib/cli-engine/formatters/junit.js +0 -82
- package/lib/cli-engine/formatters/tap.js +0 -95
- package/lib/cli-engine/formatters/unix.js +0 -58
- package/lib/cli-engine/formatters/visualstudio.js +0 -63
- package/lib/eslint/flat-eslint.js +0 -1142
- package/lib/rule-tester/flat-rule-tester.js +0 -1122
- package/lib/rules/require-jsdoc.js +0 -122
- package/lib/rules/valid-jsdoc.js +0 -516
- package/lib/shared/config-validator.js +0 -347
- package/lib/shared/relative-module-resolver.js +0 -50
package/lib/linter/linter.js
CHANGED
@@ -52,6 +52,7 @@ const DEFAULT_ECMA_VERSION = 5;
|
|
52
52
|
const commentParser = new ConfigCommentParser();
|
53
53
|
const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } };
|
54
54
|
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
55
|
+
const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
|
55
56
|
|
56
57
|
//------------------------------------------------------------------------------
|
57
58
|
// Typedefs
|
@@ -105,6 +106,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|
105
106
|
* @property {string} [filename] the filename of the source code.
|
106
107
|
* @property {boolean | "off" | "warn" | "error"} [reportUnusedDisableDirectives] Adds reported errors for
|
107
108
|
* unused `eslint-disable` directives.
|
109
|
+
* @property {Function} [ruleFilter] A predicate function that determines whether a given rule should run.
|
108
110
|
*/
|
109
111
|
|
110
112
|
/**
|
@@ -230,7 +232,7 @@ function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, ena
|
|
230
232
|
* @private
|
231
233
|
*/
|
232
234
|
function createMissingRuleMessage(ruleId) {
|
233
|
-
return Object.
|
235
|
+
return Object.hasOwn(ruleReplacements.rules, ruleId)
|
234
236
|
? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
|
235
237
|
: `Definition for rule '${ruleId}' was not found.`;
|
236
238
|
}
|
@@ -392,7 +394,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
|
|
392
394
|
}
|
393
395
|
|
394
396
|
case "exported":
|
395
|
-
Object.assign(exportedVariables, commentParser.
|
397
|
+
Object.assign(exportedVariables, commentParser.parseListConfig(directiveValue, comment));
|
396
398
|
break;
|
397
399
|
|
398
400
|
case "globals":
|
@@ -439,6 +441,15 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
|
|
439
441
|
try {
|
440
442
|
validator.validateRuleOptions(rule, name, ruleValue);
|
441
443
|
} catch (err) {
|
444
|
+
|
445
|
+
/*
|
446
|
+
* If the rule has invalid `meta.schema`, throw the error because
|
447
|
+
* this is not an invalid inline configuration but an invalid rule.
|
448
|
+
*/
|
449
|
+
if (err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA") {
|
450
|
+
throw err;
|
451
|
+
}
|
452
|
+
|
442
453
|
problems.push(createLintingProblem({
|
443
454
|
ruleId: name,
|
444
455
|
message: err.message,
|
@@ -584,7 +595,7 @@ function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
|
584
595
|
* that is used for a number of processes inside of ESLint. It's normally
|
585
596
|
* safe to assume people want the latest unless otherwise specified.
|
586
597
|
*/
|
587
|
-
return
|
598
|
+
return LATEST_ECMA_VERSION;
|
588
599
|
}
|
589
600
|
|
590
601
|
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
@@ -661,6 +672,12 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|
661
672
|
}
|
662
673
|
}
|
663
674
|
|
675
|
+
let ruleFilter = providedOptions.ruleFilter;
|
676
|
+
|
677
|
+
if (typeof ruleFilter !== "function") {
|
678
|
+
ruleFilter = () => true;
|
679
|
+
}
|
680
|
+
|
664
681
|
return {
|
665
682
|
filename: normalizeFilename(providedOptions.filename || "<input>"),
|
666
683
|
allowInlineConfig: !ignoreInlineConfig,
|
@@ -668,7 +685,8 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|
668
685
|
? `your config${configNameOfNoInlineConfig}`
|
669
686
|
: null,
|
670
687
|
reportUnusedDisableDirectives,
|
671
|
-
disableFixes: Boolean(providedOptions.disableFixes)
|
688
|
+
disableFixes: Boolean(providedOptions.disableFixes),
|
689
|
+
ruleFilter
|
672
690
|
};
|
673
691
|
}
|
674
692
|
|
@@ -885,12 +903,18 @@ function parse(text, languageOptions, filePath) {
|
|
885
903
|
|
886
904
|
/**
|
887
905
|
* Runs a rule, and gets its listeners
|
888
|
-
* @param {Rule} rule A
|
906
|
+
* @param {Rule} rule A rule object
|
889
907
|
* @param {Context} ruleContext The context that should be passed to the rule
|
908
|
+
* @throws {TypeError} If `rule` is not an object with a `create` method
|
890
909
|
* @throws {any} Any error during the rule's `create`
|
891
910
|
* @returns {Object} A map of selector listeners provided by the rule
|
892
911
|
*/
|
893
912
|
function createRuleListeners(rule, ruleContext) {
|
913
|
+
|
914
|
+
if (!rule || typeof rule !== "object" || typeof rule.create !== "function") {
|
915
|
+
throw new TypeError(`Error while loading rule '${ruleContext.id}': Rule must be an object with a \`create\` method`);
|
916
|
+
}
|
917
|
+
|
894
918
|
try {
|
895
919
|
return rule.create(ruleContext);
|
896
920
|
} catch (ex) {
|
@@ -899,43 +923,6 @@ function createRuleListeners(rule, ruleContext) {
|
|
899
923
|
}
|
900
924
|
}
|
901
925
|
|
902
|
-
// methods that exist on SourceCode object
|
903
|
-
const DEPRECATED_SOURCECODE_PASSTHROUGHS = {
|
904
|
-
getSource: "getText",
|
905
|
-
getSourceLines: "getLines",
|
906
|
-
getAllComments: "getAllComments",
|
907
|
-
getNodeByRangeIndex: "getNodeByRangeIndex",
|
908
|
-
getComments: "getComments",
|
909
|
-
getCommentsBefore: "getCommentsBefore",
|
910
|
-
getCommentsAfter: "getCommentsAfter",
|
911
|
-
getCommentsInside: "getCommentsInside",
|
912
|
-
getJSDocComment: "getJSDocComment",
|
913
|
-
getFirstToken: "getFirstToken",
|
914
|
-
getFirstTokens: "getFirstTokens",
|
915
|
-
getLastToken: "getLastToken",
|
916
|
-
getLastTokens: "getLastTokens",
|
917
|
-
getTokenAfter: "getTokenAfter",
|
918
|
-
getTokenBefore: "getTokenBefore",
|
919
|
-
getTokenByRangeStart: "getTokenByRangeStart",
|
920
|
-
getTokens: "getTokens",
|
921
|
-
getTokensAfter: "getTokensAfter",
|
922
|
-
getTokensBefore: "getTokensBefore",
|
923
|
-
getTokensBetween: "getTokensBetween"
|
924
|
-
};
|
925
|
-
|
926
|
-
|
927
|
-
const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
928
|
-
Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).reduce(
|
929
|
-
(contextInfo, methodName) =>
|
930
|
-
Object.assign(contextInfo, {
|
931
|
-
[methodName](...args) {
|
932
|
-
return this.sourceCode[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]](...args);
|
933
|
-
}
|
934
|
-
}),
|
935
|
-
{}
|
936
|
-
)
|
937
|
-
);
|
938
|
-
|
939
926
|
/**
|
940
927
|
* Runs the given rules on the given SourceCode object
|
941
928
|
* @param {SourceCode} sourceCode A SourceCode object for the given text
|
@@ -948,9 +935,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|
948
935
|
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
949
936
|
* @param {string | undefined} cwd cwd of the cli
|
950
937
|
* @param {string} physicalFilename The full path of the file on disk without any code block information
|
938
|
+
* @param {Function} ruleFilter A predicate function to filter which rules should be executed.
|
951
939
|
* @returns {LintMessage[]} An array of reported problems
|
952
940
|
*/
|
953
|
-
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
|
941
|
+
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename, ruleFilter) {
|
954
942
|
const emitter = createEmitter();
|
955
943
|
const nodeQueue = [];
|
956
944
|
let currentNode = sourceCode.ast;
|
@@ -972,30 +960,22 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
|
|
972
960
|
* properties once for each rule.
|
973
961
|
*/
|
974
962
|
const sharedTraversalContext = Object.freeze(
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
...languageOptions.parserOptions
|
992
|
-
},
|
993
|
-
parserPath: parserName,
|
994
|
-
languageOptions,
|
995
|
-
parserServices: sourceCode.parserServices,
|
996
|
-
settings
|
997
|
-
}
|
998
|
-
)
|
963
|
+
{
|
964
|
+
getCwd: () => cwd,
|
965
|
+
cwd,
|
966
|
+
getFilename: () => filename,
|
967
|
+
filename,
|
968
|
+
getPhysicalFilename: () => physicalFilename || filename,
|
969
|
+
physicalFilename: physicalFilename || filename,
|
970
|
+
getSourceCode: () => sourceCode,
|
971
|
+
sourceCode,
|
972
|
+
parserOptions: {
|
973
|
+
...languageOptions.parserOptions
|
974
|
+
},
|
975
|
+
parserPath: parserName,
|
976
|
+
languageOptions,
|
977
|
+
settings
|
978
|
+
}
|
999
979
|
);
|
1000
980
|
|
1001
981
|
const lintingProblems = [];
|
@@ -1008,6 +988,10 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
|
|
1008
988
|
return;
|
1009
989
|
}
|
1010
990
|
|
991
|
+
if (ruleFilter && !ruleFilter({ ruleId, severity })) {
|
992
|
+
return;
|
993
|
+
}
|
994
|
+
|
1011
995
|
const rule = ruleMapper(ruleId);
|
1012
996
|
|
1013
997
|
if (!rule) {
|
@@ -1217,9 +1201,9 @@ class Linter {
|
|
1217
1201
|
* Initialize the Linter.
|
1218
1202
|
* @param {Object} [config] the config object
|
1219
1203
|
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1220
|
-
* @param {"flat"|"eslintrc"} [config.configType="
|
1204
|
+
* @param {"flat"|"eslintrc"} [config.configType="flat"] the type of config used.
|
1221
1205
|
*/
|
1222
|
-
constructor({ cwd, configType } = {}) {
|
1206
|
+
constructor({ cwd, configType = "flat" } = {}) {
|
1223
1207
|
internalSlotsMap.set(this, {
|
1224
1208
|
cwd: normalizeCwd(cwd),
|
1225
1209
|
lastConfigArray: null,
|
@@ -1348,7 +1332,56 @@ class Linter {
|
|
1348
1332
|
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1349
1333
|
);
|
1350
1334
|
|
1335
|
+
/*
|
1336
|
+
* Now we determine the final configurations for rules.
|
1337
|
+
* First, let all inline rule configurations override those from the config.
|
1338
|
+
* Then, check for a special case: if a rule is configured in both places,
|
1339
|
+
* inline rule configuration that only has severity should retain options from
|
1340
|
+
* the config and just override the severity.
|
1341
|
+
*
|
1342
|
+
* Example:
|
1343
|
+
*
|
1344
|
+
* {
|
1345
|
+
* rules: {
|
1346
|
+
* curly: ["error", "multi"]
|
1347
|
+
* }
|
1348
|
+
* }
|
1349
|
+
*
|
1350
|
+
* /* eslint curly: ["warn"] * /
|
1351
|
+
*
|
1352
|
+
* Results in:
|
1353
|
+
*
|
1354
|
+
* curly: ["warn", "multi"]
|
1355
|
+
*/
|
1351
1356
|
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
1357
|
+
|
1358
|
+
if (config.rules) {
|
1359
|
+
for (const [ruleId, ruleInlineConfig] of Object.entries(commentDirectives.configuredRules)) {
|
1360
|
+
if (
|
1361
|
+
|
1362
|
+
/*
|
1363
|
+
* If inline config for the rule has only severity
|
1364
|
+
*/
|
1365
|
+
(!Array.isArray(ruleInlineConfig) || ruleInlineConfig.length === 1) &&
|
1366
|
+
|
1367
|
+
/*
|
1368
|
+
* And provided config for the rule has options
|
1369
|
+
*/
|
1370
|
+
Object.hasOwn(config.rules, ruleId) &&
|
1371
|
+
(Array.isArray(config.rules[ruleId]) && config.rules[ruleId].length > 1)
|
1372
|
+
) {
|
1373
|
+
|
1374
|
+
/*
|
1375
|
+
* Then use severity from the inline config and options from the provided config
|
1376
|
+
*/
|
1377
|
+
configuredRules[ruleId] = [
|
1378
|
+
Array.isArray(ruleInlineConfig) ? ruleInlineConfig[0] : ruleInlineConfig, // severity from the inline config
|
1379
|
+
...config.rules[ruleId].slice(1) // options from the provided config
|
1380
|
+
];
|
1381
|
+
}
|
1382
|
+
}
|
1383
|
+
}
|
1384
|
+
|
1352
1385
|
let lintingProblems;
|
1353
1386
|
|
1354
1387
|
try {
|
@@ -1362,7 +1395,8 @@ class Linter {
|
|
1362
1395
|
options.filename,
|
1363
1396
|
options.disableFixes,
|
1364
1397
|
slots.cwd,
|
1365
|
-
providedOptions.physicalFilename
|
1398
|
+
providedOptions.physicalFilename,
|
1399
|
+
null
|
1366
1400
|
);
|
1367
1401
|
} catch (err) {
|
1368
1402
|
err.message += `\nOccurred while linting ${options.filename}`;
|
@@ -1413,29 +1447,29 @@ class Linter {
|
|
1413
1447
|
? { filename: filenameOrOptions }
|
1414
1448
|
: filenameOrOptions || {};
|
1415
1449
|
|
1416
|
-
|
1417
|
-
if (configType === "flat") {
|
1418
|
-
|
1419
|
-
/*
|
1420
|
-
* Because of how Webpack packages up the files, we can't
|
1421
|
-
* compare directly to `FlatConfigArray` using `instanceof`
|
1422
|
-
* because it's not the same `FlatConfigArray` as in the tests.
|
1423
|
-
* So, we work around it by assuming an array is, in fact, a
|
1424
|
-
* `FlatConfigArray` if it has a `getConfig()` method.
|
1425
|
-
*/
|
1426
|
-
let configArray = config;
|
1427
|
-
|
1428
|
-
if (!Array.isArray(config) || typeof config.getConfig !== "function") {
|
1429
|
-
configArray = new FlatConfigArray(config, { basePath: cwd });
|
1430
|
-
configArray.normalizeSync();
|
1431
|
-
}
|
1450
|
+
const configToUse = config ?? {};
|
1432
1451
|
|
1433
|
-
|
1434
|
-
}
|
1452
|
+
if (configType !== "eslintrc") {
|
1435
1453
|
|
1436
|
-
|
1437
|
-
|
1454
|
+
/*
|
1455
|
+
* Because of how Webpack packages up the files, we can't
|
1456
|
+
* compare directly to `FlatConfigArray` using `instanceof`
|
1457
|
+
* because it's not the same `FlatConfigArray` as in the tests.
|
1458
|
+
* So, we work around it by assuming an array is, in fact, a
|
1459
|
+
* `FlatConfigArray` if it has a `getConfig()` method.
|
1460
|
+
*/
|
1461
|
+
let configArray = configToUse;
|
1462
|
+
|
1463
|
+
if (!Array.isArray(configToUse) || typeof configToUse.getConfig !== "function") {
|
1464
|
+
configArray = new FlatConfigArray(configToUse, { basePath: cwd });
|
1465
|
+
configArray.normalizeSync();
|
1438
1466
|
}
|
1467
|
+
|
1468
|
+
return this._distinguishSuppressedMessages(this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true));
|
1469
|
+
}
|
1470
|
+
|
1471
|
+
if (typeof configToUse.extractConfig === "function") {
|
1472
|
+
return this._distinguishSuppressedMessages(this._verifyWithConfigArray(textOrSourceCode, configToUse, options));
|
1439
1473
|
}
|
1440
1474
|
|
1441
1475
|
/*
|
@@ -1448,9 +1482,9 @@ class Linter {
|
|
1448
1482
|
* So we cannot apply multiple processors.
|
1449
1483
|
*/
|
1450
1484
|
if (options.preprocess || options.postprocess) {
|
1451
|
-
return this._distinguishSuppressedMessages(this._verifyWithProcessor(textOrSourceCode,
|
1485
|
+
return this._distinguishSuppressedMessages(this._verifyWithProcessor(textOrSourceCode, configToUse, options));
|
1452
1486
|
}
|
1453
|
-
return this._distinguishSuppressedMessages(this._verifyWithoutProcessors(textOrSourceCode,
|
1487
|
+
return this._distinguishSuppressedMessages(this._verifyWithoutProcessors(textOrSourceCode, configToUse, options));
|
1454
1488
|
}
|
1455
1489
|
|
1456
1490
|
/**
|
@@ -1690,9 +1724,17 @@ class Linter {
|
|
1690
1724
|
[ruleId]: ruleOptions
|
1691
1725
|
}
|
1692
1726
|
});
|
1693
|
-
mergedInlineConfig.rules[ruleId] =
|
1727
|
+
mergedInlineConfig.rules[ruleId] = ruleOptions;
|
1694
1728
|
} catch (err) {
|
1695
1729
|
|
1730
|
+
/*
|
1731
|
+
* If the rule has invalid `meta.schema`, throw the error because
|
1732
|
+
* this is not an invalid inline configuration but an invalid rule.
|
1733
|
+
*/
|
1734
|
+
if (err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA") {
|
1735
|
+
throw err;
|
1736
|
+
}
|
1737
|
+
|
1696
1738
|
let baseMessage = err.message.slice(
|
1697
1739
|
err.message.startsWith("Key \"rules\":")
|
1698
1740
|
? err.message.indexOf(":", 12) + 1
|
@@ -1721,7 +1763,58 @@ class Linter {
|
|
1721
1763
|
)
|
1722
1764
|
: { problems: [], disableDirectives: [] };
|
1723
1765
|
|
1766
|
+
/*
|
1767
|
+
* Now we determine the final configurations for rules.
|
1768
|
+
* First, let all inline rule configurations override those from the config.
|
1769
|
+
* Then, check for a special case: if a rule is configured in both places,
|
1770
|
+
* inline rule configuration that only has severity should retain options from
|
1771
|
+
* the config and just override the severity.
|
1772
|
+
*
|
1773
|
+
* Example:
|
1774
|
+
*
|
1775
|
+
* {
|
1776
|
+
* rules: {
|
1777
|
+
* curly: ["error", "multi"]
|
1778
|
+
* }
|
1779
|
+
* }
|
1780
|
+
*
|
1781
|
+
* /* eslint curly: ["warn"] * /
|
1782
|
+
*
|
1783
|
+
* Results in:
|
1784
|
+
*
|
1785
|
+
* curly: ["warn", "multi"]
|
1786
|
+
*
|
1787
|
+
* At this point, all rule configurations are normalized to arrays.
|
1788
|
+
*/
|
1724
1789
|
const configuredRules = Object.assign({}, config.rules, mergedInlineConfig.rules);
|
1790
|
+
|
1791
|
+
if (config.rules) {
|
1792
|
+
for (const [ruleId, ruleInlineConfig] of Object.entries(mergedInlineConfig.rules)) {
|
1793
|
+
if (
|
1794
|
+
|
1795
|
+
/*
|
1796
|
+
* If inline config for the rule has only severity
|
1797
|
+
*/
|
1798
|
+
ruleInlineConfig.length === 1 &&
|
1799
|
+
|
1800
|
+
/*
|
1801
|
+
* And provided config for the rule has options
|
1802
|
+
*/
|
1803
|
+
Object.hasOwn(config.rules, ruleId) &&
|
1804
|
+
config.rules[ruleId].length > 1
|
1805
|
+
) {
|
1806
|
+
|
1807
|
+
/*
|
1808
|
+
* Then use severity from the inline config and options from the provided config
|
1809
|
+
*/
|
1810
|
+
configuredRules[ruleId] = [
|
1811
|
+
ruleInlineConfig[0], // severity from the inline config
|
1812
|
+
...config.rules[ruleId].slice(1) // options from the provided config
|
1813
|
+
];
|
1814
|
+
}
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
|
1725
1818
|
let lintingProblems;
|
1726
1819
|
|
1727
1820
|
sourceCode.finalize();
|
@@ -1737,7 +1830,8 @@ class Linter {
|
|
1737
1830
|
options.filename,
|
1738
1831
|
options.disableFixes,
|
1739
1832
|
slots.cwd,
|
1740
|
-
providedOptions.physicalFilename
|
1833
|
+
providedOptions.physicalFilename,
|
1834
|
+
options.ruleFilter
|
1741
1835
|
);
|
1742
1836
|
} catch (err) {
|
1743
1837
|
err.message += `\nOccurred while linting ${options.filename}`;
|
@@ -1768,7 +1862,9 @@ class Linter {
|
|
1768
1862
|
.concat(commentDirectives.problems)
|
1769
1863
|
.concat(inlineConfigProblems)
|
1770
1864
|
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
|
1771
|
-
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
|
1865
|
+
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives,
|
1866
|
+
ruleFilter: options.ruleFilter,
|
1867
|
+
configuredRules
|
1772
1868
|
});
|
1773
1869
|
}
|
1774
1870
|
|
@@ -1986,17 +2082,17 @@ class Linter {
|
|
1986
2082
|
/**
|
1987
2083
|
* Defines a new linting rule.
|
1988
2084
|
* @param {string} ruleId A unique rule identifier
|
1989
|
-
* @param {
|
2085
|
+
* @param {Rule} rule A rule object
|
1990
2086
|
* @returns {void}
|
1991
2087
|
*/
|
1992
|
-
defineRule(ruleId,
|
2088
|
+
defineRule(ruleId, rule) {
|
1993
2089
|
assertEslintrcConfig(this);
|
1994
|
-
internalSlotsMap.get(this).ruleMap.define(ruleId,
|
2090
|
+
internalSlotsMap.get(this).ruleMap.define(ruleId, rule);
|
1995
2091
|
}
|
1996
2092
|
|
1997
2093
|
/**
|
1998
2094
|
* Defines many new linting rules.
|
1999
|
-
* @param {Record<string,
|
2095
|
+
* @param {Record<string, Rule>} rulesToDefine map from unique rule identifier to rule
|
2000
2096
|
* @returns {void}
|
2001
2097
|
*/
|
2002
2098
|
defineRules(rulesToDefine) {
|
@@ -2044,7 +2140,7 @@ class Linter {
|
|
2044
2140
|
* SourceCodeFixer.
|
2045
2141
|
*/
|
2046
2142
|
verifyAndFix(text, config, options) {
|
2047
|
-
let messages
|
2143
|
+
let messages,
|
2048
2144
|
fixedResult,
|
2049
2145
|
fixed = false,
|
2050
2146
|
passNumber = 0,
|
@@ -160,7 +160,7 @@ function mergeFixes(fixes, sourceCode) {
|
|
160
160
|
|
161
161
|
const originalText = sourceCode.text;
|
162
162
|
const start = fixes[0].range[0];
|
163
|
-
const end = fixes
|
163
|
+
const end = fixes.at(-1).range[1];
|
164
164
|
let text = "";
|
165
165
|
let lastPos = Number.MIN_SAFE_INTEGER;
|
166
166
|
|
@@ -343,7 +343,7 @@ module.exports = function createReportTranslator(metadata) {
|
|
343
343
|
if (descriptor.message) {
|
344
344
|
throw new TypeError("context.report() called with a message and a messageId. Please only pass one.");
|
345
345
|
}
|
346
|
-
if (!messages || !Object.
|
346
|
+
if (!messages || !Object.hasOwn(messages, id)) {
|
347
347
|
throw new TypeError(`context.report() called with a messageId of '${id}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`);
|
348
348
|
}
|
349
349
|
computedMessage = messages[id];
|
package/lib/linter/rules.js
CHANGED
@@ -13,18 +13,10 @@
|
|
13
13
|
const builtInRules = require("../rules");
|
14
14
|
|
15
15
|
//------------------------------------------------------------------------------
|
16
|
-
//
|
16
|
+
// Typedefs
|
17
17
|
//------------------------------------------------------------------------------
|
18
18
|
|
19
|
-
/**
|
20
|
-
* Normalizes a rule module to the new-style API
|
21
|
-
* @param {(Function|{create: Function})} rule A rule object, which can either be a function
|
22
|
-
* ("old-style") or an object with a `create` method ("new-style")
|
23
|
-
* @returns {{create: Function}} A new-style rule.
|
24
|
-
*/
|
25
|
-
function normalizeRule(rule) {
|
26
|
-
return typeof rule === "function" ? Object.assign({ create: rule }, rule) : rule;
|
27
|
-
}
|
19
|
+
/** @typedef {import("../shared/types").Rule} Rule */
|
28
20
|
|
29
21
|
//------------------------------------------------------------------------------
|
30
22
|
// Public Interface
|
@@ -41,18 +33,17 @@ class Rules {
|
|
41
33
|
/**
|
42
34
|
* Registers a rule module for rule id in storage.
|
43
35
|
* @param {string} ruleId Rule id (file name).
|
44
|
-
* @param {
|
36
|
+
* @param {Rule} rule Rule object.
|
45
37
|
* @returns {void}
|
46
38
|
*/
|
47
|
-
define(ruleId,
|
48
|
-
this._rules[ruleId] =
|
39
|
+
define(ruleId, rule) {
|
40
|
+
this._rules[ruleId] = rule;
|
49
41
|
}
|
50
42
|
|
51
43
|
/**
|
52
44
|
* Access rule handler by id (file name).
|
53
45
|
* @param {string} ruleId Rule id (file name).
|
54
|
-
* @returns {
|
55
|
-
* A rule. This is normalized to always have the new-style shape with a `create` method.
|
46
|
+
* @returns {Rule} Rule object.
|
56
47
|
*/
|
57
48
|
get(ruleId) {
|
58
49
|
if (typeof this._rules[ruleId] === "string") {
|
@@ -107,7 +107,7 @@ SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) {
|
|
107
107
|
}
|
108
108
|
|
109
109
|
messages.forEach(problem => {
|
110
|
-
if (Object.
|
110
|
+
if (Object.hasOwn(problem, "fix")) {
|
111
111
|
fixes.push(problem);
|
112
112
|
} else {
|
113
113
|
remainingMessages.push(problem);
|
package/lib/options.js
CHANGED
@@ -57,6 +57,8 @@ const optionator = require("optionator");
|
|
57
57
|
* @property {boolean} quiet Report errors only
|
58
58
|
* @property {boolean} [version] Output the version number
|
59
59
|
* @property {boolean} warnIgnored Show warnings when the file list includes ignored files
|
60
|
+
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
|
61
|
+
* the linting operation to short circuit and not report any failures.
|
60
62
|
* @property {string[]} _ Positional filenames or patterns
|
61
63
|
*/
|
62
64
|
|
@@ -168,7 +170,7 @@ module.exports = function(usingFlatConfig) {
|
|
168
170
|
alias: "c",
|
169
171
|
type: "path::String",
|
170
172
|
description: usingFlatConfig
|
171
|
-
? "Use this configuration instead of eslint.config.js"
|
173
|
+
? "Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs"
|
172
174
|
: "Use this configuration, overriding .eslintrc.* config options if present"
|
173
175
|
},
|
174
176
|
envFlag,
|
@@ -370,6 +372,12 @@ module.exports = function(usingFlatConfig) {
|
|
370
372
|
description: "Exit with exit code 2 in case of fatal error"
|
371
373
|
},
|
372
374
|
warnIgnoredFlag,
|
375
|
+
{
|
376
|
+
option: "pass-on-no-patterns",
|
377
|
+
type: "Boolean",
|
378
|
+
default: false,
|
379
|
+
description: "Exit with exit code 0 in case no file patterns are passed"
|
380
|
+
},
|
373
381
|
{
|
374
382
|
option: "debug",
|
375
383
|
type: "Boolean",
|