use super::HOVER_TEXT;
use tower_lsp_server::ls_types::{
Diagnostic, Hover, HoverContents, MarkupContent, MarkupKind, NumberOrString, Position, Range,
};
pub(super) fn hover_response() -> Hover {
Hover {
contents: HoverContents::Markup(MarkupContent {
kind: MarkupKind::Markdown,
value: HOVER_TEXT.to_string(),
}),
range: None,
}
}
pub(super) fn diagnostic_hover_response(diagnostic: &Diagnostic) -> Hover {
Hover {
contents: HoverContents::Markup(MarkupContent {
kind: MarkupKind::Markdown,
value: diagnostic_hover_markdown(diagnostic),
}),
range: Some(diagnostic.range),
}
}
pub(super) fn diagnostic_at_position<'a>(
diagnostics: &'a [Diagnostic],
position: &Position,
) -> Option<&'a Diagnostic> {
diagnostics
.iter()
.find(|diagnostic| position_in_range(position, &diagnostic.range))
}
fn diagnostic_hover_markdown(diagnostic: &Diagnostic) -> String {
let classification = diagnostic
.code
.as_ref()
.map(number_or_string_label)
.unwrap_or_else(|| "static exposure".to_string());
let mut lines = vec![
format!("**ripr** `{classification}`"),
String::new(),
diagnostic.message.clone(),
];
if let Some(data) = &diagnostic.data {
if let Some(finding_id) = data.get("finding_id").and_then(|value| value.as_str()) {
lines.push(String::new());
lines.push(format!("Finding: `{finding_id}`"));
}
if let Some(probe_id) = data.get("probe_id").and_then(|value| value.as_str()) {
lines.push(format!("Probe: `{probe_id}`"));
}
}
lines.join("\n")
}
fn number_or_string_label(value: &NumberOrString) -> String {
match value {
NumberOrString::Number(number) => number.to_string(),
NumberOrString::String(text) => text.clone(),
}
}
fn position_in_range(position: &Position, range: &Range) -> bool {
position_is_after_or_equal(position, &range.start) && position_is_before(position, &range.end)
}
fn position_is_after_or_equal(position: &Position, start: &Position) -> bool {
position.line > start.line
|| (position.line == start.line && position.character >= start.character)
}
fn position_is_before(position: &Position, end: &Position) -> bool {
position.line < end.line || (position.line == end.line && position.character < end.character)
}