@@ -8,13 +8,12 @@ import { getPhysicalFilename } from 'eslint-module-utils/contextCompat';
8
8
import { getFileExtensions } from 'eslint-module-utils/ignore' ;
9
9
import resolve from 'eslint-module-utils/resolve' ;
10
10
import visit from 'eslint-module-utils/visit' ;
11
- import { dirname , join , resolve as resolvePath } from 'path' ;
11
+ import { dirname , join } from 'path' ;
12
12
import readPkgUp from 'eslint-module-utils/readPkgUp' ;
13
13
import values from 'object.values' ;
14
14
import includes from 'array-includes' ;
15
15
import flatMap from 'array.prototype.flatmap' ;
16
16
17
- import { walkSync } from '../core/fsWalk' ;
18
17
import ExportMapBuilder from '../exportMap/builder' ;
19
18
import recursivePatternCapture from '../exportMap/patternCapture' ;
20
19
import docsUrl from '../docsUrl' ;
@@ -51,21 +50,81 @@ function requireFileEnumerator() {
51
50
}
52
51
53
52
/**
54
- *
53
+ * Given a FileEnumerator class, instantiate and load the list of files.
55
54
* @param FileEnumerator the `FileEnumerator` class from `eslint`'s internal api
56
55
* @param {string } src path to the src root
57
56
* @param {string[] } extensions list of supported extensions
58
57
* @returns {{ filename: string, ignored: boolean }[] } list of files to operate on
59
58
*/
60
59
function listFilesUsingFileEnumerator ( FileEnumerator , src , extensions ) {
61
- const e = new FileEnumerator ( {
62
- extensions,
63
- } ) ;
60
+ // We need to know whether this is being run with flat config in order to
61
+ // determine whether we need to customize the FileEnumerator or not.
62
+
63
+ // This condition is sufficient to test in v8, since the environment variable
64
+ // is necessary to turn on flat config
65
+ let isUsingFlatConfig = process . env . ESLINT_USE_FLAT_CONFIG
66
+ && process . env . ESLINT_USE_FLAT_CONFIG !== 'false' ;
67
+
68
+ // In the case of using v9, we can check the `shouldUseFlatConfig` function
69
+ // If this function is present, then we assume it's v9
70
+ try {
71
+ const { shouldUseFlatConfig } = require ( 'eslint/use-at-your-own-risk' ) ;
72
+ isUsingFlatConfig = shouldUseFlatConfig ( ) ;
73
+ } catch ( _ ) {
74
+ // We don't want to throw here, since we only want to update the
75
+ // boolean if the function is available.
76
+ }
77
+
78
+ let enumerator ;
79
+ if ( isUsingFlatConfig ) {
80
+ // If this run is using flat config, then we need to create an instance of `CascadingConfigArrayFactory`
81
+ // with eslintrc turned off, to pass to the `FileEnumerator`.
82
+ // This prevents the FileEnumerator from looking for an eslintrc file in parent directories.
83
+ // https://github.com/import-js/eslint-plugin-import/issues/3079
84
+ try {
85
+ const {
86
+ Legacy : { CascadingConfigArrayFactory } ,
87
+ } = require ( '@eslint/eslintrc' ) ; // eslint-disable-line import/no-extraneous-dependencies
88
+
89
+ const configArrayFactory = new CascadingConfigArrayFactory ( {
90
+ // These are the same as what `FileEnumerator` would normally pass in
91
+ cwd : process . cwd ( ) ,
92
+ // eslint-disable-next-line import/no-extraneous-dependencies
93
+ getEslintRecommendedConfig : ( ) => require ( '@eslint/js' ) . configs . recommended ,
94
+ // eslint-disable-next-line import/no-extraneous-dependencies
95
+ getEslintAllConfig : ( ) => require ( '@eslint/js' ) . configs . all ,
96
+
97
+ // This is what we're doing differently for flat config use
98
+ useEslintrc : false ,
99
+ } ) ;
100
+
101
+ enumerator = new FileEnumerator ( {
102
+ configArrayFactory,
103
+ extensions,
104
+ } ) ;
105
+ } catch ( e ) {
106
+ // Absorb this if we weren't able to require the config array factory
107
+ if ( e . code !== 'MODULE_NOT_FOUND' ) {
108
+ throw e ;
109
+ }
110
+ // If we can't load the config array factory, we'll just do our best
111
+ // and create the enumerator without turning off eslintrc.
112
+ // This will ultimately result in an error if the project doesn't have an
113
+ // eslintrc file in a parent directory.
114
+ enumerator = new FileEnumerator ( {
115
+ extensions,
116
+ } ) ;
117
+ }
118
+ } else {
119
+ enumerator = new FileEnumerator ( {
120
+ extensions,
121
+ } ) ;
122
+ }
64
123
65
- return Array . from (
66
- e . iterateFiles ( src ) ,
67
- ( { filePath , ignored } ) => ( { filename : filePath , ignored } ) ,
68
- ) ;
124
+ return Array . from ( enumerator . iterateFiles ( src ) , ( { filePath , ignored } ) => ( {
125
+ filename : filePath ,
126
+ ignored,
127
+ } ) ) ;
69
128
}
70
129
71
130
/**
@@ -107,70 +166,14 @@ function listFilesWithLegacyFunctions(src, extensions) {
107
166
}
108
167
}
109
168
110
- /**
111
- * Given a source root and list of supported extensions, use fsWalk and the
112
- * new `eslint` `context.session` api to build the list of files we want to operate on
113
- * @param {string[] } srcPaths array of source paths (for flat config this should just be a singular root (e.g. cwd))
114
- * @param {string[] } extensions list of supported extensions
115
- * @param {{ isDirectoryIgnored: (path: string) => boolean, isFileIgnored: (path: string) => boolean } } session eslint context session object
116
- * @returns {string[] } list of files to operate on
117
- */
118
- function listFilesWithModernApi ( srcPaths , extensions , session ) {
119
- /** @type {string[] } */
120
- const files = [ ] ;
121
-
122
- for ( let i = 0 ; i < srcPaths . length ; i ++ ) {
123
- const src = srcPaths [ i ] ;
124
- // Use walkSync along with the new session api to gather the list of files
125
- const entries = walkSync ( src , {
126
- deepFilter ( entry ) {
127
- const fullEntryPath = resolvePath ( src , entry . path ) ;
128
-
129
- // Include the directory if it's not marked as ignore by eslint
130
- return ! session . isDirectoryIgnored ( fullEntryPath ) ;
131
- } ,
132
- entryFilter ( entry ) {
133
- const fullEntryPath = resolvePath ( src , entry . path ) ;
134
-
135
- // Include the file if it's not marked as ignore by eslint and its extension is included in our list
136
- return (
137
- ! session . isFileIgnored ( fullEntryPath )
138
- && extensions . find ( ( extension ) => entry . path . endsWith ( extension ) )
139
- ) ;
140
- } ,
141
- } ) ;
142
-
143
- // Filter out directories and map entries to their paths
144
- files . push (
145
- ...entries
146
- . filter ( ( entry ) => ! entry . dirent . isDirectory ( ) )
147
- . map ( ( entry ) => entry . path ) ,
148
- ) ;
149
- }
150
- return files ;
151
- }
152
-
153
169
/**
154
170
* Given a src pattern and list of supported extensions, return a list of files to process
155
171
* with this rule.
156
172
* @param {string } src - file, directory, or glob pattern of files to act on
157
173
* @param {string[] } extensions - list of supported file extensions
158
- * @param {import('eslint').Rule.RuleContext } context - the eslint context object
159
174
* @returns {string[] | { filename: string, ignored: boolean }[] } the list of files that this rule will evaluate.
160
175
*/
161
- function listFilesToProcess ( src , extensions , context ) {
162
- // If the context object has the new session functions, then prefer those
163
- // Otherwise, fallback to using the deprecated `FileEnumerator` for legacy support.
164
- // https://github.com/eslint/eslint/issues/18087
165
- if (
166
- context . session
167
- && context . session . isFileIgnored
168
- && context . session . isDirectoryIgnored
169
- ) {
170
- return listFilesWithModernApi ( src , extensions , context . session ) ;
171
- }
172
-
173
- // Fallback to og FileEnumerator
176
+ function listFilesToProcess ( src , extensions ) {
174
177
const FileEnumerator = requireFileEnumerator ( ) ;
175
178
176
179
// If we got the FileEnumerator, then let's go with that
@@ -295,10 +298,10 @@ const isNodeModule = (path) => (/\/(node_modules)\//).test(path);
295
298
function resolveFiles ( src , ignoreExports , context ) {
296
299
const extensions = Array . from ( getFileExtensions ( context . settings ) ) ;
297
300
298
- const srcFileList = listFilesToProcess ( src , extensions , context ) ;
301
+ const srcFileList = listFilesToProcess ( src , extensions ) ;
299
302
300
303
// prepare list of ignored files
301
- const ignoredFilesList = listFilesToProcess ( ignoreExports , extensions , context ) ;
304
+ const ignoredFilesList = listFilesToProcess ( ignoreExports , extensions ) ;
302
305
303
306
// The modern api will return a list of file paths, rather than an object
304
307
if ( ignoredFilesList . length && typeof ignoredFilesList [ 0 ] === 'string' ) {
0 commit comments