]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/config/flat-config-array.js
ad8986f516ef9c936fc3d006c55f4a5b247df98d
[pve-eslint.git] / eslint / lib / config / flat-config-array.js
1 /**
2 * @fileoverview Flat Config Array
3 * @author Nicholas C. Zakas
4 */
5
6 "use strict";
7
8 //-----------------------------------------------------------------------------
9 // Requirements
10 //-----------------------------------------------------------------------------
11
12 const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array");
13 const { flatConfigSchema } = require("./flat-config-schema");
14 const { RuleValidator } = require("./rule-validator");
15 const { defaultConfig } = require("./default-config");
16 const recommendedConfig = require("../../conf/eslint-recommended");
17
18 //-----------------------------------------------------------------------------
19 // Helpers
20 //-----------------------------------------------------------------------------
21
22 const ruleValidator = new RuleValidator();
23
24 /**
25 * Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
26 * @param {string} identifier The identifier to parse.
27 * @returns {{objectName: string, pluginName: string}} The parts of the plugin
28 * name.
29 */
30 function splitPluginIdentifier(identifier) {
31 const parts = identifier.split("/");
32
33 return {
34 objectName: parts.pop(),
35 pluginName: parts.join("/")
36 };
37 }
38
39 const originalBaseConfig = Symbol("originalBaseConfig");
40
41 //-----------------------------------------------------------------------------
42 // Exports
43 //-----------------------------------------------------------------------------
44
45 /**
46 * Represents an array containing configuration information for ESLint.
47 */
48 class FlatConfigArray extends ConfigArray {
49
50 /**
51 * Creates a new instance.
52 * @param {*[]} configs An array of configuration information.
53 * @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options
54 * to use for the config array instance.
55 */
56 constructor(configs, {
57 basePath,
58 shouldIgnore = true,
59 baseConfig = defaultConfig
60 } = {}) {
61 super(configs, {
62 basePath,
63 schema: flatConfigSchema
64 });
65
66 if (baseConfig[Symbol.iterator]) {
67 this.unshift(...baseConfig);
68 } else {
69 this.unshift(baseConfig);
70 }
71
72 /**
73 * The baes config used to build the config array.
74 * @type {Array<FlatConfig>}
75 */
76 this[originalBaseConfig] = baseConfig;
77 Object.defineProperty(this, originalBaseConfig, { writable: false });
78
79 /**
80 * Determines if `ignores` fields should be honored.
81 * If true, then all `ignores` fields are honored.
82 * if false, then only `ignores` fields in the baseConfig are honored.
83 * @type {boolean}
84 */
85 this.shouldIgnore = shouldIgnore;
86 Object.defineProperty(this, "shouldIgnore", { writable: false });
87 }
88
89 /* eslint-disable class-methods-use-this -- Desired as instance method */
90 /**
91 * Replaces a config with another config to allow us to put strings
92 * in the config array that will be replaced by objects before
93 * normalization.
94 * @param {Object} config The config to preprocess.
95 * @returns {Object} The preprocessed config.
96 */
97 [ConfigArraySymbol.preprocessConfig](config) {
98 if (config === "eslint:recommended") {
99 return recommendedConfig;
100 }
101
102 if (config === "eslint:all") {
103
104 /*
105 * Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules
106 * when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones,
107 * so requiring `eslint-all.js` module loads all rule modules as a consequence.
108 */
109 return require("../../conf/eslint-all");
110 }
111
112 /*
113 * If `shouldIgnore` is false, we remove any ignore patterns specified
114 * in the config so long as it's not a default config and it doesn't
115 * have a `files` entry.
116 */
117 if (
118 !this.shouldIgnore &&
119 !this[originalBaseConfig].includes(config) &&
120 config.ignores &&
121 !config.files
122 ) {
123 /* eslint-disable-next-line no-unused-vars -- need to strip off other keys */
124 const { ignores, ...otherKeys } = config;
125
126 return otherKeys;
127 }
128
129 return config;
130 }
131
132 /**
133 * Finalizes the config by replacing plugin references with their objects
134 * and validating rule option schemas.
135 * @param {Object} config The config to finalize.
136 * @returns {Object} The finalized config.
137 * @throws {TypeError} If the config is invalid.
138 */
139 [ConfigArraySymbol.finalizeConfig](config) {
140
141 const { plugins, languageOptions, processor } = config;
142 let parserName, processorName;
143 let invalidParser = false,
144 invalidProcessor = false;
145
146 // Check parser value
147 if (languageOptions && languageOptions.parser) {
148 if (typeof languageOptions.parser === "string") {
149 const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);
150
151 parserName = languageOptions.parser;
152
153 if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {
154 throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);
155 }
156
157 languageOptions.parser = plugins[pluginName].parsers[localParserName];
158 } else {
159 invalidParser = true;
160 }
161 }
162
163 // Check processor value
164 if (processor) {
165 if (typeof processor === "string") {
166 const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor);
167
168 processorName = processor;
169
170 if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) {
171 throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`);
172 }
173
174 config.processor = plugins[pluginName].processors[localProcessorName];
175 } else {
176 invalidProcessor = true;
177 }
178 }
179
180 ruleValidator.validate(config);
181
182 // apply special logic for serialization into JSON
183 /* eslint-disable object-shorthand -- shorthand would change "this" value */
184 Object.defineProperty(config, "toJSON", {
185 value: function() {
186
187 if (invalidParser) {
188 throw new Error("Caching is not supported when parser is an object.");
189 }
190
191 if (invalidProcessor) {
192 throw new Error("Caching is not supported when processor is an object.");
193 }
194
195 return {
196 ...this,
197 plugins: Object.keys(plugins),
198 languageOptions: {
199 ...languageOptions,
200 parser: parserName
201 },
202 processor: processorName
203 };
204 }
205 });
206 /* eslint-enable object-shorthand -- ok to enable now */
207
208 return config;
209 }
210 /* eslint-enable class-methods-use-this -- Desired as instance method */
211
212 }
213
214 exports.FlatConfigArray = FlatConfigArray;