Add a note to diagnostics why the rule is enabled (#17854)

This commit is contained in:
Micha Reiser 2025-05-06 20:29:03 +02:00 committed by GitHub
parent 9085f18353
commit b2de749c32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
86 changed files with 184 additions and 3 deletions

View file

@ -505,6 +505,10 @@ impl RuleSelection {
self.lints.get(&lint).map(|(severity, _)| *severity)
}
pub fn get(&self, lint: LintId) -> Option<(Severity, LintSource)> {
self.lints.get(&lint).copied()
}
/// Returns `true` if the `lint` is enabled.
pub fn is_enabled(&self, lint: LintId) -> bool {
self.severity(lint).is_some()

View file

@ -1,7 +1,7 @@
use std::fmt;
use drop_bomb::DebugDropBomb;
use ruff_db::diagnostic::DiagnosticTag;
use ruff_db::diagnostic::{DiagnosticTag, SubDiagnostic};
use ruff_db::{
diagnostic::{Annotation, Diagnostic, DiagnosticId, IntoDiagnosticMessage, Severity, Span},
files::File,
@ -10,6 +10,7 @@ use ruff_text_size::{Ranged, TextRange};
use super::{binding_type, Type, TypeCheckDiagnostics};
use crate::lint::LintSource;
use crate::semantic_index::symbol::ScopeId;
use crate::{
lint::{LintId, LintMetadata},
@ -222,6 +223,8 @@ pub(super) struct LintDiagnosticGuard<'db, 'ctx> {
///
/// This is always `Some` until the `Drop` impl.
diag: Option<Diagnostic>,
source: LintSource,
}
impl LintDiagnosticGuard<'_, '_> {
@ -310,7 +313,19 @@ impl Drop for LintDiagnosticGuard<'_, '_> {
// OK because the only way `self.diag` is `None`
// is via this impl, which can only run at most
// once.
let diag = self.diag.take().unwrap();
let mut diag = self.diag.take().unwrap();
diag.sub(SubDiagnostic::new(
Severity::Info,
match self.source {
LintSource::Default => format!("`{}` is enabled by default", diag.id()),
LintSource::Cli => format!("`{}` was selected on the command line", diag.id()),
LintSource::File => {
format!("`{}` was selected in the configuration file", diag.id())
}
},
));
self.ctx.diagnostics.borrow_mut().push(diag);
}
}
@ -345,6 +360,7 @@ pub(super) struct LintDiagnosticGuardBuilder<'db, 'ctx> {
ctx: &'ctx InferContext<'db>,
id: DiagnosticId,
severity: Severity,
source: LintSource,
primary_span: Span,
}
@ -371,7 +387,7 @@ impl<'db, 'ctx> LintDiagnosticGuardBuilder<'db, 'ctx> {
let lint_id = LintId::of(lint);
// Skip over diagnostics if the rule
// is disabled.
let severity = ctx.db.rule_selection().severity(lint_id)?;
let (severity, source) = ctx.db.rule_selection().get(lint_id)?;
// If we're not in type checking mode,
// we can bail now.
if ctx.is_in_no_type_check() {
@ -390,6 +406,7 @@ impl<'db, 'ctx> LintDiagnosticGuardBuilder<'db, 'ctx> {
ctx,
id,
severity,
source,
primary_span,
})
}
@ -417,6 +434,7 @@ impl<'db, 'ctx> LintDiagnosticGuardBuilder<'db, 'ctx> {
diag.annotate(Annotation::primary(self.primary_span.clone()));
LintDiagnosticGuard {
ctx: self.ctx,
source: self.source,
diag: Some(diag),
}
}
@ -479,6 +497,11 @@ impl std::ops::DerefMut for DiagnosticGuard<'_, '_> {
/// being type checked.
impl Drop for DiagnosticGuard<'_, '_> {
fn drop(&mut self) {
if std::thread::panicking() {
// Don't submit diagnostics when panicking because they might be incomplete.
return;
}
// OK because the only way `self.diag` is `None`
// is via this impl, which can only run at most
// once.