Use references instead of cloning
This commit is contained in:
238
src/main.rs
238
src/main.rs
@@ -77,10 +77,16 @@ impl LintLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Debug)]
|
||||||
|
struct Lint<'a> {
|
||||||
|
id: LintId<'a>,
|
||||||
|
group: LintGroup,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
#[expect(dead_code, reason = "this is an external data definition")]
|
#[expect(dead_code, reason = "this is an external data definition")]
|
||||||
struct Lint {
|
struct LintResponse {
|
||||||
id: LintId,
|
id: String,
|
||||||
group: LintGroup,
|
group: LintGroup,
|
||||||
#[serde(rename = "level")]
|
#[serde(rename = "level")]
|
||||||
default_level: LintLevel,
|
default_level: LintLevel,
|
||||||
@@ -93,26 +99,41 @@ enum PrioritySetting {
|
|||||||
Unspecified,
|
Unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
|
impl From<Option<isize>> for PrioritySetting {
|
||||||
struct LintId(String);
|
fn from(value: Option<isize>) -> Self {
|
||||||
|
match value {
|
||||||
|
Some(i) => Self::Explicit(i),
|
||||||
|
None => Self::Unspecified,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for LintId {
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
|
struct LintId<'a>(&'a str);
|
||||||
|
|
||||||
|
impl From<&'static str> for LintId<'static> {
|
||||||
|
fn from(value: &'static str) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LintId<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LintList(Vec<LintId>);
|
struct LintList<'a>(Vec<LintId<'a>>);
|
||||||
|
|
||||||
impl From<Vec<&str>> for LintList {
|
impl<'a> From<Vec<&'a str>> for LintList<'a> {
|
||||||
fn from(value: Vec<&str>) -> Self {
|
fn from(value: Vec<&'a str>) -> Self {
|
||||||
Self(value.into_iter().map(|s| LintId(s.to_owned())).collect())
|
Self(value.into_iter().map(|s| LintId(s)).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SingleLintConfig {
|
struct SingleLintConfig<'a> {
|
||||||
lint: LintId,
|
lint: &'a LintId<'a>,
|
||||||
priority: PrioritySetting,
|
priority: PrioritySetting,
|
||||||
level: LintLevel,
|
level: LintLevel,
|
||||||
}
|
}
|
||||||
@@ -125,8 +146,8 @@ struct GroupConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Setting {
|
enum Setting<'a> {
|
||||||
Single(SingleLintConfig),
|
Single(SingleLintConfig<'a>),
|
||||||
Group(GroupConfig),
|
Group(GroupConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,38 +158,37 @@ enum ExhaustiveGroupClassification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ExhausiveGroup {
|
struct ExhausiveGroup<'a> {
|
||||||
defaults: Vec<Setting>,
|
defaults: Vec<Setting<'a>>,
|
||||||
exceptions: Vec<Setting>,
|
exceptions: Vec<Setting<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Exceptions {
|
struct Exceptions<'a> {
|
||||||
level: LintLevel,
|
level: LintLevel,
|
||||||
lints: LintList,
|
lints: LintList<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Setting {
|
impl<'a> Setting<'a> {
|
||||||
fn set_group(group: LintGroup, priority: PrioritySetting, level: LintLevel) -> Self {
|
fn group(group: LintGroup, level: LintLevel, priority: impl Into<PrioritySetting>) -> Self {
|
||||||
Self::Group(GroupConfig {
|
Self::Group(GroupConfig {
|
||||||
group,
|
group,
|
||||||
priority,
|
priority: priority.into(),
|
||||||
level,
|
level,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn warn_group(group: LintGroup, priority: PrioritySetting) -> Self {
|
|
||||||
Self::set_group(group, priority, LintLevel::Warn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deny_group(group: LintGroup, priority: PrioritySetting) -> Self {
|
fn allow(
|
||||||
Self::set_group(group, priority, LintLevel::Deny)
|
all_lints: &'a AllLints,
|
||||||
}
|
group: LintGroup,
|
||||||
|
lints: &'a [LintId<'a>],
|
||||||
fn allow(response: &Response, group: LintGroup, lints: &[&str]) -> Result<Vec<Self>> {
|
) -> Result<Vec<Self>> {
|
||||||
lints
|
lints
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lint| {
|
.map(|lint| {
|
||||||
let lint = LintId((*lint).to_owned());
|
let found = all_lints
|
||||||
let found = response.0.iter().find(|r| r.id == lint && r.group == group);
|
.0
|
||||||
|
.iter()
|
||||||
|
.find(|r| r.id == *lint && r.group == group);
|
||||||
if found.is_none() {
|
if found.is_none() {
|
||||||
Err(anyhow!("lint {} not in group {}", lint, group.as_str()))
|
Err(anyhow!("lint {} not in group {}", lint, group.as_str()))
|
||||||
} else {
|
} else {
|
||||||
@@ -183,37 +203,32 @@ impl Setting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn split_group_exhaustive(
|
fn split_group_exhaustive(
|
||||||
response: &Response,
|
all_lints: &'a AllLints,
|
||||||
group: LintGroup,
|
group: LintGroup,
|
||||||
default_level: LintLevel,
|
default_level: LintLevel,
|
||||||
exceptions: &Exceptions,
|
exceptions: &Exceptions<'a>,
|
||||||
) -> Result<ExhausiveGroup> {
|
) -> Result<ExhausiveGroup<'a>> {
|
||||||
let all_lints_in_group: Vec<LintId> = response
|
let all_lints_in_group: Vec<&LintId> = all_lints
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|lint| {
|
.filter(|lint| lint.group == group)
|
||||||
if lint.group == group {
|
.map(|lint| &lint.id)
|
||||||
Some(lint.id.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(err) = exceptions.lints.0.iter().find_map(|lint| {
|
let all_lints_in_group_len = all_lints_in_group.len();
|
||||||
if !all_lints_in_group.contains(lint) {
|
|
||||||
Some(anyhow!("lint {lint} not part of group {group}"))
|
exceptions
|
||||||
} else {
|
.lints
|
||||||
None
|
.0
|
||||||
}
|
.iter()
|
||||||
}) {
|
.find(|lint| (!all_lints_in_group.contains(lint)))
|
||||||
return Err(err);
|
.map(|lint| Err(anyhow!("lint {lint} not part of group {group}")))
|
||||||
};
|
.unwrap_or(Ok(()))?;
|
||||||
|
|
||||||
Ok(all_lints_in_group
|
Ok(all_lints_in_group
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|lint| {
|
.map(|lint| {
|
||||||
if exceptions.lints.0.contains(&lint) {
|
if exceptions.lints.0.contains(lint) {
|
||||||
(
|
(
|
||||||
ExhaustiveGroupClassification::Exception,
|
ExhaustiveGroupClassification::Exception,
|
||||||
Self::Single(SingleLintConfig {
|
Self::Single(SingleLintConfig {
|
||||||
@@ -234,9 +249,16 @@ impl Setting {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fold(
|
.fold(
|
||||||
ExhausiveGroup {
|
{
|
||||||
defaults: Vec::new(),
|
let len_1 = exceptions.lints.0.len();
|
||||||
exceptions: Vec::new(),
|
ExhausiveGroup {
|
||||||
|
defaults: Vec::with_capacity(
|
||||||
|
all_lints_in_group_len.checked_sub(len_1).expect(
|
||||||
|
"exceptions are a subset of of all lints in group, checked above",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
exceptions: Vec::with_capacity(len_1),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|mut acc, (classification, setting)| {
|
|mut acc, (classification, setting)| {
|
||||||
match classification {
|
match classification {
|
||||||
@@ -250,15 +272,15 @@ impl Setting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ConfigGroup {
|
struct ConfigGroup<'a> {
|
||||||
comment: Option<String>,
|
comment: Option<String>,
|
||||||
settings: Vec<Setting>,
|
settings: Vec<Setting<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Config(Vec<ConfigGroup>);
|
struct Config<'a>(Vec<ConfigGroup<'a>>);
|
||||||
|
|
||||||
impl Config {
|
impl Config<'_> {
|
||||||
fn to_toml(&self, args: &Args) -> String {
|
fn to_toml(&self, args: &Args) -> String {
|
||||||
let mut output = if args.workspace {
|
let mut output = if args.workspace {
|
||||||
String::from("[workspace.lints.clippy]\n")
|
String::from("[workspace.lints.clippy]\n")
|
||||||
@@ -330,17 +352,37 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Response(Vec<Lint>);
|
struct Response(Vec<LintResponse>);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct AllLints<'a>(Vec<Lint<'a>>);
|
||||||
|
|
||||||
|
impl<'a> AllLints<'a> {
|
||||||
|
fn from_response(response: &'a Response) -> Self {
|
||||||
|
Self(
|
||||||
|
response
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|lint| Lint {
|
||||||
|
id: LintId(&lint.id),
|
||||||
|
group: lint.group,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let response: Response = ureq::get("https://rust-lang.github.io/rust-clippy/stable/lints.json")
|
let response: Response = ureq::get("https://rust-lang.github.io/rust-clippy/stable/lints.json")
|
||||||
.call()?
|
.call()?
|
||||||
.into_json()?;
|
.into_json::<Response>()?;
|
||||||
|
|
||||||
|
let all_lints = AllLints::from_response(&response);
|
||||||
|
|
||||||
let restriction_group = Setting::split_group_exhaustive(
|
let restriction_group = Setting::split_group_exhaustive(
|
||||||
&response,
|
&all_lints,
|
||||||
LintGroup::Restriction,
|
LintGroup::Restriction,
|
||||||
LintLevel::Allow,
|
LintLevel::Allow,
|
||||||
&Exceptions {
|
&Exceptions {
|
||||||
@@ -429,60 +471,62 @@ fn main() -> Result<()> {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let cargo_lints = {
|
||||||
|
let mut v = vec!["multiple_crate_versions".into()];
|
||||||
|
match args.profile {
|
||||||
|
Profile::Publish => (),
|
||||||
|
Profile::Personal => v.push("cargo_common_metadata".into()),
|
||||||
|
}
|
||||||
|
v
|
||||||
|
};
|
||||||
|
|
||||||
|
let pedantic_allows = &[
|
||||||
|
"too_many_lines".into(),
|
||||||
|
"must_use_candidate".into(),
|
||||||
|
"map_unwrap_or".into(),
|
||||||
|
"missing_errors_doc".into(),
|
||||||
|
"if_not_else".into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let nursery_allows = &["missing_const_for_fn".into(), "option_if_let_else".into()];
|
||||||
|
|
||||||
|
let complexity_allows = &["too_many_arguments".into()];
|
||||||
|
|
||||||
|
let style_allows = &["new_without_default".into(), "redundant_closure".into()];
|
||||||
|
|
||||||
let config = Config(vec![
|
let config = Config(vec![
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("enabled groups".to_owned()),
|
comment: Some("enabled groups".to_owned()),
|
||||||
settings: vec![
|
settings: vec![
|
||||||
Setting::deny_group(LintGroup::Correctness, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Correctness, LintLevel::Deny, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Suspicious, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Suspicious, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Style, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Style, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Complexity, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Complexity, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Perf, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Perf, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Cargo, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Cargo, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Pedantic, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Pedantic, LintLevel::Warn, Some(-1)),
|
||||||
Setting::warn_group(LintGroup::Nursery, PrioritySetting::Explicit(-1)),
|
Setting::group(LintGroup::Nursery, LintLevel::Warn, Some(-1)),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("pedantic overrides".to_owned()),
|
comment: Some("pedantic overrides".to_owned()),
|
||||||
settings: Setting::allow(
|
settings: Setting::allow(&all_lints, LintGroup::Pedantic, pedantic_allows)?,
|
||||||
&response,
|
|
||||||
LintGroup::Pedantic,
|
|
||||||
&[
|
|
||||||
"too_many_lines",
|
|
||||||
"must_use_candidate",
|
|
||||||
"map_unwrap_or",
|
|
||||||
"missing_errors_doc",
|
|
||||||
"if_not_else",
|
|
||||||
],
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("nursery overrides".to_owned()),
|
comment: Some("nursery overrides".to_owned()),
|
||||||
settings: Setting::allow(
|
settings: Setting::allow(&all_lints, LintGroup::Nursery, nursery_allows)?,
|
||||||
&response,
|
|
||||||
LintGroup::Nursery,
|
|
||||||
&["missing_const_for_fn", "option_if_let_else"],
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("complexity overrides".to_owned()),
|
comment: Some("complexity overrides".to_owned()),
|
||||||
settings: Setting::allow(&response, LintGroup::Complexity, &["too_many_arguments"])?,
|
settings: Setting::allow(&all_lints, LintGroup::Complexity, complexity_allows)?,
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("style overrides".to_owned()),
|
comment: Some("style overrides".to_owned()),
|
||||||
settings: Setting::allow(&response, LintGroup::Style, &["new_without_default"])?,
|
settings: Setting::allow(&all_lints, LintGroup::Style, style_allows)?,
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("cargo overrides".to_owned()),
|
comment: Some("cargo overrides".to_owned()),
|
||||||
settings: Setting::allow(&response, LintGroup::Cargo, &{
|
settings: Setting::allow(&all_lints, LintGroup::Cargo, &cargo_lints)?,
|
||||||
let mut v = vec!["multiple_crate_versions"];
|
|
||||||
match args.profile {
|
|
||||||
Profile::Publish => (),
|
|
||||||
Profile::Personal => v.push("cargo_common_metadata"),
|
|
||||||
}
|
|
||||||
v
|
|
||||||
})?,
|
|
||||||
},
|
},
|
||||||
ConfigGroup {
|
ConfigGroup {
|
||||||
comment: Some("selected restrictions".to_owned()),
|
comment: Some("selected restrictions".to_owned()),
|
||||||
|
|||||||
Reference in New Issue
Block a user