Skip to content

Commit

Permalink
Add diagnostic_item_path lint
Browse files Browse the repository at this point in the history
  • Loading branch information
smoelius committed Oct 1, 2022
1 parent 3619092 commit 7a22c07
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 0 deletions.
1 change: 1 addition & 0 deletions clippy_lints/src/lib.register_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS),
LintId::of(utils::internal_lints::DEFAULT_DEPRECATION_REASON),
LintId::of(utils::internal_lints::DEFAULT_LINT),
LintId::of(utils::internal_lints::DIAGNOSTIC_ITEM_PATH),
LintId::of(utils::internal_lints::IF_CHAIN_STYLE),
LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL),
LintId::of(utils::internal_lints::INVALID_CLIPPY_VERSION_ATTRIBUTE),
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.register_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ store.register_lints(&[
#[cfg(feature = "internal")]
utils::internal_lints::DEFAULT_LINT,
#[cfg(feature = "internal")]
utils::internal_lints::DIAGNOSTIC_ITEM_PATH,
#[cfg(feature = "internal")]
utils::internal_lints::IF_CHAIN_STYLE,
#[cfg(feature = "internal")]
utils::internal_lints::INTERNING_DEFINED_SYMBOL,
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce));
store.register_late_pass(|_| Box::new(utils::internal_lints::CollapsibleCalls));
store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
store.register_late_pass(|_| Box::new(utils::internal_lints::DiagnosticItemPath));
store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle));
store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths));
store.register_late_pass(|_| Box::<utils::internal_lints::InterningDefinedSymbol>::default());
Expand Down
3 changes: 3 additions & 0 deletions clippy_lints/src/utils/internal_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ pub use collapsible_calls::{CollapsibleCalls, COLLAPSIBLE_SPAN_LINT_CALLS};
mod compiler_lint_functions;
pub use compiler_lint_functions::{CompilerLintFunctions, COMPILER_LINT_FUNCTIONS};

mod diagnostic_item_path;
pub use diagnostic_item_path::{DiagnosticItemPath, DIAGNOSTIC_ITEM_PATH};

mod if_chain_style;
pub use if_chain_style::{IfChainStyle, IF_CHAIN_STYLE};

Expand Down
50 changes: 50 additions & 0 deletions clippy_lints/src/utils/internal_lints/diagnostic_item_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use clippy_utils::def_path_res;
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::LitKind;
use rustc_hir::{def::Res, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
/// ### What it does
/// Checks for hardcoded paths to diagnostic items.
///
/// ### Why is this bad?
/// See: https://github.com/rust-lang/rust-clippy/issues/5393
#[clippy::version = "1.66.0"]
pub DIAGNOSTIC_ITEM_PATH,
internal,
"hardcoded paths to diagnostic items"
}

declare_lint_pass!(DiagnosticItemPath => [DIAGNOSTIC_ITEM_PATH]);

impl LateLintPass<'_> for DiagnosticItemPath {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Array(elements) = expr.kind
&& let Some(path) = elements
.iter()
.map(|element| {
if let ExprKind::Lit(lit) = &element.kind
&& let LitKind::Str(s, _) = lit.node
{
Some(s.as_str().to_owned())
} else {
None
}
})
.collect::<Option<Vec<_>>>()
&& let Res::Def(_, def_id) = def_path_res(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>())
&& let Some(sym) = cx.tcx.get_diagnostic_name(def_id)
{
span_lint_and_help(
cx,
DIAGNOSTIC_ITEM_PATH,
expr.span,
"hardcoded path to a diagnostic item",
None,
&format!("rewrite the code to use `sym::{sym}`"),
);
}
}
}
11 changes: 11 additions & 0 deletions tests/ui-internal/diagnostic_item_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![allow(unused)]
#![warn(clippy::diagnostic_item_path)]

fn main() {
const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];

const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];

// Not yet a diagnostic item
const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
}
19 changes: 19 additions & 0 deletions tests/ui-internal/diagnostic_item_path.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error: hardcoded path to a diagnostic item
--> $DIR/diagnostic_item_path.rs:5:36
|
LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::diagnostic-item-path` implied by `-D warnings`
= help: rewrite the code to use `sym::Deref`

error: hardcoded path to a diagnostic item
--> $DIR/diagnostic_item_path.rs:7:43
|
LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: rewrite the code to use `sym::deref_method`

error: aborting due to 2 previous errors

0 comments on commit 7a22c07

Please sign in to comment.