Minimizing changes
This commit is contained in:
parent
f9c1d155b4
commit
2a4571d959
|
@ -331,8 +331,11 @@ mod zero_div_zero;
|
|||
mod zero_sized_map_values;
|
||||
// end lints modules, do not remove this comment, it’s used in `update_lints`
|
||||
|
||||
use crate::utils::conf::{format_error, TryConf};
|
||||
pub use crate::utils::conf::{lookup_conf_file, Conf};
|
||||
use crate::utils::{
|
||||
conf::{format_error, metadata::get_configuration_metadata, TryConf},
|
||||
FindAll,
|
||||
};
|
||||
|
||||
/// Register all pre expansion lints
|
||||
///
|
||||
|
@ -388,7 +391,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>
|
|||
conf
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default)] //~ ERROR no such field
|
||||
struct RegistrationGroups {
|
||||
all: Vec<LintId>,
|
||||
cargo: Vec<LintId>,
|
||||
|
@ -471,7 +474,22 @@ pub(crate) struct LintInfo {
|
|||
pub fn explain(name: &str) {
|
||||
let target = format!("clippy::{}", name.to_ascii_uppercase());
|
||||
match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
|
||||
Some(info) => print!("{}", info.explanation),
|
||||
Some(info) => {
|
||||
println!("{}", info.explanation);
|
||||
// Check if the lint has configuration
|
||||
let mdconf = get_configuration_metadata();
|
||||
if let Some(config_vec_positions) = mdconf
|
||||
.iter()
|
||||
.find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
|
||||
{
|
||||
// If it has, print it
|
||||
println!("### Configuration for {}:", info.lint.name_lower());
|
||||
for position in config_vec_positions {
|
||||
let conf = &mdconf[position];
|
||||
println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default);
|
||||
}
|
||||
}
|
||||
},
|
||||
None => println!("unknown lint: {name}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,16 +174,15 @@ macro_rules! define_Conf {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "internal")]
|
||||
pub mod metadata {
|
||||
use crate::utils::internal_lints::metadata_collector::ClippyConfiguration;
|
||||
use crate::utils::ClippyConfiguration;
|
||||
|
||||
macro_rules! wrap_option {
|
||||
() => (None);
|
||||
($x:literal) => (Some($x));
|
||||
}
|
||||
|
||||
pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
|
||||
pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
|
||||
vec![
|
||||
$(
|
||||
{
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
//! a simple mistake)
|
||||
|
||||
use crate::renamed_lints::RENAMED_LINTS;
|
||||
use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
|
||||
use crate::utils::{
|
||||
collect_configs,
|
||||
internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type},
|
||||
ClippyConfiguration,
|
||||
};
|
||||
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
|
||||
|
@ -520,111 +524,6 @@ impl Serialize for ApplicabilityInfo {
|
|||
}
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// Configuration
|
||||
// ==================================================================
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ClippyConfiguration {
|
||||
name: String,
|
||||
config_type: &'static str,
|
||||
default: String,
|
||||
lints: Vec<String>,
|
||||
doc: String,
|
||||
#[allow(dead_code)]
|
||||
deprecation_reason: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl ClippyConfiguration {
|
||||
pub fn new(
|
||||
name: &'static str,
|
||||
config_type: &'static str,
|
||||
default: String,
|
||||
doc_comment: &'static str,
|
||||
deprecation_reason: Option<&'static str>,
|
||||
) -> Self {
|
||||
let (lints, doc) = parse_config_field_doc(doc_comment)
|
||||
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
|
||||
|
||||
Self {
|
||||
name: to_kebab(name),
|
||||
lints,
|
||||
doc,
|
||||
config_type,
|
||||
default,
|
||||
deprecation_reason,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_markdown_paragraph(&self) -> String {
|
||||
format!(
|
||||
"### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
|
||||
self.name,
|
||||
self.doc
|
||||
.lines()
|
||||
.map(|line| line.strip_prefix(" ").unwrap_or(line))
|
||||
.join("\n"),
|
||||
self.default,
|
||||
self.config_type,
|
||||
self.lints
|
||||
.iter()
|
||||
.map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
|
||||
.map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
fn to_markdown_table_entry(&self) -> String {
|
||||
format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_configs() -> Vec<ClippyConfiguration> {
|
||||
crate::utils::conf::metadata::get_configuration_metadata()
|
||||
}
|
||||
|
||||
/// This parses the field documentation of the config struct.
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
|
||||
/// ```
|
||||
///
|
||||
/// Would yield:
|
||||
/// ```rust, ignore
|
||||
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
|
||||
/// ```
|
||||
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
|
||||
const DOC_START: &str = " Lint: ";
|
||||
if_chain! {
|
||||
if doc_comment.starts_with(DOC_START);
|
||||
if let Some(split_pos) = doc_comment.find('.');
|
||||
then {
|
||||
let mut doc_comment = doc_comment.to_string();
|
||||
let mut documentation = doc_comment.split_off(split_pos);
|
||||
|
||||
// Extract lints
|
||||
doc_comment.make_ascii_lowercase();
|
||||
let lints: Vec<String> = doc_comment
|
||||
.split_off(DOC_START.len())
|
||||
.split(", ")
|
||||
.map(str::to_string)
|
||||
.collect();
|
||||
|
||||
// Format documentation correctly
|
||||
// split off leading `.` from lint name list and indent for correct formatting
|
||||
documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
|
||||
|
||||
Some((lints, documentation))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
|
||||
fn to_kebab(config_name: &str) -> String {
|
||||
config_name.replace('_', "-")
|
||||
}
|
||||
|
||||
impl fmt::Display for ClippyConfiguration {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(
|
||||
|
|
|
@ -4,3 +4,143 @@ pub mod dump_hir;
|
|||
pub mod format_args_collector;
|
||||
#[cfg(feature = "internal")]
|
||||
pub mod internal_lints;
|
||||
#[cfg(feature = "internal")]
|
||||
use itertools::Itertools;
|
||||
|
||||
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
|
||||
fn to_kebab(config_name: &str) -> String {
|
||||
config_name.replace('_', "-")
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// Configuration
|
||||
// ==================================================================
|
||||
#[derive(Debug, Clone, Default)] //~ ERROR no such field
|
||||
pub struct ClippyConfiguration {
|
||||
pub name: String,
|
||||
#[allow(dead_code)]
|
||||
config_type: &'static str,
|
||||
pub default: String,
|
||||
pub lints: Vec<String>,
|
||||
pub doc: String,
|
||||
#[allow(dead_code)]
|
||||
deprecation_reason: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl ClippyConfiguration {
|
||||
pub fn new(
|
||||
name: &'static str,
|
||||
config_type: &'static str,
|
||||
default: String,
|
||||
doc_comment: &'static str,
|
||||
deprecation_reason: Option<&'static str>,
|
||||
) -> Self {
|
||||
let (lints, doc) = parse_config_field_doc(doc_comment)
|
||||
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
|
||||
|
||||
Self {
|
||||
name: to_kebab(name),
|
||||
lints,
|
||||
doc,
|
||||
config_type,
|
||||
default,
|
||||
deprecation_reason,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "internal")]
|
||||
fn to_markdown_paragraph(&self) -> String {
|
||||
format!(
|
||||
"### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
|
||||
self.name,
|
||||
self.doc
|
||||
.lines()
|
||||
.map(|line| line.strip_prefix(" ").unwrap_or(line))
|
||||
.join("\n"),
|
||||
self.default,
|
||||
self.config_type,
|
||||
self.lints
|
||||
.iter()
|
||||
.map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
|
||||
.map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "internal")]
|
||||
fn to_markdown_table_entry(&self) -> String {
|
||||
format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "internal")]
|
||||
fn collect_configs() -> Vec<ClippyConfiguration> {
|
||||
crate::utils::conf::metadata::get_configuration_metadata()
|
||||
}
|
||||
|
||||
/// This parses the field documentation of the config struct.
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
|
||||
/// ```
|
||||
///
|
||||
/// Would yield:
|
||||
/// ```rust, ignore
|
||||
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
|
||||
/// ```
|
||||
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
|
||||
const DOC_START: &str = " Lint: ";
|
||||
if_chain! {
|
||||
if doc_comment.starts_with(DOC_START);
|
||||
if let Some(split_pos) = doc_comment.find('.');
|
||||
then {
|
||||
let mut doc_comment = doc_comment.to_string();
|
||||
let mut documentation = doc_comment.split_off(split_pos);
|
||||
|
||||
// Extract lints
|
||||
doc_comment.make_ascii_lowercase();
|
||||
let lints: Vec<String> = doc_comment
|
||||
.split_off(DOC_START.len())
|
||||
.split(", ")
|
||||
.map(str::to_string)
|
||||
.collect();
|
||||
|
||||
// Format documentation correctly
|
||||
// split off leading `.` from lint name list and indent for correct formatting
|
||||
documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
|
||||
|
||||
Some((lints, documentation))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
|
||||
pub trait FindAll: Iterator + Sized {
|
||||
fn find_all<P>(&mut self, predicate: P) -> Option<Vec<usize>>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool;
|
||||
}
|
||||
|
||||
impl<I> FindAll for I
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
fn find_all<P>(&mut self, mut predicate: P) -> Option<Vec<usize>>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
let mut occurences = Vec::<usize>::default();
|
||||
for (index, element) in self.enumerate() {
|
||||
if predicate(&element) {
|
||||
occurences.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
match occurences.len() {
|
||||
0 => None,
|
||||
_ => Some(occurences),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue