Introduce LinterSettings

## 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`
This commit is contained in:
Micha Reiser 2023-09-20 17:02:34 +02:00 committed by GitHub
parent 222f1c37b8
commit b34278e0cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
101 changed files with 753 additions and 716 deletions

View file

@ -65,7 +65,7 @@ pub(crate) fn add_noqa(
return None;
}
};
match add_noqa_to_path(path, package, &source_kind, source_type, settings) {
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());

View file

@ -16,7 +16,7 @@ use rustc_hash::FxHashMap;
use ruff_diagnostics::Diagnostic;
use ruff_linter::message::Message;
use ruff_linter::registry::Rule;
use ruff_linter::settings::{flags, Settings};
use ruff_linter::settings::{flags, LinterSettings};
use ruff_linter::{fs, warn_user_once, IOError};
use ruff_python_ast::imports::ImportMap;
use ruff_source_file::SourceFileBuilder;
@ -119,7 +119,7 @@ pub(crate) fn check(
}
});
lint_path(path, package, settings, cache, noqa, autofix).map_err(|e| {
lint_path(path, package, &settings.linter, cache, noqa, autofix).map_err(|e| {
(Some(path.to_owned()), {
let mut error = e.to_string();
for cause in e.chain() {
@ -142,7 +142,7 @@ pub(crate) fn check(
.unwrap_or_else(|(path, message)| {
if let Some(path) = &path {
let settings = resolver.resolve(path, pyproject_config);
if settings.rules.enabled(Rule::IOError) {
if settings.linter.rules.enabled(Rule::IOError) {
let dummy =
SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish();
@ -195,7 +195,7 @@ pub(crate) fn check(
fn lint_path(
path: &Path,
package: Option<&Path>,
settings: &Settings,
settings: &LinterSettings,
cache: Option<&Cache>,
noqa: flags::Noqa,
autofix: flags::FixMode,
@ -238,7 +238,7 @@ mod test {
use ruff_linter::message::{Emitter, EmitterContext, TextEmitter};
use ruff_linter::registry::Rule;
use ruff_linter::settings::{flags, Settings};
use ruff_linter::settings::{flags, LinterSettings, Settings};
use ruff_workspace::resolver::{PyprojectConfig, PyprojectDiscoveryStrategy};
use crate::args::CliOverrides;
@ -268,7 +268,10 @@ mod test {
// Configure
let snapshot = format!("{}_{}", rule_code.noqa_code(), path);
// invalid pyproject.toml is not active by default
let settings = Settings::for_rules(vec![rule_code, Rule::InvalidPyprojectToml]);
let settings = Settings {
linter: LinterSettings::for_rules(vec![rule_code, Rule::InvalidPyprojectToml]),
..Settings::default()
};
let pyproject_config =
PyprojectConfig::new(PyprojectDiscoveryStrategy::Fixed, settings, None);

View file

@ -24,7 +24,7 @@ pub(crate) fn check_stdin(
}
}
let package_root = filename.and_then(Path::parent).and_then(|path| {
packaging::detect_package_root(path, &pyproject_config.settings.namespace_packages)
packaging::detect_package_root(path, &pyproject_config.settings.linter.namespace_packages)
});
let stdin = read_from_stdin()?;
let mut diagnostics = lint_stdin(

View file

@ -77,11 +77,12 @@ pub(crate) fn format(
let resolved_settings = resolver.resolve(path, &pyproject_config);
let preview = match resolved_settings.preview {
// TODO(micha): Use `formatter` settings instead
let preview = match resolved_settings.linter.preview {
PreviewMode::Enabled => ruff_python_formatter::PreviewMode::Enabled,
PreviewMode::Disabled => ruff_python_formatter::PreviewMode::Disabled,
};
let line_length = resolved_settings.line_length;
let line_length = resolved_settings.linter.line_length;
let options = PyFormatOptions::from_source_type(source_type)
.with_line_width(LineWidth::from(NonZeroU16::from(line_length)))

View file

@ -39,11 +39,12 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
// Format the file.
let path = cli.stdin_filename.as_deref();
let preview = match pyproject_config.settings.preview {
// TODO(micha): Use Formatter settings
let preview = match pyproject_config.settings.linter.preview {
PreviewMode::Enabled => ruff_python_formatter::PreviewMode::Enabled,
PreviewMode::Disabled => ruff_python_formatter::PreviewMode::Disabled,
};
let line_length = pyproject_config.settings.line_length;
let line_length = pyproject_config.settings.linter.line_length;
let options = path
.map(PyFormatOptions::from_extension)