eslint 7.0.0-alpha.1 → 7.0.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 +329 -0
- package/README.md +7 -7
- package/bin/eslint.js +115 -77
- package/conf/category-list.json +2 -3
- package/conf/environments.js +2 -1
- package/conf/eslint-recommended.js +3 -0
- package/lib/api.js +2 -0
- package/lib/cli-engine/cascading-config-array-factory.js +16 -2
- package/lib/cli-engine/cli-engine.js +53 -47
- package/lib/cli-engine/config-array/config-array.js +30 -1
- package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
- package/lib/cli-engine/config-array-factory.js +244 -235
- package/lib/cli.js +181 -95
- package/lib/eslint/eslint.js +656 -0
- package/lib/eslint/index.js +7 -0
- package/lib/init/autoconfig.js +4 -4
- package/lib/init/config-file.js +2 -2
- package/lib/init/config-initializer.js +2 -4
- package/lib/init/source-code-utils.js +2 -2
- package/lib/linter/node-event-generator.js +2 -2
- package/lib/options.js +0 -1
- package/lib/rule-tester/rule-tester.js +178 -23
- package/lib/rules/accessor-pairs.js +2 -2
- package/lib/rules/array-callback-return.js +3 -18
- package/lib/rules/arrow-body-style.js +26 -15
- package/lib/rules/callback-return.js +4 -0
- package/lib/rules/camelcase.js +38 -1
- package/lib/rules/comma-style.js +3 -8
- package/lib/rules/computed-property-spacing.js +2 -2
- package/lib/rules/curly.js +124 -40
- package/lib/rules/func-call-spacing.js +4 -3
- package/lib/rules/func-names.js +31 -24
- package/lib/rules/getter-return.js +2 -12
- package/lib/rules/global-require.js +4 -0
- package/lib/rules/handle-callback-err.js +4 -0
- package/lib/rules/id-blacklist.js +140 -64
- package/lib/rules/id-length.js +14 -4
- package/lib/rules/indent-legacy.js +0 -16
- package/lib/rules/key-spacing.js +1 -1
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-per-chained-call.js +6 -3
- package/lib/rules/no-alert.js +5 -3
- package/lib/rules/no-buffer-constructor.js +4 -0
- package/lib/rules/no-dupe-else-if.js +1 -1
- package/lib/rules/no-empty-function.js +4 -2
- package/lib/rules/no-eval.js +3 -2
- package/lib/rules/no-extra-bind.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +168 -38
- package/lib/rules/no-extra-parens.js +9 -5
- package/lib/rules/no-implied-eval.js +83 -101
- package/lib/rules/no-import-assign.js +1 -1
- package/lib/rules/no-inner-declarations.js +31 -39
- package/lib/rules/no-lone-blocks.js +1 -1
- package/lib/rules/no-magic-numbers.js +72 -37
- package/lib/rules/no-mixed-requires.js +4 -0
- package/lib/rules/no-new-object.js +15 -3
- package/lib/rules/no-new-require.js +4 -0
- package/lib/rules/no-new-wrappers.js +1 -1
- package/lib/rules/no-obj-calls.js +24 -5
- package/lib/rules/no-path-concat.js +4 -0
- package/lib/rules/no-plusplus.js +39 -3
- package/lib/rules/no-process-env.js +4 -0
- package/lib/rules/no-process-exit.js +4 -0
- package/lib/rules/no-prototype-builtins.js +1 -1
- package/lib/rules/no-restricted-modules.js +52 -18
- package/lib/rules/no-setter-return.js +1 -1
- package/lib/rules/no-sync.js +4 -0
- package/lib/rules/no-underscore-dangle.js +1 -1
- package/lib/rules/no-unexpected-multiline.js +22 -12
- package/lib/rules/no-useless-concat.js +1 -1
- package/lib/rules/operator-assignment.js +3 -3
- package/lib/rules/operator-linebreak.js +4 -16
- package/lib/rules/prefer-numeric-literals.js +3 -3
- package/lib/rules/prefer-object-spread.js +2 -2
- package/lib/rules/require-await.js +1 -1
- package/lib/rules/space-before-function-paren.js +5 -2
- package/lib/rules/template-curly-spacing.js +59 -42
- package/lib/rules/utils/ast-utils.js +65 -4
- package/lib/rules/wrap-iife.js +54 -17
- package/lib/rules/yoda.js +101 -51
- package/lib/shared/relative-module-resolver.js +1 -0
- package/lib/shared/types.js +9 -2
- package/messages/plugin-conflict.txt +7 -0
- package/package.json +27 -26
@@ -90,7 +90,24 @@ const configFilenames = [
|
|
90
90
|
* @typedef {Object} ConfigArrayFactoryInternalSlots
|
91
91
|
* @property {Map<string,Plugin>} additionalPluginPool The map for additional plugins.
|
92
92
|
* @property {string} cwd The path to the current working directory.
|
93
|
-
* @property {string} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
|
93
|
+
* @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
|
94
|
+
*/
|
95
|
+
|
96
|
+
/**
|
97
|
+
* @typedef {Object} ConfigArrayFactoryLoadingContext
|
98
|
+
* @property {string} filePath The path to the current configuration.
|
99
|
+
* @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
|
100
|
+
* @property {string} name The name of the current configuration.
|
101
|
+
* @property {string} pluginBasePath The base path to resolve plugins.
|
102
|
+
* @property {"config" | "ignore" | "implicit-processor"} type The type of the current configuration. This is `"config"` in normal. This is `"ignore"` if it came from `.eslintignore`. This is `"implicit-processor"` if it came from legacy file-extension processors.
|
103
|
+
*/
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @typedef {Object} ConfigArrayFactoryLoadingContext
|
107
|
+
* @property {string} filePath The path to the current configuration.
|
108
|
+
* @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
|
109
|
+
* @property {string} name The name of the current configuration.
|
110
|
+
* @property {"config" | "ignore" | "implicit-processor"} type The type of the current configuration. This is `"config"` in normal. This is `"ignore"` if it came from `.eslintignore`. This is `"implicit-processor"` if it came from legacy file-extension processors.
|
94
111
|
*/
|
95
112
|
|
96
113
|
/** @type {WeakMap<ConfigArrayFactory, ConfigArrayFactoryInternalSlots>} */
|
@@ -328,21 +345,39 @@ function writeDebugLogForLoading(request, relativeTo, filePath) {
|
|
328
345
|
}
|
329
346
|
|
330
347
|
/**
|
331
|
-
*
|
332
|
-
* @param {
|
333
|
-
* @param {
|
334
|
-
* @
|
348
|
+
* Create a new context with default values.
|
349
|
+
* @param {ConfigArrayFactoryInternalSlots} slots The internal slots.
|
350
|
+
* @param {"config" | "ignore" | "implicit-processor" | undefined} providedType The type of the current configuration. Default is `"config"`.
|
351
|
+
* @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.
|
352
|
+
* @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.
|
353
|
+
* @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.
|
354
|
+
* @returns {ConfigArrayFactoryLoadingContext} The created context.
|
335
355
|
*/
|
336
|
-
function
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
356
|
+
function createContext(
|
357
|
+
{ cwd, resolvePluginsRelativeTo },
|
358
|
+
providedType,
|
359
|
+
providedName,
|
360
|
+
providedFilePath,
|
361
|
+
providedMatchBasePath
|
362
|
+
) {
|
363
|
+
const filePath = providedFilePath
|
364
|
+
? path.resolve(cwd, providedFilePath)
|
365
|
+
: "";
|
366
|
+
const matchBasePath =
|
367
|
+
(providedMatchBasePath && path.resolve(cwd, providedMatchBasePath)) ||
|
368
|
+
(filePath && path.dirname(filePath)) ||
|
369
|
+
cwd;
|
370
|
+
const name =
|
371
|
+
providedName ||
|
372
|
+
(filePath && path.relative(cwd, filePath)) ||
|
373
|
+
"";
|
374
|
+
const pluginBasePath =
|
375
|
+
resolvePluginsRelativeTo ||
|
376
|
+
(filePath && path.dirname(filePath)) ||
|
377
|
+
cwd;
|
378
|
+
const type = providedType || "config";
|
379
|
+
|
380
|
+
return { filePath, matchBasePath, name, pluginBasePath, type };
|
346
381
|
}
|
347
382
|
|
348
383
|
/**
|
@@ -377,63 +412,95 @@ class ConfigArrayFactory {
|
|
377
412
|
constructor({
|
378
413
|
additionalPluginPool = new Map(),
|
379
414
|
cwd = process.cwd(),
|
380
|
-
resolvePluginsRelativeTo
|
415
|
+
resolvePluginsRelativeTo
|
381
416
|
} = {}) {
|
382
|
-
internalSlotsMap.set(this, {
|
417
|
+
internalSlotsMap.set(this, {
|
418
|
+
additionalPluginPool,
|
419
|
+
cwd,
|
420
|
+
resolvePluginsRelativeTo:
|
421
|
+
resolvePluginsRelativeTo &&
|
422
|
+
path.resolve(cwd, resolvePluginsRelativeTo)
|
423
|
+
});
|
383
424
|
}
|
384
425
|
|
385
426
|
/**
|
386
427
|
* Create `ConfigArray` instance from a config data.
|
387
428
|
* @param {ConfigData|null} configData The config data to create.
|
388
429
|
* @param {Object} [options] The options.
|
430
|
+
* @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
|
389
431
|
* @param {string} [options.filePath] The path to this config data.
|
390
432
|
* @param {string} [options.name] The config name.
|
391
|
-
* @param {ConfigArray} [options.parent] The parent config array.
|
392
433
|
* @returns {ConfigArray} Loaded config.
|
393
434
|
*/
|
394
|
-
create(configData, { filePath, name
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
);
|
435
|
+
create(configData, { basePath, filePath, name } = {}) {
|
436
|
+
if (!configData) {
|
437
|
+
return new ConfigArray();
|
438
|
+
}
|
439
|
+
|
440
|
+
const slots = internalSlotsMap.get(this);
|
441
|
+
const ctx = createContext(slots, "config", name, filePath, basePath);
|
442
|
+
const elements = this._normalizeConfigData(configData, ctx);
|
443
|
+
|
444
|
+
return new ConfigArray(...elements);
|
401
445
|
}
|
402
446
|
|
403
447
|
/**
|
404
448
|
* Load a config file.
|
405
449
|
* @param {string} filePath The path to a config file.
|
406
450
|
* @param {Object} [options] The options.
|
451
|
+
* @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
|
407
452
|
* @param {string} [options.name] The config name.
|
408
|
-
* @param {ConfigArray} [options.parent] The parent config array.
|
409
453
|
* @returns {ConfigArray} Loaded config.
|
410
454
|
*/
|
411
|
-
loadFile(filePath, {
|
412
|
-
const
|
413
|
-
const
|
455
|
+
loadFile(filePath, { basePath, name } = {}) {
|
456
|
+
const slots = internalSlotsMap.get(this);
|
457
|
+
const ctx = createContext(slots, "config", name, filePath, basePath);
|
414
458
|
|
415
|
-
return
|
416
|
-
this._loadConfigData(absolutePath, name),
|
417
|
-
parent
|
418
|
-
);
|
459
|
+
return new ConfigArray(...this._loadConfigData(ctx));
|
419
460
|
}
|
420
461
|
|
421
462
|
/**
|
422
463
|
* Load the config file on a given directory if exists.
|
423
464
|
* @param {string} directoryPath The path to a directory.
|
424
465
|
* @param {Object} [options] The options.
|
466
|
+
* @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
|
425
467
|
* @param {string} [options.name] The config name.
|
426
|
-
* @param {ConfigArray} [options.parent] The parent config array.
|
427
468
|
* @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
|
428
469
|
*/
|
429
|
-
loadInDirectory(directoryPath, {
|
430
|
-
const
|
431
|
-
const absolutePath = path.resolve(cwd, directoryPath);
|
470
|
+
loadInDirectory(directoryPath, { basePath, name } = {}) {
|
471
|
+
const slots = internalSlotsMap.get(this);
|
432
472
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
473
|
+
for (const filename of configFilenames) {
|
474
|
+
const ctx = createContext(
|
475
|
+
slots,
|
476
|
+
"config",
|
477
|
+
name,
|
478
|
+
path.join(directoryPath, filename),
|
479
|
+
basePath
|
480
|
+
);
|
481
|
+
|
482
|
+
if (fs.existsSync(ctx.filePath)) {
|
483
|
+
let configData;
|
484
|
+
|
485
|
+
try {
|
486
|
+
configData = loadConfigFile(ctx.filePath);
|
487
|
+
} catch (error) {
|
488
|
+
if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
|
489
|
+
throw error;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
if (configData) {
|
494
|
+
debug(`Config file found: ${ctx.filePath}`);
|
495
|
+
return new ConfigArray(
|
496
|
+
...this._normalizeConfigData(configData, ctx)
|
497
|
+
);
|
498
|
+
}
|
499
|
+
}
|
500
|
+
}
|
501
|
+
|
502
|
+
debug(`Config file not found on ${directoryPath}`);
|
503
|
+
return new ConfigArray();
|
437
504
|
}
|
438
505
|
|
439
506
|
/**
|
@@ -465,13 +532,18 @@ class ConfigArrayFactory {
|
|
465
532
|
* @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
|
466
533
|
*/
|
467
534
|
loadESLintIgnore(filePath) {
|
468
|
-
const
|
469
|
-
const
|
470
|
-
|
471
|
-
|
535
|
+
const slots = internalSlotsMap.get(this);
|
536
|
+
const ctx = createContext(
|
537
|
+
slots,
|
538
|
+
"ignore",
|
539
|
+
void 0,
|
540
|
+
filePath,
|
541
|
+
slots.cwd
|
542
|
+
);
|
543
|
+
const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);
|
472
544
|
|
473
|
-
return
|
474
|
-
this._normalizeESLintIgnoreData(ignorePatterns,
|
545
|
+
return new ConfigArray(
|
546
|
+
...this._normalizeESLintIgnoreData(ignorePatterns, ctx)
|
475
547
|
);
|
476
548
|
}
|
477
549
|
|
@@ -480,9 +552,9 @@ class ConfigArrayFactory {
|
|
480
552
|
* @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
|
481
553
|
*/
|
482
554
|
loadDefaultESLintIgnore() {
|
483
|
-
const
|
484
|
-
const eslintIgnorePath = path.resolve(cwd, ".eslintignore");
|
485
|
-
const packageJsonPath = path.resolve(cwd, "package.json");
|
555
|
+
const slots = internalSlotsMap.get(this);
|
556
|
+
const eslintIgnorePath = path.resolve(slots.cwd, ".eslintignore");
|
557
|
+
const packageJsonPath = path.resolve(slots.cwd, "package.json");
|
486
558
|
|
487
559
|
if (fs.existsSync(eslintIgnorePath)) {
|
488
560
|
return this.loadESLintIgnore(eslintIgnorePath);
|
@@ -494,12 +566,16 @@ class ConfigArrayFactory {
|
|
494
566
|
if (!Array.isArray(data.eslintIgnore)) {
|
495
567
|
throw new Error("Package.json eslintIgnore property requires an array of paths");
|
496
568
|
}
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
569
|
+
const ctx = createContext(
|
570
|
+
slots,
|
571
|
+
"ignore",
|
572
|
+
"eslintIgnore in package.json",
|
573
|
+
packageJsonPath,
|
574
|
+
slots.cwd
|
575
|
+
);
|
576
|
+
|
577
|
+
return new ConfigArray(
|
578
|
+
...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)
|
503
579
|
);
|
504
580
|
}
|
505
581
|
}
|
@@ -509,65 +585,25 @@ class ConfigArrayFactory {
|
|
509
585
|
|
510
586
|
/**
|
511
587
|
* Load a given config file.
|
512
|
-
* @param {
|
513
|
-
* @param {string} name The config name.
|
588
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
514
589
|
* @returns {IterableIterator<ConfigArrayElement>} Loaded config.
|
515
590
|
* @private
|
516
591
|
*/
|
517
|
-
_loadConfigData(
|
518
|
-
return this._normalizeConfigData(
|
519
|
-
loadConfigFile(filePath),
|
520
|
-
filePath,
|
521
|
-
name
|
522
|
-
);
|
523
|
-
}
|
524
|
-
|
525
|
-
/**
|
526
|
-
* Load the config file in a given directory if exists.
|
527
|
-
* @param {string} directoryPath The path to a directory.
|
528
|
-
* @param {string} name The config name.
|
529
|
-
* @returns {IterableIterator<ConfigArrayElement> | null} Loaded config. `null` if any config doesn't exist.
|
530
|
-
* @private
|
531
|
-
*/
|
532
|
-
_loadConfigDataInDirectory(directoryPath, name) {
|
533
|
-
for (const filename of configFilenames) {
|
534
|
-
const filePath = path.join(directoryPath, filename);
|
535
|
-
|
536
|
-
if (fs.existsSync(filePath)) {
|
537
|
-
let configData;
|
538
|
-
|
539
|
-
try {
|
540
|
-
configData = loadConfigFile(filePath);
|
541
|
-
} catch (error) {
|
542
|
-
if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
|
543
|
-
throw error;
|
544
|
-
}
|
545
|
-
}
|
546
|
-
|
547
|
-
if (configData) {
|
548
|
-
debug(`Config file found: ${filePath}`);
|
549
|
-
return this._normalizeConfigData(configData, filePath, name);
|
550
|
-
}
|
551
|
-
}
|
552
|
-
}
|
553
|
-
|
554
|
-
debug(`Config file not found on ${directoryPath}`);
|
555
|
-
return null;
|
592
|
+
_loadConfigData(ctx) {
|
593
|
+
return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);
|
556
594
|
}
|
557
595
|
|
558
596
|
/**
|
559
597
|
* Normalize a given `.eslintignore` data to config array elements.
|
560
598
|
* @param {string[]} ignorePatterns The patterns to ignore files.
|
561
|
-
* @param {
|
562
|
-
* @param {string|undefined} name The name of this config.
|
599
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
563
600
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
564
601
|
* @private
|
565
602
|
*/
|
566
|
-
*_normalizeESLintIgnoreData(ignorePatterns,
|
603
|
+
*_normalizeESLintIgnoreData(ignorePatterns, ctx) {
|
567
604
|
const elements = this._normalizeObjectConfigData(
|
568
|
-
{
|
569
|
-
|
570
|
-
name
|
605
|
+
{ ignorePatterns },
|
606
|
+
ctx
|
571
607
|
);
|
572
608
|
|
573
609
|
// Set `ignorePattern.loose` flag for backward compatibility.
|
@@ -582,53 +618,38 @@ class ConfigArrayFactory {
|
|
582
618
|
/**
|
583
619
|
* Normalize a given config to an array.
|
584
620
|
* @param {ConfigData} configData The config data to normalize.
|
585
|
-
* @param {
|
586
|
-
* @param {string|undefined} providedName The name of this config.
|
621
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
587
622
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
588
623
|
* @private
|
589
624
|
*/
|
590
|
-
_normalizeConfigData(configData,
|
591
|
-
|
592
|
-
|
593
|
-
? path.resolve(cwd, providedFilePath)
|
594
|
-
: "";
|
595
|
-
const name = providedName || (filePath && path.relative(cwd, filePath));
|
596
|
-
|
597
|
-
validateConfigSchema(configData, name || filePath);
|
598
|
-
|
599
|
-
return this._normalizeObjectConfigData(configData, filePath, name);
|
625
|
+
_normalizeConfigData(configData, ctx) {
|
626
|
+
validateConfigSchema(configData, ctx.name || ctx.filePath);
|
627
|
+
return this._normalizeObjectConfigData(configData, ctx);
|
600
628
|
}
|
601
629
|
|
602
630
|
/**
|
603
631
|
* Normalize a given config to an array.
|
604
632
|
* @param {ConfigData|OverrideConfigData} configData The config data to normalize.
|
605
|
-
* @param {
|
606
|
-
* @param {string} name The name of this config.
|
633
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
607
634
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
608
635
|
* @private
|
609
636
|
*/
|
610
|
-
*_normalizeObjectConfigData(configData,
|
611
|
-
const { cwd } = internalSlotsMap.get(this);
|
637
|
+
*_normalizeObjectConfigData(configData, ctx) {
|
612
638
|
const { files, excludedFiles, ...configBody } = configData;
|
613
|
-
const
|
614
|
-
|
615
|
-
|
616
|
-
|
639
|
+
const criteria = OverrideTester.create(
|
640
|
+
files,
|
641
|
+
excludedFiles,
|
642
|
+
ctx.matchBasePath
|
643
|
+
);
|
644
|
+
const elements = this._normalizeObjectConfigDataBody(configBody, ctx);
|
617
645
|
|
618
646
|
// Apply the criteria to every element.
|
619
647
|
for (const element of elements) {
|
620
648
|
|
621
|
-
// Adopt the base path of the entry file (the outermost base path).
|
622
|
-
if (element.criteria) {
|
623
|
-
element.criteria.basePath = basePath;
|
624
|
-
}
|
625
|
-
if (element.ignorePattern) {
|
626
|
-
element.ignorePattern.basePath = basePath;
|
627
|
-
}
|
628
|
-
|
629
649
|
/*
|
630
|
-
* Merge the criteria
|
631
|
-
* `overrides`
|
650
|
+
* Merge the criteria.
|
651
|
+
* This is for the `overrides` entries that came from the
|
652
|
+
* configurations of `overrides[].extends`.
|
632
653
|
*/
|
633
654
|
element.criteria = OverrideTester.and(criteria, element.criteria);
|
634
655
|
|
@@ -647,8 +668,7 @@ class ConfigArrayFactory {
|
|
647
668
|
/**
|
648
669
|
* Normalize a given config to an array.
|
649
670
|
* @param {ConfigData} configData The config data to normalize.
|
650
|
-
* @param {
|
651
|
-
* @param {string} name The name of this config.
|
671
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
652
672
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
653
673
|
* @private
|
654
674
|
*/
|
@@ -667,41 +687,37 @@ class ConfigArrayFactory {
|
|
667
687
|
root,
|
668
688
|
rules,
|
669
689
|
settings,
|
670
|
-
type = "config",
|
671
690
|
overrides: overrideList = []
|
672
691
|
},
|
673
|
-
|
674
|
-
name
|
692
|
+
ctx
|
675
693
|
) {
|
676
694
|
const extendList = Array.isArray(extend) ? extend : [extend];
|
677
695
|
const ignorePattern = ignorePatterns && new IgnorePattern(
|
678
696
|
Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
|
679
|
-
|
697
|
+
ctx.matchBasePath
|
680
698
|
);
|
681
699
|
|
682
700
|
// Flatten `extends`.
|
683
701
|
for (const extendName of extendList.filter(Boolean)) {
|
684
|
-
yield* this._loadExtends(extendName,
|
702
|
+
yield* this._loadExtends(extendName, ctx);
|
685
703
|
}
|
686
704
|
|
687
705
|
// Load parser & plugins.
|
688
|
-
const parser =
|
689
|
-
|
690
|
-
const plugins =
|
691
|
-
pluginList && this._loadPlugins(pluginList, filePath, name);
|
706
|
+
const parser = parserName && this._loadParser(parserName, ctx);
|
707
|
+
const plugins = pluginList && this._loadPlugins(pluginList, ctx);
|
692
708
|
|
693
709
|
// Yield pseudo config data for file extension processors.
|
694
710
|
if (plugins) {
|
695
|
-
yield* this._takeFileExtensionProcessors(plugins,
|
711
|
+
yield* this._takeFileExtensionProcessors(plugins, ctx);
|
696
712
|
}
|
697
713
|
|
698
714
|
// Yield the config data except `extends` and `overrides`.
|
699
715
|
yield {
|
700
716
|
|
701
717
|
// Debug information.
|
702
|
-
type,
|
703
|
-
name,
|
704
|
-
filePath,
|
718
|
+
type: ctx.type,
|
719
|
+
name: ctx.name,
|
720
|
+
filePath: ctx.filePath,
|
705
721
|
|
706
722
|
// Config data.
|
707
723
|
criteria: null,
|
@@ -723,8 +739,7 @@ class ConfigArrayFactory {
|
|
723
739
|
for (let i = 0; i < overrideList.length; ++i) {
|
724
740
|
yield* this._normalizeObjectConfigData(
|
725
741
|
overrideList[i],
|
726
|
-
|
727
|
-
`${name}#overrides[${i}]`
|
742
|
+
{ ...ctx, name: `${ctx.name}#overrides[${i}]` }
|
728
743
|
);
|
729
744
|
}
|
730
745
|
}
|
@@ -732,34 +747,22 @@ class ConfigArrayFactory {
|
|
732
747
|
/**
|
733
748
|
* Load configs of an element in `extends`.
|
734
749
|
* @param {string} extendName The name of a base config.
|
735
|
-
* @param {
|
736
|
-
* @param {string} importerName The name of the config which has the `extends` property.
|
750
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
737
751
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
738
752
|
* @private
|
739
753
|
*/
|
740
|
-
_loadExtends(extendName,
|
741
|
-
debug("Loading {extends:%j} relative to %s", extendName,
|
754
|
+
_loadExtends(extendName, ctx) {
|
755
|
+
debug("Loading {extends:%j} relative to %s", extendName, ctx.filePath);
|
742
756
|
try {
|
743
757
|
if (extendName.startsWith("eslint:")) {
|
744
|
-
return this._loadExtendedBuiltInConfig(
|
745
|
-
extendName,
|
746
|
-
importerName
|
747
|
-
);
|
758
|
+
return this._loadExtendedBuiltInConfig(extendName, ctx);
|
748
759
|
}
|
749
760
|
if (extendName.startsWith("plugin:")) {
|
750
|
-
return this._loadExtendedPluginConfig(
|
751
|
-
extendName,
|
752
|
-
importerPath,
|
753
|
-
importerName
|
754
|
-
);
|
761
|
+
return this._loadExtendedPluginConfig(extendName, ctx);
|
755
762
|
}
|
756
|
-
return this._loadExtendedShareableConfig(
|
757
|
-
extendName,
|
758
|
-
importerPath,
|
759
|
-
importerName
|
760
|
-
);
|
763
|
+
return this._loadExtendedShareableConfig(extendName, ctx);
|
761
764
|
} catch (error) {
|
762
|
-
error.message += `\nReferenced from: ${
|
765
|
+
error.message += `\nReferenced from: ${ctx.filePath || ctx.name}`;
|
763
766
|
throw error;
|
764
767
|
}
|
765
768
|
}
|
@@ -767,32 +770,37 @@ class ConfigArrayFactory {
|
|
767
770
|
/**
|
768
771
|
* Load configs of an element in `extends`.
|
769
772
|
* @param {string} extendName The name of a base config.
|
770
|
-
* @param {
|
773
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
771
774
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
772
775
|
* @private
|
773
776
|
*/
|
774
|
-
_loadExtendedBuiltInConfig(extendName,
|
775
|
-
const name = `${importerName} » ${extendName}`;
|
776
|
-
|
777
|
+
_loadExtendedBuiltInConfig(extendName, ctx) {
|
777
778
|
if (extendName === "eslint:recommended") {
|
778
|
-
return this._loadConfigData(
|
779
|
+
return this._loadConfigData({
|
780
|
+
...ctx,
|
781
|
+
filePath: eslintRecommendedPath,
|
782
|
+
name: `${ctx.name} » ${extendName}`
|
783
|
+
});
|
779
784
|
}
|
780
785
|
if (extendName === "eslint:all") {
|
781
|
-
return this._loadConfigData(
|
786
|
+
return this._loadConfigData({
|
787
|
+
...ctx,
|
788
|
+
filePath: eslintAllPath,
|
789
|
+
name: `${ctx.name} » ${extendName}`
|
790
|
+
});
|
782
791
|
}
|
783
792
|
|
784
|
-
throw configMissingError(extendName,
|
793
|
+
throw configMissingError(extendName, ctx.name);
|
785
794
|
}
|
786
795
|
|
787
796
|
/**
|
788
797
|
* Load configs of an element in `extends`.
|
789
798
|
* @param {string} extendName The name of a base config.
|
790
|
-
* @param {
|
791
|
-
* @param {string} importerName The name of the config which has the `extends` property.
|
799
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
792
800
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
793
801
|
* @private
|
794
802
|
*/
|
795
|
-
_loadExtendedPluginConfig(extendName,
|
803
|
+
_loadExtendedPluginConfig(extendName, ctx) {
|
796
804
|
const slashIndex = extendName.lastIndexOf("/");
|
797
805
|
const pluginName = extendName.slice("plugin:".length, slashIndex);
|
798
806
|
const configName = extendName.slice(slashIndex + 1);
|
@@ -801,33 +809,32 @@ class ConfigArrayFactory {
|
|
801
809
|
throw new Error("'extends' cannot use a file path for plugins.");
|
802
810
|
}
|
803
811
|
|
804
|
-
const plugin = this._loadPlugin(pluginName,
|
812
|
+
const plugin = this._loadPlugin(pluginName, ctx);
|
805
813
|
const configData =
|
806
814
|
plugin.definition &&
|
807
815
|
plugin.definition.configs[configName];
|
808
816
|
|
809
817
|
if (configData) {
|
810
|
-
return this._normalizeConfigData(
|
811
|
-
|
812
|
-
plugin.filePath,
|
813
|
-
`${
|
814
|
-
);
|
818
|
+
return this._normalizeConfigData(configData, {
|
819
|
+
...ctx,
|
820
|
+
filePath: plugin.filePath || ctx.filePath,
|
821
|
+
name: `${ctx.name} » plugin:${plugin.id}/${configName}`
|
822
|
+
});
|
815
823
|
}
|
816
824
|
|
817
|
-
throw plugin.error || configMissingError(extendName,
|
825
|
+
throw plugin.error || configMissingError(extendName, ctx.filePath);
|
818
826
|
}
|
819
827
|
|
820
828
|
/**
|
821
829
|
* Load configs of an element in `extends`.
|
822
830
|
* @param {string} extendName The name of a base config.
|
823
|
-
* @param {
|
824
|
-
* @param {string} importerName The name of the config which has the `extends` property.
|
831
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
825
832
|
* @returns {IterableIterator<ConfigArrayElement>} The normalized config.
|
826
833
|
* @private
|
827
834
|
*/
|
828
|
-
_loadExtendedShareableConfig(extendName,
|
835
|
+
_loadExtendedShareableConfig(extendName, ctx) {
|
829
836
|
const { cwd } = internalSlotsMap.get(this);
|
830
|
-
const relativeTo =
|
837
|
+
const relativeTo = ctx.filePath || path.join(cwd, "__placeholder__.js");
|
831
838
|
let request;
|
832
839
|
|
833
840
|
if (isFilePath(extendName)) {
|
@@ -848,29 +855,32 @@ class ConfigArrayFactory {
|
|
848
855
|
} catch (error) {
|
849
856
|
/* istanbul ignore else */
|
850
857
|
if (error && error.code === "MODULE_NOT_FOUND") {
|
851
|
-
throw configMissingError(extendName,
|
858
|
+
throw configMissingError(extendName, ctx.filePath);
|
852
859
|
}
|
853
860
|
throw error;
|
854
861
|
}
|
855
862
|
|
856
863
|
writeDebugLogForLoading(request, relativeTo, filePath);
|
857
|
-
return this._loadConfigData(
|
864
|
+
return this._loadConfigData({
|
865
|
+
...ctx,
|
866
|
+
filePath,
|
867
|
+
name: `${ctx.name} » ${request}`
|
868
|
+
});
|
858
869
|
}
|
859
870
|
|
860
871
|
/**
|
861
872
|
* Load given plugins.
|
862
873
|
* @param {string[]} names The plugin names to load.
|
863
|
-
* @param {
|
864
|
-
* @param {string} importerName The name of a config file that imports it. This is just a debug info.
|
874
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
865
875
|
* @returns {Record<string,DependentPlugin>} The loaded parser.
|
866
876
|
* @private
|
867
877
|
*/
|
868
|
-
_loadPlugins(names,
|
878
|
+
_loadPlugins(names, ctx) {
|
869
879
|
return names.reduce((map, name) => {
|
870
880
|
if (isFilePath(name)) {
|
871
881
|
throw new Error("Plugins array cannot includes file paths.");
|
872
882
|
}
|
873
|
-
const plugin = this._loadPlugin(name,
|
883
|
+
const plugin = this._loadPlugin(name, ctx);
|
874
884
|
|
875
885
|
map[plugin.id] = plugin;
|
876
886
|
|
@@ -881,15 +891,14 @@ class ConfigArrayFactory {
|
|
881
891
|
/**
|
882
892
|
* Load a given parser.
|
883
893
|
* @param {string} nameOrPath The package name or the path to a parser file.
|
884
|
-
* @param {
|
885
|
-
* @param {string} importerName The name of a config file that imports it. This is just a debug info.
|
894
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
886
895
|
* @returns {DependentParser} The loaded parser.
|
887
896
|
*/
|
888
|
-
_loadParser(nameOrPath,
|
889
|
-
debug("Loading parser %j from %s", nameOrPath,
|
897
|
+
_loadParser(nameOrPath, ctx) {
|
898
|
+
debug("Loading parser %j from %s", nameOrPath, ctx.filePath);
|
890
899
|
|
891
900
|
const { cwd } = internalSlotsMap.get(this);
|
892
|
-
const relativeTo =
|
901
|
+
const relativeTo = ctx.filePath || path.join(cwd, "__placeholder__.js");
|
893
902
|
|
894
903
|
try {
|
895
904
|
const filePath = ModuleResolver.resolve(nameOrPath, relativeTo);
|
@@ -900,8 +909,8 @@ class ConfigArrayFactory {
|
|
900
909
|
definition: require(filePath),
|
901
910
|
filePath,
|
902
911
|
id: nameOrPath,
|
903
|
-
importerName,
|
904
|
-
importerPath
|
912
|
+
importerName: ctx.name,
|
913
|
+
importerPath: ctx.filePath
|
905
914
|
});
|
906
915
|
} catch (error) {
|
907
916
|
|
@@ -912,19 +921,19 @@ class ConfigArrayFactory {
|
|
912
921
|
definition: require("espree"),
|
913
922
|
filePath: require.resolve("espree"),
|
914
923
|
id: nameOrPath,
|
915
|
-
importerName,
|
916
|
-
importerPath
|
924
|
+
importerName: ctx.name,
|
925
|
+
importerPath: ctx.filePath
|
917
926
|
});
|
918
927
|
}
|
919
928
|
|
920
|
-
debug("Failed to load parser '%s' declared in '%s'.", nameOrPath,
|
921
|
-
error.message = `Failed to load parser '${nameOrPath}' declared in '${
|
929
|
+
debug("Failed to load parser '%s' declared in '%s'.", nameOrPath, ctx.name);
|
930
|
+
error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;
|
922
931
|
|
923
932
|
return new ConfigDependency({
|
924
933
|
error,
|
925
934
|
id: nameOrPath,
|
926
|
-
importerName,
|
927
|
-
importerPath
|
935
|
+
importerName: ctx.name,
|
936
|
+
importerPath: ctx.filePath
|
928
937
|
});
|
929
938
|
}
|
930
939
|
}
|
@@ -932,18 +941,17 @@ class ConfigArrayFactory {
|
|
932
941
|
/**
|
933
942
|
* Load a given plugin.
|
934
943
|
* @param {string} name The plugin name to load.
|
935
|
-
* @param {
|
936
|
-
* @param {string} importerName The name of a config file that imports it. This is just a debug info.
|
944
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
937
945
|
* @returns {DependentPlugin} The loaded plugin.
|
938
946
|
* @private
|
939
947
|
*/
|
940
|
-
_loadPlugin(name,
|
941
|
-
debug("Loading plugin %j from %s", name,
|
948
|
+
_loadPlugin(name, ctx) {
|
949
|
+
debug("Loading plugin %j from %s", name, ctx.filePath);
|
942
950
|
|
943
|
-
const { additionalPluginPool
|
951
|
+
const { additionalPluginPool } = internalSlotsMap.get(this);
|
944
952
|
const request = naming.normalizePackageName(name, "eslint-plugin");
|
945
953
|
const id = naming.getShorthandName(request, "eslint-plugin");
|
946
|
-
const relativeTo = path.join(
|
954
|
+
const relativeTo = path.join(ctx.pluginBasePath, "__placeholder__.js");
|
947
955
|
|
948
956
|
if (name.match(/\s+/u)) {
|
949
957
|
const error = Object.assign(
|
@@ -957,8 +965,8 @@ class ConfigArrayFactory {
|
|
957
965
|
return new ConfigDependency({
|
958
966
|
error,
|
959
967
|
id,
|
960
|
-
importerName,
|
961
|
-
importerPath
|
968
|
+
importerName: ctx.name,
|
969
|
+
importerPath: ctx.filePath
|
962
970
|
});
|
963
971
|
}
|
964
972
|
|
@@ -970,10 +978,10 @@ class ConfigArrayFactory {
|
|
970
978
|
if (plugin) {
|
971
979
|
return new ConfigDependency({
|
972
980
|
definition: normalizePlugin(plugin),
|
973
|
-
filePath:
|
981
|
+
filePath: "", // It's unknown where the plugin came from.
|
974
982
|
id,
|
975
|
-
importerName,
|
976
|
-
importerPath
|
983
|
+
importerName: ctx.name,
|
984
|
+
importerPath: ctx.filePath
|
977
985
|
});
|
978
986
|
}
|
979
987
|
|
@@ -989,8 +997,8 @@ class ConfigArrayFactory {
|
|
989
997
|
error.messageTemplate = "plugin-missing";
|
990
998
|
error.messageData = {
|
991
999
|
pluginName: request,
|
992
|
-
resolvePluginsRelativeTo,
|
993
|
-
importerName
|
1000
|
+
resolvePluginsRelativeTo: ctx.pluginBasePath,
|
1001
|
+
importerName: ctx.name
|
994
1002
|
};
|
995
1003
|
}
|
996
1004
|
}
|
@@ -1008,33 +1016,32 @@ class ConfigArrayFactory {
|
|
1008
1016
|
definition: normalizePlugin(pluginDefinition),
|
1009
1017
|
filePath,
|
1010
1018
|
id,
|
1011
|
-
importerName,
|
1012
|
-
importerPath
|
1019
|
+
importerName: ctx.name,
|
1020
|
+
importerPath: ctx.filePath
|
1013
1021
|
});
|
1014
1022
|
} catch (loadError) {
|
1015
1023
|
error = loadError;
|
1016
1024
|
}
|
1017
1025
|
}
|
1018
1026
|
|
1019
|
-
debug("Failed to load plugin '%s' declared in '%s'.", name,
|
1020
|
-
error.message = `Failed to load plugin '${name}' declared in '${
|
1027
|
+
debug("Failed to load plugin '%s' declared in '%s'.", name, ctx.name);
|
1028
|
+
error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;
|
1021
1029
|
return new ConfigDependency({
|
1022
1030
|
error,
|
1023
1031
|
id,
|
1024
|
-
importerName,
|
1025
|
-
importerPath
|
1032
|
+
importerName: ctx.name,
|
1033
|
+
importerPath: ctx.filePath
|
1026
1034
|
});
|
1027
1035
|
}
|
1028
1036
|
|
1029
1037
|
/**
|
1030
1038
|
* Take file expression processors as config array elements.
|
1031
1039
|
* @param {Record<string,DependentPlugin>} plugins The plugin definitions.
|
1032
|
-
* @param {
|
1033
|
-
* @param {string} name The name of this config.
|
1040
|
+
* @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
|
1034
1041
|
* @returns {IterableIterator<ConfigArrayElement>} The config array elements of file expression processors.
|
1035
1042
|
* @private
|
1036
1043
|
*/
|
1037
|
-
*_takeFileExtensionProcessors(plugins,
|
1044
|
+
*_takeFileExtensionProcessors(plugins, ctx) {
|
1038
1045
|
for (const pluginId of Object.keys(plugins)) {
|
1039
1046
|
const processors =
|
1040
1047
|
plugins[pluginId] &&
|
@@ -1049,12 +1056,14 @@ class ConfigArrayFactory {
|
|
1049
1056
|
if (processorId.startsWith(".")) {
|
1050
1057
|
yield* this._normalizeObjectConfigData(
|
1051
1058
|
{
|
1052
|
-
type: "implicit-processor",
|
1053
1059
|
files: [`*${processorId}`],
|
1054
1060
|
processor: `${pluginId}/${processorId}`
|
1055
1061
|
},
|
1056
|
-
|
1057
|
-
|
1062
|
+
{
|
1063
|
+
...ctx,
|
1064
|
+
type: "implicit-processor",
|
1065
|
+
name: `${ctx.name}#processors["${pluginId}/${processorId}"]`
|
1066
|
+
}
|
1058
1067
|
);
|
1059
1068
|
}
|
1060
1069
|
}
|
@@ -1062,4 +1071,4 @@ class ConfigArrayFactory {
|
|
1062
1071
|
}
|
1063
1072
|
}
|
1064
1073
|
|
1065
|
-
module.exports = { ConfigArrayFactory };
|
1074
|
+
module.exports = { ConfigArrayFactory, createContext };
|