| use clippy_utils::diagnostics::span_lint_and_help; |
| use rustc_ast::ast::{GenericParam, GenericParamKind}; |
| use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; |
| use rustc_middle::lint::in_external_macro; |
| use rustc_session::{declare_lint_pass, declare_tool_lint}; |
| |
| declare_clippy_lint! { |
| /// ### What it does |
| /// Checks for lifetimes with names which are one character |
| /// long. |
| /// |
| /// ### Why is this bad? |
| /// A single character is likely not enough to express the |
| /// purpose of a lifetime. Using a longer name can make code |
| /// easier to understand, especially for those who are new to |
| /// Rust. |
| /// |
| /// ### Known problems |
| /// Rust programmers and learning resources tend to use single |
| /// character lifetimes, so this lint is at odds with the |
| /// ecosystem at large. In addition, the lifetime's purpose may |
| /// be obvious or, rarely, expressible in one character. |
| /// |
| /// ### Example |
| /// ```no_run |
| /// struct DiagnosticCtx<'a> { |
| /// source: &'a str, |
| /// } |
| /// ``` |
| /// Use instead: |
| /// ```no_run |
| /// struct DiagnosticCtx<'src> { |
| /// source: &'src str, |
| /// } |
| /// ``` |
| #[clippy::version = "1.60.0"] |
| pub SINGLE_CHAR_LIFETIME_NAMES, |
| restriction, |
| "warns against single-character lifetime names" |
| } |
| |
| declare_lint_pass!(SingleCharLifetimeNames => [SINGLE_CHAR_LIFETIME_NAMES]); |
| |
| impl EarlyLintPass for SingleCharLifetimeNames { |
| fn check_generic_param(&mut self, ctx: &EarlyContext<'_>, param: &GenericParam) { |
| if in_external_macro(ctx.sess(), param.ident.span) { |
| return; |
| } |
| |
| if let GenericParamKind::Lifetime = param.kind { |
| if !param.is_placeholder && param.ident.as_str().len() <= 2 { |
| span_lint_and_help( |
| ctx, |
| SINGLE_CHAR_LIFETIME_NAMES, |
| param.ident.span, |
| "single-character lifetime names are likely uninformative", |
| None, |
| "use a more informative name", |
| ); |
| } |
| } |
| } |
| } |