## Stack Summary This stack splits `Settings` into `FormatterSettings` and `LinterSettings` and moves it into `ruff_workspace`. This change is necessary to add the `FormatterSettings` to `Settings` without adding `ruff_python_formatter` as a dependency to `ruff_linter` (and the linter should not contain the formatter settings). A quick overview of our settings struct at play: * `Options`: 1:1 representation of the options in the `pyproject.toml` or `ruff.toml`. Used for deserialization. * `Configuration`: Resolved `Options`, potentially merged from multiple configurations (when using `extend`). The representation is very close if not identical to the `Options`. * `Settings`: The resolved configuration that uses a data format optimized for reading. Optional fields are initialized with their default values. Initialized by `Configuration::into_settings` . The goal of this stack is to split `Settings` into tool-specific resolved `Settings` that are independent of each other. This comes at the advantage that the individual crates don't need to know anything about the other tools. The downside is that information gets duplicated between `Settings`. Right now the duplication is minimal (`line-length`, `tab-width`) but we may need to come up with a solution if more expensive data needs sharing. This stack focuses on `Settings`. Splitting `Configuration` into some smaller structs is something I'll follow up on later. ## PR Summary This PR extracts the linter-specific settings into a new `LinterSettings` struct and adds it as a `linter` field to the `Settings` struct. This is in preparation for moving `Settings` from `ruff_linter` to `ruff_workspace` ## Test Plan `cargo test`
83 lines
2.6 KiB
Rust
83 lines
2.6 KiB
Rust
use std::path::PathBuf;
|
|
use std::time::Instant;
|
|
|
|
use anyhow::Result;
|
|
use log::{debug, error};
|
|
#[cfg(not(target_family = "wasm"))]
|
|
use rayon::prelude::*;
|
|
|
|
use ruff_linter::linter::add_noqa_to_path;
|
|
use ruff_linter::warn_user_once;
|
|
use ruff_python_ast::{PySourceType, SourceType};
|
|
use ruff_workspace::resolver::{python_files_in_path, PyprojectConfig};
|
|
|
|
use crate::args::CliOverrides;
|
|
use crate::diagnostics::LintSource;
|
|
|
|
/// Add `noqa` directives to a collection of files.
|
|
pub(crate) fn add_noqa(
|
|
files: &[PathBuf],
|
|
pyproject_config: &PyprojectConfig,
|
|
overrides: &CliOverrides,
|
|
) -> Result<usize> {
|
|
// Collect all the files to check.
|
|
let start = Instant::now();
|
|
let (paths, resolver) = python_files_in_path(files, pyproject_config, overrides)?;
|
|
let duration = start.elapsed();
|
|
debug!("Identified files to lint in: {:?}", duration);
|
|
|
|
if paths.is_empty() {
|
|
warn_user_once!("No Python files found under the given path(s)");
|
|
return Ok(0);
|
|
}
|
|
|
|
// Discover the package root for each Python file.
|
|
let package_roots = resolver.package_roots(
|
|
&paths
|
|
.iter()
|
|
.flatten()
|
|
.map(ignore::DirEntry::path)
|
|
.collect::<Vec<_>>(),
|
|
pyproject_config,
|
|
);
|
|
|
|
let start = Instant::now();
|
|
let modifications: usize = paths
|
|
.par_iter()
|
|
.flatten()
|
|
.filter_map(|entry| {
|
|
let path = entry.path();
|
|
let SourceType::Python(source_type @ (PySourceType::Python | PySourceType::Stub)) =
|
|
SourceType::from(path)
|
|
else {
|
|
return None;
|
|
};
|
|
let package = path
|
|
.parent()
|
|
.and_then(|parent| package_roots.get(parent))
|
|
.and_then(|package| *package);
|
|
let settings = resolver.resolve(path, pyproject_config);
|
|
let LintSource(source_kind) = match LintSource::try_from_path(path, source_type) {
|
|
Ok(Some(source)) => source,
|
|
Ok(None) => return None,
|
|
Err(e) => {
|
|
error!("Failed to extract source from {}: {e}", path.display());
|
|
return None;
|
|
}
|
|
};
|
|
match add_noqa_to_path(path, package, &source_kind, source_type, &settings.linter) {
|
|
Ok(count) => Some(count),
|
|
Err(e) => {
|
|
error!("Failed to add noqa to {}: {e}", path.display());
|
|
None
|
|
}
|
|
}
|
|
})
|
|
.sum();
|
|
|
|
let duration = start.elapsed();
|
|
debug!("Added noqa to files in: {:?}", duration);
|
|
|
|
Ok(modifications)
|
|
}
|