d647696c1f
So, some context for this, well, more a story. I'm not used to scripting, I've never really scripted anything, even if it's a valuable skill. I just never really needed it. Now, `@flip1995` correctly suggested using a script for this in `rust-clippy#7813`... And I decided to write a script using nushell because why not? This was a mistake... I spend way more time on this than I would like to admit. It has definitely been more than 4 hours. It shouldn't take that long, but me being new to scripting and nushell just wasn't a good mixture... Anyway, here is the script that creates another script which adds the versions. Fun... Just execute this on the `gh-pages` branch and the resulting `replacer.sh` in `clippy_lints` and it should all work. ```nu mv v0.0.212 rust-1.00.0; mv beta rust-1.57.0; mv master rust-1.58.0; let paths = (open ./rust-1.58.0/lints.json | select id id_span | flatten | select id path); let versions = ( ls | where name =~ "rust-" | select name | format {name}/lints.json | each { open $it | select id | insert version $it | str substring "5,11" version} | group-by id | rotate counter-clockwise id version | update version {get version | first 1} | flatten | select id version); $paths | each { |row| let version = ($versions | where id == ($row.id) | format {version}) let idu = ($row.id | str upcase) $"sed -i '0,/($idu),/{s/pub ($idu),/#[clippy::version = "($version)"]\n pub ($idu),/}' ($row.path)" } | str collect ";" | str find-replace --all '1.00.0' 'pre 1.29.0' | save "replacer.sh"; ``` And this still has some problems, but at this point I just want to be done -.-
167 lines
5.0 KiB
Rust
167 lines
5.0 KiB
Rust
use clippy_utils::diagnostics::span_lint_and_help;
|
|
use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
|
|
use rustc_hir::CRATE_HIR_ID;
|
|
use rustc_lint::{LateContext, LateLintPass};
|
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
|
use rustc_span::source_map::DUMMY_SP;
|
|
|
|
declare_clippy_lint! {
|
|
/// ### What it does
|
|
/// Checks for feature names with prefix `use-`, `with-` or suffix `-support`
|
|
///
|
|
/// ### Why is this bad?
|
|
/// These prefixes and suffixes have no significant meaning.
|
|
///
|
|
/// ### Example
|
|
/// ```toml
|
|
/// # The `Cargo.toml` with feature name redundancy
|
|
/// [features]
|
|
/// default = ["use-abc", "with-def", "ghi-support"]
|
|
/// use-abc = [] // redundant
|
|
/// with-def = [] // redundant
|
|
/// ghi-support = [] // redundant
|
|
/// ```
|
|
///
|
|
/// Use instead:
|
|
/// ```toml
|
|
/// [features]
|
|
/// default = ["abc", "def", "ghi"]
|
|
/// abc = []
|
|
/// def = []
|
|
/// ghi = []
|
|
/// ```
|
|
///
|
|
#[clippy::version = "1.57.0"]
|
|
pub REDUNDANT_FEATURE_NAMES,
|
|
cargo,
|
|
"usage of a redundant feature name"
|
|
}
|
|
|
|
declare_clippy_lint! {
|
|
/// ### What it does
|
|
/// Checks for negative feature names with prefix `no-` or `not-`
|
|
///
|
|
/// ### Why is this bad?
|
|
/// Features are supposed to be additive, and negatively-named features violate it.
|
|
///
|
|
/// ### Example
|
|
/// ```toml
|
|
/// # The `Cargo.toml` with negative feature names
|
|
/// [features]
|
|
/// default = []
|
|
/// no-abc = []
|
|
/// not-def = []
|
|
///
|
|
/// ```
|
|
/// Use instead:
|
|
/// ```toml
|
|
/// [features]
|
|
/// default = ["abc", "def"]
|
|
/// abc = []
|
|
/// def = []
|
|
///
|
|
/// ```
|
|
#[clippy::version = "1.57.0"]
|
|
pub NEGATIVE_FEATURE_NAMES,
|
|
cargo,
|
|
"usage of a negative feature name"
|
|
}
|
|
|
|
declare_lint_pass!(FeatureName => [REDUNDANT_FEATURE_NAMES, NEGATIVE_FEATURE_NAMES]);
|
|
|
|
static PREFIXES: [&str; 8] = ["no-", "no_", "not-", "not_", "use-", "use_", "with-", "with_"];
|
|
static SUFFIXES: [&str; 2] = ["-support", "_support"];
|
|
|
|
fn is_negative_prefix(s: &str) -> bool {
|
|
s.starts_with("no")
|
|
}
|
|
|
|
fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
|
|
let is_negative = is_prefix && is_negative_prefix(substring);
|
|
span_lint_and_help(
|
|
cx,
|
|
if is_negative {
|
|
NEGATIVE_FEATURE_NAMES
|
|
} else {
|
|
REDUNDANT_FEATURE_NAMES
|
|
},
|
|
DUMMY_SP,
|
|
&format!(
|
|
"the \"{}\" {} in the feature name \"{}\" is {}",
|
|
substring,
|
|
if is_prefix { "prefix" } else { "suffix" },
|
|
feature,
|
|
if is_negative { "negative" } else { "redundant" }
|
|
),
|
|
None,
|
|
&format!(
|
|
"consider renaming the feature to \"{}\"{}",
|
|
if is_prefix {
|
|
feature.strip_prefix(substring)
|
|
} else {
|
|
feature.strip_suffix(substring)
|
|
}
|
|
.unwrap(),
|
|
if is_negative {
|
|
", but make sure the feature adds functionality"
|
|
} else {
|
|
""
|
|
}
|
|
),
|
|
);
|
|
}
|
|
|
|
impl LateLintPass<'_> for FeatureName {
|
|
fn check_crate(&mut self, cx: &LateContext<'_>) {
|
|
if is_lint_allowed(cx, REDUNDANT_FEATURE_NAMES, CRATE_HIR_ID)
|
|
&& is_lint_allowed(cx, NEGATIVE_FEATURE_NAMES, CRATE_HIR_ID)
|
|
{
|
|
return;
|
|
}
|
|
|
|
let metadata = unwrap_cargo_metadata!(cx, REDUNDANT_FEATURE_NAMES, false);
|
|
|
|
for package in metadata.packages {
|
|
let mut features: Vec<&String> = package.features.keys().collect();
|
|
features.sort();
|
|
for feature in features {
|
|
let prefix_opt = {
|
|
let i = PREFIXES.partition_point(|prefix| prefix < &feature.as_str());
|
|
if i > 0 && feature.starts_with(PREFIXES[i - 1]) {
|
|
Some(PREFIXES[i - 1])
|
|
} else {
|
|
None
|
|
}
|
|
};
|
|
if let Some(prefix) = prefix_opt {
|
|
lint(cx, feature, prefix, true);
|
|
}
|
|
|
|
let suffix_opt: Option<&str> = {
|
|
let i = SUFFIXES.partition_point(|suffix| {
|
|
suffix.bytes().rev().cmp(feature.bytes().rev()) == std::cmp::Ordering::Less
|
|
});
|
|
if i > 0 && feature.ends_with(SUFFIXES[i - 1]) {
|
|
Some(SUFFIXES[i - 1])
|
|
} else {
|
|
None
|
|
}
|
|
};
|
|
if let Some(suffix) = suffix_opt {
|
|
lint(cx, feature, suffix, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_prefixes_sorted() {
|
|
let mut sorted_prefixes = PREFIXES;
|
|
sorted_prefixes.sort_unstable();
|
|
assert_eq!(PREFIXES, sorted_prefixes);
|
|
let mut sorted_suffixes = SUFFIXES;
|
|
sorted_suffixes.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev()));
|
|
assert_eq!(SUFFIXES, sorted_suffixes);
|
|
}
|