1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- var debugOrig = require('debug');
- var fs = require('fs');
- var importFresh = require('import-fresh');
- var Module = require('module');
- var path = require('path');
- var stripComments = require('strip-json-comments');
- var assert = require('assert');
- var ignore = require('ignore');
- var util = require('util');
- var minimatch = require('minimatch');
- var Ajv = require('ajv');
- var globals = require('globals');
- var os = require('os');
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
- var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig);
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
- var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh);
- var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module);
- var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
- var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments);
- var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
- var ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
- var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
- var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
- var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
- var globals__default = /*#__PURE__*/_interopDefaultLegacy(globals);
- var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
- /**
- * @fileoverview `IgnorePattern` class.
- *
- * `IgnorePattern` class has the set of glob patterns and the base path.
- *
- * It provides two static methods.
- *
- * - `IgnorePattern.createDefaultIgnore(cwd)`
- * Create the default predicate function.
- * - `IgnorePattern.createIgnore(ignorePatterns)`
- * Create the predicate function from multiple `IgnorePattern` objects.
- *
- * It provides two properties and a method.
- *
- * - `patterns`
- * The glob patterns that ignore to lint.
- * - `basePath`
- * The base path of the glob patterns. If absolute paths existed in the
- * glob patterns, those are handled as relative paths to the base path.
- * - `getPatternsRelativeTo(basePath)`
- * Get `patterns` as modified for a given base path. It modifies the
- * absolute paths in the patterns as prepending the difference of two base
- * paths.
- *
- * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
- * `ignorePatterns` properties.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- const debug$3 = debugOrig__default["default"]("eslintrc:ignore-pattern");
- /** @typedef {ReturnType<import("ignore").default>} Ignore */
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- /**
- * Get the path to the common ancestor directory of given paths.
- * @param {string[]} sourcePaths The paths to calculate the common ancestor.
- * @returns {string} The path to the common ancestor directory.
- */
- function getCommonAncestorPath(sourcePaths) {
- let result = sourcePaths[0];
- for (let i = 1; i < sourcePaths.length; ++i) {
- const a = result;
- const b = sourcePaths[i];
- // Set the shorter one (it's the common ancestor if one includes the other).
- result = a.length < b.length ? a : b;
- // Set the common ancestor.
- for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
- if (a[j] !== b[j]) {
- result = a.slice(0, lastSepPos);
- break;
- }
- if (a[j] === path__default["default"].sep) {
- lastSepPos = j;
- }
- }
- }
- let resolvedResult = result || path__default["default"].sep;
- // if Windows common ancestor is root of drive must have trailing slash to be absolute.
- if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
- resolvedResult += path__default["default"].sep;
- }
- return resolvedResult;
- }
- /**
- * Make relative path.
- * @param {string} from The source path to get relative path.
- * @param {string} to The destination path to get relative path.
- * @returns {string} The relative path.
- */
- function relative(from, to) {
- const relPath = path__default["default"].relative(from, to);
- if (path__default["default"].sep === "/") {
- return relPath;
- }
- return relPath.split(path__default["default"].sep).join("/");
- }
- /**
- * Get the trailing slash if existed.
- * @param {string} filePath The path to check.
- * @returns {string} The trailing slash if existed.
- */
- function dirSuffix(filePath) {
- const isDir = (
- filePath.endsWith(path__default["default"].sep) ||
- (process.platform === "win32" && filePath.endsWith("/"))
- );
- return isDir ? "/" : "";
- }
- const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
- const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
- //------------------------------------------------------------------------------
- // Public
- //------------------------------------------------------------------------------
- class IgnorePattern {
- /**
- * The default patterns.
- * @type {string[]}
- */
- static get DefaultPatterns() {
- return DefaultPatterns;
- }
- /**
- * Create the default predicate function.
- * @param {string} cwd The current working directory.
- * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
- * The preficate function.
- * The first argument is an absolute path that is checked.
- * The second argument is the flag to not ignore dotfiles.
- * If the predicate function returned `true`, it means the path should be ignored.
- */
- static createDefaultIgnore(cwd) {
- return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
- }
- /**
- * Create the predicate function from multiple `IgnorePattern` objects.
- * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
- * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
- * The preficate function.
- * The first argument is an absolute path that is checked.
- * The second argument is the flag to not ignore dotfiles.
- * If the predicate function returned `true`, it means the path should be ignored.
- */
- static createIgnore(ignorePatterns) {
- debug$3("Create with: %o", ignorePatterns);
- const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
- const patterns = [].concat(
- ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
- );
- const ig = ignore__default["default"]({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);
- const dotIg = ignore__default["default"]({ allowRelativePaths: true }).add(patterns);
- debug$3(" processed: %o", { basePath, patterns });
- return Object.assign(
- (filePath, dot = false) => {
- assert__default["default"](path__default["default"].isAbsolute(filePath), "'filePath' should be an absolute path.");
- const relPathRaw = relative(basePath, filePath);
- const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
- const adoptedIg = dot ? dotIg : ig;
- const result = relPath !== "" && adoptedIg.ignores(relPath);
- debug$3("Check", { filePath, dot, relativePath: relPath, result });
- return result;
- },
- { basePath, patterns }
- );
- }
- /**
- * Initialize a new `IgnorePattern` instance.
- * @param {string[]} patterns The glob patterns that ignore to lint.
- * @param {string} basePath The base path of `patterns`.
- */
- constructor(patterns, basePath) {
- assert__default["default"](path__default["default"].isAbsolute(basePath), "'basePath' should be an absolute path.");
- /**
- * The glob patterns that ignore to lint.
- * @type {string[]}
- */
- this.patterns = patterns;
- /**
- * The base path of `patterns`.
- * @type {string}
- */
- this.basePath = basePath;
- /**
- * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
- *
- * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
- * It's `false` as-is for `ignorePatterns` property in config files.
- * @type {boolean}
- */
- this.loose = false;
- }
- /**
- * Get `patterns` as modified for a given base path. It modifies the
- * absolute paths in the patterns as prepending the difference of two base
- * paths.
- * @param {string} newBasePath The base path.
- * @returns {string[]} Modifired patterns.
- */
- getPatternsRelativeTo(newBasePath) {
- assert__default["default"](path__default["default"].isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
- const { basePath, loose, patterns } = this;
- if (newBasePath === basePath) {
- return patterns;
- }
- const prefix = `/${relative(newBasePath, basePath)}`;
- return patterns.map(pattern => {
- const negative = pattern.startsWith("!");
- const head = negative ? "!" : "";
- const body = negative ? pattern.slice(1) : pattern;
- if (body.startsWith("/") || body.startsWith("../")) {
- return `${head}${prefix}${body}`;
- }
- return loose ? pattern : `${head}${prefix}/**/${body}`;
- });
- }
- }
- /**
- * @fileoverview `ExtractedConfig` class.
- *
- * `ExtractedConfig` class expresses a final configuration for a specific file.
- *
- * It provides one method.
- *
- * - `toCompatibleObjectAsConfigFileContent()`
- * Convert this configuration to the compatible object as the content of
- * config files. It converts the loaded parser and plugins to strings.
- * `CLIEngine#getConfigForFile(filePath)` method uses this method.
- *
- * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- // For VSCode intellisense
- /** @typedef {import("../../shared/types").ConfigData} ConfigData */
- /** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
- /** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
- /** @typedef {import("./config-dependency").DependentParser} DependentParser */
- /** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
- /**
- * Check if `xs` starts with `ys`.
- * @template T
- * @param {T[]} xs The array to check.
- * @param {T[]} ys The array that may be the first part of `xs`.
- * @returns {boolean} `true` if `xs` starts with `ys`.
- */
- function startsWith(xs, ys) {
- return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
- }
- /**
- * The class for extracted config data.
- */
- class ExtractedConfig {
- constructor() {
- /**
- * The config name what `noInlineConfig` setting came from.
- * @type {string}
- */
- this.configNameOfNoInlineConfig = "";
- /**
- * Environments.
- * @type {Record<string, boolean>}
- */
- this.env = {};
- /**
- * Global variables.
- * @type {Record<string, GlobalConf>}
- */
- this.globals = {};
- /**
- * The glob patterns that ignore to lint.
- * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
- */
- this.ignores = void 0;
- /**
- * The flag that disables directive comments.
- * @type {boolean|undefined}
- */
- this.noInlineConfig = void 0;
- /**
- * Parser definition.
- * @type {DependentParser|null}
- */
- this.parser = null;
- /**
- * Options for the parser.
- * @type {Object}
- */
- this.parserOptions = {};
- /**
- * Plugin definitions.
- * @type {Record<string, DependentPlugin>}
- */
- this.plugins = {};
- /**
- * Processor ID.
- * @type {string|null}
- */
- this.processor = null;
- /**
- * The flag that reports unused `eslint-disable` directive comments.
- * @type {boolean|undefined}
- */
- this.reportUnusedDisableDirectives = void 0;
- /**
- * Rule settings.
- * @type {Record<string, [SeverityConf, ...any[]]>}
- */
- this.rules = {};
- /**
- * Shared settings.
- * @type {Object}
- */
- this.settings = {};
- }
- /**
- * Convert this config to the compatible object as a config file content.
- * @returns {ConfigData} The converted object.
- */
- toCompatibleObjectAsConfigFileContent() {
- const {
- /* eslint-disable no-unused-vars */
- configNameOfNoInlineConfig: _ignore1,
- processor: _ignore2,
- /* eslint-enable no-unused-vars */
- ignores,
- ...config
- } = this;
- config.parser = config.parser && config.parser.filePath;
- config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
- config.ignorePatterns = ignores ? ignores.patterns : [];
- // Strip the default patterns from `ignorePatterns`.
- if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
- config.ignorePatterns =
- config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
- }
- return config;
- }
- }
- /**
- * @fileoverview `ConfigArray` class.
- *
- * `ConfigArray` class expresses the full of a configuration. It has the entry
- * config file, base config files that were extended, loaded parsers, and loaded
- * plugins.
- *
- * `ConfigArray` class provides three properties and two methods.
- *
- * - `pluginEnvironments`
- * - `pluginProcessors`
- * - `pluginRules`
- * The `Map` objects that contain the members of all plugins that this
- * config array contains. Those map objects don't have mutation methods.
- * Those keys are the member ID such as `pluginId/memberName`.
- * - `isRoot()`
- * If `true` then this configuration has `root:true` property.
- * - `extractConfig(filePath)`
- * Extract the final configuration for a given file. This means merging
- * every config array element which that `criteria` property matched. The
- * `filePath` argument must be an absolute path.
- *
- * `ConfigArrayFactory` provides the loading logic of config files.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- // Define types for VSCode IntelliSense.
- /** @typedef {import("../../shared/types").Environment} Environment */
- /** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
- /** @typedef {import("../../shared/types").RuleConf} RuleConf */
- /** @typedef {import("../../shared/types").Rule} Rule */
- /** @typedef {import("../../shared/types").Plugin} Plugin */
- /** @typedef {import("../../shared/types").Processor} Processor */
- /** @typedef {import("./config-dependency").DependentParser} DependentParser */
- /** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
- /** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
- /**
- * @typedef {Object} ConfigArrayElement
- * @property {string} name The name of this config element.
- * @property {string} filePath The path to the source file of this config element.
- * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
- * @property {Record<string, boolean>|undefined} env The environment settings.
- * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
- * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
- * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
- * @property {DependentParser|undefined} parser The parser loader.
- * @property {Object|undefined} parserOptions The parser options.
- * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
- * @property {string|undefined} processor The processor name to refer plugin's processor.
- * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
- * @property {boolean|undefined} root The flag to express root.
- * @property {Record<string, RuleConf>|undefined} rules The rule settings
- * @property {Object|undefined} settings The shared settings.
- * @property {"config" | "ignore" | "implicit-processor"} type The element type.
- */
- /**
- * @typedef {Object} ConfigArrayInternalSlots
- * @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
- * @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
- * @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
- * @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
- */
- /** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
- const internalSlotsMap$2 = new class extends WeakMap {
- get(key) {
- let value = super.get(key);
- if (!value) {
- value = {
- cache: new Map(),
- envMap: null,
- processorMap: null,
- ruleMap: null
- };
- super.set(key, value);
- }
- return value;
- }
- }();
- /**
- * Get the indices which are matched to a given file.
- * @param {ConfigArrayElement[]} elements The elements.
- * @param {string} filePath The path to a target file.
- * @returns {number[]} The indices.
- */
- function getMatchedIndices(elements, filePath) {
- const indices = [];
- for (let i = elements.length - 1; i >= 0; --i) {
- const element = elements[i];
- if (!element.criteria || (filePath && element.criteria.test(filePath))) {
- indices.push(i);
- }
- }
- return indices;
- }
- /**
- * Check if a value is a non-null object.
- * @param {any} x The value to check.
- * @returns {boolean} `true` if the value is a non-null object.
- */
- function isNonNullObject(x) {
- return typeof x === "object" && x !== null;
- }
- /**
- * Merge two objects.
- *
- * Assign every property values of `y` to `x` if `x` doesn't have the property.
- * If `x`'s property value is an object, it does recursive.
- * @param {Object} target The destination to merge
- * @param {Object|undefined} source The source to merge.
- * @returns {void}
- */
- function mergeWithoutOverwrite(target, source) {
- if (!isNonNullObject(source)) {
- return;
- }
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- if (isNonNullObject(target[key])) {
- mergeWithoutOverwrite(target[key], source[key]);
- } else if (target[key] === void 0) {
- if (isNonNullObject(source[key])) {
- target[key] = Array.isArray(source[key]) ? [] : {};
- mergeWithoutOverwrite(target[key], source[key]);
- } else if (source[key] !== void 0) {
- target[key] = source[key];
- }
- }
- }
- }
- /**
- * The error for plugin conflicts.
- */
- class PluginConflictError extends Error {
- /**
- * Initialize this error object.
- * @param {string} pluginId The plugin ID.
- * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
- */
- constructor(pluginId, plugins) {
- super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
- this.messageTemplate = "plugin-conflict";
- this.messageData = { pluginId, plugins };
- }
- }
- /**
- * Merge plugins.
- * `target`'s definition is prior to `source`'s.
- * @param {Record<string, DependentPlugin>} target The destination to merge
- * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
- * @returns {void}
- */
- function mergePlugins(target, source) {
- if (!isNonNullObject(source)) {
- return;
- }
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- const targetValue = target[key];
- const sourceValue = source[key];
- // Adopt the plugin which was found at first.
- if (targetValue === void 0) {
- if (sourceValue.error) {
- throw sourceValue.error;
- }
- target[key] = sourceValue;
- } else if (sourceValue.filePath !== targetValue.filePath) {
- throw new PluginConflictError(key, [
- {
- filePath: targetValue.filePath,
- importerName: targetValue.importerName
- },
- {
- filePath: sourceValue.filePath,
- importerName: sourceValue.importerName
- }
- ]);
- }
- }
- }
- /**
- * Merge rule configs.
- * `target`'s definition is prior to `source`'s.
- * @param {Record<string, Array>} target The destination to merge
- * @param {Record<string, RuleConf>|undefined} source The source to merge.
- * @returns {void}
- */
- function mergeRuleConfigs(target, source) {
- if (!isNonNullObject(source)) {
- return;
- }
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- const targetDef = target[key];
- const sourceDef = source[key];
- // Adopt the rule config which was found at first.
- if (targetDef === void 0) {
- if (Array.isArray(sourceDef)) {
- target[key] = [...sourceDef];
- } else {
- target[key] = [sourceDef];
- }
- /*
- * If the first found rule config is severity only and the current rule
- * config has options, merge the severity and the options.
- */
- } else if (
- targetDef.length === 1 &&
- Array.isArray(sourceDef) &&
- sourceDef.length >= 2
- ) {
- targetDef.push(...sourceDef.slice(1));
- }
- }
- }
- /**
- * Create the extracted config.
- * @param {ConfigArray} instance The config elements.
- * @param {number[]} indices The indices to use.
- * @returns {ExtractedConfig} The extracted config.
- */
- function createConfig(instance, indices) {
- const config = new ExtractedConfig();
- const ignorePatterns = [];
- // Merge elements.
- for (const index of indices) {
- const element = instance[index];
- // Adopt the parser which was found at first.
- if (!config.parser && element.parser) {
- if (element.parser.error) {
- throw element.parser.error;
- }
- config.parser = element.parser;
- }
- // Adopt the processor which was found at first.
- if (!config.processor && element.processor) {
- config.processor = element.processor;
- }
- // Adopt the noInlineConfig which was found at first.
- if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
- config.noInlineConfig = element.noInlineConfig;
- config.configNameOfNoInlineConfig = element.name;
- }
- // Adopt the reportUnusedDisableDirectives which was found at first.
- if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
- config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
- }
- // Collect ignorePatterns
- if (element.ignorePattern) {
- ignorePatterns.push(element.ignorePattern);
- }
- // Merge others.
- mergeWithoutOverwrite(config.env, element.env);
- mergeWithoutOverwrite(config.globals, element.globals);
- mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
- mergeWithoutOverwrite(config.settings, element.settings);
- mergePlugins(config.plugins, element.plugins);
- mergeRuleConfigs(config.rules, element.rules);
- }
- // Create the predicate function for ignore patterns.
- if (ignorePatterns.length > 0) {
- config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
- }
- return config;
- }
- /**
- * Collect definitions.
- * @template T, U
- * @param {string} pluginId The plugin ID for prefix.
- * @param {Record<string,T>} defs The definitions to collect.
- * @param {Map<string, U>} map The map to output.
- * @param {function(T): U} [normalize] The normalize function for each value.
- * @returns {void}
- */
- function collect(pluginId, defs, map, normalize) {
- if (defs) {
- const prefix = pluginId && `${pluginId}/`;
- for (const [key, value] of Object.entries(defs)) {
- map.set(
- `${prefix}${key}`,
- normalize ? normalize(value) : value
- );
- }
- }
- }
- /**
- * Normalize a rule definition.
- * @param {Function|Rule} rule The rule definition to normalize.
- * @returns {Rule} The normalized rule definition.
- */
- function normalizePluginRule(rule) {
- return typeof rule === "function" ? { create: rule } : rule;
- }
- /**
- * Delete the mutation methods from a given map.
- * @param {Map<any, any>} map The map object to delete.
- * @returns {void}
- */
- function deleteMutationMethods(map) {
- Object.defineProperties(map, {
- clear: { configurable: true, value: void 0 },
- delete: { configurable: true, value: void 0 },
- set: { configurable: true, value: void 0 }
- });
- }
- /**
- * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
- * @param {ConfigArrayElement[]} elements The config elements.
- * @param {ConfigArrayInternalSlots} slots The internal slots.
- * @returns {void}
- */
- function initPluginMemberMaps(elements, slots) {
- const processed = new Set();
- slots.envMap = new Map();
- slots.processorMap = new Map();
- slots.ruleMap = new Map();
- for (const element of elements) {
- if (!element.plugins) {
- continue;
- }
- for (const [pluginId, value] of Object.entries(element.plugins)) {
- const plugin = value.definition;
- if (!plugin || processed.has(pluginId)) {
- continue;
- }
- processed.add(pluginId);
- collect(pluginId, plugin.environments, slots.envMap);
- collect(pluginId, plugin.processors, slots.processorMap);
- collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
- }
- }
- deleteMutationMethods(slots.envMap);
- deleteMutationMethods(slots.processorMap);
- deleteMutationMethods(slots.ruleMap);
- }
- /**
- * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
- * @param {ConfigArray} instance The config elements.
- * @returns {ConfigArrayInternalSlots} The extracted config.
- */
- function ensurePluginMemberMaps(instance) {
- const slots = internalSlotsMap$2.get(instance);
- if (!slots.ruleMap) {
- initPluginMemberMaps(instance, slots);
- }
- return slots;
- }
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- /**
- * The Config Array.
- *
- * `ConfigArray` instance contains all settings, parsers, and plugins.
- * You need to call `ConfigArray#extractConfig(filePath)` method in order to
- * extract, merge and get only the config data which is related to an arbitrary
- * file.
- * @extends {Array<ConfigArrayElement>}
- */
- class ConfigArray extends Array {
- /**
- * Get the plugin environments.
- * The returned map cannot be mutated.
- * @type {ReadonlyMap<string, Environment>} The plugin environments.
- */
- get pluginEnvironments() {
- return ensurePluginMemberMaps(this).envMap;
- }
- /**
- * Get the plugin processors.
- * The returned map cannot be mutated.
- * @type {ReadonlyMap<string, Processor>} The plugin processors.
- */
- get pluginProcessors() {
- return ensurePluginMemberMaps(this).processorMap;
- }
- /**
- * Get the plugin rules.
- * The returned map cannot be mutated.
- * @returns {ReadonlyMap<string, Rule>} The plugin rules.
- */
- get pluginRules() {
- return ensurePluginMemberMaps(this).ruleMap;
- }
- /**
- * Check if this config has `root` flag.
- * @returns {boolean} `true` if this config array is root.
- */
- isRoot() {
- for (let i = this.length - 1; i >= 0; --i) {
- const root = this[i].root;
- if (typeof root === "boolean") {
- return root;
- }
- }
- return false;
- }
- /**
- * Extract the config data which is related to a given file.
- * @param {string} filePath The absolute path to the target file.
- * @returns {ExtractedConfig} The extracted config data.
- */
- extractConfig(filePath) {
- const { cache } = internalSlotsMap$2.get(this);
- const indices = getMatchedIndices(this, filePath);
- const cacheKey = indices.join(",");
- if (!cache.has(cacheKey)) {
- cache.set(cacheKey, createConfig(this, indices));
- }
- return cache.get(cacheKey);
- }
- /**
- * Check if a given path is an additional lint target.
- * @param {string} filePath The absolute path to the target file.
- * @returns {boolean} `true` if the file is an additional lint target.
- */
- isAdditionalTargetPath(filePath) {
- for (const { criteria, type } of this) {
- if (
- type === "config" &&
- criteria &&
- !criteria.endsWithWildcard &&
- criteria.test(filePath)
- ) {
- return true;
- }
- }
- return false;
- }
- }
- /**
- * Get the used extracted configs.
- * CLIEngine will use this method to collect used deprecated rules.
- * @param {ConfigArray} instance The config array object to get.
- * @returns {ExtractedConfig[]} The used extracted configs.
- * @private
- */
- function getUsedExtractedConfigs(instance) {
- const { cache } = internalSlotsMap$2.get(instance);
- return Array.from(cache.values());
- }
- /**
- * @fileoverview `ConfigDependency` class.
- *
- * `ConfigDependency` class expresses a loaded parser or plugin.
- *
- * If the parser or plugin was loaded successfully, it has `definition` property
- * and `filePath` property. Otherwise, it has `error` property.
- *
- * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
- * omits `definition` property.
- *
- * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
- * or plugins.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- /**
- * The class is to store parsers or plugins.
- * This class hides the loaded object from `JSON.stringify()` and `console.log`.
- * @template T
- */
- class ConfigDependency {
- /**
- * Initialize this instance.
- * @param {Object} data The dependency data.
- * @param {T} [data.definition] The dependency if the loading succeeded.
- * @param {Error} [data.error] The error object if the loading failed.
- * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
- * @param {string} data.id The ID of this dependency.
- * @param {string} data.importerName The name of the config file which loads this dependency.
- * @param {string} data.importerPath The path to the config file which loads this dependency.
- */
- constructor({
- definition = null,
- error = null,
- filePath = null,
- id,
- importerName,
- importerPath
- }) {
- /**
- * The loaded dependency if the loading succeeded.
- * @type {T|null}
- */
- this.definition = definition;
- /**
- * The error object if the loading failed.
- * @type {Error|null}
- */
- this.error = error;
- /**
- * The loaded dependency if the loading succeeded.
- * @type {string|null}
- */
- this.filePath = filePath;
- /**
- * The ID of this dependency.
- * @type {string}
- */
- this.id = id;
- /**
- * The name of the config file which loads this dependency.
- * @type {string}
- */
- this.importerName = importerName;
- /**
- * The path to the config file which loads this dependency.
- * @type {string}
- */
- this.importerPath = importerPath;
- }
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} a JSON compatible object.
- */
- toJSON() {
- const obj = this[util__default["default"].inspect.custom]();
- // Display `error.message` (`Error#message` is unenumerable).
- if (obj.error instanceof Error) {
- obj.error = { ...obj.error, message: obj.error.message };
- }
- return obj;
- }
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} an object to display by `console.log()`.
- */
- [util__default["default"].inspect.custom]() {
- const {
- definition: _ignore, // eslint-disable-line no-unused-vars
- ...obj
- } = this;
- return obj;
- }
- }
- /**
- * @fileoverview `OverrideTester` class.
- *
- * `OverrideTester` class handles `files` property and `excludedFiles` property
- * of `overrides` config.
- *
- * It provides one method.
- *
- * - `test(filePath)`
- * Test if a file path matches the pair of `files` property and
- * `excludedFiles` property. The `filePath` argument must be an absolute
- * path.
- *
- * `ConfigArrayFactory` creates `OverrideTester` objects when it processes
- * `overrides` properties.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- const { Minimatch } = minimatch__default["default"];
- const minimatchOpts = { dot: true, matchBase: true };
- /**
- * @typedef {Object} Pattern
- * @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
- * @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
- */
- /**
- * Normalize a given pattern to an array.
- * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
- * @returns {string[]|null} Normalized patterns.
- * @private
- */
- function normalizePatterns(patterns) {
- if (Array.isArray(patterns)) {
- return patterns.filter(Boolean);
- }
- if (typeof patterns === "string" && patterns) {
- return [patterns];
- }
- return [];
- }
- /**
- * Create the matchers of given patterns.
- * @param {string[]} patterns The patterns.
- * @returns {InstanceType<Minimatch>[] | null} The matchers.
- */
- function toMatcher(patterns) {
- if (patterns.length === 0) {
- return null;
- }
- return patterns.map(pattern => {
- if (/^\.[/\\]/u.test(pattern)) {
- return new Minimatch(
- pattern.slice(2),
- // `./*.js` should not match with `subdir/foo.js`
- { ...minimatchOpts, matchBase: false }
- );
- }
- return new Minimatch(pattern, minimatchOpts);
- });
- }
- /**
- * Convert a given matcher to string.
- * @param {Pattern} matchers The matchers.
- * @returns {string} The string expression of the matcher.
- */
- function patternToJson({ includes, excludes }) {
- return {
- includes: includes && includes.map(m => m.pattern),
- excludes: excludes && excludes.map(m => m.pattern)
- };
- }
- /**
- * The class to test given paths are matched by the patterns.
- */
- class OverrideTester {
- /**
- * Create a tester with given criteria.
- * If there are no criteria, returns `null`.
- * @param {string|string[]} files The glob patterns for included files.
- * @param {string|string[]} excludedFiles The glob patterns for excluded files.
- * @param {string} basePath The path to the base directory to test paths.
- * @returns {OverrideTester|null} The created instance or `null`.
- */
- static create(files, excludedFiles, basePath) {
- const includePatterns = normalizePatterns(files);
- const excludePatterns = normalizePatterns(excludedFiles);
- let endsWithWildcard = false;
- if (includePatterns.length === 0) {
- return null;
- }
- // Rejects absolute paths or relative paths to parents.
- for (const pattern of includePatterns) {
- if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
- throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
- }
- if (pattern.endsWith("*")) {
- endsWithWildcard = true;
- }
- }
- for (const pattern of excludePatterns) {
- if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
- throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
- }
- }
- const includes = toMatcher(includePatterns);
- const excludes = toMatcher(excludePatterns);
- return new OverrideTester(
- [{ includes, excludes }],
- basePath,
- endsWithWildcard
- );
- }
- /**
- * Combine two testers by logical and.
- * If either of the testers was `null`, returns the other tester.
- * The `basePath` property of the two must be the same value.
- * @param {OverrideTester|null} a A tester.
- * @param {OverrideTester|null} b Another tester.
- * @returns {OverrideTester|null} Combined tester.
- */
- static and(a, b) {
- if (!b) {
- return a && new OverrideTester(
- a.patterns,
- a.basePath,
- a.endsWithWildcard
- );
- }
- if (!a) {
- return new OverrideTester(
- b.patterns,
- b.basePath,
- b.endsWithWildcard
- );
- }
- assert__default["default"].strictEqual(a.basePath, b.basePath);
- return new OverrideTester(
- a.patterns.concat(b.patterns),
- a.basePath,
- a.endsWithWildcard || b.endsWithWildcard
- );
- }
- /**
- * Initialize this instance.
- * @param {Pattern[]} patterns The matchers.
- * @param {string} basePath The base path.
- * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
- */
- constructor(patterns, basePath, endsWithWildcard = false) {
- /** @type {Pattern[]} */
- this.patterns = patterns;
- /** @type {string} */
- this.basePath = basePath;
- /** @type {boolean} */
- this.endsWithWildcard = endsWithWildcard;
- }
- /**
- * Test if a given path is matched or not.
- * @param {string} filePath The absolute path to the target file.
- * @returns {boolean} `true` if the path was matched.
- */
- test(filePath) {
- if (typeof filePath !== "string" || !path__default["default"].isAbsolute(filePath)) {
- throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
- }
- const relativePath = path__default["default"].relative(this.basePath, filePath);
- return this.patterns.every(({ includes, excludes }) => (
- (!includes || includes.some(m => m.match(relativePath))) &&
- (!excludes || !excludes.some(m => m.match(relativePath)))
- ));
- }
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} a JSON compatible object.
- */
- toJSON() {
- if (this.patterns.length === 1) {
- return {
- ...patternToJson(this.patterns[0]),
- basePath: this.basePath
- };
- }
- return {
- AND: this.patterns.map(patternToJson),
- basePath: this.basePath
- };
- }
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} an object to display by `console.log()`.
- */
- [util__default["default"].inspect.custom]() {
- return this.toJSON();
- }
- }
- /**
- * @fileoverview `ConfigArray` class.
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- /**
- * @fileoverview Config file operations. This file must be usable in the browser,
- * so no Node-specific code can be here.
- * @author Nicholas C. Zakas
- */
- //------------------------------------------------------------------------------
- // Private
- //------------------------------------------------------------------------------
- const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
- RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
- map[value] = index;
- return map;
- }, {}),
- VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- /**
- * Normalizes the severity value of a rule's configuration to a number
- * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
- * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
- * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
- * whose first element is one of the above values. Strings are matched case-insensitively.
- * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
- */
- function getRuleSeverity(ruleConfig) {
- const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
- if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
- return severityValue;
- }
- if (typeof severityValue === "string") {
- return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
- }
- return 0;
- }
- /**
- * Converts old-style severity settings (0, 1, 2) into new-style
- * severity settings (off, warn, error) for all rules. Assumption is that severity
- * values have already been validated as correct.
- * @param {Object} config The config object to normalize.
- * @returns {void}
- */
- function normalizeToStrings(config) {
- if (config.rules) {
- Object.keys(config.rules).forEach(ruleId => {
- const ruleConfig = config.rules[ruleId];
- if (typeof ruleConfig === "number") {
- config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
- } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
- ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
- }
- });
- }
- }
- /**
- * Determines if the severity for the given rule configuration represents an error.
- * @param {int|string|Array} ruleConfig The configuration for an individual rule.
- * @returns {boolean} True if the rule represents an error, false if not.
- */
- function isErrorSeverity(ruleConfig) {
- return getRuleSeverity(ruleConfig) === 2;
- }
- /**
- * Checks whether a given config has valid severity or not.
- * @param {number|string|Array} ruleConfig The configuration for an individual rule.
- * @returns {boolean} `true` if the configuration has valid severity.
- */
- function isValidSeverity(ruleConfig) {
- let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
- if (typeof severity === "string") {
- severity = severity.toLowerCase();
- }
- return VALID_SEVERITIES.indexOf(severity) !== -1;
- }
- /**
- * Checks whether every rule of a given config has valid severity or not.
- * @param {Object} config The configuration for rules.
- * @returns {boolean} `true` if the configuration has valid severity.
- */
- function isEverySeverityValid(config) {
- return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));
- }
- /**
- * Normalizes a value for a global in a config
- * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
- * a global directive comment
- * @returns {("readable"|"writeable"|"off")} The value normalized as a string
- * @throws Error if global value is invalid
- */
- function normalizeConfigGlobal(configuredValue) {
- switch (configuredValue) {
- case "off":
- return "off";
- case true:
- case "true":
- case "writeable":
- case "writable":
- return "writable";
- case null:
- case false:
- case "false":
- case "readable":
- case "readonly":
- return "readonly";
- default:
- throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
- }
- }
- var ConfigOps = {
- __proto__: null,
- getRuleSeverity: getRuleSeverity,
- normalizeToStrings: normalizeToStrings,
- isErrorSeverity: isErrorSeverity,
- isValidSeverity: isValidSeverity,
- isEverySeverityValid: isEverySeverityValid,
- normalizeConfigGlobal: normalizeConfigGlobal
- };
- /**
- * @fileoverview Provide the function that emits deprecation warnings.
- * @author Toru Nagashima <http://github.com/mysticatea>
- */
- //------------------------------------------------------------------------------
- // Private
- //------------------------------------------------------------------------------
- // Defitions for deprecation warnings.
- const deprecationWarningMessages = {
- ESLINT_LEGACY_ECMAFEATURES:
- "The 'ecmaFeatures' config file property is deprecated and has no effect.",
- ESLINT_PERSONAL_CONFIG_LOAD:
- "'~/.eslintrc.*' config files have been deprecated. " +
- "Please use a config file per project or the '--config' option.",
- ESLINT_PERSONAL_CONFIG_SUPPRESS:
- "'~/.eslintrc.*' config files have been deprecated. " +
- "Please remove it or add 'root:true' to the config files in your " +
- "projects in order to avoid loading '~/.eslintrc.*' accidentally."
- };
- const sourceFileErrorCache = new Set();
- /**
- * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
- * for each unique file path, but repeated invocations with the same file path have no effect.
- * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
- * @param {string} source The name of the configuration source to report the warning for.
- * @param {string} errorCode The warning message to show.
- * @returns {void}
- */
- function emitDeprecationWarning(source, errorCode) {
- const cacheKey = JSON.stringify({ source, errorCode });
- if (sourceFileErrorCache.has(cacheKey)) {
- return;
- }
- sourceFileErrorCache.add(cacheKey);
- const rel = path__default["default"].relative(process.cwd(), source);
- const message = deprecationWarningMessages[errorCode];
- process.emitWarning(
- `${message} (found in "${rel}")`,
- "DeprecationWarning",
- errorCode
- );
- }
- /**
- * @fileoverview The instance of Ajv validator.
- * @author Evgeny Poberezkin
- */
- //-----------------------------------------------------------------------------
- // Helpers
- //-----------------------------------------------------------------------------
- /*
- * Copied from ajv/lib/refs/json-schema-draft-04.json
- * The MIT License (MIT)
- * Copyright (c) 2015-2017 Evgeny Poberezkin
- */
- const metaSchema = {
- id: "http://json-schema.org/draft-04/schema#",
- $schema: "http://json-schema.org/draft-04/schema#",
- description: "Core schema meta-schema",
- definitions: {
- schemaArray: {
- type: "array",
- minItems: 1,
- items: { $ref: "#" }
- },
- positiveInteger: {
- type: "integer",
- minimum: 0
- },
- positiveIntegerDefault0: {
- allOf: [{ $ref: "#/definitions/positiveInteger" }, { default: 0 }]
- },
- simpleTypes: {
- enum: ["array", "boolean", "integer", "null", "number", "object", "string"]
- },
- stringArray: {
- type: "array",
- items: { type: "string" },
- minItems: 1,
- uniqueItems: true
- }
- },
- type: "object",
- properties: {
- id: {
- type: "string"
- },
- $schema: {
- type: "string"
- },
- title: {
- type: "string"
- },
- description: {
- type: "string"
- },
- default: { },
- multipleOf: {
- type: "number",
- minimum: 0,
- exclusiveMinimum: true
- },
- maximum: {
- type: "number"
- },
- exclusiveMaximum: {
- type: "boolean",
- default: false
- },
- minimum: {
- type: "number"
- },
- exclusiveMinimum: {
- type: "boolean",
- default: false
- },
- maxLength: { $ref: "#/definitions/positiveInteger" },
- minLength: { $ref: "#/definitions/positiveIntegerDefault0" },
- pattern: {
- type: "string",
- format: "regex"
- },
- additionalItems: {
- anyOf: [
- { type: "boolean" },
- { $ref: "#" }
- ],
- default: { }
- },
- items: {
- anyOf: [
- { $ref: "#" },
- { $ref: "#/definitions/schemaArray" }
- ],
- default: { }
- },
- maxItems: { $ref: "#/definitions/positiveInteger" },
- minItems: { $ref: "#/definitions/positiveIntegerDefault0" },
- uniqueItems: {
- type: "boolean",
- default: false
- },
- maxProperties: { $ref: "#/definitions/positiveInteger" },
- minProperties: { $ref: "#/definitions/positiveIntegerDefault0" },
- required: { $ref: "#/definitions/stringArray" },
- additionalProperties: {
- anyOf: [
- { type: "boolean" },
- { $ref: "#" }
- ],
- default: { }
- },
- definitions: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- properties: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- patternProperties: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- dependencies: {
- type: "object",
- additionalProperties: {
- anyOf: [
- { $ref: "#" },
- { $ref: "#/definitions/stringArray" }
- ]
- }
- },
- enum: {
- type: "array",
- minItems: 1,
- uniqueItems: true
- },
- type: {
- anyOf: [
- { $ref: "#/definitions/simpleTypes" },
- {
- type: "array",
- items: { $ref: "#/definitions/simpleTypes" },
- minItems: 1,
- uniqueItems: true
- }
- ]
- },
- format: { type: "string" },
- allOf: { $ref: "#/definitions/schemaArray" },
- anyOf: { $ref: "#/definitions/schemaArray" },
- oneOf: { $ref: "#/definitions/schemaArray" },
- not: { $ref: "#" }
- },
- dependencies: {
- exclusiveMaximum: ["maximum"],
- exclusiveMinimum: ["minimum"]
- },
- default: { }
- };
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- var ajvOrig = (additionalOptions = {}) => {
- const ajv = new Ajv__default["default"]({
- meta: false,
- useDefaults: true,
- validateSchema: false,
- missingRefs: "ignore",
- verbose: true,
- schemaId: "auto",
- ...additionalOptions
- });
- ajv.addMetaSchema(metaSchema);
- // eslint-disable-next-line no-underscore-dangle
- ajv._opts.defaultMeta = metaSchema.id;
- return ajv;
- };
- /**
- * @fileoverview Defines a schema for configs.
- * @author Sylvan Mably
- */
- const baseConfigProperties = {
- $schema: { type: "string" },
- env: { type: "object" },
- extends: { $ref: "#/definitions/stringOrStrings" },
- globals: { type: "object" },
- overrides: {
- type: "array",
- items: { $ref: "#/definitions/overrideConfig" },
- additionalItems: false
- },
- parser: { type: ["string", "null"] },
- parserOptions: { type: "object" },
- plugins: { type: "array" },
- processor: { type: "string" },
- rules: { type: "object" },
- settings: { type: "object" },
- noInlineConfig: { type: "boolean" },
- reportUnusedDisableDirectives: { type: "boolean" },
- ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
- };
- const configSchema = {
- definitions: {
- stringOrStrings: {
- oneOf: [
- { type: "string" },
- {
- type: "array",
- items: { type: "string" },
- additionalItems: false
- }
- ]
- },
- stringOrStringsRequired: {
- oneOf: [
- { type: "string" },
- {
- type: "array",
- items: { type: "string" },
- additionalItems: false,
- minItems: 1
- }
- ]
- },
- // Config at top-level.
- objectConfig: {
- type: "object",
- properties: {
- root: { type: "boolean" },
- ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
- ...baseConfigProperties
- },
- additionalProperties: false
- },
- // Config in `overrides`.
- overrideConfig: {
- type: "object",
- properties: {
- excludedFiles: { $ref: "#/definitions/stringOrStrings" },
- files: { $ref: "#/definitions/stringOrStringsRequired" },
- ...baseConfigProperties
- },
- required: ["files"],
- additionalProperties: false
- }
- },
- $ref: "#/definitions/objectConfig"
- };
- /**
- * @fileoverview Defines environment settings and globals.
- * @author Elan Shanker
- */
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- /**
- * Get the object that has difference.
- * @param {Record<string,boolean>} current The newer object.
- * @param {Record<string,boolean>} prev The older object.
- * @returns {Record<string,boolean>} The difference object.
- */
- function getDiff(current, prev) {
- const retv = {};
- for (const [key, value] of Object.entries(current)) {
- if (!Object.hasOwnProperty.call(prev, key)) {
- retv[key] = value;
- }
- }
- return retv;
- }
- const newGlobals2015 = getDiff(globals__default["default"].es2015, globals__default["default"].es5); // 19 variables such as Promise, Map, ...
- const newGlobals2017 = {
- Atomics: false,
- SharedArrayBuffer: false
- };
- const newGlobals2020 = {
- BigInt: false,
- BigInt64Array: false,
- BigUint64Array: false,
- globalThis: false
- };
- const newGlobals2021 = {
- AggregateError: false,
- FinalizationRegistry: false,
- WeakRef: false
- };
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- /** @type {Map<string, import("../lib/shared/types").Environment>} */
- var environments = new Map(Object.entries({
- // Language
- builtin: {
- globals: globals__default["default"].es5
- },
- es6: {
- globals: newGlobals2015,
- parserOptions: {
- ecmaVersion: 6
- }
- },
- es2015: {
- globals: newGlobals2015,
- parserOptions: {
- ecmaVersion: 6
- }
- },
- es2016: {
- globals: newGlobals2015,
- parserOptions: {
- ecmaVersion: 7
- }
- },
- es2017: {
- globals: { ...newGlobals2015, ...newGlobals2017 },
- parserOptions: {
- ecmaVersion: 8
- }
- },
- es2018: {
- globals: { ...newGlobals2015, ...newGlobals2017 },
- parserOptions: {
- ecmaVersion: 9
- }
- },
- es2019: {
- globals: { ...newGlobals2015, ...newGlobals2017 },
- parserOptions: {
- ecmaVersion: 10
- }
- },
- es2020: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
- parserOptions: {
- ecmaVersion: 11
- }
- },
- es2021: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
- parserOptions: {
- ecmaVersion: 12
- }
- },
- es2022: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
- parserOptions: {
- ecmaVersion: 13
- }
- },
- es2023: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
- parserOptions: {
- ecmaVersion: 14
- }
- },
- es2024: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
- parserOptions: {
- ecmaVersion: 15
- }
- },
- // Platforms
- browser: {
- globals: globals__default["default"].browser
- },
- node: {
- globals: globals__default["default"].node,
- parserOptions: {
- ecmaFeatures: {
- globalReturn: true
- }
- }
- },
- "shared-node-browser": {
- globals: globals__default["default"]["shared-node-browser"]
- },
- worker: {
- globals: globals__default["default"].worker
- },
- serviceworker: {
- globals: globals__default["default"].serviceworker
- },
- // Frameworks
- commonjs: {
- globals: globals__default["default"].commonjs,
- parserOptions: {
- ecmaFeatures: {
- globalReturn: true
- }
- }
- },
- amd: {
- globals: globals__default["default"].amd
- },
- mocha: {
- globals: globals__default["default"].mocha
- },
- jasmine: {
- globals: globals__default["default"].jasmine
- },
- jest: {
- globals: globals__default["default"].jest
- },
- phantomjs: {
- globals: globals__default["default"].phantomjs
- },
- jquery: {
- globals: globals__default["default"].jquery
- },
- qunit: {
- globals: globals__default["default"].qunit
- },
- prototypejs: {
- globals: globals__default["default"].prototypejs
- },
- shelljs: {
- globals: globals__default["default"].shelljs
- },
- meteor: {
- globals: globals__default["default"].meteor
- },
- mongo: {
- globals: globals__default["default"].mongo
- },
- protractor: {
- globals: globals__default["default"].protractor
- },
- applescript: {
- globals: globals__default["default"].applescript
- },
- nashorn: {
- globals: globals__default["default"].nashorn
- },
- atomtest: {
- globals: globals__default["default"].atomtest
- },
- embertest: {
- globals: globals__default["default"].embertest
- },
- webextensions: {
- globals: globals__default["default"].webextensions
- },
- greasemonkey: {
- globals: globals__default["default"].greasemonkey
- }
- }));
- /**
- * @fileoverview Validates configs.
- * @author Brandon Mills
- */
- const ajv = ajvOrig();
- const ruleValidators = new WeakMap();
- const noop = Function.prototype;
- //------------------------------------------------------------------------------
- // Private
- //------------------------------------------------------------------------------
- let validateSchema;
- const severityMap = {
- error: 2,
- warn: 1,
- off: 0
- };
- const validated = new WeakSet();
- //-----------------------------------------------------------------------------
- // Exports
- //-----------------------------------------------------------------------------
- class ConfigValidator {
- constructor({ builtInRules = new Map() } = {}) {
- this.builtInRules = builtInRules;
- }
- /**
- * Gets a complete options schema for a rule.
- * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
- * @returns {Object} JSON Schema for the rule's options.
- */
- getRuleOptionsSchema(rule) {
- if (!rule) {
- return null;
- }
- const schema = rule.schema || rule.meta && rule.meta.schema;
- // Given a tuple of schemas, insert warning level at the beginning
- if (Array.isArray(schema)) {
- if (schema.length) {
- return {
- type: "array",
- items: schema,
- minItems: 0,
- maxItems: schema.length
- };
- }
- return {
- type: "array",
- minItems: 0,
- maxItems: 0
- };
- }
- // Given a full schema, leave it alone
- return schema || null;
- }
- /**
- * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
- * @param {options} options The given options for the rule.
- * @returns {number|string} The rule's severity value
- */
- validateRuleSeverity(options) {
- const severity = Array.isArray(options) ? options[0] : options;
- const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
- if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
- return normSeverity;
- }
- throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util__default["default"].inspect(severity).replace(/'/gu, "\"").replace(/\n/gu, "")}').\n`);
- }
- /**
- * Validates the non-severity options passed to a rule, based on its schema.
- * @param {{create: Function}} rule The rule to validate
- * @param {Array} localOptions The options for the rule, excluding severity
- * @returns {void}
- */
- validateRuleSchema(rule, localOptions) {
- if (!ruleValidators.has(rule)) {
- const schema = this.getRuleOptionsSchema(rule);
- if (schema) {
- ruleValidators.set(rule, ajv.compile(schema));
- }
- }
- const validateRule = ruleValidators.get(rule);
- if (validateRule) {
- validateRule(localOptions);
- if (validateRule.errors) {
- throw new Error(validateRule.errors.map(
- error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
- ).join(""));
- }
- }
- }
- /**
- * Validates a rule's options against its schema.
- * @param {{create: Function}|null} rule The rule that the config is being validated for
- * @param {string} ruleId The rule's unique name.
- * @param {Array|number} options The given options for the rule.
- * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
- * no source is prepended to the message.
- * @returns {void}
- */
- validateRuleOptions(rule, ruleId, options, source = null) {
- try {
- const severity = this.validateRuleSeverity(options);
- if (severity !== 0) {
- this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
- }
- } catch (err) {
- const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
- if (typeof source === "string") {
- throw new Error(`${source}:\n\t${enhancedMessage}`);
- } else {
- throw new Error(enhancedMessage);
- }
- }
- }
- /**
- * Validates an environment object
- * @param {Object} environment The environment config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
- * @returns {void}
- */
- validateEnvironment(
- environment,
- source,
- getAdditionalEnv = noop
- ) {
- // not having an environment is ok
- if (!environment) {
- return;
- }
- Object.keys(environment).forEach(id => {
- const env = getAdditionalEnv(id) || environments.get(id) || null;
- if (!env) {
- const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
- throw new Error(message);
- }
- });
- }
- /**
- * Validates a rules config object
- * @param {Object} rulesConfig The rules config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
- * @returns {void}
- */
- validateRules(
- rulesConfig,
- source,
- getAdditionalRule = noop
- ) {
- if (!rulesConfig) {
- return;
- }
- Object.keys(rulesConfig).forEach(id => {
- const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
- this.validateRuleOptions(rule, id, rulesConfig[id], source);
- });
- }
- /**
- * Validates a `globals` section of a config file
- * @param {Object} globalsConfig The `globals` section
- * @param {string|null} source The name of the configuration source to report in the event of an error.
- * @returns {void}
- */
- validateGlobals(globalsConfig, source = null) {
- if (!globalsConfig) {
- return;
- }
- Object.entries(globalsConfig)
- .forEach(([configuredGlobal, configuredValue]) => {
- try {
- normalizeConfigGlobal(configuredValue);
- } catch (err) {
- throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
- }
- });
- }
- /**
- * Validate `processor` configuration.
- * @param {string|undefined} processorName The processor name.
- * @param {string} source The name of config file.
- * @param {function(id:string): Processor} getProcessor The getter of defined processors.
- * @returns {void}
- */
- validateProcessor(processorName, source, getProcessor) {
- if (processorName && !getProcessor(processorName)) {
- throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
- }
- }
- /**
- * Formats an array of schema validation errors.
- * @param {Array} errors An array of error messages to format.
- * @returns {string} Formatted error message
- */
- formatErrors(errors) {
- return errors.map(error => {
- if (error.keyword === "additionalProperties") {
- const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
- return `Unexpected top-level property "${formattedPropertyPath}"`;
- }
- if (error.keyword === "type") {
- const formattedField = error.dataPath.slice(1);
- const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
- const formattedValue = JSON.stringify(error.data);
- return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
- }
- const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
- return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
- }).map(message => `\t- ${message}.\n`).join("");
- }
- /**
- * Validates the top level properties of the config object.
- * @param {Object} config The config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @returns {void}
- */
- validateConfigSchema(config, source = null) {
- validateSchema = validateSchema || ajv.compile(configSchema);
- if (!validateSchema(config)) {
- throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
- }
- if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
- emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
- }
- }
- /**
- * Validates an entire config object.
- * @param {Object} config The config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
- * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
- * @returns {void}
- */
- validate(config, source, getAdditionalRule, getAdditionalEnv) {
- this.validateConfigSchema(config, source);
- this.validateRules(config.rules, source, getAdditionalRule);
- this.validateEnvironment(config.env, source, getAdditionalEnv);
- this.validateGlobals(config.globals, source);
- for (const override of config.overrides || []) {
- this.validateRules(override.rules, source, getAdditionalRule);
- this.validateEnvironment(override.env, source, getAdditionalEnv);
- this.validateGlobals(config.globals, source);
- }
- }
- /**
- * Validate config array object.
- * @param {ConfigArray} configArray The config array to validate.
- * @returns {void}
- */
- validateConfigArray(configArray) {
- const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
- const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
- const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
- // Validate.
- for (const element of configArray) {
- if (validated.has(element)) {
- continue;
- }
- validated.add(element);
- this.validateEnvironment(element.env, element.name, getPluginEnv);
- this.validateGlobals(element.globals, element.name);
- this.validateProcessor(element.processor, element.name, getPluginProcessor);
- this.validateRules(element.rules, element.name, getPluginRule);
- }
- }
- }
- /**
- * @fileoverview Common helpers for naming of plugins, formatters and configs
- */
- const NAMESPACE_REGEX = /^@.*\//iu;
- /**
- * Brings package name to correct format based on prefix
- * @param {string} name The name of the package.
- * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
- * @returns {string} Normalized name of the package
- * @private
- */
- function normalizePackageName(name, prefix) {
- let normalizedName = name;
- /**
- * On Windows, name can come in with Windows slashes instead of Unix slashes.
- * Normalize to Unix first to avoid errors later on.
- * https://github.com/eslint/eslint/issues/5644
- */
- if (normalizedName.includes("\\")) {
- normalizedName = normalizedName.replace(/\\/gu, "/");
- }
- if (normalizedName.charAt(0) === "@") {
- /**
- * it's a scoped package
- * package name is the prefix, or just a username
- */
- const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
- scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
- if (scopedPackageShortcutRegex.test(normalizedName)) {
- normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
- } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
- /**
- * for scoped packages, insert the prefix after the first / unless
- * the path is already @scope/eslint or @scope/eslint-xxx-yyy
- */
- normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
- }
- } else if (!normalizedName.startsWith(`${prefix}-`)) {
- normalizedName = `${prefix}-${normalizedName}`;
- }
- return normalizedName;
- }
- /**
- * Removes the prefix from a fullname.
- * @param {string} fullname The term which may have the prefix.
- * @param {string} prefix The prefix to remove.
- * @returns {string} The term without prefix.
- */
- function getShorthandName(fullname, prefix) {
- if (fullname[0] === "@") {
- let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
- if (matchResult) {
- return matchResult[1];
- }
- matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
- if (matchResult) {
- return `${matchResult[1]}/${matchResult[2]}`;
- }
- } else if (fullname.startsWith(`${prefix}-`)) {
- return fullname.slice(prefix.length + 1);
- }
- return fullname;
- }
- /**
- * Gets the scope (namespace) of a term.
- * @param {string} term The term which may have the namespace.
- * @returns {string} The namespace of the term if it has one.
- */
- function getNamespaceFromTerm(term) {
- const match = term.match(NAMESPACE_REGEX);
- return match ? match[0] : "";
- }
- var naming = {
- __proto__: null,
- normalizePackageName: normalizePackageName,
- getShorthandName: getShorthandName,
- getNamespaceFromTerm: getNamespaceFromTerm
- };
- /**
- * Utility for resolving a module relative to another module
- * @author Teddy Katz
- */
- /*
- * `Module.createRequire` is added in v12.2.0. It supports URL as well.
- * We only support the case where the argument is a filepath, not a URL.
- */
- const createRequire = Module__default["default"].createRequire;
- /**
- * Resolves a Node module relative to another module
- * @param {string} moduleName The name of a Node module, or a path to a Node module.
- * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
- * a file rather than a directory, but the file need not actually exist.
- * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
- */
- function resolve(moduleName, relativeToPath) {
- try {
- return createRequire(relativeToPath).resolve(moduleName);
- } catch (error) {
- // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
- if (
- typeof error === "object" &&
- error !== null &&
- error.code === "MODULE_NOT_FOUND" &&
- !error.requireStack &&
- error.message.includes(moduleName)
- ) {
- error.message += `\nRequire stack:\n- ${relativeToPath}`;
- }
- throw error;
- }
- }
- var ModuleResolver = {
- __proto__: null,
- resolve: resolve
- };
- /**
- * @fileoverview The factory of `ConfigArray` objects.
- *
- * This class provides methods to create `ConfigArray` instance.
- *
- * - `create(configData, options)`
- * Create a `ConfigArray` instance from a config data. This is to handle CLI
- * options except `--config`.
- * - `loadFile(filePath, options)`
- * Create a `ConfigArray` instance from a config file. This is to handle
- * `--config` option. If the file was not found, throws the following error:
- * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.
- * - If the filename was `package.json`, an IO error or an
- * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.
- * - Otherwise, an IO error such as `ENOENT`.
- * - `loadInDirectory(directoryPath, options)`
- * Create a `ConfigArray` instance from a config file which is on a given
- * directory. This tries to load `.eslintrc.*` or `package.json`. If not
- * found, returns an empty `ConfigArray`.
- * - `loadESLintIgnore(filePath)`
- * Create a `ConfigArray` instance from a config file that is `.eslintignore`
- * format. This is to handle `--ignore-path` option.
- * - `loadDefaultESLintIgnore()`
- * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in
- * the current working directory.
- *
- * `ConfigArrayFactory` class has the responsibility that loads configuration
- * files, including loading `extends`, `parser`, and `plugins`. The created
- * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.
- *
- * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class
- * handles cascading and hierarchy.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- const require$1 = Module.createRequire(require('url').pathToFileURL(__filename).toString());
- const debug$2 = debugOrig__default["default"]("eslintrc:config-array-factory");
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- const configFilenames = [
- ".eslintrc.js",
- ".eslintrc.cjs",
- ".eslintrc.yaml",
- ".eslintrc.yml",
- ".eslintrc.json",
- ".eslintrc",
- "package.json"
- ];
- // Define types for VSCode IntelliSense.
- /** @typedef {import("./shared/types").ConfigData} ConfigData */
- /** @typedef {import("./shared/types").OverrideConfigData} OverrideConfigData */
- /** @typedef {import("./shared/types").Parser} Parser */
- /** @typedef {import("./shared/types").Plugin} Plugin */
- /** @typedef {import("./shared/types").Rule} Rule */
- /** @typedef {import("./config-array/config-dependency").DependentParser} DependentParser */
- /** @typedef {import("./config-array/config-dependency").DependentPlugin} DependentPlugin */
- /** @typedef {ConfigArray[0]} ConfigArrayElement */
- /**
- * @typedef {Object} ConfigArrayFactoryOptions
- * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
- * @property {string} [cwd] The path to the current working directory.
- * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
- */
- /**
- * @typedef {Object} ConfigArrayFactoryInternalSlots
- * @property {Map<string,Plugin>} additionalPluginPool The map for additional plugins.
- * @property {string} cwd The path to the current working directory.
- * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
- */
- /**
- * @typedef {Object} ConfigArrayFactoryLoadingContext
- * @property {string} filePath The path to the current configuration.
- * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @property {string} name The name of the current configuration.
- * @property {string} pluginBasePath The base path to resolve plugins.
- * @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.
- */
- /**
- * @typedef {Object} ConfigArrayFactoryLoadingContext
- * @property {string} filePath The path to the current configuration.
- * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @property {string} name The name of the current configuration.
- * @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.
- */
- /** @type {WeakMap<ConfigArrayFactory, ConfigArrayFactoryInternalSlots>} */
- const internalSlotsMap$1 = new WeakMap();
- /** @type {WeakMap<object, Plugin>} */
- const normalizedPlugins = new WeakMap();
- /**
- * Check if a given string is a file path.
- * @param {string} nameOrPath A module name or file path.
- * @returns {boolean} `true` if the `nameOrPath` is a file path.
- */
- function isFilePath(nameOrPath) {
- return (
- /^\.{1,2}[/\\]/u.test(nameOrPath) ||
- path__default["default"].isAbsolute(nameOrPath)
- );
- }
- /**
- * Convenience wrapper for synchronously reading file contents.
- * @param {string} filePath The filename to read.
- * @returns {string} The file contents, with the BOM removed.
- * @private
- */
- function readFile(filePath) {
- return fs__default["default"].readFileSync(filePath, "utf8").replace(/^\ufeff/u, "");
- }
- /**
- * Loads a YAML configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
- function loadYAMLConfigFile(filePath) {
- debug$2(`Loading YAML config file: ${filePath}`);
- // lazy load YAML to improve performance when not used
- const yaml = require$1("js-yaml");
- try {
- // empty YAML file can be null, so always use
- return yaml.load(readFile(filePath)) || {};
- } catch (e) {
- debug$2(`Error reading YAML file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
- }
- /**
- * Loads a JSON configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
- function loadJSONConfigFile(filePath) {
- debug$2(`Loading JSON config file: ${filePath}`);
- try {
- return JSON.parse(stripComments__default["default"](readFile(filePath)));
- } catch (e) {
- debug$2(`Error reading JSON file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- e.messageTemplate = "failed-to-read-json";
- e.messageData = {
- path: filePath,
- message: e.message
- };
- throw e;
- }
- }
- /**
- * Loads a legacy (.eslintrc) configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
- function loadLegacyConfigFile(filePath) {
- debug$2(`Loading legacy config file: ${filePath}`);
- // lazy load YAML to improve performance when not used
- const yaml = require$1("js-yaml");
- try {
- return yaml.load(stripComments__default["default"](readFile(filePath))) || /* istanbul ignore next */ {};
- } catch (e) {
- debug$2("Error reading YAML file: %s\n%o", filePath, e);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
- }
- /**
- * Loads a JavaScript configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
- function loadJSConfigFile(filePath) {
- debug$2(`Loading JS config file: ${filePath}`);
- try {
- return importFresh__default["default"](filePath);
- } catch (e) {
- debug$2(`Error reading JavaScript file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
- }
- /**
- * Loads a configuration from a package.json file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
- function loadPackageJSONConfigFile(filePath) {
- debug$2(`Loading package.json config file: ${filePath}`);
- try {
- const packageData = loadJSONConfigFile(filePath);
- if (!Object.hasOwnProperty.call(packageData, "eslintConfig")) {
- throw Object.assign(
- new Error("package.json file doesn't have 'eslintConfig' field."),
- { code: "ESLINT_CONFIG_FIELD_NOT_FOUND" }
- );
- }
- return packageData.eslintConfig;
- } catch (e) {
- debug$2(`Error reading package.json file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
- }
- /**
- * Loads a `.eslintignore` from a file.
- * @param {string} filePath The filename to load.
- * @returns {string[]} The ignore patterns from the file.
- * @private
- */
- function loadESLintIgnoreFile(filePath) {
- debug$2(`Loading .eslintignore file: ${filePath}`);
- try {
- return readFile(filePath)
- .split(/\r?\n/gu)
- .filter(line => line.trim() !== "" && !line.startsWith("#"));
- } catch (e) {
- debug$2(`Error reading .eslintignore file: ${filePath}`);
- e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
- }
- /**
- * Creates an error to notify about a missing config to extend from.
- * @param {string} configName The name of the missing config.
- * @param {string} importerName The name of the config that imported the missing config
- * @param {string} messageTemplate The text template to source error strings from.
- * @returns {Error} The error object to throw
- * @private
- */
- function configInvalidError(configName, importerName, messageTemplate) {
- return Object.assign(
- new Error(`Failed to load config "${configName}" to extend from.`),
- {
- messageTemplate,
- messageData: { configName, importerName }
- }
- );
- }
- /**
- * Loads a configuration file regardless of the source. Inspects the file path
- * to determine the correctly way to load the config file.
- * @param {string} filePath The path to the configuration.
- * @returns {ConfigData|null} The configuration information.
- * @private
- */
- function loadConfigFile(filePath) {
- switch (path__default["default"].extname(filePath)) {
- case ".js":
- case ".cjs":
- return loadJSConfigFile(filePath);
- case ".json":
- if (path__default["default"].basename(filePath) === "package.json") {
- return loadPackageJSONConfigFile(filePath);
- }
- return loadJSONConfigFile(filePath);
- case ".yaml":
- case ".yml":
- return loadYAMLConfigFile(filePath);
- default:
- return loadLegacyConfigFile(filePath);
- }
- }
- /**
- * Write debug log.
- * @param {string} request The requested module name.
- * @param {string} relativeTo The file path to resolve the request relative to.
- * @param {string} filePath The resolved file path.
- * @returns {void}
- */
- function writeDebugLogForLoading(request, relativeTo, filePath) {
- /* istanbul ignore next */
- if (debug$2.enabled) {
- let nameAndVersion = null;
- try {
- const packageJsonPath = resolve(
- `${request}/package.json`,
- relativeTo
- );
- const { version = "unknown" } = require$1(packageJsonPath);
- nameAndVersion = `${request}@${version}`;
- } catch (error) {
- debug$2("package.json was not found:", error.message);
- nameAndVersion = request;
- }
- debug$2("Loaded: %s (%s)", nameAndVersion, filePath);
- }
- }
- /**
- * Create a new context with default values.
- * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.
- * @param {"config" | "ignore" | "implicit-processor" | undefined} providedType The type of the current configuration. Default is `"config"`.
- * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.
- * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.
- * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.
- * @returns {ConfigArrayFactoryLoadingContext} The created context.
- */
- function createContext(
- { cwd, resolvePluginsRelativeTo },
- providedType,
- providedName,
- providedFilePath,
- providedMatchBasePath
- ) {
- const filePath = providedFilePath
- ? path__default["default"].resolve(cwd, providedFilePath)
- : "";
- const matchBasePath =
- (providedMatchBasePath && path__default["default"].resolve(cwd, providedMatchBasePath)) ||
- (filePath && path__default["default"].dirname(filePath)) ||
- cwd;
- const name =
- providedName ||
- (filePath && path__default["default"].relative(cwd, filePath)) ||
- "";
- const pluginBasePath =
- resolvePluginsRelativeTo ||
- (filePath && path__default["default"].dirname(filePath)) ||
- cwd;
- const type = providedType || "config";
- return { filePath, matchBasePath, name, pluginBasePath, type };
- }
- /**
- * Normalize a given plugin.
- * - Ensure the object to have four properties: configs, environments, processors, and rules.
- * - Ensure the object to not have other properties.
- * @param {Plugin} plugin The plugin to normalize.
- * @returns {Plugin} The normalized plugin.
- */
- function normalizePlugin(plugin) {
- // first check the cache
- let normalizedPlugin = normalizedPlugins.get(plugin);
- if (normalizedPlugin) {
- return normalizedPlugin;
- }
- normalizedPlugin = {
- configs: plugin.configs || {},
- environments: plugin.environments || {},
- processors: plugin.processors || {},
- rules: plugin.rules || {}
- };
- // save the reference for later
- normalizedPlugins.set(plugin, normalizedPlugin);
- return normalizedPlugin;
- }
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- /**
- * The factory of `ConfigArray` objects.
- */
- class ConfigArrayFactory {
- /**
- * Initialize this instance.
- * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.
- */
- constructor({
- additionalPluginPool = new Map(),
- cwd = process.cwd(),
- resolvePluginsRelativeTo,
- builtInRules,
- resolver = ModuleResolver,
- eslintAllPath,
- getEslintAllConfig,
- eslintRecommendedPath,
- getEslintRecommendedConfig
- } = {}) {
- internalSlotsMap$1.set(this, {
- additionalPluginPool,
- cwd,
- resolvePluginsRelativeTo:
- resolvePluginsRelativeTo &&
- path__default["default"].resolve(cwd, resolvePluginsRelativeTo),
- builtInRules,
- resolver,
- eslintAllPath,
- getEslintAllConfig,
- eslintRecommendedPath,
- getEslintRecommendedConfig
- });
- }
- /**
- * Create `ConfigArray` instance from a config data.
- * @param {ConfigData|null} configData The config data to create.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.filePath] The path to this config data.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config.
- */
- create(configData, { basePath, filePath, name } = {}) {
- if (!configData) {
- return new ConfigArray();
- }
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(slots, "config", name, filePath, basePath);
- const elements = this._normalizeConfigData(configData, ctx);
- return new ConfigArray(...elements);
- }
- /**
- * Load a config file.
- * @param {string} filePath The path to a config file.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config.
- */
- loadFile(filePath, { basePath, name } = {}) {
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(slots, "config", name, filePath, basePath);
- return new ConfigArray(...this._loadConfigData(ctx));
- }
- /**
- * Load the config file on a given directory if exists.
- * @param {string} directoryPath The path to a directory.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
- */
- loadInDirectory(directoryPath, { basePath, name } = {}) {
- const slots = internalSlotsMap$1.get(this);
- for (const filename of configFilenames) {
- const ctx = createContext(
- slots,
- "config",
- name,
- path__default["default"].join(directoryPath, filename),
- basePath
- );
- if (fs__default["default"].existsSync(ctx.filePath) && fs__default["default"].statSync(ctx.filePath).isFile()) {
- let configData;
- try {
- configData = loadConfigFile(ctx.filePath);
- } catch (error) {
- if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
- throw error;
- }
- }
- if (configData) {
- debug$2(`Config file found: ${ctx.filePath}`);
- return new ConfigArray(
- ...this._normalizeConfigData(configData, ctx)
- );
- }
- }
- }
- debug$2(`Config file not found on ${directoryPath}`);
- return new ConfigArray();
- }
- /**
- * Check if a config file on a given directory exists or not.
- * @param {string} directoryPath The path to a directory.
- * @returns {string | null} The path to the found config file. If not found then null.
- */
- static getPathToConfigFileInDirectory(directoryPath) {
- for (const filename of configFilenames) {
- const filePath = path__default["default"].join(directoryPath, filename);
- if (fs__default["default"].existsSync(filePath)) {
- if (filename === "package.json") {
- try {
- loadPackageJSONConfigFile(filePath);
- return filePath;
- } catch { /* ignore */ }
- } else {
- return filePath;
- }
- }
- }
- return null;
- }
- /**
- * Load `.eslintignore` file.
- * @param {string} filePath The path to a `.eslintignore` file to load.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
- */
- loadESLintIgnore(filePath) {
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(
- slots,
- "ignore",
- void 0,
- filePath,
- slots.cwd
- );
- const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);
- return new ConfigArray(
- ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)
- );
- }
- /**
- * Load `.eslintignore` file in the current working directory.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
- */
- loadDefaultESLintIgnore() {
- const slots = internalSlotsMap$1.get(this);
- const eslintIgnorePath = path__default["default"].resolve(slots.cwd, ".eslintignore");
- const packageJsonPath = path__default["default"].resolve(slots.cwd, "package.json");
- if (fs__default["default"].existsSync(eslintIgnorePath)) {
- return this.loadESLintIgnore(eslintIgnorePath);
- }
- if (fs__default["default"].existsSync(packageJsonPath)) {
- const data = loadJSONConfigFile(packageJsonPath);
- if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
- if (!Array.isArray(data.eslintIgnore)) {
- throw new Error("Package.json eslintIgnore property requires an array of paths");
- }
- const ctx = createContext(
- slots,
- "ignore",
- "eslintIgnore in package.json",
- packageJsonPath,
- slots.cwd
- );
- return new ConfigArray(
- ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)
- );
- }
- }
- return new ConfigArray();
- }
- /**
- * Load a given config file.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} Loaded config.
- * @private
- */
- _loadConfigData(ctx) {
- return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);
- }
- /**
- * Normalize a given `.eslintignore` data to config array elements.
- * @param {string[]} ignorePatterns The patterns to ignore files.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- *_normalizeESLintIgnoreData(ignorePatterns, ctx) {
- const elements = this._normalizeObjectConfigData(
- { ignorePatterns },
- ctx
- );
- // Set `ignorePattern.loose` flag for backward compatibility.
- for (const element of elements) {
- if (element.ignorePattern) {
- element.ignorePattern.loose = true;
- }
- yield element;
- }
- }
- /**
- * Normalize a given config to an array.
- * @param {ConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- _normalizeConfigData(configData, ctx) {
- const validator = new ConfigValidator();
- validator.validateConfigSchema(configData, ctx.name || ctx.filePath);
- return this._normalizeObjectConfigData(configData, ctx);
- }
- /**
- * Normalize a given config to an array.
- * @param {ConfigData|OverrideConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- *_normalizeObjectConfigData(configData, ctx) {
- const { files, excludedFiles, ...configBody } = configData;
- const criteria = OverrideTester.create(
- files,
- excludedFiles,
- ctx.matchBasePath
- );
- const elements = this._normalizeObjectConfigDataBody(configBody, ctx);
- // Apply the criteria to every element.
- for (const element of elements) {
- /*
- * Merge the criteria.
- * This is for the `overrides` entries that came from the
- * configurations of `overrides[].extends`.
- */
- element.criteria = OverrideTester.and(criteria, element.criteria);
- /*
- * Remove `root` property to ignore `root` settings which came from
- * `extends` in `overrides`.
- */
- if (element.criteria) {
- element.root = void 0;
- }
- yield element;
- }
- }
- /**
- * Normalize a given config to an array.
- * @param {ConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- *_normalizeObjectConfigDataBody(
- {
- env,
- extends: extend,
- globals,
- ignorePatterns,
- noInlineConfig,
- parser: parserName,
- parserOptions,
- plugins: pluginList,
- processor,
- reportUnusedDisableDirectives,
- root,
- rules,
- settings,
- overrides: overrideList = []
- },
- ctx
- ) {
- const extendList = Array.isArray(extend) ? extend : [extend];
- const ignorePattern = ignorePatterns && new IgnorePattern(
- Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
- ctx.matchBasePath
- );
- // Flatten `extends`.
- for (const extendName of extendList.filter(Boolean)) {
- yield* this._loadExtends(extendName, ctx);
- }
- // Load parser & plugins.
- const parser = parserName && this._loadParser(parserName, ctx);
- const plugins = pluginList && this._loadPlugins(pluginList, ctx);
- // Yield pseudo config data for file extension processors.
- if (plugins) {
- yield* this._takeFileExtensionProcessors(plugins, ctx);
- }
- // Yield the config data except `extends` and `overrides`.
- yield {
- // Debug information.
- type: ctx.type,
- name: ctx.name,
- filePath: ctx.filePath,
- // Config data.
- criteria: null,
- env,
- globals,
- ignorePattern,
- noInlineConfig,
- parser,
- parserOptions,
- plugins,
- processor,
- reportUnusedDisableDirectives,
- root,
- rules,
- settings
- };
- // Flatten `overries`.
- for (let i = 0; i < overrideList.length; ++i) {
- yield* this._normalizeObjectConfigData(
- overrideList[i],
- { ...ctx, name: `${ctx.name}#overrides[${i}]` }
- );
- }
- }
- /**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- _loadExtends(extendName, ctx) {
- debug$2("Loading {extends:%j} relative to %s", extendName, ctx.filePath);
- try {
- if (extendName.startsWith("eslint:")) {
- return this._loadExtendedBuiltInConfig(extendName, ctx);
- }
- if (extendName.startsWith("plugin:")) {
- return this._loadExtendedPluginConfig(extendName, ctx);
- }
- return this._loadExtendedShareableConfig(extendName, ctx);
- } catch (error) {
- error.message += `\nReferenced from: ${ctx.filePath || ctx.name}`;
- throw error;
- }
- }
- /**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- _loadExtendedBuiltInConfig(extendName, ctx) {
- const {
- eslintAllPath,
- getEslintAllConfig,
- eslintRecommendedPath,
- getEslintRecommendedConfig
- } = internalSlotsMap$1.get(this);
- if (extendName === "eslint:recommended") {
- const name = `${ctx.name} » ${extendName}`;
- if (getEslintRecommendedConfig) {
- if (typeof getEslintRecommendedConfig !== "function") {
- throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);
- }
- return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: "" });
- }
- return this._loadConfigData({
- ...ctx,
- name,
- filePath: eslintRecommendedPath
- });
- }
- if (extendName === "eslint:all") {
- const name = `${ctx.name} » ${extendName}`;
- if (getEslintAllConfig) {
- if (typeof getEslintAllConfig !== "function") {
- throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);
- }
- return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: "" });
- }
- return this._loadConfigData({
- ...ctx,
- name,
- filePath: eslintAllPath
- });
- }
- throw configInvalidError(extendName, ctx.name, "extend-config-missing");
- }
- /**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- _loadExtendedPluginConfig(extendName, ctx) {
- const slashIndex = extendName.lastIndexOf("/");
- if (slashIndex === -1) {
- throw configInvalidError(extendName, ctx.filePath, "plugin-invalid");
- }
- const pluginName = extendName.slice("plugin:".length, slashIndex);
- const configName = extendName.slice(slashIndex + 1);
- if (isFilePath(pluginName)) {
- throw new Error("'extends' cannot use a file path for plugins.");
- }
- const plugin = this._loadPlugin(pluginName, ctx);
- const configData =
- plugin.definition &&
- plugin.definition.configs[configName];
- if (configData) {
- return this._normalizeConfigData(configData, {
- ...ctx,
- filePath: plugin.filePath || ctx.filePath,
- name: `${ctx.name} » plugin:${plugin.id}/${configName}`
- });
- }
- throw plugin.error || configInvalidError(extendName, ctx.filePath, "extend-config-missing");
- }
- /**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- _loadExtendedShareableConfig(extendName, ctx) {
- const { cwd, resolver } = internalSlotsMap$1.get(this);
- const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
- let request;
- if (isFilePath(extendName)) {
- request = extendName;
- } else if (extendName.startsWith(".")) {
- request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.
- } else {
- request = normalizePackageName(
- extendName,
- "eslint-config"
- );
- }
- let filePath;
- try {
- filePath = resolver.resolve(request, relativeTo);
- } catch (error) {
- /* istanbul ignore else */
- if (error && error.code === "MODULE_NOT_FOUND") {
- throw configInvalidError(extendName, ctx.filePath, "extend-config-missing");
- }
- throw error;
- }
- writeDebugLogForLoading(request, relativeTo, filePath);
- return this._loadConfigData({
- ...ctx,
- filePath,
- name: `${ctx.name} » ${request}`
- });
- }
- /**
- * Load given plugins.
- * @param {string[]} names The plugin names to load.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {Record<string,DependentPlugin>} The loaded parser.
- * @private
- */
- _loadPlugins(names, ctx) {
- return names.reduce((map, name) => {
- if (isFilePath(name)) {
- throw new Error("Plugins array cannot includes file paths.");
- }
- const plugin = this._loadPlugin(name, ctx);
- map[plugin.id] = plugin;
- return map;
- }, {});
- }
- /**
- * Load a given parser.
- * @param {string} nameOrPath The package name or the path to a parser file.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {DependentParser} The loaded parser.
- */
- _loadParser(nameOrPath, ctx) {
- debug$2("Loading parser %j from %s", nameOrPath, ctx.filePath);
- const { cwd, resolver } = internalSlotsMap$1.get(this);
- const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
- try {
- const filePath = resolver.resolve(nameOrPath, relativeTo);
- writeDebugLogForLoading(nameOrPath, relativeTo, filePath);
- return new ConfigDependency({
- definition: require$1(filePath),
- filePath,
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- } catch (error) {
- // If the parser name is "espree", load the espree of ESLint.
- if (nameOrPath === "espree") {
- debug$2("Fallback espree.");
- return new ConfigDependency({
- definition: require$1("espree"),
- filePath: require$1.resolve("espree"),
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
- debug$2("Failed to load parser '%s' declared in '%s'.", nameOrPath, ctx.name);
- error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;
- return new ConfigDependency({
- error,
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
- }
- /**
- * Load a given plugin.
- * @param {string} name The plugin name to load.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {DependentPlugin} The loaded plugin.
- * @private
- */
- _loadPlugin(name, ctx) {
- debug$2("Loading plugin %j from %s", name, ctx.filePath);
- const { additionalPluginPool, resolver } = internalSlotsMap$1.get(this);
- const request = normalizePackageName(name, "eslint-plugin");
- const id = getShorthandName(request, "eslint-plugin");
- const relativeTo = path__default["default"].join(ctx.pluginBasePath, "__placeholder__.js");
- if (name.match(/\s+/u)) {
- const error = Object.assign(
- new Error(`Whitespace found in plugin name '${name}'`),
- {
- messageTemplate: "whitespace-found",
- messageData: { pluginName: request }
- }
- );
- return new ConfigDependency({
- error,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
- // Check for additional pool.
- const plugin =
- additionalPluginPool.get(request) ||
- additionalPluginPool.get(id);
- if (plugin) {
- return new ConfigDependency({
- definition: normalizePlugin(plugin),
- filePath: "", // It's unknown where the plugin came from.
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
- let filePath;
- let error;
- try {
- filePath = resolver.resolve(request, relativeTo);
- } catch (resolveError) {
- error = resolveError;
- /* istanbul ignore else */
- if (error && error.code === "MODULE_NOT_FOUND") {
- error.messageTemplate = "plugin-missing";
- error.messageData = {
- pluginName: request,
- resolvePluginsRelativeTo: ctx.pluginBasePath,
- importerName: ctx.name
- };
- }
- }
- if (filePath) {
- try {
- writeDebugLogForLoading(request, relativeTo, filePath);
- const startTime = Date.now();
- const pluginDefinition = require$1(filePath);
- debug$2(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
- return new ConfigDependency({
- definition: normalizePlugin(pluginDefinition),
- filePath,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- } catch (loadError) {
- error = loadError;
- }
- }
- debug$2("Failed to load plugin '%s' declared in '%s'.", name, ctx.name);
- error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;
- return new ConfigDependency({
- error,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
- /**
- * Take file expression processors as config array elements.
- * @param {Record<string,DependentPlugin>} plugins The plugin definitions.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The config array elements of file expression processors.
- * @private
- */
- *_takeFileExtensionProcessors(plugins, ctx) {
- for (const pluginId of Object.keys(plugins)) {
- const processors =
- plugins[pluginId] &&
- plugins[pluginId].definition &&
- plugins[pluginId].definition.processors;
- if (!processors) {
- continue;
- }
- for (const processorId of Object.keys(processors)) {
- if (processorId.startsWith(".")) {
- yield* this._normalizeObjectConfigData(
- {
- files: [`*${processorId}`],
- processor: `${pluginId}/${processorId}`
- },
- {
- ...ctx,
- type: "implicit-processor",
- name: `${ctx.name}#processors["${pluginId}/${processorId}"]`
- }
- );
- }
- }
- }
- }
- }
- /**
- * @fileoverview `CascadingConfigArrayFactory` class.
- *
- * `CascadingConfigArrayFactory` class has a responsibility:
- *
- * 1. Handles cascading of config files.
- *
- * It provides two methods:
- *
- * - `getConfigArrayForFile(filePath)`
- * Get the corresponded configuration of a given file. This method doesn't
- * throw even if the given file didn't exist.
- * - `clearCache()`
- * Clear the internal cache. You have to call this method when
- * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
- * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
- const debug$1 = debugOrig__default["default"]("eslintrc:cascading-config-array-factory");
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- // Define types for VSCode IntelliSense.
- /** @typedef {import("./shared/types").ConfigData} ConfigData */
- /** @typedef {import("./shared/types").Parser} Parser */
- /** @typedef {import("./shared/types").Plugin} Plugin */
- /** @typedef {import("./shared/types").Rule} Rule */
- /** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
- /**
- * @typedef {Object} CascadingConfigArrayFactoryOptions
- * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
- * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
- * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
- * @property {string} [cwd] The base directory to start lookup.
- * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
- * @property {string[]} [rulePaths] The value of `--rulesdir` option.
- * @property {string} [specificConfigPath] The value of `--config` option.
- * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
- * @property {Function} loadRules The function to use to load rules.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
- */
- /**
- * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
- * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
- * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
- * @property {ConfigArray} cliConfigArray The config array of CLI options.
- * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
- * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
- * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
- * @property {string} cwd The base directory to start lookup.
- * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
- * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
- * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
- * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
- * @property {boolean} useEslintrc if `false` then it doesn't load config files.
- * @property {Function} loadRules The function to use to load rules.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
- */
- /** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
- const internalSlotsMap = new WeakMap();
- /**
- * Create the config array from `baseConfig` and `rulePaths`.
- * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
- * @returns {ConfigArray} The config array of the base configs.
- */
- function createBaseConfigArray({
- configArrayFactory,
- baseConfigData,
- rulePaths,
- cwd,
- loadRules
- }) {
- const baseConfigArray = configArrayFactory.create(
- baseConfigData,
- { name: "BaseConfig" }
- );
- /*
- * Create the config array element for the default ignore patterns.
- * This element has `ignorePattern` property that ignores the default
- * patterns in the current working directory.
- */
- baseConfigArray.unshift(configArrayFactory.create(
- { ignorePatterns: IgnorePattern.DefaultPatterns },
- { name: "DefaultIgnorePattern" }
- )[0]);
- /*
- * Load rules `--rulesdir` option as a pseudo plugin.
- * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
- * the rule's options with only information in the config array.
- */
- if (rulePaths && rulePaths.length > 0) {
- baseConfigArray.push({
- type: "config",
- name: "--rulesdir",
- filePath: "",
- plugins: {
- "": new ConfigDependency({
- definition: {
- rules: rulePaths.reduce(
- (map, rulesPath) => Object.assign(
- map,
- loadRules(rulesPath, cwd)
- ),
- {}
- )
- },
- filePath: "",
- id: "",
- importerName: "--rulesdir",
- importerPath: ""
- })
- }
- });
- }
- return baseConfigArray;
- }
- /**
- * Create the config array from CLI options.
- * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
- * @returns {ConfigArray} The config array of the base configs.
- */
- function createCLIConfigArray({
- cliConfigData,
- configArrayFactory,
- cwd,
- ignorePath,
- specificConfigPath
- }) {
- const cliConfigArray = configArrayFactory.create(
- cliConfigData,
- { name: "CLIOptions" }
- );
- cliConfigArray.unshift(
- ...(ignorePath
- ? configArrayFactory.loadESLintIgnore(ignorePath)
- : configArrayFactory.loadDefaultESLintIgnore())
- );
- if (specificConfigPath) {
- cliConfigArray.unshift(
- ...configArrayFactory.loadFile(
- specificConfigPath,
- { name: "--config", basePath: cwd }
- )
- );
- }
- return cliConfigArray;
- }
- /**
- * The error type when there are files matched by a glob, but all of them have been ignored.
- */
- class ConfigurationNotFoundError extends Error {
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @param {string} directoryPath The directory path.
- */
- constructor(directoryPath) {
- super(`No ESLint configuration found in ${directoryPath}.`);
- this.messageTemplate = "no-config-found";
- this.messageData = { directoryPath };
- }
- }
- /**
- * This class provides the functionality that enumerates every file which is
- * matched by given glob patterns and that configuration.
- */
- class CascadingConfigArrayFactory {
- /**
- * Initialize this enumerator.
- * @param {CascadingConfigArrayFactoryOptions} options The options.
- */
- constructor({
- additionalPluginPool = new Map(),
- baseConfig: baseConfigData = null,
- cliConfig: cliConfigData = null,
- cwd = process.cwd(),
- ignorePath,
- resolvePluginsRelativeTo,
- rulePaths = [],
- specificConfigPath = null,
- useEslintrc = true,
- builtInRules = new Map(),
- loadRules,
- resolver,
- eslintRecommendedPath,
- getEslintRecommendedConfig,
- eslintAllPath,
- getEslintAllConfig
- } = {}) {
- const configArrayFactory = new ConfigArrayFactory({
- additionalPluginPool,
- cwd,
- resolvePluginsRelativeTo,
- builtInRules,
- resolver,
- eslintRecommendedPath,
- getEslintRecommendedConfig,
- eslintAllPath,
- getEslintAllConfig
- });
- internalSlotsMap.set(this, {
- baseConfigArray: createBaseConfigArray({
- baseConfigData,
- configArrayFactory,
- cwd,
- rulePaths,
- loadRules
- }),
- baseConfigData,
- cliConfigArray: createCLIConfigArray({
- cliConfigData,
- configArrayFactory,
- cwd,
- ignorePath,
- specificConfigPath
- }),
- cliConfigData,
- configArrayFactory,
- configCache: new Map(),
- cwd,
- finalizeCache: new WeakMap(),
- ignorePath,
- rulePaths,
- specificConfigPath,
- useEslintrc,
- builtInRules,
- loadRules
- });
- }
- /**
- * The path to the current working directory.
- * This is used by tests.
- * @type {string}
- */
- get cwd() {
- const { cwd } = internalSlotsMap.get(this);
- return cwd;
- }
- /**
- * Get the config array of a given file.
- * If `filePath` was not given, it returns the config which contains only
- * `baseConfigData` and `cliConfigData`.
- * @param {string} [filePath] The file path to a file.
- * @param {Object} [options] The options.
- * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
- * @returns {ConfigArray} The config array of the file.
- */
- getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
- const {
- baseConfigArray,
- cliConfigArray,
- cwd
- } = internalSlotsMap.get(this);
- if (!filePath) {
- return new ConfigArray(...baseConfigArray, ...cliConfigArray);
- }
- const directoryPath = path__default["default"].dirname(path__default["default"].resolve(cwd, filePath));
- debug$1(`Load config files for ${directoryPath}.`);
- return this._finalizeConfigArray(
- this._loadConfigInAncestors(directoryPath),
- directoryPath,
- ignoreNotFoundError
- );
- }
- /**
- * Set the config data to override all configs.
- * Require to call `clearCache()` method after this method is called.
- * @param {ConfigData} configData The config data to override all configs.
- * @returns {void}
- */
- setOverrideConfig(configData) {
- const slots = internalSlotsMap.get(this);
- slots.cliConfigData = configData;
- }
- /**
- * Clear config cache.
- * @returns {void}
- */
- clearCache() {
- const slots = internalSlotsMap.get(this);
- slots.baseConfigArray = createBaseConfigArray(slots);
- slots.cliConfigArray = createCLIConfigArray(slots);
- slots.configCache.clear();
- }
- /**
- * Load and normalize config files from the ancestor directories.
- * @param {string} directoryPath The path to a leaf directory.
- * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
- * @returns {ConfigArray} The loaded config.
- * @private
- */
- _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
- const {
- baseConfigArray,
- configArrayFactory,
- configCache,
- cwd,
- useEslintrc
- } = internalSlotsMap.get(this);
- if (!useEslintrc) {
- return baseConfigArray;
- }
- let configArray = configCache.get(directoryPath);
- // Hit cache.
- if (configArray) {
- debug$1(`Cache hit: ${directoryPath}.`);
- return configArray;
- }
- debug$1(`No cache found: ${directoryPath}.`);
- const homePath = os__default["default"].homedir();
- // Consider this is root.
- if (directoryPath === homePath && cwd !== homePath) {
- debug$1("Stop traversing because of considered root.");
- if (configsExistInSubdirs) {
- const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
- if (filePath) {
- emitDeprecationWarning(
- filePath,
- "ESLINT_PERSONAL_CONFIG_SUPPRESS"
- );
- }
- }
- return this._cacheConfig(directoryPath, baseConfigArray);
- }
- // Load the config on this directory.
- try {
- configArray = configArrayFactory.loadInDirectory(directoryPath);
- } catch (error) {
- /* istanbul ignore next */
- if (error.code === "EACCES") {
- debug$1("Stop traversing because of 'EACCES' error.");
- return this._cacheConfig(directoryPath, baseConfigArray);
- }
- throw error;
- }
- if (configArray.length > 0 && configArray.isRoot()) {
- debug$1("Stop traversing because of 'root:true'.");
- configArray.unshift(...baseConfigArray);
- return this._cacheConfig(directoryPath, configArray);
- }
- // Load from the ancestors and merge it.
- const parentPath = path__default["default"].dirname(directoryPath);
- const parentConfigArray = parentPath && parentPath !== directoryPath
- ? this._loadConfigInAncestors(
- parentPath,
- configsExistInSubdirs || configArray.length > 0
- )
- : baseConfigArray;
- if (configArray.length > 0) {
- configArray.unshift(...parentConfigArray);
- } else {
- configArray = parentConfigArray;
- }
- // Cache and return.
- return this._cacheConfig(directoryPath, configArray);
- }
- /**
- * Freeze and cache a given config.
- * @param {string} directoryPath The path to a directory as a cache key.
- * @param {ConfigArray} configArray The config array as a cache value.
- * @returns {ConfigArray} The `configArray` (frozen).
- */
- _cacheConfig(directoryPath, configArray) {
- const { configCache } = internalSlotsMap.get(this);
- Object.freeze(configArray);
- configCache.set(directoryPath, configArray);
- return configArray;
- }
- /**
- * Finalize a given config array.
- * Concatenate `--config` and other CLI options.
- * @param {ConfigArray} configArray The parent config array.
- * @param {string} directoryPath The path to the leaf directory to find config files.
- * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
- * @returns {ConfigArray} The loaded config.
- * @private
- */
- _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
- const {
- cliConfigArray,
- configArrayFactory,
- finalizeCache,
- useEslintrc,
- builtInRules
- } = internalSlotsMap.get(this);
- let finalConfigArray = finalizeCache.get(configArray);
- if (!finalConfigArray) {
- finalConfigArray = configArray;
- // Load the personal config if there are no regular config files.
- if (
- useEslintrc &&
- configArray.every(c => !c.filePath) &&
- cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
- ) {
- const homePath = os__default["default"].homedir();
- debug$1("Loading the config file of the home directory:", homePath);
- const personalConfigArray = configArrayFactory.loadInDirectory(
- homePath,
- { name: "PersonalConfig" }
- );
- if (
- personalConfigArray.length > 0 &&
- !directoryPath.startsWith(homePath)
- ) {
- const lastElement =
- personalConfigArray[personalConfigArray.length - 1];
- emitDeprecationWarning(
- lastElement.filePath,
- "ESLINT_PERSONAL_CONFIG_LOAD"
- );
- }
- finalConfigArray = finalConfigArray.concat(personalConfigArray);
- }
- // Apply CLI options.
- if (cliConfigArray.length > 0) {
- finalConfigArray = finalConfigArray.concat(cliConfigArray);
- }
- // Validate rule settings and environments.
- const validator = new ConfigValidator({
- builtInRules
- });
- validator.validateConfigArray(finalConfigArray);
- // Cache it.
- Object.freeze(finalConfigArray);
- finalizeCache.set(configArray, finalConfigArray);
- debug$1(
- "Configuration was determined: %o on %s",
- finalConfigArray,
- directoryPath
- );
- }
- // At least one element (the default ignore patterns) exists.
- if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
- throw new ConfigurationNotFoundError(directoryPath);
- }
- return finalConfigArray;
- }
- }
- /**
- * @fileoverview Compatibility class for flat config.
- * @author Nicholas C. Zakas
- */
- //-----------------------------------------------------------------------------
- // Helpers
- //-----------------------------------------------------------------------------
- /** @typedef {import("../../shared/types").Environment} Environment */
- /** @typedef {import("../../shared/types").Processor} Processor */
- const debug = debugOrig__default["default"]("eslintrc:flat-compat");
- const cafactory = Symbol("cafactory");
- /**
- * Translates an ESLintRC-style config object into a flag-config-style config
- * object.
- * @param {Object} eslintrcConfig An ESLintRC-style config object.
- * @param {Object} options Options to help translate the config.
- * @param {string} options.resolveConfigRelativeTo To the directory to resolve
- * configs from.
- * @param {string} options.resolvePluginsRelativeTo The directory to resolve
- * plugins from.
- * @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment
- * names to objects.
- * @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor
- * names to objects.
- * @returns {Object} A flag-config-style config object.
- */
- function translateESLintRC(eslintrcConfig, {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo,
- pluginEnvironments,
- pluginProcessors
- }) {
- const flatConfig = {};
- const configs = [];
- const languageOptions = {};
- const linterOptions = {};
- const keysToCopy = ["settings", "rules", "processor"];
- const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"];
- const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"];
- // copy over simple translations
- for (const key of keysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- flatConfig[key] = eslintrcConfig[key];
- }
- }
- // copy over languageOptions
- for (const key of languageOptionsKeysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- // create the languageOptions key in the flat config
- flatConfig.languageOptions = languageOptions;
- if (key === "parser") {
- debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);
- if (eslintrcConfig[key].error) {
- throw eslintrcConfig[key].error;
- }
- languageOptions[key] = eslintrcConfig[key].definition;
- continue;
- }
- // clone any object values that are in the eslintrc config
- if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") {
- languageOptions[key] = {
- ...eslintrcConfig[key]
- };
- } else {
- languageOptions[key] = eslintrcConfig[key];
- }
- }
- }
- // copy over linterOptions
- for (const key of linterOptionsKeysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- flatConfig.linterOptions = linterOptions;
- linterOptions[key] = eslintrcConfig[key];
- }
- }
- // move ecmaVersion a level up
- if (languageOptions.parserOptions) {
- if ("ecmaVersion" in languageOptions.parserOptions) {
- languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;
- delete languageOptions.parserOptions.ecmaVersion;
- }
- if ("sourceType" in languageOptions.parserOptions) {
- languageOptions.sourceType = languageOptions.parserOptions.sourceType;
- delete languageOptions.parserOptions.sourceType;
- }
- // check to see if we even need parserOptions anymore and remove it if not
- if (Object.keys(languageOptions.parserOptions).length === 0) {
- delete languageOptions.parserOptions;
- }
- }
- // overrides
- if (eslintrcConfig.criteria) {
- flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];
- }
- // translate plugins
- if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") {
- debug(`Translating plugins: ${eslintrcConfig.plugins}`);
- flatConfig.plugins = {};
- for (const pluginName of Object.keys(eslintrcConfig.plugins)) {
- debug(`Translating plugin: ${pluginName}`);
- debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);
- const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];
- if (error) {
- throw error;
- }
- flatConfig.plugins[pluginName] = plugin;
- // create a config for any processors
- if (plugin.processors) {
- for (const processorName of Object.keys(plugin.processors)) {
- if (processorName.startsWith(".")) {
- debug(`Assigning processor: ${pluginName}/${processorName}`);
- configs.unshift({
- files: [`**/*${processorName}`],
- processor: pluginProcessors.get(`${pluginName}/${processorName}`)
- });
- }
- }
- }
- }
- }
- // translate env - must come after plugins
- if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") {
- for (const envName of Object.keys(eslintrcConfig.env)) {
- // only add environments that are true
- if (eslintrcConfig.env[envName]) {
- debug(`Translating environment: ${envName}`);
- if (environments.has(envName)) {
- // built-in environments should be defined first
- configs.unshift(...translateESLintRC(environments.get(envName), {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo
- }));
- } else if (pluginEnvironments.has(envName)) {
- // if the environment comes from a plugin, it should come after the plugin config
- configs.push(...translateESLintRC(pluginEnvironments.get(envName), {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo
- }));
- }
- }
- }
- }
- // only add if there are actually keys in the config
- if (Object.keys(flatConfig).length > 0) {
- configs.push(flatConfig);
- }
- return configs;
- }
- //-----------------------------------------------------------------------------
- // Exports
- //-----------------------------------------------------------------------------
- /**
- * A compatibility class for working with configs.
- */
- class FlatCompat {
- constructor({
- baseDirectory = process.cwd(),
- resolvePluginsRelativeTo = baseDirectory,
- recommendedConfig,
- allConfig
- } = {}) {
- this.baseDirectory = baseDirectory;
- this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
- this[cafactory] = new ConfigArrayFactory({
- cwd: baseDirectory,
- resolvePluginsRelativeTo,
- getEslintAllConfig: () => {
- if (!allConfig) {
- throw new TypeError("Missing parameter 'allConfig' in FlatCompat constructor.");
- }
- return allConfig;
- },
- getEslintRecommendedConfig: () => {
- if (!recommendedConfig) {
- throw new TypeError("Missing parameter 'recommendedConfig' in FlatCompat constructor.");
- }
- return recommendedConfig;
- }
- });
- }
- /**
- * Translates an ESLintRC-style config into a flag-config-style config.
- * @param {Object} eslintrcConfig The ESLintRC-style config object.
- * @returns {Object} A flag-config-style config object.
- */
- config(eslintrcConfig) {
- const eslintrcArray = this[cafactory].create(eslintrcConfig, {
- basePath: this.baseDirectory
- });
- const flatArray = [];
- let hasIgnorePatterns = false;
- eslintrcArray.forEach(configData => {
- if (configData.type === "config") {
- hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;
- flatArray.push(...translateESLintRC(configData, {
- resolveConfigRelativeTo: path__default["default"].join(this.baseDirectory, "__placeholder.js"),
- resolvePluginsRelativeTo: path__default["default"].join(this.resolvePluginsRelativeTo, "__placeholder.js"),
- pluginEnvironments: eslintrcArray.pluginEnvironments,
- pluginProcessors: eslintrcArray.pluginProcessors
- }));
- }
- });
- // combine ignorePatterns to emulate ESLintRC behavior better
- if (hasIgnorePatterns) {
- flatArray.unshift({
- ignores: [filePath => {
- // Compute the final config for this file.
- // This filters config array elements by `files`/`excludedFiles` then merges the elements.
- const finalConfig = eslintrcArray.extractConfig(filePath);
- // Test the `ignorePattern` properties of the final config.
- return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);
- }]
- });
- }
- return flatArray;
- }
- /**
- * Translates the `env` section of an ESLintRC-style config.
- * @param {Object} envConfig The `env` section of an ESLintRC config.
- * @returns {Object[]} An array of flag-config objects representing the environments.
- */
- env(envConfig) {
- return this.config({
- env: envConfig
- });
- }
- /**
- * Translates the `extends` section of an ESLintRC-style config.
- * @param {...string} configsToExtend The names of the configs to load.
- * @returns {Object[]} An array of flag-config objects representing the config.
- */
- extends(...configsToExtend) {
- return this.config({
- extends: configsToExtend
- });
- }
- /**
- * Translates the `plugins` section of an ESLintRC-style config.
- * @param {...string} plugins The names of the plugins to load.
- * @returns {Object[]} An array of flag-config objects representing the plugins.
- */
- plugins(...plugins) {
- return this.config({
- plugins
- });
- }
- }
- /**
- * @fileoverview Package exports for @eslint/eslintrc
- * @author Nicholas C. Zakas
- */
- //-----------------------------------------------------------------------------
- // Exports
- //-----------------------------------------------------------------------------
- const Legacy = {
- ConfigArray,
- createConfigArrayFactoryContext: createContext,
- CascadingConfigArrayFactory,
- ConfigArrayFactory,
- ConfigDependency,
- ExtractedConfig,
- IgnorePattern,
- OverrideTester,
- getUsedExtractedConfigs,
- environments,
- // shared
- ConfigOps,
- ConfigValidator,
- ModuleResolver,
- naming
- };
- exports.FlatCompat = FlatCompat;
- exports.Legacy = Legacy;
- //# sourceMappingURL=eslintrc.cjs.map
|