| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 | /** * @fileoverview Flat Config Array * @author Nicholas C. Zakas */"use strict";//-----------------------------------------------------------------------------// Requirements//-----------------------------------------------------------------------------const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array");const { flatConfigSchema } = require("./flat-config-schema");const { RuleValidator } = require("./rule-validator");const { defaultConfig } = require("./default-config");const recommendedConfig = require("../../conf/eslint-recommended");//-----------------------------------------------------------------------------// Helpers//-----------------------------------------------------------------------------const ruleValidator = new RuleValidator();/** * Splits a plugin identifier in the form a/b/c into two parts: a/b and c. * @param {string} identifier The identifier to parse. * @returns {{objectName: string, pluginName: string}} The parts of the plugin *      name. */function splitPluginIdentifier(identifier) {    const parts = identifier.split("/");    return {        objectName: parts.pop(),        pluginName: parts.join("/")    };}const originalBaseConfig = Symbol("originalBaseConfig");//-----------------------------------------------------------------------------// Exports//-----------------------------------------------------------------------------/** * Represents an array containing configuration information for ESLint. */class FlatConfigArray extends ConfigArray {    /**     * Creates a new instance.     * @param {*[]} configs An array of configuration information.     * @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options     *      to use for the config array instance.     */    constructor(configs, {        basePath,        shouldIgnore = true,        baseConfig = defaultConfig    } = {}) {        super(configs, {            basePath,            schema: flatConfigSchema        });        if (baseConfig[Symbol.iterator]) {            this.unshift(...baseConfig);        } else {            this.unshift(baseConfig);        }        /**         * The base config used to build the config array.         * @type {Array<FlatConfig>}         */        this[originalBaseConfig] = baseConfig;        Object.defineProperty(this, originalBaseConfig, { writable: false });        /**         * Determines if `ignores` fields should be honored.         * If true, then all `ignores` fields are honored.         * if false, then only `ignores` fields in the baseConfig are honored.         * @type {boolean}         */        this.shouldIgnore = shouldIgnore;        Object.defineProperty(this, "shouldIgnore", { writable: false });    }    /* eslint-disable class-methods-use-this -- Desired as instance method */    /**     * Replaces a config with another config to allow us to put strings     * in the config array that will be replaced by objects before     * normalization.     * @param {Object} config The config to preprocess.     * @returns {Object} The preprocessed config.     */    [ConfigArraySymbol.preprocessConfig](config) {        if (config === "eslint:recommended") {            return recommendedConfig;        }        if (config === "eslint:all") {            /*             * Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules             * when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones,             * so requiring `eslint-all.js` module loads all rule modules as a consequence.             */            return require("../../conf/eslint-all");        }        /*         * If `shouldIgnore` is false, we remove any ignore patterns specified         * in the config so long as it's not a default config and it doesn't         * have a `files` entry.         */        if (            !this.shouldIgnore &&            !this[originalBaseConfig].includes(config) &&            config.ignores &&            !config.files        ) {            /* eslint-disable-next-line no-unused-vars -- need to strip off other keys */            const { ignores, ...otherKeys } = config;            return otherKeys;        }        return config;    }    /**     * Finalizes the config by replacing plugin references with their objects     * and validating rule option schemas.     * @param {Object} config The config to finalize.     * @returns {Object} The finalized config.     * @throws {TypeError} If the config is invalid.     */    [ConfigArraySymbol.finalizeConfig](config) {        const { plugins, languageOptions, processor } = config;        let parserName, processorName;        let invalidParser = false,            invalidProcessor = false;        // Check parser value        if (languageOptions && languageOptions.parser) {            if (typeof languageOptions.parser === "string") {                const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);                parserName = languageOptions.parser;                if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {                    throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);                }                languageOptions.parser = plugins[pluginName].parsers[localParserName];            } else {                invalidParser = true;            }        }        // Check processor value        if (processor) {            if (typeof processor === "string") {                const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor);                processorName = processor;                if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) {                    throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`);                }                config.processor = plugins[pluginName].processors[localProcessorName];            } else {                invalidProcessor = true;            }        }        ruleValidator.validate(config);        // apply special logic for serialization into JSON        /* eslint-disable object-shorthand -- shorthand would change "this" value */        Object.defineProperty(config, "toJSON", {            value: function() {                if (invalidParser) {                    throw new Error("Caching is not supported when parser is an object.");                }                if (invalidProcessor) {                    throw new Error("Caching is not supported when processor is an object.");                }                return {                    ...this,                    plugins: Object.keys(plugins),                    languageOptions: {                        ...languageOptions,                        parser: parserName                    },                    processor: processorName                };            }        });        /* eslint-enable object-shorthand -- ok to enable now */        return config;    }    /* eslint-enable class-methods-use-this -- Desired as instance method */}exports.FlatConfigArray = FlatConfigArray;
 |