mirror of https://github.com/astral-sh/ruff
[red-knot] Add support for the LSP diagnostic tag (#17657)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
b51c4f82ea
commit
8535af8516
|
|
@ -227,6 +227,11 @@ impl Diagnostic {
|
||||||
pub fn primary_span(&self) -> Option<Span> {
|
pub fn primary_span(&self) -> Option<Span> {
|
||||||
self.primary_annotation().map(|ann| ann.span.clone())
|
self.primary_annotation().map(|ann| ann.span.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the tags from the primary annotation of this diagnostic if it exists.
|
||||||
|
pub fn primary_tags(&self) -> Option<&[DiagnosticTag]> {
|
||||||
|
self.primary_annotation().map(|ann| ann.tags.as_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
|
@ -338,6 +343,8 @@ pub struct Annotation {
|
||||||
/// Whether this annotation is "primary" or not. When it isn't primary, an
|
/// Whether this annotation is "primary" or not. When it isn't primary, an
|
||||||
/// annotation is said to be "secondary."
|
/// annotation is said to be "secondary."
|
||||||
is_primary: bool,
|
is_primary: bool,
|
||||||
|
/// The diagnostic tags associated with this annotation.
|
||||||
|
tags: Vec<DiagnosticTag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Annotation {
|
impl Annotation {
|
||||||
|
|
@ -355,6 +362,7 @@ impl Annotation {
|
||||||
span,
|
span,
|
||||||
message: None,
|
message: None,
|
||||||
is_primary: true,
|
is_primary: true,
|
||||||
|
tags: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,6 +378,7 @@ impl Annotation {
|
||||||
span,
|
span,
|
||||||
message: None,
|
message: None,
|
||||||
is_primary: false,
|
is_primary: false,
|
||||||
|
tags: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,6 +421,36 @@ impl Annotation {
|
||||||
pub fn get_span(&self) -> &Span {
|
pub fn get_span(&self) -> &Span {
|
||||||
&self.span
|
&self.span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the tags associated with this annotation.
|
||||||
|
pub fn get_tags(&self) -> &[DiagnosticTag] {
|
||||||
|
&self.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attaches this tag to this annotation.
|
||||||
|
///
|
||||||
|
/// It will not replace any existing tags.
|
||||||
|
pub fn tag(mut self, tag: DiagnosticTag) -> Annotation {
|
||||||
|
self.tags.push(tag);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attaches an additional tag to this annotation.
|
||||||
|
pub fn push_tag(&mut self, tag: DiagnosticTag) {
|
||||||
|
self.tags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tags that can be associated with an annotation.
|
||||||
|
///
|
||||||
|
/// These tags are used to provide additional information about the annotation.
|
||||||
|
/// and are passed through to the language server protocol.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub enum DiagnosticTag {
|
||||||
|
/// Unused or unnecessary code. Used for unused parameters, unreachable code, etc.
|
||||||
|
Unnecessary,
|
||||||
|
/// Deprecated or obsolete code.
|
||||||
|
Deprecated,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A string identifier for a lint rule.
|
/// A string identifier for a lint rule.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use drop_bomb::DebugDropBomb;
|
use drop_bomb::DebugDropBomb;
|
||||||
|
use ruff_db::diagnostic::DiagnosticTag;
|
||||||
use ruff_db::{
|
use ruff_db::{
|
||||||
diagnostic::{Annotation, Diagnostic, DiagnosticId, IntoDiagnosticMessage, Severity, Span},
|
diagnostic::{Annotation, Diagnostic, DiagnosticId, IntoDiagnosticMessage, Severity, Span},
|
||||||
files::File,
|
files::File,
|
||||||
|
|
@ -259,6 +260,21 @@ impl LintDiagnosticGuard<'_, '_> {
|
||||||
let ann = self.primary_annotation_mut().unwrap();
|
let ann = self.primary_annotation_mut().unwrap();
|
||||||
ann.set_message(message);
|
ann.set_message(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a tag on the primary annotation for this diagnostic.
|
||||||
|
///
|
||||||
|
/// This tag is associated with the primary annotation created
|
||||||
|
/// for every `Diagnostic` that uses the `LintDiagnosticGuard` API.
|
||||||
|
/// Specifically, the annotation is derived from the `TextRange` given to
|
||||||
|
/// the `InferContext::report_lint` API.
|
||||||
|
///
|
||||||
|
/// Callers can add additional primary or secondary annotations via the
|
||||||
|
/// `DerefMut` trait implementation to a `Diagnostic`.
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub(super) fn add_primary_tag(&mut self, tag: DiagnosticTag) {
|
||||||
|
let ann = self.primary_annotation_mut().unwrap();
|
||||||
|
ann.push_tag(tag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for LintDiagnosticGuard<'_, '_> {
|
impl std::ops::Deref for LintDiagnosticGuard<'_, '_> {
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use lsp_types::request::DocumentDiagnosticRequest;
|
use lsp_types::request::DocumentDiagnosticRequest;
|
||||||
use lsp_types::{
|
use lsp_types::{
|
||||||
Diagnostic, DiagnosticSeverity, DocumentDiagnosticParams, DocumentDiagnosticReport,
|
Diagnostic, DiagnosticSeverity, DiagnosticTag, DocumentDiagnosticParams,
|
||||||
DocumentDiagnosticReportResult, FullDocumentDiagnosticReport, NumberOrString, Range,
|
DocumentDiagnosticReport, DocumentDiagnosticReportResult, FullDocumentDiagnosticReport,
|
||||||
RelatedFullDocumentDiagnosticReport, Url,
|
NumberOrString, Range, RelatedFullDocumentDiagnosticReport, Url,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::document::ToRangeExt;
|
use crate::document::ToRangeExt;
|
||||||
|
|
@ -92,10 +92,22 @@ fn to_lsp_diagnostic(
|
||||||
Severity::Error | Severity::Fatal => DiagnosticSeverity::ERROR,
|
Severity::Error | Severity::Fatal => DiagnosticSeverity::ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tags = diagnostic
|
||||||
|
.primary_tags()
|
||||||
|
.map(|tags| {
|
||||||
|
tags.iter()
|
||||||
|
.map(|tag| match tag {
|
||||||
|
ruff_db::diagnostic::DiagnosticTag::Unnecessary => DiagnosticTag::UNNECESSARY,
|
||||||
|
ruff_db::diagnostic::DiagnosticTag::Deprecated => DiagnosticTag::DEPRECATED,
|
||||||
|
})
|
||||||
|
.collect::<Vec<DiagnosticTag>>()
|
||||||
|
})
|
||||||
|
.filter(|mapped_tags| !mapped_tags.is_empty());
|
||||||
|
|
||||||
Diagnostic {
|
Diagnostic {
|
||||||
range,
|
range,
|
||||||
severity: Some(severity),
|
severity: Some(severity),
|
||||||
tags: None,
|
tags,
|
||||||
code: Some(NumberOrString::String(diagnostic.id().to_string())),
|
code: Some(NumberOrString::String(diagnostic.id().to_string())),
|
||||||
code_description: None,
|
code_description: None,
|
||||||
source: Some("ty".into()),
|
source: Some("ty".into()),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue