use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir::HirId;
use rustc_lint::{LateContext, Lint, LintContext};
use rustc_span::source_map::Span;
use std::env;
fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
diag.help(&format!(
"for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
&option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
format!("rust-{}", n.rsplit_once('.').unwrap().1)
})
));
}
}
}
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
cx.struct_span_lint(lint, sp, msg, |diag| {
docs_link(diag, lint);
diag
});
}
pub fn span_lint_and_help<T: LintContext>(
cx: &T,
lint: &'static Lint,
span: impl Into<MultiSpan>,
msg: &str,
help_span: Option<Span>,
help: &str,
) {
cx.struct_span_lint(lint, span, msg, |diag| {
if let Some(help_span) = help_span {
diag.span_help(help_span, help);
} else {
diag.help(help);
}
docs_link(diag, lint);
diag
});
}
pub fn span_lint_and_note<T: LintContext>(
cx: &T,
lint: &'static Lint,
span: impl Into<MultiSpan>,
msg: &str,
note_span: Option<Span>,
note: &str,
) {
cx.struct_span_lint(lint, span, msg, |diag| {
if let Some(note_span) = note_span {
diag.span_note(note_span, note);
} else {
diag.note(note);
}
docs_link(diag, lint);
diag
});
}
pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F)
where
C: LintContext,
S: Into<MultiSpan>,
F: FnOnce(&mut Diagnostic),
{
cx.struct_span_lint(lint, sp, msg, |diag| {
f(diag);
docs_link(diag, lint);
diag
});
}
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
docs_link(diag, lint);
diag
});
}
pub fn span_lint_hir_and_then(
cx: &LateContext<'_>,
lint: &'static Lint,
hir_id: HirId,
sp: impl Into<MultiSpan>,
msg: &str,
f: impl FnOnce(&mut Diagnostic),
) {
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
f(diag);
docs_link(diag, lint);
diag
});
}
#[cfg_attr(feature = "internal", allow(clippy::collapsible_span_lint_calls))]
pub fn span_lint_and_sugg<T: LintContext>(
cx: &T,
lint: &'static Lint,
sp: Span,
msg: &str,
help: &str,
sugg: String,
applicability: Applicability,
) {
span_lint_and_then(cx, lint, sp, msg, |diag| {
diag.span_suggestion(sp, help, sugg, applicability);
});
}
pub fn multispan_sugg<I>(diag: &mut Diagnostic, help_msg: &str, sugg: I)
where
I: IntoIterator<Item = (Span, String)>,
{
multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg);
}
pub fn multispan_sugg_with_applicability<I>(
diag: &mut Diagnostic,
help_msg: &str,
applicability: Applicability,
sugg: I,
) where
I: IntoIterator<Item = (Span, String)>,
{
diag.multipart_suggestion(help_msg, sugg.into_iter().collect(), applicability);
}