Make all formatting to happen on the client's buffers, as needed

Kirill Bulatov created

Change summary

crates/language/src/proto.rs    |  41 -----------
crates/prettier/src/prettier.rs | 104 ++---------------------------
crates/project/src/project.rs   | 122 ----------------------------------
crates/rpc/proto/zed.proto      |  39 ----------
crates/rpc/src/proto.rs         |   8 --
5 files changed, 14 insertions(+), 300 deletions(-)

Detailed changes

crates/language/src/proto.rs 🔗

@@ -1,6 +1,6 @@
 use crate::{
     diagnostic_set::DiagnosticEntry, CodeAction, CodeLabel, Completion, CursorShape, Diagnostic,
-    Diff, Language,
+    Language,
 };
 use anyhow::{anyhow, Result};
 use clock::ReplicaId;
@@ -587,42 +587,3 @@ pub fn serialize_version(version: &clock::Global) -> Vec<proto::VectorClockEntry
         })
         .collect()
 }
-
-pub fn serialize_diff(diff: Diff) -> proto::Diff {
-    proto::Diff {
-        version: serialize_version(&diff.base_version),
-        line_ending: serialize_line_ending(diff.line_ending) as i32,
-        edits: diff
-            .edits
-            .into_iter()
-            .map(|(range, edit)| proto::DiffEdit {
-                range: Some(proto::Range {
-                    start: range.start as u64,
-                    end: range.end as u64,
-                }),
-                edit: edit.to_string(),
-            })
-            .collect(),
-    }
-}
-
-pub fn deserialize_diff(diff: proto::Diff) -> Diff {
-    Diff {
-        base_version: deserialize_version(&diff.version),
-        line_ending: deserialize_line_ending(
-            rpc::proto::LineEnding::from_i32(diff.line_ending)
-                .unwrap_or_else(|| panic!("invalid line ending {}", diff.line_ending)),
-        ),
-        edits: diff
-            .edits
-            .into_iter()
-            .map(|edit| {
-                let range = edit.range.expect("incorrect edit without a range");
-                (
-                    range.start as usize..range.end as usize,
-                    Arc::from(edit.edit.as_str()),
-                )
-            })
-            .collect(),
-    }
-}

crates/prettier/src/prettier.rs 🔗

@@ -3,40 +3,29 @@ use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
 use anyhow::Context;
-use client::{proto, Client};
 use collections::{HashMap, HashSet};
 use fs::Fs;
 use gpui::{AsyncAppContext, ModelHandle};
 use language::language_settings::language_settings;
-use language::proto::deserialize_diff;
 use language::{Buffer, BundledFormatter, Diff};
-use lsp::request::Request;
 use lsp::{LanguageServer, LanguageServerId};
 use node_runtime::NodeRuntime;
 use serde::{Deserialize, Serialize};
 use util::paths::DEFAULT_PRETTIER_DIR;
 
 pub enum Prettier {
-    Local(Local),
-    Remote(Remote),
+    Real(RealPrettier),
     #[cfg(any(test, feature = "test-support"))]
     Test(TestPrettier),
 }
 
