From 564225c4015340bdd87bfae551b690ea16904119 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 15:39:52 -0700 Subject: [PATCH] Provide diagnostic context to codeAction Co-authored-by: Max Brunsfeld --- crates/language/src/diagnostic_set.rs | 17 +++++++++++ crates/language/src/language.rs | 19 +++++++------ crates/project/src/lsp_command.rs | 14 ++++----- crates/project/src/project.rs | 41 +++++++++++++-------------- crates/server/src/rpc.rs | 13 +++------ 5 files changed, 59 insertions(+), 45 deletions(-) diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 490789a8c8..51c921e61c 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -34,6 +34,23 @@ pub struct Summary { count: usize, } +impl DiagnosticEntry { + // Used to provide diagnostic context to lsp codeAction request + pub fn to_lsp_diagnostic_stub(&self) -> lsp::Diagnostic { + let code = self + .diagnostic + .code + .clone() + .map(lsp::NumberOrString::String); + + lsp::Diagnostic { + code, + severity: Some(self.diagnostic.severity), + ..Default::default() + } + } +} + impl DiagnosticSet { pub fn from_sorted_entries(iter: I, buffer: &text::BufferSnapshot) -> Self where diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 66cafb422b..2435973201 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -662,18 +662,21 @@ impl LspAdapter for FakeLspAdapter { } } -impl ToLspPosition for PointUtf16 { - fn to_lsp_position(self) -> lsp::Position { - lsp::Position::new(self.row, self.column) - } +pub fn point_to_lsp(point: PointUtf16) -> lsp::Position { + lsp::Position::new(point.row, point.column) } pub fn point_from_lsp(point: lsp::Position) -> PointUtf16 { PointUtf16::new(point.line, point.character) } -pub fn range_from_lsp(range: lsp::Range) -> Range { - let start = PointUtf16::new(range.start.line, range.start.character); - let end = PointUtf16::new(range.end.line, range.end.character); - start..end +pub fn range_to_lsp(range: Range) -> lsp::Range { + lsp::Range { + start: point_to_lsp(range.start), + end: point_to_lsp(range.end), + } +} + +pub fn range_from_lsp(range: lsp::Range) -> Range { + point_from_lsp(range.start)..point_from_lsp(range.end) } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index b6f007659d..71ad489d07 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -4,9 +4,9 @@ use async_trait::async_trait; use client::{proto, PeerId}; use gpui::{AppContext, AsyncAppContext, ModelHandle}; use language::{ - point_from_lsp, + point_from_lsp, point_to_lsp, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, - range_from_lsp, Anchor, Bias, Buffer, PointUtf16, ToLspPosition, ToPointUtf16, + range_from_lsp, Anchor, Bias, Buffer, PointUtf16, ToPointUtf16, }; use lsp::{DocumentHighlightKind, ServerCapabilities}; use std::{cmp::Reverse, ops::Range, path::Path}; @@ -91,7 +91,7 @@ impl LspCommand for PrepareRename { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), } } @@ -208,7 +208,7 @@ impl LspCommand for PerformRename { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, new_name: self.new_name.clone(), work_done_progress_params: Default::default(), @@ -325,7 +325,7 @@ impl LspCommand for GetDefinition { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), @@ -497,7 +497,7 @@ impl LspCommand for GetReferences { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), @@ -659,7 +659,7 @@ impl LspCommand for GetDocumentHighlights { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index df84aec0c5..65c943c888 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -15,11 +15,12 @@ use gpui::{ MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle, }; use language::{ + point_to_lsp, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, - range_from_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, - DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, LanguageRegistry, - LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch, PointUtf16, - TextBufferSnapshot, ToLspPosition, ToOffset, ToPointUtf16, Transaction, + range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion, + Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, + LanguageRegistry, LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch, + PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, }; use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer}; use lsp_command::*; @@ -1215,8 +1216,8 @@ impl Project { .collect(); lsp::TextDocumentContentChangeEvent { range: Some(lsp::Range::new( - edit_start.to_lsp_position(), - edit_end.to_lsp_position(), + point_to_lsp(edit_start), + point_to_lsp(edit_end), )), range_length: None, text: new_text, @@ -2061,9 +2062,8 @@ impl Project { .map_or(false, |provider| *provider != lsp::OneOf::Left(false)) { let buffer_start = lsp::Position::new(0, 0); - let buffer_end = buffer - .read_with(&cx, |buffer, _| buffer.max_point_utf16()) - .to_lsp_position(); + let buffer_end = + buffer.read_with(&cx, |buffer, _| point_to_lsp(buffer.max_point_utf16())); language_server .request::( lsp::DocumentRangeFormattingParams { @@ -2337,7 +2337,7 @@ impl Project { lsp::TextDocumentIdentifier::new( lsp::Url::from_file_path(buffer_abs_path).unwrap(), ), - position.to_lsp_position(), + point_to_lsp(position), ), context: Default::default(), work_done_progress_params: Default::default(), @@ -2511,7 +2511,7 @@ impl Project { } } - pub fn code_actions( + pub fn code_actions( &self, buffer_handle: &ModelHandle, range: Range, @@ -2519,6 +2519,11 @@ impl Project { ) -> Task>> { let buffer_handle = buffer_handle.clone(); let buffer = buffer_handle.read(cx); + let snapshot = buffer.snapshot(); + let relevant_diagnostics = snapshot + .diagnostics_in_range::(range.to_offset(&snapshot), false) + .map(|entry| entry.to_lsp_diagnostic_stub()) + .collect(); let buffer_id = buffer.remote_id(); let worktree; let buffer_abs_path; @@ -2539,10 +2544,7 @@ impl Project { return Task::ready(Ok(Default::default())); }; - let lsp_range = lsp::Range::new( - range.start.to_point_utf16(buffer).to_lsp_position(), - range.end.to_point_utf16(buffer).to_lsp_position(), - ); + let lsp_range = range_to_lsp(range.to_point_utf16(buffer)); cx.foreground().spawn(async move { if !lang_server.capabilities().code_action_provider.is_some() { return Ok(Default::default()); @@ -2557,11 +2559,12 @@ impl Project { work_done_progress_params: Default::default(), partial_result_params: Default::default(), context: lsp::CodeActionContext { - diagnostics: Default::default(), + diagnostics: relevant_diagnostics, only: Some(vec![ lsp::CodeActionKind::QUICKFIX, lsp::CodeActionKind::REFACTOR, lsp::CodeActionKind::REFACTOR_EXTRACT, + lsp::CodeActionKind::SOURCE, ]), }, }) @@ -2636,11 +2639,7 @@ impl Project { .and_then(|d| d.get_mut("codeActionParams")) .and_then(|d| d.get_mut("range")) { - *lsp_range = serde_json::to_value(&lsp::Range::new( - range.start.to_lsp_position(), - range.end.to_lsp_position(), - )) - .unwrap(); + *lsp_range = serde_json::to_value(&range_to_lsp(range)).unwrap(); action.lsp_action = lang_server .request::(action.lsp_action) .await?; diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 1b22d09b56..a010e55c32 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1088,8 +1088,8 @@ mod tests { }; use gpui::{executor, geometry::vector::vec2f, ModelHandle, TestAppContext, ViewHandle}; use language::{ - tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, - LanguageRegistry, OffsetRangeExt, Point, ToLspPosition, + range_to_lsp, tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, + LanguageConfig, LanguageRegistry, OffsetRangeExt, Point, }; use lsp::{self, FakeLanguageServer}; use parking_lot::Mutex; @@ -4979,14 +4979,9 @@ mod tests { for _ in 0..highlight_count { let range = buffer.random_byte_range(prev_end, &mut *rng.lock()); - let start = buffer - .offset_to_point_utf16(range.start) - .to_lsp_position(); - let end = buffer - .offset_to_point_utf16(range.end) - .to_lsp_position(); + highlights.push(lsp::DocumentHighlight { - range: lsp::Range::new(start, end), + range: range_to_lsp(range.to_point_utf16(buffer)), kind: Some(lsp::DocumentHighlightKind::READ), }); prev_end = range.end;