Finalize the command

This commit is contained in:
Kirill Bulatov 2023-12-11 12:01:04 +02:00
parent e3fc810b3d
commit 3694265b6b
9 changed files with 126 additions and 53 deletions

View file

@ -997,7 +997,6 @@ pub mod tests {
movement, movement,
test::{editor_test_context::EditorTestContext, marked_display_snapshot}, test::{editor_test_context::EditorTestContext, marked_display_snapshot},
}; };
use client::Client;
use gpui::{div, font, observe, px, AppContext, Context, Element, Hsla}; use gpui::{div, font, observe, px, AppContext, Context, Element, Hsla};
use language::{ use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent}, language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
@ -1009,10 +1008,7 @@ pub mod tests {
use smol::stream::StreamExt; use smol::stream::StreamExt;
use std::{env, sync::Arc}; use std::{env, sync::Arc};
use theme::{LoadThemes, SyntaxTheme}; use theme::{LoadThemes, SyntaxTheme};
use util::{ use util::test::{marked_text_ranges, sample_text};
http::FakeHttpClient,
test::{marked_text_ranges, sample_text},
};
use Bias::*; use Bias::*;
#[gpui::test(iterations = 100)] #[gpui::test(iterations = 100)]

View file

@ -74,7 +74,7 @@ pub use multi_buffer::{
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction}; use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::{prelude::*, rngs::adapter}; use rand::prelude::*;
use rpc::proto::{self, *}; use rpc::proto::{self, *};
use scroll::{ use scroll::{
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide, autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
@ -9343,7 +9343,6 @@ impl Render for Editor {
scrollbar_width: px(12.), scrollbar_width: px(12.),
syntax: cx.theme().syntax().clone(), syntax: cx.theme().syntax().clone(),
diagnostic_style: cx.theme().diagnostic_style(), diagnostic_style: cx.theme().diagnostic_style(),
// TODO kb find `HighlightStyle` usages
// todo!("what about the rest of the highlight style parts?") // todo!("what about the rest of the highlight style parts?")
inlays_style: HighlightStyle { inlays_style: HighlightStyle {
color: Some(cx.theme().status().hint), color: Some(cx.theme().status().hint),

View file

@ -29,7 +29,6 @@ use std::{cell::RefCell, future::Future, rc::Rc, time::Instant};
use unindent::Unindent; use unindent::Unindent;
use util::{ use util::{
assert_set_eq, assert_set_eq,
http::FakeHttpClient,
test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
}; };
use workspace::{ use workspace::{

View file

@ -1202,7 +1202,6 @@ pub mod tests {
scroll::{autoscroll::Autoscroll, scroll_amount::ScrollAmount}, scroll::{autoscroll::Autoscroll, scroll_amount::ScrollAmount},
ExcerptRange, ExcerptRange,
}; };
use client::Client;
use futures::StreamExt; use futures::StreamExt;
use gpui::{Context, TestAppContext, View, WindowHandle}; use gpui::{Context, TestAppContext, View, WindowHandle};
use itertools::Itertools; use itertools::Itertools;
@ -1215,7 +1214,6 @@ pub mod tests {
use serde_json::json; use serde_json::json;
use settings::SettingsStore; use settings::SettingsStore;
use text::{Point, ToPoint}; use text::{Point, ToPoint};
use util::http::FakeHttpClient;
use workspace::Workspace; use workspace::Workspace;
use crate::editor_tests::update_test_language_settings; use crate::editor_tests::update_test_language_settings;

View file

@ -460,11 +460,10 @@ mod tests {
test::{editor_test_context::EditorTestContext, marked_display_snapshot}, test::{editor_test_context::EditorTestContext, marked_display_snapshot},
Buffer, DisplayMap, ExcerptRange, InlayId, MultiBuffer, Buffer, DisplayMap, ExcerptRange, InlayId, MultiBuffer,
}; };
use client::Client;
use gpui::{font, Context as _}; use gpui::{font, Context as _};
use project::Project; use project::Project;
use settings::SettingsStore; use settings::SettingsStore;
use util::{http::FakeHttpClient, post_inc}; use util::post_inc;
#[gpui::test] #[gpui::test]
fn test_previous_word_start(cx: &mut gpui::AppContext) { fn test_previous_word_start(cx: &mut gpui::AppContext) {

View file

@ -1,11 +1,11 @@
use std::{path::Path, sync::Arc}; use std::sync::Arc;
use gpui::{AppContext, AsyncAppContext, Model, View, ViewContext, WindowContext}; use anyhow::Context as _;
use language::Buffer; use gpui::{Context, Model, View, ViewContext, VisualContext, WindowContext};
use lsp::{LanguageServer, LanguageServerId}; use language::Language;
use project::{lsp_command::LspCommand, lsp_ext_command::ExpandMacro, Project}; use multi_buffer::MultiBuffer;
use rpc::proto::{self, PeerId}; use project::lsp_ext_command::ExpandMacro;
use serde::{Deserialize, Serialize}; use text::ToPointUtf16;
use crate::{element::register_action, Editor, ExpandMacroRecursively}; use crate::{element::register_action, Editor, ExpandMacroRecursively};
@ -16,7 +16,10 @@ pub fn apply_related_actions(editor: &View<Editor>, cx: &mut WindowContext) {
.read(cx) .read(cx)
.all_buffers() .all_buffers()
.iter() .iter()
.any(|b| b.read(cx).language().map(|l| l.name()).as_deref() == Some("Rust")) .any(|b| match b.read(cx).language() {
Some(l) => is_rust_language(l),
None => false,
})
}); });
if is_rust_related { if is_rust_related {
@ -35,24 +38,39 @@ pub fn expand_macro_recursively(
let Some(project) = &editor.project else { let Some(project) = &editor.project else {
return; return;
}; };
let Some(workspace) = editor.workspace() else {
return;
};
let multibuffer = editor.buffer().read(cx); let multibuffer = editor.buffer().read(cx);
let Some((trigger_anchor, server_to_query, buffer)) = editor let Some((trigger_anchor, rust_language, server_to_query, buffer)) = editor
.selections .selections
.disjoint_anchors() .disjoint_anchors()
.into_iter() .into_iter()
.filter(|selection| selection.start == selection.end) .filter(|selection| selection.start == selection.end)
.filter_map(|selection| Some((selection.start.buffer_id?, selection.start))) .filter_map(|selection| Some((selection.start.buffer_id?, selection.start)))
.find_map(|(buffer_id, trigger_anchor)| { .filter_map(|(buffer_id, trigger_anchor)| {
let buffer = multibuffer.buffer(buffer_id)?; let buffer = multibuffer.buffer(buffer_id)?;
let rust_language = buffer.read(cx).language_at(trigger_anchor.text_anchor)?;
if !is_rust_language(&rust_language) {
return None;
}
Some((trigger_anchor, rust_language, buffer))
})
.find_map(|(trigger_anchor, rust_language, buffer)| {
project project
.read(cx) .read(cx)
.language_servers_for_buffer(buffer.read(cx), cx) .language_servers_for_buffer(buffer.read(cx), cx)
.into_iter() .into_iter()
.find_map(|(adapter, server)| { .find_map(|(adapter, server)| {
if adapter.name.0.as_ref() == "rust-analyzer" { if adapter.name.0.as_ref() == "rust-analyzer" {
Some((trigger_anchor, server.server_id(), buffer.clone())) Some((
trigger_anchor,
Arc::clone(&rust_language),
server.server_id(),
buffer.clone(),
))
} else { } else {
None None
} }
@ -62,14 +80,40 @@ pub fn expand_macro_recursively(
return; return;
}; };
let z = project.update(cx, |project, cx| { let project = project.clone();
let buffer_snapshot = buffer.read(cx).snapshot();
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
let expand_macro_task = project.update(cx, |project, cx| {
project.request_lsp( project.request_lsp(
buffer, buffer,
project::LanguageServerToQuery::Other(server_to_query), project::LanguageServerToQuery::Other(server_to_query),
ExpandMacro {}, ExpandMacro { position },
cx, cx,
) )
}); });
cx.spawn(|editor, mut cx| async move {
let macro_expansion = expand_macro_task.await.context("expand macro")?;
if macro_expansion.is_empty() {
log::info!("Empty macro expansion for position {position:?}");
return Ok(());
}
// todo!("TODO kb") let buffer = project.update(&mut cx, |project, cx| {
project.create_buffer(&macro_expansion.expansion, Some(rust_language), cx)
})??;
workspace.update(&mut cx, |workspace, cx| {
let buffer = cx.build_model(|cx| {
MultiBuffer::singleton(buffer, cx).with_title(macro_expansion.name)
});
workspace.add_item(
Box::new(cx.build_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))),
cx,
);
})
})
.detach_and_log_err(cx);
}
fn is_rust_language(language: &Language) -> bool {
language.name().as_ref() == "Rust"
} }

View file

@ -5,9 +5,7 @@ use std::{
}; };
use anyhow::Result; use anyhow::Result;
use client::Client;
use serde_json::json; use serde_json::json;
use util::http::FakeHttpClient;
use crate::{Editor, ToPoint}; use crate::{Editor, ToPoint};
use collections::HashSet; use collections::HashSet;

View file

@ -1,11 +1,13 @@
use std::{path::Path, sync::Arc}; use std::{path::Path, sync::Arc};
use anyhow::Context;
use async_trait::async_trait; use async_trait::async_trait;
use gpui::{AppContext, AsyncAppContext, Model}; use gpui::{AppContext, AsyncAppContext, Model};
use language::Buffer; use language::{point_to_lsp, proto::deserialize_anchor, Buffer};
use lsp::{LanguageServer, LanguageServerId}; use lsp::{LanguageServer, LanguageServerId};
use rpc::proto::{self, PeerId}; use rpc::proto::{self, PeerId};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use text::{PointUtf16, ToPointUtf16};
use crate::{lsp_command::LspCommand, Project}; use crate::{lsp_command::LspCommand, Project};
@ -31,9 +33,16 @@ pub struct ExpandedMacro {
pub expansion: String, pub expansion: String,
} }
pub struct ExpandMacro {} impl ExpandedMacro {
pub fn is_empty(&self) -> bool {
self.name.is_empty() && self.expansion.is_empty()
}
}
pub struct ExpandMacro {
pub position: PointUtf16,
}
// TODO kb
#[async_trait(?Send)] #[async_trait(?Send)]
impl LspCommand for ExpandMacro { impl LspCommand for ExpandMacro {
type Response = ExpandedMacro; type Response = ExpandedMacro;
@ -43,55 +52,83 @@ impl LspCommand for ExpandMacro {
fn to_lsp( fn to_lsp(
&self, &self,
path: &Path, path: &Path,
buffer: &Buffer, _: &Buffer,
language_server: &Arc<LanguageServer>, _: &Arc<LanguageServer>,
cx: &AppContext, _: &AppContext,
) -> ExpandMacroParams { ) -> ExpandMacroParams {
todo!() ExpandMacroParams {
text_document: lsp::TextDocumentIdentifier {
uri: lsp::Url::from_file_path(path).unwrap(),
},
position: point_to_lsp(self.position),
}
} }
async fn response_from_lsp( async fn response_from_lsp(
self, self,
message: Option<ExpandedMacro>, message: Option<ExpandedMacro>,
project: Model<Project>, _: Model<Project>,
buffer: Model<Buffer>, _: Model<Buffer>,
server_id: LanguageServerId, _: LanguageServerId,
cx: AsyncAppContext, _: AsyncAppContext,
) -> anyhow::Result<ExpandedMacro> { ) -> anyhow::Result<ExpandedMacro> {
anyhow::bail!("TODO kb") Ok(message
.map(|message| ExpandedMacro {
name: message.name,
expansion: message.expansion,
})
.unwrap_or_default())
} }
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LspExtExpandMacro { fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LspExtExpandMacro {
todo!() proto::LspExtExpandMacro {
project_id,
buffer_id: buffer.remote_id(),
position: Some(language::proto::serialize_anchor(
&buffer.anchor_before(self.position),
)),
}
} }
async fn from_proto( async fn from_proto(
message: Self::ProtoRequest, message: Self::ProtoRequest,
project: Model<Project>, _: Model<Project>,
buffer: Model<Buffer>, buffer: Model<Buffer>,
cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
todo!() let position = message
.position
.and_then(deserialize_anchor)
.context("invalid position")?;
Ok(Self {
position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
})
} }
fn response_to_proto( fn response_to_proto(
response: ExpandedMacro, response: ExpandedMacro,
project: &mut Project, _: &mut Project,
peer_id: PeerId, _: PeerId,
buffer_version: &clock::Global, _: &clock::Global,
cx: &mut AppContext, _: &mut AppContext,
) -> proto::LspExtExpandMacroResponse { ) -> proto::LspExtExpandMacroResponse {
todo!() proto::LspExtExpandMacroResponse {
name: response.name,
expansion: response.expansion,
}
} }
async fn response_from_proto( async fn response_from_proto(
self, self,
message: proto::LspExtExpandMacroResponse, message: proto::LspExtExpandMacroResponse,
project: Model<Project>, _: Model<Project>,
buffer: Model<Buffer>, _: Model<Buffer>,
cx: AsyncAppContext, _: AsyncAppContext,
) -> anyhow::Result<ExpandedMacro> { ) -> anyhow::Result<ExpandedMacro> {
todo!() Ok(ExpandedMacro {
name: message.name,
expansion: message.expansion,
})
} }
fn buffer_id_from_proto(message: &proto::LspExtExpandMacro) -> u64 { fn buffer_id_from_proto(message: &proto::LspExtExpandMacro) -> u64 {

View file

@ -1625,7 +1625,10 @@ message Notification {
message LspExtExpandMacro { message LspExtExpandMacro {
uint64 project_id = 1; uint64 project_id = 1;
uint64 buffer_id = 2; uint64 buffer_id = 2;
Anchor position = 3;
} }
message LspExtExpandMacroResponse { message LspExtExpandMacroResponse {
string name = 1;
string expansion = 2;
} }