-pub struct Local {
+pub struct RealPrettier {
     worktree_id: Option<usize>,
     default: bool,
     prettier_dir: PathBuf,
     server: Arc<LanguageServer>,
 }
 
-pub struct Remote {
-    project_id: u64,
-    worktree_id: Option<usize>,
-    prettier_dir: PathBuf,
-    client: Arc<Client>,
-}
-
 #[cfg(any(test, feature = "test-support"))]
 pub struct TestPrettier {
     worktree_id: Option<usize>,
@@ -74,20 +63,6 @@ impl Prettier {
     #[cfg(any(test, feature = "test-support"))]
     pub const FORMAT_SUFFIX: &str = "\nformatted by test prettier";
 
-    pub fn remote(
-        project_id: u64,
-        worktree_id: Option<usize>,
-        prettier_dir: PathBuf,
-        client: Arc<Client>,
-    ) -> Self {
-        Self::Remote(Remote {
-            project_id,
-            worktree_id,
-            prettier_dir,
-            client,
-        })
-    }
-
     pub async fn locate(
         starting_path: Option<LocateStart>,
         fs: Arc<dyn Fs>,
@@ -249,7 +224,7 @@ impl Prettier {
             .spawn(server.initialize(None))
             .await
             .context("prettier server initialization")?;
-        Ok(Self::Local(Local {
+        Ok(Self::Real(RealPrettier {
             worktree_id,
             server,
             default: prettier_dir == DEFAULT_PRETTIER_DIR.as_path(),
@@ -257,31 +232,6 @@ impl Prettier {
         }))
     }
 
-    pub async fn invoke(
-        &self,
-        buffer: Option<&ModelHandle<Buffer>>,
-        buffer_path: Option<PathBuf>,
-        method: &str,
-        cx: &AsyncAppContext,
-    ) -> anyhow::Result<Option<Diff>> {
-        match method {
-            Format::METHOD => self
-                .format(
-                    buffer.expect("missing buffer for format invocation"),
-                    buffer_path,
-                    cx,
-                )
-                .await
-                .context("invoke method")
-                .map(Some),
-            ClearCache::METHOD => {
-                self.clear_cache().await.context("invoke method")?;
-                Ok(None)
-            }
-            unknown => anyhow::bail!("Unknown method {unknown}"),
-        }
-    }
-
     pub async fn format(
         &self,
         buffer: &ModelHandle<Buffer>,
@@ -289,7 +239,7 @@ impl Prettier {
         cx: &AsyncAppContext,
     ) -> anyhow::Result<Diff> {
         match self {
-            Self::Local(local) => {
+            Self::Real(local) => {
                 let params = buffer.read_with(cx, |buffer, cx| {
                     let buffer_language = buffer.language();
                     let parsers_with_plugins = buffer_language
@@ -418,21 +368,6 @@ impl Prettier {
                 let diff_task = buffer.read_with(cx, |buffer, cx| buffer.diff(response.text, cx));
                 Ok(diff_task.await)
             }
-            Self::Remote(remote) => buffer
-                .read_with(cx, |buffer, _| {
-                    remote.client.request(proto::InvokePrettierForBuffer {
-                        buffer_id: Some(buffer.remote_id()),
-                        worktree_id: self.worktree_id().map(|id| id as u64),
-                        method: Format::METHOD.to_string(),
-                        project_id: remote.project_id,
-                        prettier_path: remote.prettier_dir.to_string_lossy().to_string(),
-                    })
-                })
-                .await
-                .context("prettier diff invoke")?
-                .diff
-                .map(deserialize_diff)
-                .context("missing diff after prettier diff invocation"),
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(_) => Ok(buffer
                 .read_with(cx, |buffer, cx| {
@@ -445,28 +380,11 @@ impl Prettier {
 
     pub async fn clear_cache(&self) -> anyhow::Result<()> {
         match self {
-            Self::Local(local) => local
+            Self::Real(local) => local
                 .server
                 .request::<ClearCache>(())
                 .await
                 .context("prettier clear cache"),
-            Self::Remote(remote) => remote
-                .client
-                .request(proto::InvokePrettierForBuffer {
-                    buffer_id: None,
-                    worktree_id: self.worktree_id().map(|id| id as u64),
-                    method: ClearCache::METHOD.to_string(),
-                    project_id: remote.project_id,
-                    prettier_path: remote.prettier_dir.to_string_lossy().to_string(),
-                })
-                .await
-                .map(|response| {
-                    debug_assert!(
-                        response.diff.is_none(),
-                        "Cleare cache invocation returned diff data"
-                    )
-                })
-                .context("prettier invoke clear cache"),
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(_) => Ok(()),
         }
@@ -474,8 +392,7 @@ impl Prettier {
 
     pub fn server(&self) -> Option<&Arc<LanguageServer>> {
         match self {
-            Self::Local(local) => Some(&local.server),
-            Self::Remote(_) => None,
+            Self::Real(local) => Some(&local.server),
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(_) => None,
         }
@@ -483,8 +400,7 @@ impl Prettier {
 
     pub fn is_default(&self) -> bool {
         match self {
-            Self::Local(local) => local.default,
-            Self::Remote(_) => false,
+            Self::Real(local) => local.default,
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(test_prettier) => test_prettier.default,
         }
@@ -492,8 +408,7 @@ impl Prettier {
 
     pub fn prettier_dir(&self) -> &Path {
         match self {
-            Self::Local(local) => &local.prettier_dir,
-            Self::Remote(remote) => &remote.prettier_dir,
+            Self::Real(local) => &local.prettier_dir,
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(test_prettier) => &test_prettier.prettier_dir,
         }
@@ -501,8 +416,7 @@ impl Prettier {
 
     pub fn worktree_id(&self) -> Option<usize> {
         match self {
-            Self::Local(local) => local.worktree_id,
-            Self::Remote(remote) => remote.worktree_id,
+            Self::Real(local) => local.worktree_id,
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(test_prettier) => test_prettier.worktree_id,
         }

crates/project/src/project.rs 🔗

@@ -37,7 +37,7 @@ use language::{
     point_to_lsp,
     proto::{
         deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
-        serialize_anchor, serialize_diff, serialize_version, split_operations,
+        serialize_anchor, serialize_version, split_operations,
     },
     range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, BundledFormatter, CachedLspAdapter,
     CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff,
@@ -613,8 +613,6 @@ impl Project {
         client.add_model_request_handler(Self::handle_open_buffer_by_path);
         client.add_model_request_handler(Self::handle_save_buffer);
         client.add_model_message_handler(Self::handle_update_diff_base);
-        client.add_model_request_handler(Self::handle_prettier_instance_for_buffer);
-        client.add_model_request_handler(Self::handle_invoke_prettier);
     }
 
     pub fn local(
@@ -8310,84 +8308,6 @@ impl Project {
         }
     }
 
-    async fn handle_prettier_instance_for_buffer(
-        this: ModelHandle<Self>,
-        envelope: TypedEnvelope<proto::PrettierInstanceForBuffer>,
-        _: Arc<Client>,
-        mut cx: AsyncAppContext,
-    ) -> anyhow::Result<proto::PrettierInstanceForBufferResponse> {
-        let prettier_instance_for_buffer_task = this.update(&mut cx, |this, cx| {
-            let buffer = this
-                .opened_buffers
-                .get(&envelope.payload.buffer_id)
-                .and_then(|buffer| buffer.upgrade(cx))
-                .with_context(|| format!("unknown buffer id {}", envelope.payload.buffer_id))?;
-            anyhow::Ok(this.prettier_instance_for_buffer(&buffer, cx))
-        })?;
-
-        let prettier_path = match prettier_instance_for_buffer_task.await {
-            Some(prettier) => match prettier.await {
-                Ok(prettier) => Some(prettier.prettier_dir().display().to_string()),
-                Err(e) => {
-                    anyhow::bail!("Failed to create prettier instance for remote request: {e:#}")
-                }
-            },
-            None => None,
-        };
-        Ok(proto::PrettierInstanceForBufferResponse { prettier_path })
-    }
-
-    async fn handle_invoke_prettier(
-        this: ModelHandle<Self>,
-        envelope: TypedEnvelope<proto::InvokePrettierForBuffer>,
-        _: Arc<Client>,
-        mut cx: AsyncAppContext,
-    ) -> anyhow::Result<proto::InvokePrettierForBufferResponse> {
-        let prettier = this
-            .read_with(&cx, |this, _| {
-                this.prettier_instances
-                    .get(&(
-                        envelope.payload.worktree_id.map(WorktreeId::from_proto),
-                        PathBuf::from(&envelope.payload.prettier_path),
-                    ))
-                    .cloned()
-            })
-            .with_context(|| {
-                format!(
-                    "Missing prettier for worktree {:?} and path {:?}",
-                    envelope.payload.worktree_id, envelope.payload.prettier_path,
-                )
-            })?
-            .await;
-        let prettier = match prettier {
-            Ok(prettier) => prettier,
-            Err(e) => anyhow::bail!("Prettier instance failed to start: {e:#}"),
-        };
-
-        let buffer = this.update(&mut cx, |this, cx| {
-            envelope
-                .payload
-                .buffer_id
-                .and_then(|id| this.opened_buffers.get(&id))
-                .and_then(|buffer| buffer.upgrade(cx))
-        });
-
-        let buffer_path = buffer.as_ref().and_then(|buffer| {
-            buffer.read_with(&cx, |buffer, cx| {
-                File::from_dyn(buffer.file()).map(|f| f.full_path(cx))
-            })
-        });
-
-        let diff = prettier
-            .invoke(buffer.as_ref(), buffer_path, &envelope.payload.method, &cx)
-            .await
-            .with_context(|| format!("prettier invoke method {}", &envelope.payload.method))?;
-
-        Ok(proto::InvokePrettierForBufferResponse {
-            diff: diff.map(serialize_diff),
-        })
-    }
-
     fn prettier_instance_for_buffer(
         &mut self,
         buffer: &ModelHandle<Buffer>,
@@ -8531,44 +8451,8 @@ impl Project {
                 });
                 Some(new_prettier_task)
             })
-        } else if let Some(project_id) = self.remote_id() {
-            let client = self.client.clone();
-            let request = proto::PrettierInstanceForBuffer {
-                project_id,
-                buffer_id: buffer.remote_id(),
-            };
-            cx.spawn(|this, mut cx| async move {
-                match client.request(request).await {
-                    Ok(response) => {
-                        response
-                            .prettier_path
-                            .map(PathBuf::from)
-                            .map(|prettier_path| {
-                                let prettier_task = Task::ready(
-                                    Ok(Arc::new(Prettier::remote(
-                                        project_id,
-                                        worktree_id.map(|id| id.to_usize()),
-                                        prettier_path.clone(),
-                                        client,
-                                    )))
-                                    .map_err(Arc::new),
-                                )
-                                .shared();
-                                this.update(&mut cx, |project, _| {
-                                    project.prettier_instances.insert(
-                                        (worktree_id, prettier_path),
-                                        prettier_task.clone(),
-                                    );
-                                });
-                                prettier_task
-                            })
-                    }
-                    Err(e) => {
-                        log::error!("Prettier init remote request failed: {e:#}");
-                        None
-                    }
-                }
-            })
+        } else if self.remote_id().is_some() {
+            return Task::ready(None);
         } else {
             Task::ready(Some(
                 Task::ready(Err(Arc::new(anyhow!("project does not have a remote id")))).shared(),

crates/rpc/proto/zed.proto 🔗

@@ -170,12 +170,7 @@ message Envelope {
 
         LinkChannel link_channel = 140;
         UnlinkChannel unlink_channel = 141;
-        MoveChannel move_channel = 142;
-
-        PrettierInstanceForBuffer prettier_instance_for_buffer = 145;
-        PrettierInstanceForBufferResponse prettier_instance_for_buffer_response = 146;
-        InvokePrettierForBuffer invoke_prettier_for_buffer = 147;
-        InvokePrettierForBufferResponse invoke_prettier_for_buffer_response = 148;  // Current max: 148
+        MoveChannel move_channel = 142; // Current max: 144
     }
 }
 
@@ -1562,35 +1557,3 @@ message UpdateDiffBase {
     uint64 buffer_id = 2;
     optional string diff_base = 3;
 }
-
-message PrettierInstanceForBuffer {
-    uint64 project_id = 1;
-    uint64 buffer_id = 2;
-}
-
-message PrettierInstanceForBufferResponse {
-    optional string prettier_path = 1;
-}
-
-message InvokePrettierForBuffer {
-    uint64 project_id = 1;
-    string prettier_path = 2;
-    optional uint64 buffer_id = 3;
-    optional uint64 worktree_id = 4;
-    string method = 5;
-}
-
-message InvokePrettierForBufferResponse {
-    optional Diff diff = 1;
-}
-
-message Diff {
-    repeated VectorClockEntry version = 1;
-    LineEnding line_ending = 2;
-    repeated DiffEdit edits = 3;
-}
-
-message DiffEdit {
-    Range range = 1;
-    string edit = 2;
-}

crates/rpc/src/proto.rs 🔗

@@ -273,10 +273,6 @@ messages!(
     (UpdateChannelBufferCollaborators, Foreground),
     (AckBufferOperation, Background),
     (AckChannelMessage, Background),
-    (PrettierInstanceForBuffer, Background),
-    (InvokePrettierForBuffer, Background),
-    (PrettierInstanceForBufferResponse, Background),
-    (InvokePrettierForBufferResponse, Background),
 );
 
 request_messages!(
@@ -354,8 +350,6 @@ request_messages!(
     (UpdateWorktree, Ack),
     (JoinChannelBuffer, JoinChannelBufferResponse),
     (LeaveChannelBuffer, Ack),
-    (PrettierInstanceForBuffer, PrettierInstanceForBufferResponse),
-    (InvokePrettierForBuffer, InvokePrettierForBufferResponse),
 );
 
 entity_messages!(
@@ -407,8 +401,6 @@ entity_messages!(
     UpdateWorktree,
     UpdateWorktreeSettings,
     UpdateDiffBase,
-    PrettierInstanceForBuffer,
-    InvokePrettierForBuffer,
 );
 
 entity_messages!(