Use LspCommand
to handle code actions
This commit is contained in:
parent
651a83977e
commit
5898600239
2 changed files with 199 additions and 153 deletions
|
@ -9,8 +9,8 @@ use gpui::{AppContext, AsyncAppContext, ModelHandle};
|
||||||
use language::{
|
use language::{
|
||||||
point_from_lsp, point_to_lsp,
|
point_from_lsp, point_to_lsp,
|
||||||
proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
|
proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
|
||||||
range_from_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, Completion, PointUtf16,
|
range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction,
|
||||||
ToOffset, ToPointUtf16, Unclipped,
|
Completion, OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Unclipped,
|
||||||
};
|
};
|
||||||
use lsp::{DocumentHighlightKind, LanguageServer, ServerCapabilities};
|
use lsp::{DocumentHighlightKind, LanguageServer, ServerCapabilities};
|
||||||
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag};
|
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag};
|
||||||
|
@ -29,6 +29,8 @@ pub(crate) trait LspCommand: 'static + Sized {
|
||||||
fn to_lsp(
|
fn to_lsp(
|
||||||
&self,
|
&self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
buffer: &Buffer,
|
||||||
|
language_server: &Arc<LanguageServer>,
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> <Self::LspRequest as lsp::request::Request>::Params;
|
) -> <Self::LspRequest as lsp::request::Request>::Params;
|
||||||
async fn response_from_lsp(
|
async fn response_from_lsp(
|
||||||
|
@ -97,6 +99,10 @@ pub(crate) struct GetCompletions {
|
||||||
pub position: PointUtf16,
|
pub position: PointUtf16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct GetCodeActions {
|
||||||
|
pub range: Range<Anchor>,
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl LspCommand for PrepareRename {
|
impl LspCommand for PrepareRename {
|
||||||
type Response = Option<Range<Anchor>>;
|
type Response = Option<Range<Anchor>>;
|
||||||
|
@ -111,7 +117,13 @@ impl LspCommand for PrepareRename {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::TextDocumentPositionParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::TextDocumentPositionParams {
|
||||||
lsp::TextDocumentPositionParams {
|
lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
uri: lsp::Url::from_file_path(path).unwrap(),
|
uri: lsp::Url::from_file_path(path).unwrap(),
|
||||||
|
@ -227,7 +239,13 @@ impl LspCommand for PerformRename {
|
||||||
type LspRequest = lsp::request::Rename;
|
type LspRequest = lsp::request::Rename;
|
||||||
type ProtoRequest = proto::PerformRename;
|
type ProtoRequest = proto::PerformRename;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::RenameParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::RenameParams {
|
||||||
lsp::RenameParams {
|
lsp::RenameParams {
|
||||||
text_document_position: lsp::TextDocumentPositionParams {
|
text_document_position: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -338,7 +356,13 @@ impl LspCommand for GetDefinition {
|
||||||
type LspRequest = lsp::request::GotoDefinition;
|
type LspRequest = lsp::request::GotoDefinition;
|
||||||
type ProtoRequest = proto::GetDefinition;
|
type ProtoRequest = proto::GetDefinition;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::GotoDefinitionParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::GotoDefinitionParams {
|
||||||
lsp::GotoDefinitionParams {
|
lsp::GotoDefinitionParams {
|
||||||
text_document_position_params: lsp::TextDocumentPositionParams {
|
text_document_position_params: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -424,7 +448,13 @@ impl LspCommand for GetTypeDefinition {
|
||||||
type LspRequest = lsp::request::GotoTypeDefinition;
|
type LspRequest = lsp::request::GotoTypeDefinition;
|
||||||
type ProtoRequest = proto::GetTypeDefinition;
|
type ProtoRequest = proto::GetTypeDefinition;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::GotoTypeDefinitionParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::GotoTypeDefinitionParams {
|
||||||
lsp::GotoTypeDefinitionParams {
|
lsp::GotoTypeDefinitionParams {
|
||||||
text_document_position_params: lsp::TextDocumentPositionParams {
|
text_document_position_params: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -699,7 +729,13 @@ impl LspCommand for GetReferences {
|
||||||
type LspRequest = lsp::request::References;
|
type LspRequest = lsp::request::References;
|
||||||
type ProtoRequest = proto::GetReferences;
|
type ProtoRequest = proto::GetReferences;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::ReferenceParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::ReferenceParams {
|
||||||
lsp::ReferenceParams {
|
lsp::ReferenceParams {
|
||||||
text_document_position: lsp::TextDocumentPositionParams {
|
text_document_position: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -857,7 +893,13 @@ impl LspCommand for GetDocumentHighlights {
|
||||||
capabilities.document_highlight_provider.is_some()
|
capabilities.document_highlight_provider.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::DocumentHighlightParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::DocumentHighlightParams {
|
||||||
lsp::DocumentHighlightParams {
|
lsp::DocumentHighlightParams {
|
||||||
text_document_position_params: lsp::TextDocumentPositionParams {
|
text_document_position_params: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -997,7 +1039,13 @@ impl LspCommand for GetHover {
|
||||||
type LspRequest = lsp::request::HoverRequest;
|
type LspRequest = lsp::request::HoverRequest;
|
||||||
type ProtoRequest = proto::GetHover;
|
type ProtoRequest = proto::GetHover;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::HoverParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::HoverParams {
|
||||||
lsp::HoverParams {
|
lsp::HoverParams {
|
||||||
text_document_position_params: lsp::TextDocumentPositionParams {
|
text_document_position_params: lsp::TextDocumentPositionParams {
|
||||||
text_document: lsp::TextDocumentIdentifier {
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
@ -1212,7 +1260,13 @@ impl LspCommand for GetCompletions {
|
||||||
type LspRequest = lsp::request::Completion;
|
type LspRequest = lsp::request::Completion;
|
||||||
type ProtoRequest = proto::GetCompletions;
|
type ProtoRequest = proto::GetCompletions;
|
||||||
|
|
||||||
fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::CompletionParams {
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::CompletionParams {
|
||||||
lsp::CompletionParams {
|
lsp::CompletionParams {
|
||||||
text_document_position: lsp::TextDocumentPositionParams::new(
|
text_document_position: lsp::TextDocumentPositionParams::new(
|
||||||
lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
|
lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
|
||||||
|
@ -1406,3 +1460,135 @@ impl LspCommand for GetCompletions {
|
||||||
message.buffer_id
|
message.buffer_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl LspCommand for GetCodeActions {
|
||||||
|
type Response = Vec<CodeAction>;
|
||||||
|
type LspRequest = lsp::request::CodeActionRequest;
|
||||||
|
type ProtoRequest = proto::GetCodeActions;
|
||||||
|
|
||||||
|
fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
|
||||||
|
capabilities.code_action_provider.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
buffer: &Buffer,
|
||||||
|
language_server: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::CodeActionParams {
|
||||||
|
let relevant_diagnostics = buffer
|
||||||
|
.snapshot()
|
||||||
|
.diagnostics_in_range::<_, usize>(self.range.clone(), false)
|
||||||
|
.map(|entry| entry.to_lsp_diagnostic_stub())
|
||||||
|
.collect();
|
||||||
|
lsp::CodeActionParams {
|
||||||
|
text_document: lsp::TextDocumentIdentifier::new(
|
||||||
|
lsp::Url::from_file_path(path).unwrap(),
|
||||||
|
),
|
||||||
|
range: range_to_lsp(self.range.to_point_utf16(buffer)),
|
||||||
|
work_done_progress_params: Default::default(),
|
||||||
|
partial_result_params: Default::default(),
|
||||||
|
context: lsp::CodeActionContext {
|
||||||
|
diagnostics: relevant_diagnostics,
|
||||||
|
only: language_server.code_action_kinds(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn response_from_lsp(
|
||||||
|
self,
|
||||||
|
actions: Option<lsp::CodeActionResponse>,
|
||||||
|
_: ModelHandle<Project>,
|
||||||
|
_: ModelHandle<Buffer>,
|
||||||
|
_: AsyncAppContext,
|
||||||
|
) -> Result<Vec<CodeAction>> {
|
||||||
|
Ok(actions
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| {
|
||||||
|
if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
|
||||||
|
Some(CodeAction {
|
||||||
|
range: self.range.clone(),
|
||||||
|
lsp_action,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
|
||||||
|
proto::GetCodeActions {
|
||||||
|
project_id,
|
||||||
|
buffer_id: buffer.remote_id(),
|
||||||
|
start: Some(language::proto::serialize_anchor(&self.range.start)),
|
||||||
|
end: Some(language::proto::serialize_anchor(&self.range.end)),
|
||||||
|
version: serialize_version(&buffer.version()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn from_proto(
|
||||||
|
message: proto::GetCodeActions,
|
||||||
|
_: ModelHandle<Project>,
|
||||||
|
buffer: ModelHandle<Buffer>,
|
||||||
|
mut cx: AsyncAppContext,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let start = message
|
||||||
|
.start
|
||||||
|
.and_then(language::proto::deserialize_anchor)
|
||||||
|
.ok_or_else(|| anyhow!("invalid start"))?;
|
||||||
|
let end = message
|
||||||
|
.end
|
||||||
|
.and_then(language::proto::deserialize_anchor)
|
||||||
|
.ok_or_else(|| anyhow!("invalid end"))?;
|
||||||
|
buffer
|
||||||
|
.update(&mut cx, |buffer, _| {
|
||||||
|
buffer.wait_for_version(deserialize_version(&message.version))
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Self { range: start..end })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn response_to_proto(
|
||||||
|
code_actions: Vec<CodeAction>,
|
||||||
|
_: &mut Project,
|
||||||
|
_: PeerId,
|
||||||
|
buffer_version: &clock::Global,
|
||||||
|
_: &mut AppContext,
|
||||||
|
) -> proto::GetCodeActionsResponse {
|
||||||
|
proto::GetCodeActionsResponse {
|
||||||
|
actions: code_actions
|
||||||
|
.iter()
|
||||||
|
.map(language::proto::serialize_code_action)
|
||||||
|
.collect(),
|
||||||
|
version: serialize_version(&buffer_version),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn response_from_proto(
|
||||||
|
self,
|
||||||
|
message: proto::GetCodeActionsResponse,
|
||||||
|
_: ModelHandle<Project>,
|
||||||
|
buffer: ModelHandle<Buffer>,
|
||||||
|
mut cx: AsyncAppContext,
|
||||||
|
) -> Result<Vec<CodeAction>> {
|
||||||
|
buffer
|
||||||
|
.update(&mut cx, |buffer, _| {
|
||||||
|
buffer.wait_for_version(deserialize_version(&message.version))
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
message
|
||||||
|
.actions
|
||||||
|
.into_iter()
|
||||||
|
.map(language::proto::deserialize_code_action)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_id_from_proto(message: &proto::GetCodeActions) -> u64 {
|
||||||
|
message.buffer_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -409,7 +409,7 @@ impl Project {
|
||||||
client.add_model_request_handler(Self::handle_reload_buffers);
|
client.add_model_request_handler(Self::handle_reload_buffers);
|
||||||
client.add_model_request_handler(Self::handle_synchronize_buffers);
|
client.add_model_request_handler(Self::handle_synchronize_buffers);
|
||||||
client.add_model_request_handler(Self::handle_format_buffers);
|
client.add_model_request_handler(Self::handle_format_buffers);
|
||||||
client.add_model_request_handler(Self::handle_get_code_actions);
|
client.add_model_request_handler(Self::handle_lsp_command::<GetCodeActions>);
|
||||||
client.add_model_request_handler(Self::handle_lsp_command::<GetCompletions>);
|
client.add_model_request_handler(Self::handle_lsp_command::<GetCompletions>);
|
||||||
client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
|
client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
|
||||||
client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
|
client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
|
||||||
|
@ -3704,106 +3704,9 @@ impl Project {
|
||||||
range: Range<T>,
|
range: Range<T>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<Vec<CodeAction>>> {
|
) -> Task<Result<Vec<CodeAction>>> {
|
||||||
let buffer_handle = buffer_handle.clone();
|
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
let snapshot = buffer.snapshot();
|
|
||||||
let relevant_diagnostics = snapshot
|
|
||||||
.diagnostics_in_range::<usize, usize>(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;
|
|
||||||
if let Some(file) = File::from_dyn(buffer.file()) {
|
|
||||||
worktree = file.worktree.clone();
|
|
||||||
buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
|
|
||||||
} else {
|
|
||||||
return Task::ready(Ok(Vec::new()));
|
|
||||||
};
|
|
||||||
let range = buffer.anchor_before(range.start)..buffer.anchor_before(range.end);
|
let range = buffer.anchor_before(range.start)..buffer.anchor_before(range.end);
|
||||||
|
self.request_lsp(buffer_handle.clone(), GetCodeActions { range }, cx)
|
||||||
if worktree.read(cx).as_local().is_some() {
|
|
||||||
let buffer_abs_path = buffer_abs_path.unwrap();
|
|
||||||
let lang_server = if let Some((_, server)) = self.language_server_for_buffer(buffer, cx)
|
|
||||||
{
|
|
||||||
server.clone()
|
|
||||||
} else {
|
|
||||||
return Task::ready(Ok(Vec::new()));
|
|
||||||
};
|
|
||||||
|
|
||||||
let lsp_range = range_to_lsp(range.to_point_utf16(buffer));
|
|
||||||
cx.foreground().spawn(async move {
|
|
||||||
if lang_server.capabilities().code_action_provider.is_none() {
|
|
||||||
return Ok(Vec::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(lang_server
|
|
||||||
.request::<lsp::request::CodeActionRequest>(lsp::CodeActionParams {
|
|
||||||
text_document: lsp::TextDocumentIdentifier::new(
|
|
||||||
lsp::Url::from_file_path(buffer_abs_path).unwrap(),
|
|
||||||
),
|
|
||||||
range: lsp_range,
|
|
||||||
work_done_progress_params: Default::default(),
|
|
||||||
partial_result_params: Default::default(),
|
|
||||||
context: lsp::CodeActionContext {
|
|
||||||
diagnostics: relevant_diagnostics,
|
|
||||||
only: lang_server.code_action_kinds(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
.unwrap_or_default()
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|entry| {
|
|
||||||
if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
|
|
||||||
Some(CodeAction {
|
|
||||||
range: range.clone(),
|
|
||||||
lsp_action,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
})
|
|
||||||
} else if let Some(project_id) = self.remote_id() {
|
|
||||||
let rpc = self.client.clone();
|
|
||||||
let version = buffer.version();
|
|
||||||
cx.spawn_weak(|this, mut cx| async move {
|
|
||||||
let response = rpc
|
|
||||||
.request(proto::GetCodeActions {
|
|
||||||
project_id,
|
|
||||||
buffer_id,
|
|
||||||
start: Some(language::proto::serialize_anchor(&range.start)),
|
|
||||||
end: Some(language::proto::serialize_anchor(&range.end)),
|
|
||||||
version: serialize_version(&version),
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if this
|
|
||||||
.upgrade(&cx)
|
|
||||||
.ok_or_else(|| anyhow!("project was dropped"))?
|
|
||||||
.read_with(&cx, |this, _| this.is_read_only())
|
|
||||||
{
|
|
||||||
return Err(anyhow!(
|
|
||||||
"failed to get code actions: project was disconnected"
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
buffer_handle
|
|
||||||
.update(&mut cx, |buffer, _| {
|
|
||||||
buffer.wait_for_version(deserialize_version(&response.version))
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
response
|
|
||||||
.actions
|
|
||||||
.into_iter()
|
|
||||||
.map(language::proto::deserialize_code_action)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Task::ready(Ok(Default::default()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_code_action(
|
pub fn apply_code_action(
|
||||||
|
@ -4288,7 +4191,7 @@ impl Project {
|
||||||
self.language_server_for_buffer(buffer, cx)
|
self.language_server_for_buffer(buffer, cx)
|
||||||
.map(|(_, server)| server.clone()),
|
.map(|(_, server)| server.clone()),
|
||||||
) {
|
) {
|
||||||
let lsp_params = request.to_lsp(&file.abs_path(cx), cx);
|
let lsp_params = request.to_lsp(&file.abs_path(cx), buffer, &language_server, cx);
|
||||||
return cx.spawn(|this, cx| async move {
|
return cx.spawn(|this, cx| async move {
|
||||||
if !request.check_capabilities(language_server.capabilities()) {
|
if !request.check_capabilities(language_server.capabilities()) {
|
||||||
return Ok(Default::default());
|
return Ok(Default::default());
|
||||||
|
@ -5493,49 +5396,6 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_get_code_actions(
|
|
||||||
this: ModelHandle<Self>,
|
|
||||||
envelope: TypedEnvelope<proto::GetCodeActions>,
|
|
||||||
_: Arc<Client>,
|
|
||||||
mut cx: AsyncAppContext,
|
|
||||||
) -> Result<proto::GetCodeActionsResponse> {
|
|
||||||
let start = envelope
|
|
||||||
.payload
|
|
||||||
.start
|
|
||||||
.and_then(language::proto::deserialize_anchor)
|
|
||||||
.ok_or_else(|| anyhow!("invalid start"))?;
|
|
||||||
let end = envelope
|
|
||||||
.payload
|
|
||||||
.end
|
|
||||||
.and_then(language::proto::deserialize_anchor)
|
|
||||||
.ok_or_else(|| anyhow!("invalid end"))?;
|
|
||||||
let buffer = this.update(&mut cx, |this, cx| {
|
|
||||||
this.opened_buffers
|
|
||||||
.get(&envelope.payload.buffer_id)
|
|
||||||
.and_then(|buffer| buffer.upgrade(cx))
|
|
||||||
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
|
|
||||||
})?;
|
|
||||||
buffer
|
|
||||||
.update(&mut cx, |buffer, _| {
|
|
||||||
buffer.wait_for_version(deserialize_version(&envelope.payload.version))
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let version = buffer.read_with(&cx, |buffer, _| buffer.version());
|
|
||||||
let code_actions = this.update(&mut cx, |this, cx| {
|
|
||||||
Ok::<_, anyhow::Error>(this.code_actions(&buffer, start..end, cx))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(proto::GetCodeActionsResponse {
|
|
||||||
actions: code_actions
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.map(language::proto::serialize_code_action)
|
|
||||||
.collect(),
|
|
||||||
version: serialize_version(&version),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_apply_code_action(
|
async fn handle_apply_code_action(
|
||||||
this: ModelHandle<Self>,
|
this: ModelHandle<Self>,
|
||||||
envelope: TypedEnvelope<proto::ApplyCodeAction>,
|
envelope: TypedEnvelope<proto::ApplyCodeAction>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue