Skip to content

Commit e132aba

Browse files
committed
refactor(linter): extract nested config searching to a fn (#10860)
moves the nested config code out into a functin to improve readability + prep for future changes
1 parent bac29eb commit e132aba

File tree

1 file changed

+81
-63
lines changed

1 file changed

+81
-63
lines changed

apps/oxlint/src/lint.rs

Lines changed: 81 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::{
2-
env, fs,
2+
env,
3+
ffi::OsStr,
4+
fs,
35
io::{ErrorKind, Write},
46
path::{Path, PathBuf, absolute},
7+
sync::Arc,
58
time::Instant,
69
};
710

@@ -166,71 +169,16 @@ impl Runner for LintRunner {
166169
let paths = walker.paths();
167170
let number_of_files = paths.len();
168171

169-
// TODO(perf): benchmark whether or not it is worth it to store the configurations on a
170-
// per-file or per-directory basis, to avoid calling `.parent()` on every path.
171-
let mut nested_oxlintrc = FxHashMap::<&Path, Oxlintrc>::default();
172-
let mut nested_configs = FxHashMap::<PathBuf, ConfigStore>::default();
173-
174172
let handler = GraphicalReportHandler::new();
175173

176-
if search_for_nested_configs {
177-
// get all of the unique directories among the paths to use for search for
178-
// oxlint config files in those directories and their ancestors
179-
// e.g. `/some/file.js` will check `/some` and `/`
180-
// `/some/other/file.js` will check `/some/other`, `/some`, and `/`
181-
let mut directories = FxHashSet::default();
182-
for path in &paths {
183-
let path = Path::new(path);
184-
// Start from the file's parent directory and walk up the tree
185-
let mut current = path.parent();
186-
while let Some(dir) = current {
187-
// NOTE: Initial benchmarking showed that it was faster to iterate over the directories twice
188-
// rather than constructing the configs in one iteration. It's worth re-benchmarking that though.
189-
directories.insert(dir);
190-
current = dir.parent();
191-
}
174+
let nested_configs = if search_for_nested_configs {
175+
match Self::get_nested_configs(stdout, &handler, &filters, &paths) {
176+
Ok(v) => v,
177+
Err(v) => return v,
192178
}
193-
for directory in directories {
194-
if let Ok(config) = Self::find_oxlint_config_in_directory(directory) {
195-
nested_oxlintrc.insert(directory, config);
196-
}
197-
}
198-
199-
// iterate over each config and build the ConfigStore
200-
for (dir, oxlintrc) in nested_oxlintrc {
201-
// TODO(refactor): clean up all of the error handling in this function
202-
let builder = match ConfigStoreBuilder::from_oxlintrc(false, oxlintrc) {
203-
Ok(builder) => builder,
204-
Err(e) => {
205-
print_and_flush_stdout(
206-
stdout,
207-
&format!(
208-
"Failed to parse configuration file.\n{}\n",
209-
render_report(&handler, &OxcDiagnostic::error(e.to_string()))
210-
),
211-
);
212-
213-
return CliRunResult::InvalidOptionConfig;
214-
}
215-
}
216-
.with_filters(&filters);
217-
218-
match builder.build() {
219-
Ok(config) => nested_configs.insert(dir.to_path_buf(), config),
220-
Err(diagnostic) => {
221-
print_and_flush_stdout(
222-
stdout,
223-
&format!(
224-
"Failed to parse configuration file.\n{}\n",
225-
render_report(&handler, &diagnostic)
226-
),
227-
);
228-
229-
return CliRunResult::InvalidOptionConfig;
230-
}
231-
};
232-
}
233-
}
179+
} else {
180+
FxHashMap::default()
181+
};
234182

235183
enable_plugins.apply_overrides(&mut oxlintrc.plugins);
236184

@@ -447,6 +395,76 @@ impl LintRunner {
447395
Ok(filters)
448396
}
449397

398+
fn get_nested_configs(
399+
stdout: &mut dyn Write,
400+
handler: &GraphicalReportHandler,
401+
filters: &Vec<LintFilter>,
402+
paths: &Vec<Arc<OsStr>>,
403+
) -> Result<FxHashMap<PathBuf, ConfigStore>, CliRunResult> {
404+
// TODO(perf): benchmark whether or not it is worth it to store the configurations on a
405+
// per-file or per-directory basis, to avoid calling `.parent()` on every path.
406+
let mut nested_oxlintrc = FxHashMap::<&Path, Oxlintrc>::default();
407+
let mut nested_configs = FxHashMap::<PathBuf, ConfigStore>::default();
408+
// get all of the unique directories among the paths to use for search for
409+
// oxlint config files in those directories and their ancestors
410+
// e.g. `/some/file.js` will check `/some` and `/`
411+
// `/some/other/file.js` will check `/some/other`, `/some`, and `/`
412+
let mut directories = FxHashSet::default();
413+
for path in paths {
414+
let path = Path::new(path);
415+
// Start from the file's parent directory and walk up the tree
416+
let mut current = path.parent();
417+
while let Some(dir) = current {
418+
// NOTE: Initial benchmarking showed that it was faster to iterate over the directories twice
419+
// rather than constructing the configs in one iteration. It's worth re-benchmarking that though.
420+
directories.insert(dir);
421+
current = dir.parent();
422+
}
423+
}
424+
for directory in directories {
425+
if let Ok(config) = Self::find_oxlint_config_in_directory(directory) {
426+
nested_oxlintrc.insert(directory, config);
427+
}
428+
}
429+
430+
// iterate over each config and build the ConfigStore
431+
for (dir, oxlintrc) in nested_oxlintrc {
432+
// TODO(refactor): clean up all of the error handling in this function
433+
let builder = match ConfigStoreBuilder::from_oxlintrc(false, oxlintrc) {
434+
Ok(builder) => builder,
435+
Err(e) => {
436+
print_and_flush_stdout(
437+
stdout,
438+
&format!(
439+
"Failed to parse configuration file.\n{}\n",
440+
render_report(handler, &OxcDiagnostic::error(e.to_string()))
441+
),
442+
);
443+
444+
return Err(CliRunResult::InvalidOptionConfig);
445+
}
446+
}
447+
.with_filters(filters);
448+
449+
match builder.build() {
450+
Ok(config) => nested_configs.insert(dir.to_path_buf(), config),
451+
Err(diagnostic) => {
452+
print_and_flush_stdout(
453+
stdout,
454+
&format!(
455+
"Failed to parse configuration file.\n{}\n",
456+
render_report(handler, &diagnostic)
457+
),
458+
);
459+
460+
return Err(CliRunResult::InvalidOptionConfig);
461+
}
462+
};
463+
}
464+
465+
Ok(nested_configs)
466+
}
467+
450468
// finds the oxlint config
451469
// when config is provided, but not found, an String with the formatted error is returned, else the oxlintrc config file is returned
452470
// when no config is provided, it will search for the default file names in the current working directory

0 commit comments

Comments
 (0)