Skip to content

Commit

Permalink
Move pyproject_config into Resolver (#9453)
Browse files Browse the repository at this point in the history
## Summary

Sort of a random PR to make the coupling between `pyproject_config` and
`resolver` more explicit by passing it to the `Resolver`, rather than
threading it through to each individual method.
  • Loading branch information
charliermarsh authored Jan 10, 2024
1 parent 79f4abb commit 4a3bb67
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 149 deletions.
23 changes: 6 additions & 17 deletions crates/ruff_cli/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ use ruff_notebook::NotebookIndex;
use ruff_python_ast::imports::ImportMap;
use ruff_source_file::SourceFileBuilder;
use ruff_text_size::{TextRange, TextSize};
use ruff_workspace::resolver::{PyprojectConfig, PyprojectDiscoveryStrategy, Resolver};
use ruff_workspace::resolver::Resolver;
use ruff_workspace::Settings;

use crate::cache;
use crate::diagnostics::Diagnostics;

/// [`Path`] that is relative to the package root in [`PackageCache`].
Expand Down Expand Up @@ -443,7 +442,7 @@ pub(super) struct CacheMessage {
pub(crate) trait PackageCaches {
fn get(&self, package_root: &Path) -> Option<&Cache>;

fn persist(self) -> anyhow::Result<()>;
fn persist(self) -> Result<()>;
}

impl<T> PackageCaches for Option<T>
Expand All @@ -469,27 +468,17 @@ pub(crate) struct PackageCacheMap<'a>(FxHashMap<&'a Path, Cache>);

impl<'a> PackageCacheMap<'a> {
pub(crate) fn init(
pyproject_config: &PyprojectConfig,
package_roots: &FxHashMap<&'a Path, Option<&'a Path>>,
resolver: &Resolver,
) -> Self {
fn init_cache(path: &Path) {
if let Err(e) = cache::init(path) {
if let Err(e) = init(path) {
error!("Failed to initialize cache at {}: {e:?}", path.display());
}
}

match pyproject_config.strategy {
PyprojectDiscoveryStrategy::Fixed => {
init_cache(&pyproject_config.settings.cache_dir);
}
PyprojectDiscoveryStrategy::Hierarchical => {
for settings in
std::iter::once(&pyproject_config.settings).chain(resolver.settings())
{
init_cache(&settings.cache_dir);
}
}
for settings in resolver.settings() {
init_cache(&settings.cache_dir);
}

Self(
Expand All @@ -499,7 +488,7 @@ impl<'a> PackageCacheMap<'a> {
.unique()
.par_bridge()
.map(|cache_root| {
let settings = resolver.resolve(cache_root, pyproject_config);
let settings = resolver.resolve(cache_root);
let cache = Cache::open(cache_root.to_path_buf(), settings);
(cache_root, cache)
})
Expand Down
3 changes: 1 addition & 2 deletions crates/ruff_cli/src/commands/add_noqa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub(crate) fn add_noqa(
.flatten()
.map(ResolvedFile::path)
.collect::<Vec<_>>(),
pyproject_config,
);

let start = Instant::now();
Expand All @@ -57,7 +56,7 @@ pub(crate) fn add_noqa(
.parent()
.and_then(|parent| package_roots.get(parent))
.and_then(|package| *package);
let settings = resolver.resolve(path, pyproject_config);
let settings = resolver.resolve(path);
let source_kind = match SourceKind::from_path(path, source_type) {
Ok(Some(source_kind)) => source_kind,
Ok(None) => return None,
Expand Down
11 changes: 3 additions & 8 deletions crates/ruff_cli/src/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,11 @@ pub(crate) fn check(
.flatten()
.map(ResolvedFile::path)
.collect::<Vec<_>>(),
pyproject_config,
);

// Load the caches.
let caches = if bool::from(cache) {
Some(PackageCacheMap::init(
pyproject_config,
&package_roots,
&resolver,
))
Some(PackageCacheMap::init(&package_roots, &resolver))
} else {
None
};
Expand All @@ -81,7 +76,7 @@ pub(crate) fn check(
.and_then(|parent| package_roots.get(parent))
.and_then(|package| *package);

let settings = resolver.resolve(path, pyproject_config);
let settings = resolver.resolve(path);

if (settings.file_resolver.force_exclude || !resolved_file.is_root())
&& match_exclusion(
Expand Down Expand Up @@ -128,7 +123,7 @@ pub(crate) fn check(

Some(result.unwrap_or_else(|(path, message)| {
if let Some(path) = &path {
let settings = resolver.resolve(path, pyproject_config);
let settings = resolver.resolve(path);
if settings.linter.rules.enabled(Rule::IOError) {
let dummy =
SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish();
Expand Down
20 changes: 10 additions & 10 deletions crates/ruff_cli/src/commands/check_stdin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use anyhow::Result;

use ruff_linter::packaging;
use ruff_linter::settings::flags;
use ruff_workspace::resolver::{match_exclusion, python_file_at_path, PyprojectConfig};
use ruff_workspace::resolver::{match_exclusion, python_file_at_path, PyprojectConfig, Resolver};

use crate::args::CliOverrides;
use crate::diagnostics::{lint_stdin, Diagnostics};
Expand All @@ -18,20 +18,20 @@ pub(crate) fn check_stdin(
noqa: flags::Noqa,
fix_mode: flags::FixMode,
) -> Result<Diagnostics> {
if pyproject_config.settings.file_resolver.force_exclude {
let mut resolver = Resolver::new(pyproject_config);

if resolver.force_exclude() {
if let Some(filename) = filename {
if !python_file_at_path(filename, pyproject_config, overrides)? {
if !python_file_at_path(filename, &mut resolver, overrides)? {
if fix_mode.is_apply() {
parrot_stdin()?;
}
return Ok(Diagnostics::default());
}

let lint_settings = &pyproject_config.settings.linter;
if filename
.file_name()
.is_some_and(|name| match_exclusion(filename, name, &lint_settings.exclude))
{
if filename.file_name().is_some_and(|name| {
match_exclusion(filename, name, &resolver.base_settings().linter.exclude)
}) {
if fix_mode.is_apply() {
parrot_stdin()?;
}
Expand All @@ -41,13 +41,13 @@ pub(crate) fn check_stdin(
}
let stdin = read_from_stdin()?;
let package_root = filename.and_then(Path::parent).and_then(|path| {
packaging::detect_package_root(path, &pyproject_config.settings.linter.namespace_packages)
packaging::detect_package_root(path, &resolver.base_settings().linter.namespace_packages)
});
let mut diagnostics = lint_stdin(
filename,
package_root,
stdin,
&pyproject_config.settings,
resolver.base_settings(),
noqa,
fix_mode,
)?;
Expand Down
28 changes: 7 additions & 21 deletions crates/ruff_cli/src/commands/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ use ruff_linter::warn_user_once;
use ruff_python_ast::{PySourceType, SourceType};
use ruff_python_formatter::{format_module_source, FormatModuleError, QuoteStyle};
use ruff_text_size::{TextLen, TextRange, TextSize};
use ruff_workspace::resolver::{
match_exclusion, python_files_in_path, PyprojectConfig, ResolvedFile, Resolver,
};
use ruff_workspace::resolver::{match_exclusion, python_files_in_path, ResolvedFile, Resolver};
use ruff_workspace::FormatterSettings;

use crate::args::{CliOverrides, FormatArguments};
Expand Down Expand Up @@ -79,7 +77,7 @@ pub(crate) fn format(
return Ok(ExitStatus::Success);
}

warn_incompatible_formatter_settings(&pyproject_config, Some(&resolver));
warn_incompatible_formatter_settings(&resolver);

// Discover the package root for each Python file.
let package_roots = resolver.package_roots(
Expand All @@ -88,7 +86,6 @@ pub(crate) fn format(
.flatten()
.map(ResolvedFile::path)
.collect::<Vec<_>>(),
&pyproject_config,
);

let caches = if cli.no_cache {
Expand All @@ -99,11 +96,7 @@ pub(crate) fn format(
#[cfg(debug_assertions)]
crate::warn_user!("Detected debug build without --no-cache.");

Some(PackageCacheMap::init(
&pyproject_config,
&package_roots,
&resolver,
))
Some(PackageCacheMap::init(&package_roots, &resolver))
};

let start = Instant::now();
Expand All @@ -118,7 +111,7 @@ pub(crate) fn format(
return None;
};

let settings = resolver.resolve(path, &pyproject_config);
let settings = resolver.resolve(path);

// Ignore files that are excluded from formatting
if (settings.file_resolver.force_exclude || !resolved_file.is_root())
Expand Down Expand Up @@ -723,15 +716,10 @@ impl Display for FormatCommandError {
}
}

pub(super) fn warn_incompatible_formatter_settings(
pyproject_config: &PyprojectConfig,
resolver: Option<&Resolver>,
) {
pub(super) fn warn_incompatible_formatter_settings(resolver: &Resolver) {
// First, collect all rules that are incompatible regardless of the linter-specific settings.
let mut incompatible_rules = FxHashSet::default();
for setting in std::iter::once(&pyproject_config.settings)
.chain(resolver.iter().flat_map(|resolver| resolver.settings()))
{
for setting in resolver.settings() {
for rule in [
// The formatter might collapse implicit string concatenation on a single line.
Rule::SingleLineImplicitStringConcatenation,
Expand Down Expand Up @@ -760,9 +748,7 @@ pub(super) fn warn_incompatible_formatter_settings(
}

// Next, validate settings-specific incompatibilities.
for setting in std::iter::once(&pyproject_config.settings)
.chain(resolver.iter().flat_map(|resolver| resolver.settings()))
{
for setting in resolver.settings() {
// Validate all rules that rely on tab styles.
if setting.linter.rules.enabled(Rule::TabIndentation)
&& setting.formatter.indent_style.is_tab()
Expand Down
24 changes: 9 additions & 15 deletions crates/ruff_cli/src/commands/format_stdin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use log::error;

use ruff_linter::source_kind::SourceKind;
use ruff_python_ast::{PySourceType, SourceType};
use ruff_workspace::resolver::{match_exclusion, python_file_at_path};
use ruff_workspace::resolver::{match_exclusion, python_file_at_path, Resolver};
use ruff_workspace::FormatterSettings;

use crate::args::{CliOverrides, FormatArguments};
Expand All @@ -27,24 +27,23 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
cli.stdin_filename.as_deref(),
)?;

warn_incompatible_formatter_settings(&pyproject_config, None);
let mut resolver = Resolver::new(&pyproject_config);
warn_incompatible_formatter_settings(&resolver);

let mode = FormatMode::from_cli(cli);

if pyproject_config.settings.file_resolver.force_exclude {
if resolver.force_exclude() {
if let Some(filename) = cli.stdin_filename.as_deref() {
if !python_file_at_path(filename, &pyproject_config, overrides)? {
if !python_file_at_path(filename, &mut resolver, overrides)? {
if mode.is_write() {
parrot_stdin()?;
}
return Ok(ExitStatus::Success);
}

let format_settings = &pyproject_config.settings.formatter;
if filename
.file_name()
.is_some_and(|name| match_exclusion(filename, name, &format_settings.exclude))
{
if filename.file_name().is_some_and(|name| {
match_exclusion(filename, name, &resolver.base_settings().formatter.exclude)
}) {
if mode.is_write() {
parrot_stdin()?;
}
Expand All @@ -63,12 +62,7 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
};

// Format the file.
match format_source_code(
path,
&pyproject_config.settings.formatter,
source_type,
mode,
) {
match format_source_code(path, &resolver.base_settings().formatter, source_type, mode) {
Ok(result) => match mode {
FormatMode::Write => Ok(ExitStatus::Success),
FormatMode::Check | FormatMode::Diff => {
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_cli/src/commands/show_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub(crate) fn show_settings(
bail!("No files found under the given path");
};

let settings = resolver.resolve(&path, pyproject_config);
let settings = resolver.resolve(&path);

writeln!(writer, "Resolved settings for: {path:?}")?;
if let Some(settings_path) = pyproject_config.path.as_ref() {
Expand Down
Loading

0 comments on commit 4a3bb67

Please sign in to comment.