Merge subsettings when extending configurations (#4431)

This commit is contained in:
Ben Doerry 2023-05-15 03:34:58 +01:00 committed by GitHub
parent f70c286e6a
commit d6930ca991
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 197 additions and 64 deletions

View file

@ -2,10 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::CacheKey;
use ruff_macros::ConfigurationOptions;
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
fn default_tmp_dirs() -> Vec<String> {
["/tmp", "/var/tmp", "/dev/shm"]
@ -10,7 +10,9 @@ fn default_tmp_dirs() -> Vec<String> {
.to_vec()
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -1,8 +1,10 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -3,7 +3,7 @@
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
("altair", "alt"),
@ -20,7 +20,9 @@ const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
("pyarrow", "pa"),
];
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use super::types;
@ -20,7 +20,9 @@ fn default_broad_exceptions() -> Vec<String> {
.to_vec()
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
@ -20,7 +20,9 @@ impl Default for Quote {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,13 +2,15 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
// By default, ignore the `namedtuple` methods and attributes, which are underscore-prefixed to
// prevent conflicts with field names.
const IGNORE_NAMES: [&str; 5] = ["_make", "_asdict", "_replace", "_fields", "_field_defaults"];
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -3,13 +3,15 @@
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use ruff_macros::ConfigurationOptions;
use ruff_macros::{CombineOptions, ConfigurationOptions};
use super::banned_api::ApiBan;
use super::relative_imports::Strictness;
use super::Settings;
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -2,9 +2,11 @@
use serde::{Deserialize, Serialize};
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -7,7 +7,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use crate::rules::isort::categorize::KnownModules;
use crate::rules::isort::ImportType;
@ -33,7 +33,9 @@ impl Default for RelativeImportsOrder {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -1,9 +1,11 @@
//! Settings for the `mccabe` plugin.
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -1,6 +1,6 @@
//! Settings for the `pep8-naming` plugin.
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use serde::{Deserialize, Serialize};
const IGNORE_NAMES: [&str; 12] = [
@ -18,7 +18,9 @@ const IGNORE_NAMES: [&str; 12] = [
"maxDiff",
];
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -1,9 +1,11 @@
//! Settings for the `pycodestyle` plugin.
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(deny_unknown_fields, rename_all = "kebab-case", rename = "Pycodestyle")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Options {

View file

@ -1,7 +1,7 @@
//! Settings for the `pydocstyle` plugin.
use crate::registry::Rule;
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
@ -68,7 +68,9 @@ impl Convention {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(deny_unknown_fields, rename_all = "kebab-case", rename = "Pydocstyle")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Options {

View file

@ -1,7 +1,7 @@
//! Settings for the `pylint` plugin.
use anyhow::anyhow;
use ruff_macros::{CacheKey, ConfigurationOptions};
use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
use rustpython_parser::ast::Constant;
use serde::{Deserialize, Serialize};
@ -35,7 +35,9 @@ impl TryFrom<&Constant> for ConstantType {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
#[derive(
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, CombineOptions,
)]
#[serde(
deny_unknown_fields,
rename_all = "kebab-case",

View file

@ -268,33 +268,53 @@ impl Configuration {
task_tags: self.task_tags.or(config.task_tags),
typing_modules: self.typing_modules.or(config.typing_modules),
// Plugins
flake8_annotations: self.flake8_annotations.or(config.flake8_annotations),
flake8_bandit: self.flake8_bandit.or(config.flake8_bandit),
flake8_bugbear: self.flake8_bugbear.or(config.flake8_bugbear),
flake8_builtins: self.flake8_builtins.or(config.flake8_builtins),
flake8_comprehensions: self.flake8_comprehensions.or(config.flake8_comprehensions),
flake8_errmsg: self.flake8_errmsg.or(config.flake8_errmsg),
flake8_gettext: self.flake8_gettext.or(config.flake8_gettext),
flake8_annotations: self.flake8_annotations.combine(config.flake8_annotations),
flake8_bandit: self.flake8_bandit.combine(config.flake8_bandit),
flake8_bugbear: self.flake8_bugbear.combine(config.flake8_bugbear),
flake8_builtins: self.flake8_builtins.combine(config.flake8_builtins),
flake8_comprehensions: self
.flake8_comprehensions
.combine(config.flake8_comprehensions),
flake8_errmsg: self.flake8_errmsg.combine(config.flake8_errmsg),
flake8_gettext: self.flake8_gettext.combine(config.flake8_gettext),
flake8_implicit_str_concat: self
.flake8_implicit_str_concat
.or(config.flake8_implicit_str_concat),
.combine(config.flake8_implicit_str_concat),
flake8_import_conventions: self
.flake8_import_conventions
.or(config.flake8_import_conventions),
flake8_pytest_style: self.flake8_pytest_style.or(config.flake8_pytest_style),
flake8_quotes: self.flake8_quotes.or(config.flake8_quotes),
flake8_self: self.flake8_self.or(config.flake8_self),
flake8_tidy_imports: self.flake8_tidy_imports.or(config.flake8_tidy_imports),
flake8_type_checking: self.flake8_type_checking.or(config.flake8_type_checking),
.combine(config.flake8_import_conventions),
flake8_pytest_style: self.flake8_pytest_style.combine(config.flake8_pytest_style),
flake8_quotes: self.flake8_quotes.combine(config.flake8_quotes),
flake8_self: self.flake8_self.combine(config.flake8_self),
flake8_tidy_imports: self.flake8_tidy_imports.combine(config.flake8_tidy_imports),
flake8_type_checking: self
.flake8_type_checking
.combine(config.flake8_type_checking),
flake8_unused_arguments: self
.flake8_unused_arguments
.or(config.flake8_unused_arguments),
isort: self.isort.or(config.isort),
mccabe: self.mccabe.or(config.mccabe),
pep8_naming: self.pep8_naming.or(config.pep8_naming),
pycodestyle: self.pycodestyle.or(config.pycodestyle),
pydocstyle: self.pydocstyle.or(config.pydocstyle),
pylint: self.pylint.or(config.pylint),
.combine(config.flake8_unused_arguments),
isort: self.isort.combine(config.isort),
mccabe: self.mccabe.combine(config.mccabe),
pep8_naming: self.pep8_naming.combine(config.pep8_naming),
pycodestyle: self.pycodestyle.combine(config.pycodestyle),
pydocstyle: self.pydocstyle.combine(config.pydocstyle),
pylint: self.pylint.combine(config.pylint),
}
}
}
pub trait CombinePluginOptions {
#[must_use]
fn combine(self, other: Self) -> Self;
}
impl<T: CombinePluginOptions> CombinePluginOptions for Option<T> {
fn combine(self, other: Self) -> Self {
match (self, other) {
(Some(base), Some(other)) => Some(base.combine(other)),
(Some(base), None) => Some(base),
(None, Some(other)) => Some(other),
(None, None) => None,
}
}
}

View file

@ -0,0 +1,62 @@
use quote::{quote, quote_spanned};
use syn::{Data, DataStruct, DeriveInput, Field, Fields, Path, PathSegment, Type, TypePath};
pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
let DeriveInput { ident, data, .. } = input;
match data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => {
let output = fields
.named
.iter()
.map(handle_field)
.collect::<Result<Vec<_>, _>>()?;
Ok(quote! {
use crate::settings::configuration::CombinePluginOptions;
impl CombinePluginOptions for #ident {
fn combine(self, other: Self) -> Self {
Self {
#(
#output
),*
}
}
}
})
}
_ => Err(syn::Error::new(
ident.span(),
"Can only derive CombineOptions from structs with named fields.",
)),
}
}
fn handle_field(field: &Field) -> syn::Result<proc_macro2::TokenStream> {
let ident = field
.ident
.as_ref()
.expect("Expected to handle named fields");
match &field.ty {
Type::Path(TypePath {
path: Path { segments, .. },
..
}) => match segments.first() {
Some(PathSegment {
ident: type_ident, ..
}) if type_ident == "Option" => Ok(quote_spanned!(
ident.span() => #ident: self.#ident.or(other.#ident)
)),
_ => Err(syn::Error::new(
ident.span(),
"Expected `Option<_>` or `Vec<_>` as type.",
)),
},
_ => Err(syn::Error::new(ident.span(), "Expected type.")),
}
}

View file

@ -5,6 +5,7 @@ use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, ItemFn, ItemStruct};
mod cache_key;
mod combine_options;
mod config;
mod derive_message_formats;
mod map_codes;
@ -22,6 +23,15 @@ pub fn derive_config(input: proc_macro::TokenStream) -> proc_macro::TokenStream
.into()
}
#[proc_macro_derive(CombineOptions)]
pub fn derive_combine_options(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
combine_options::derive_impl(input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
#[proc_macro_derive(CacheKey)]
pub fn cache_key(input: TokenStream) -> TokenStream {
let item = parse_macro_input!(input as DeriveInput);