Fix minor issues pointed out in the review

Isaac Clayton created

Change summary

crates/collab/src/integration_tests.rs        | 285 ++++++++++----------
crates/editor/src/display_map.rs              |  18 
crates/editor/src/editor.rs                   |  46 +-
crates/editor/src/test.rs                     |  10 
crates/language/src/language.rs               |  35 -
crates/language/src/proto.rs                  |  20 
crates/plugin/Cargo.toml                      |   2 
crates/plugin/src/lib.rs                      |   5 
crates/plugin_macros/src/lib.rs               |   1 
crates/plugin_runtime/README.md               |   1 
crates/plugin_runtime/build.rs                |   4 
crates/plugin_runtime/src/plugin.rs           |   4 
crates/project/src/project_tests.rs           | 124 +++++---
crates/project_symbols/src/project_symbols.rs |   4 
crates/zed/src/languages/go.rs                |   2 
crates/zed/src/languages/rust.rs              |   4 
crates/zed/src/main.rs                        |   6 
17 files changed, 297 insertions(+), 274 deletions(-)

Detailed changes

crates/collab/src/integration_tests.rs 🔗

@@ -1440,7 +1440,7 @@ async fn test_collaborating_with_diagnostics(
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     // Share a project as client A
@@ -1675,16 +1675,18 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        capabilities: lsp::ServerCapabilities {
-            completion_provider: Some(lsp::CompletionOptions {
-                trigger_characters: Some(vec![".".to_string()]),
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                completion_provider: Some(lsp::CompletionOptions {
+                    trigger_characters: Some(vec![".".to_string()]),
+                    ..Default::default()
+                }),
                 ..Default::default()
-            }),
+            },
             ..Default::default()
-        },
-        ..Default::default()
-    }));
+        }))
+        .await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -1928,7 +1930,7 @@ async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     // Here we insert a fake tree with a directory that exists on disk. This is needed
@@ -2014,7 +2016,7 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -2123,7 +2125,7 @@ async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -2303,7 +2305,7 @@ async fn test_document_highlights(cx_a: &mut TestAppContext, cx_b: &mut TestAppC
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
@@ -2400,7 +2402,7 @@ async fn test_lsp_hover(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
@@ -2488,7 +2490,7 @@ async fn test_project_symbols(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -2591,7 +2593,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -2662,7 +2664,7 @@ async fn test_collaborating_with_code_actions(
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -2867,16 +2869,18 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        capabilities: lsp::ServerCapabilities {
-            rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
-                prepare_provider: Some(true),
-                work_done_progress_options: Default::default(),
-            })),
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
+                    prepare_provider: Some(true),
+                    work_done_progress_options: Default::default(),
+                })),
+                ..Default::default()
+            },
             ..Default::default()
-        },
-        ..Default::default()
-    }));
+        }))
+        .await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -3051,10 +3055,12 @@ async fn test_language_server_statuses(
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "the-language-server",
-        ..Default::default()
-    }));
+    let mut fake_language_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "the-language-server",
+            ..Default::default()
+        }))
+        .await;
     client_a.language_registry.add(Arc::new(language));
 
     client_a
@@ -4577,119 +4583,124 @@ async fn test_random_collaboration(
         },
         None,
     );
-    let _fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "the-fake-language-server",
-        capabilities: lsp::LanguageServer::full_capabilities(),
-        initializer: Some(Box::new({
-            let rng = rng.clone();
-            let fs = fs.clone();
-            let project = host_project.downgrade();
-            move |fake_server: &mut FakeLanguageServer| {
-                fake_server.handle_request::<lsp::request::Completion, _, _>(|_, _| async move {
-                    Ok(Some(lsp::CompletionResponse::Array(vec![
-                        lsp::CompletionItem {
-                            text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-                                range: lsp::Range::new(
-                                    lsp::Position::new(0, 0),
-                                    lsp::Position::new(0, 0),
-                                ),
-                                new_text: "the-new-text".to_string(),
-                            })),
-                            ..Default::default()
+    let _fake_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "the-fake-language-server",
+            capabilities: lsp::LanguageServer::full_capabilities(),
+            initializer: Some(Box::new({
+                let rng = rng.clone();
+                let fs = fs.clone();
+                let project = host_project.downgrade();
+                move |fake_server: &mut FakeLanguageServer| {
+                    fake_server.handle_request::<lsp::request::Completion, _, _>(
+                        |_, _| async move {
+                            Ok(Some(lsp::CompletionResponse::Array(vec![
+                                lsp::CompletionItem {
+                                    text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                                        range: lsp::Range::new(
+                                            lsp::Position::new(0, 0),
+                                            lsp::Position::new(0, 0),
+                                        ),
+                                        new_text: "the-new-text".to_string(),
+                                    })),
+                                    ..Default::default()
+                                },
+                            ])))
                         },
-                    ])))
-                });
-
-                fake_server.handle_request::<lsp::request::CodeActionRequest, _, _>(
-                    |_, _| async move {
-                        Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
-                            lsp::CodeAction {
-                                title: "the-code-action".to_string(),
-                                ..Default::default()
-                            },
-                        )]))
-                    },
-                );
+                    );
 
-                fake_server.handle_request::<lsp::request::PrepareRenameRequest, _, _>(
-                    |params, _| async move {
-                        Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
-                            params.position,
-                            params.position,
-                        ))))
-                    },
-                );
+                    fake_server.handle_request::<lsp::request::CodeActionRequest, _, _>(
+                        |_, _| async move {
+                            Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
+                                lsp::CodeAction {
+                                    title: "the-code-action".to_string(),
+                                    ..Default::default()
+                                },
+                            )]))
+                        },
+                    );
 
-                fake_server.handle_request::<lsp::request::GotoDefinition, _, _>({
-                    let fs = fs.clone();
-                    let rng = rng.clone();
-                    move |_, _| {
+                    fake_server.handle_request::<lsp::request::PrepareRenameRequest, _, _>(
+                        |params, _| async move {
+                            Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
+                                params.position,
+                                params.position,
+                            ))))
+                        },
+                    );
+
+                    fake_server.handle_request::<lsp::request::GotoDefinition, _, _>({
                         let fs = fs.clone();
                         let rng = rng.clone();
-                        async move {
-                            let files = fs.files().await;
-                            let mut rng = rng.lock();
-                            let count = rng.gen_range::<usize, _>(1..3);
-                            let files = (0..count)
-                                .map(|_| files.choose(&mut *rng).unwrap())
-                                .collect::<Vec<_>>();
-                            log::info!("LSP: Returning definitions in files {:?}", &files);
-                            Ok(Some(lsp::GotoDefinitionResponse::Array(
-                                files
-                                    .into_iter()
-                                    .map(|file| lsp::Location {
-                                        uri: lsp::Url::from_file_path(file).unwrap(),
-                                        range: Default::default(),
-                                    })
-                                    .collect(),
-                            )))
+                        move |_, _| {
+                            let fs = fs.clone();
+                            let rng = rng.clone();
+                            async move {
+                                let files = fs.files().await;
+                                let mut rng = rng.lock();
+                                let count = rng.gen_range::<usize, _>(1..3);
+                                let files = (0..count)
+                                    .map(|_| files.choose(&mut *rng).unwrap())
+                                    .collect::<Vec<_>>();
+                                log::info!("LSP: Returning definitions in files {:?}", &files);
+                                Ok(Some(lsp::GotoDefinitionResponse::Array(
+                                    files
+                                        .into_iter()
+                                        .map(|file| lsp::Location {
+                                            uri: lsp::Url::from_file_path(file).unwrap(),
+                                            range: Default::default(),
+                                        })
+                                        .collect(),
+                                )))
+                            }
                         }
-                    }
-                });
-
-                fake_server.handle_request::<lsp::request::DocumentHighlightRequest, _, _>({
-                    let rng = rng.clone();
-                    let project = project.clone();
-                    move |params, mut cx| {
-                        let highlights = if let Some(project) = project.upgrade(&cx) {
-                            project.update(&mut cx, |project, cx| {
-                                let path = params
-                                    .text_document_position_params
-                                    .text_document
-                                    .uri
-                                    .to_file_path()
-                                    .unwrap();
-                                let (worktree, relative_path) =
-                                    project.find_local_worktree(&path, cx)?;
-                                let project_path =
-                                    ProjectPath::from((worktree.read(cx).id(), relative_path));
-                                let buffer = project.get_open_buffer(&project_path, cx)?.read(cx);
-
-                                let mut highlights = Vec::new();
-                                let highlight_count = rng.lock().gen_range(1..=5);
-                                let mut prev_end = 0;
-                                for _ in 0..highlight_count {
-                                    let range =
-                                        buffer.random_byte_range(prev_end, &mut *rng.lock());
-
-                                    highlights.push(lsp::DocumentHighlight {
-                                        range: range_to_lsp(range.to_point_utf16(buffer)),
-                                        kind: Some(lsp::DocumentHighlightKind::READ),
-                                    });
-                                    prev_end = range.end;
-                                }
-                                Some(highlights)
-                            })
-                        } else {
-                            None
-                        };
-                        async move { Ok(highlights) }
-                    }
-                });
-            }
-        })),
-        ..Default::default()
-    }));
+                    });
+
+                    fake_server.handle_request::<lsp::request::DocumentHighlightRequest, _, _>({
+                        let rng = rng.clone();
+                        let project = project.clone();
+                        move |params, mut cx| {
+                            let highlights = if let Some(project) = project.upgrade(&cx) {
+                                project.update(&mut cx, |project, cx| {
+                                    let path = params
+                                        .text_document_position_params
+                                        .text_document
+                                        .uri
+                                        .to_file_path()
+                                        .unwrap();
+                                    let (worktree, relative_path) =
+                                        project.find_local_worktree(&path, cx)?;
+                                    let project_path =
+                                        ProjectPath::from((worktree.read(cx).id(), relative_path));
+                                    let buffer =
+                                        project.get_open_buffer(&project_path, cx)?.read(cx);
+
+                                    let mut highlights = Vec::new();
+                                    let highlight_count = rng.lock().gen_range(1..=5);
+                                    let mut prev_end = 0;
+                                    for _ in 0..highlight_count {
+                                        let range =
+                                            buffer.random_byte_range(prev_end, &mut *rng.lock());
+
+                                        highlights.push(lsp::DocumentHighlight {
+                                            range: range_to_lsp(range.to_point_utf16(buffer)),
+                                            kind: Some(lsp::DocumentHighlightKind::READ),
+                                        });
+                                        prev_end = range.end;
+                                    }
+                                    Some(highlights)
+                                })
+                            } else {
+                                None
+                            };
+                            async move { Ok(highlights) }
+                        }
+                    });
+                }
+            })),
+            ..Default::default()
+        }))
+        .await;
     host_language_registry.add(Arc::new(language));
 
     let op_start_signal = futures::channel::mpsc::unbounded();

crates/editor/src/display_map.rs 🔗

@@ -959,10 +959,10 @@ pub mod tests {
             }"#
         .unindent();
 
-        let theme = Arc::new(SyntaxTheme::new(vec![
+        let theme = SyntaxTheme::new(vec![
             ("mod.body".to_string(), Color::red().into()),
             ("fn.name".to_string(), Color::blue().into()),
-        ]));
+        ]);
         let language = Arc::new(
             Language::new(
                 LanguageConfig {
@@ -980,7 +980,7 @@ pub mod tests {
             )
             .unwrap(),
         );
-        language.set_theme(theme.clone());
+        language.set_theme(&theme);
         cx.update(|cx| {
             let mut settings = Settings::test(cx);
             settings.language_settings.tab_size = Some(2.try_into().unwrap());
@@ -1049,10 +1049,10 @@ pub mod tests {
             }"#
         .unindent();
 
-        let theme = Arc::new(SyntaxTheme::new(vec![
+        let theme = SyntaxTheme::new(vec![
             ("mod.body".to_string(), Color::red().into()),
             ("fn.name".to_string(), Color::blue().into()),
-        ]));
+        ]);
         let language = Arc::new(
             Language::new(
                 LanguageConfig {
@@ -1070,7 +1070,7 @@ pub mod tests {
             )
             .unwrap(),
         );
-        language.set_theme(theme.clone());
+        language.set_theme(&theme);
 
         cx.update(|cx| cx.set_global(Settings::test(cx)));
 
@@ -1120,10 +1120,10 @@ pub mod tests {
         cx.foreground().set_block_on_ticks(usize::MAX..=usize::MAX);
 
         cx.update(|cx| cx.set_global(Settings::test(cx)));
-        let theme = Arc::new(SyntaxTheme::new(vec![
+        let theme = SyntaxTheme::new(vec![
             ("operator".to_string(), Color::red().into()),
             ("string".to_string(), Color::green().into()),
-        ]));
+        ]);
         let language = Arc::new(
             Language::new(
                 LanguageConfig {
@@ -1141,7 +1141,7 @@ pub mod tests {
             )
             .unwrap(),
         );
-        language.set_theme(theme.clone());
+        language.set_theme(&theme);
 
         let (text, highlighted_ranges) = marked_text_ranges(r#"const[] [a]: B = "c [d]""#);
 

crates/editor/src/editor.rs 🔗

@@ -9302,13 +9302,15 @@ mod tests {
             },
             Some(tree_sitter_rust::language()),
         );
-        let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-            capabilities: lsp::ServerCapabilities {
-                document_formatting_provider: Some(lsp::OneOf::Left(true)),
+        let mut fake_servers = language
+            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+                capabilities: lsp::ServerCapabilities {
+                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
+                    ..Default::default()
+                },
                 ..Default::default()
-            },
-            ..Default::default()
-        }));
+            }))
+            .await;
 
         let fs = FakeFs::new(cx.background().clone());
         fs.insert_file("/file.rs", Default::default()).await;
@@ -9414,13 +9416,15 @@ mod tests {
             },
             Some(tree_sitter_rust::language()),
         );
-        let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-            capabilities: lsp::ServerCapabilities {
-                document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
+        let mut fake_servers = language
+            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+                capabilities: lsp::ServerCapabilities {
+                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
+                    ..Default::default()
+                },
                 ..Default::default()
-            },
-            ..Default::default()
-        }));
+            }))
+            .await;
 
         let fs = FakeFs::new(cx.background().clone());
         fs.insert_file("/file.rs", Default::default()).await;
@@ -9526,16 +9530,18 @@ mod tests {
             },
             Some(tree_sitter_rust::language()),
         );
-        let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-            capabilities: lsp::ServerCapabilities {
-                completion_provider: Some(lsp::CompletionOptions {
-                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
+        let mut fake_servers = language
+            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+                capabilities: lsp::ServerCapabilities {
+                    completion_provider: Some(lsp::CompletionOptions {
+                        trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
+                        ..Default::default()
+                    }),
                     ..Default::default()
-                }),
+                },
                 ..Default::default()
-            },
-            ..Default::default()
-        }));
+            }))
+            .await;
 
         let text = "
             one

crates/editor/src/test.rs 🔗

@@ -457,10 +457,12 @@ impl<'a> EditorLspTestContext<'a> {
                 .unwrap_or(&"txt".to_string())
         );
 
-        let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-            capabilities,
-            ..Default::default()
-        }));
+        let mut fake_servers = language
+            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+                capabilities,
+                ..Default::default()
+            }))
+            .await;
 
         let project = Project::test(params.fs.clone(), [], cx).await;
         project.update(cx, |project, _| project.languages().add(Arc::new(language)));

crates/language/src/language.rs 🔗

@@ -31,7 +31,7 @@ use std::{
     str,
     sync::Arc,
 };
-use theme::SyntaxTheme;
+use theme::{SyntaxTheme, Theme};
 use tree_sitter::{self, Query};
 use util::ResultExt;
 
@@ -255,9 +255,6 @@ fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D
     }
 }
 
-// #[cfg(any(test, feature = "test-support"))]
-// pub type FakeLspAdapter = Arc<FakeLspAdapterInner>;
-
 #[cfg(any(test, feature = "test-support"))]
 pub struct FakeLspAdapter {
     pub name: &'static str,
@@ -279,7 +276,6 @@ pub struct Language {
     pub(crate) config: LanguageConfig,
     pub(crate) grammar: Option<Arc<Grammar>>,
     pub(crate) adapter: Option<Arc<LspAdapter>>,
-    pub(crate) theme: RwLock<Option<Arc<SyntaxTheme>>>,
 
     #[cfg(any(test, feature = "test-support"))]
     fake_adapter: Option<(
@@ -319,7 +315,7 @@ pub struct LanguageRegistry {
         >,
     >,
     subscription: RwLock<(watch::Sender<()>, watch::Receiver<()>)>,
-    theme: RwLock<Option<Arc<SyntaxTheme>>>,
+    theme: RwLock<Option<Arc<Theme>>>,
 }
 
 impl LanguageRegistry {
@@ -344,7 +340,7 @@ impl LanguageRegistry {
 
     pub fn add(&self, language: Arc<Language>) {
         if let Some(theme) = self.theme.read().clone() {
-            language.set_theme(theme);
+            language.set_theme(&theme.editor.syntax);
         }
         self.languages.write().push(language.clone());
         *self.subscription.write().0.borrow_mut() = ();
@@ -354,10 +350,10 @@ impl LanguageRegistry {
         self.subscription.read().1.clone()
     }
 
-    pub fn set_theme(&self, theme: Arc<SyntaxTheme>) {
+    pub fn set_theme(&self, theme: Arc<Theme>) {
         *self.theme.write() = Some(theme.clone());
         for language in self.languages.read().iter() {
-            language.set_theme(theme.clone());
+            language.set_theme(&theme.editor.syntax);
         }
     }
 
@@ -579,7 +575,6 @@ impl Language {
                 })
             }),
             adapter: None,
-            theme: Default::default(),
 
             #[cfg(any(test, feature = "test-support"))]
             fake_adapter: None,
@@ -624,13 +619,13 @@ impl Language {
     }
 
     #[cfg(any(test, feature = "test-support"))]
-    pub fn set_fake_lsp_adapter(
+    pub async fn set_fake_lsp_adapter(
         &mut self,
         fake_lsp_adapter: Arc<FakeLspAdapter>,
     ) -> mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
         let (servers_tx, servers_rx) = mpsc::unbounded();
         self.fake_adapter = Some((servers_tx, fake_lsp_adapter.clone()));
-        let adapter = smol::block_on(LspAdapter::new(fake_lsp_adapter));
+        let adapter = LspAdapter::new(fake_lsp_adapter).await;
         self.adapter = Some(adapter);
         servers_rx
     }
@@ -716,21 +711,11 @@ impl Language {
         c.is_whitespace() || self.config.autoclose_before.contains(c)
     }
 
-    /// Sets the theme to the given theme, and then calls [`highlight`].
-    pub fn set_theme(&self, theme: Arc<SyntaxTheme>) {
-        *self.theme.write() = Some(theme.clone());
-        self.highlight()
-    }
-
-    /// Highlights the grammar according to the current theme,
-    /// if one has been set using [`set_theme`].
-    pub fn highlight(&self) {
+    pub fn set_theme(&self, theme: &SyntaxTheme) {
         if let Some(grammar) = self.grammar.as_ref() {
             if let Some(highlights_query) = &grammar.highlights_query {
-                if let Some(theme) = self.theme.read().as_ref() {
-                    *grammar.highlight_map.lock() =
-                        HighlightMap::new(highlights_query.capture_names(), &theme);
-                }
+                *grammar.highlight_map.lock() =
+                    HighlightMap::new(highlights_query.capture_names(), theme);
             }
         }
     }

crates/language/src/proto.rs 🔗

@@ -410,20 +410,18 @@ pub async fn deserialize_completion(
         .and_then(deserialize_anchor)
         .ok_or_else(|| anyhow!("invalid old end"))?;
     let lsp_completion = serde_json::from_slice(&completion.lsp_completion)?;
+    let label = match language {
+        Some(l) => l.label_for_completion(&lsp_completion).await,
+        None => None,
+    };
+
     Ok(Completion {
         old_range: old_start..old_end,
         new_text: completion.new_text,
-        label: {
-            let label = match language {
-                Some(l) => l.label_for_completion(&lsp_completion).await,
-                None => None,
-            };
-
-            label.unwrap_or(CodeLabel::plain(
-                lsp_completion.label.clone(),
-                lsp_completion.filter_text.as_deref(),
-            ))
-        },
+        label: label.unwrap_or(CodeLabel::plain(
+            lsp_completion.label.clone(),
+            lsp_completion.filter_text.as_deref(),
+        )),
         lsp_completion,
     })
 }

crates/plugin/Cargo.toml 🔗

@@ -6,4 +6,4 @@ edition = "2021"
 [dependencies]
 serde = "1.0"
 bincode = "1.3"
-plugin_macros = { path = "../plugin_macros" }
+plugin_macros = { path = "../plugin_macros" }

crates/plugin/src/lib.rs 🔗

@@ -1,7 +1,10 @@
 pub use bincode;
 pub use serde;
 
-// TODO: move the implementation to one place?
+/// This is the buffer that is used Wasm side.
+/// Note that it mirrors the functionality of
+/// the `WasiBuffer` found in `plugin_runtime/src/plugin.rs`,
+/// But has a few different methods.
 pub struct __Buffer {
     pub ptr: u32, // *const u8,
     pub len: u32, // usize,

crates/plugin_macros/src/lib.rs 🔗

@@ -67,7 +67,6 @@ pub fn export(args: TokenStream, function: TokenStream) -> TokenStream {
         #inner_fn
 
         #[no_mangle]
-        // TODO: switch len from usize to u32?
         pub extern "C" fn #outer_fn_name(packed_buffer: u64) -> u64 {
             // setup
             let data = unsafe { ::plugin::__Buffer::from_u64(packed_buffer).to_vec() };

crates/plugin_runtime/README.md 🔗

@@ -31,6 +31,7 @@ All functions that Plugin exports must have the following properties:
 Additionally, Plugin must export an:
 
 - `__alloc_buffer` function that, given a `u32` length, returns a `u32` pointer to a buffer of that length.
+- `__free_buffer` function that, given a buffer encoded as a `u64`, frees the buffer at the given location, and does not return anything.
 
 Note that all of these requirements are automatically fullfilled for any Rust Wasm plugin that uses the `plugin` crate, and imports the `prelude`. 
 

crates/plugin_runtime/build.rs 🔗

@@ -4,8 +4,8 @@ use wasmtime::{Config, Engine};
 fn main() {
     let base = Path::new("../../plugins");
 
-    // println!("cargo:rerun-if-changed=../../plugins/*");
-    println!("cargo:warning=Precompiling plugins...");
+    println!("cargo:rerun-if-changed={}", base.display());
+    println!("cargo:warning=Rebuilding precompiled plugins...");
 
     let _ = std::fs::remove_dir_all(base.join("bin"));
     let _ =

crates/plugin_runtime/src/plugin.rs 🔗

@@ -16,7 +16,9 @@ use wasmtime_wasi::{Dir, WasiCtx, WasiCtxBuilder};
 /// Represents a resource currently managed by the plugin, like a file descriptor.
 pub struct PluginResource(u32);
 
-#[repr(C)]
+/// This is the buffer that is used Host side.
+/// Note that it mirrors the functionality of
+/// the `__Buffer` found in the `plugin/src/lib.rs` prelude.
 struct WasiBuffer {
     ptr: u32,
     len: u32,

crates/project/src/project_tests.rs 🔗

@@ -86,28 +86,32 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
         },
         None,
     );
-    let mut fake_rust_servers = rust_language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "the-rust-language-server",
-        capabilities: lsp::ServerCapabilities {
-            completion_provider: Some(lsp::CompletionOptions {
-                trigger_characters: Some(vec![".".to_string(), "::".to_string()]),
+    let mut fake_rust_servers = rust_language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "the-rust-language-server",
+            capabilities: lsp::ServerCapabilities {
+                completion_provider: Some(lsp::CompletionOptions {
+                    trigger_characters: Some(vec![".".to_string(), "::".to_string()]),
+                    ..Default::default()
+                }),
                 ..Default::default()
-            }),
+            },
             ..Default::default()
-        },
-        ..Default::default()
-    }));
-    let mut fake_json_servers = json_language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "the-json-language-server",
-        capabilities: lsp::ServerCapabilities {
-            completion_provider: Some(lsp::CompletionOptions {
-                trigger_characters: Some(vec![":".to_string()]),
+        }))
+        .await;
+    let mut fake_json_servers = json_language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "the-json-language-server",
+            capabilities: lsp::ServerCapabilities {
+                completion_provider: Some(lsp::CompletionOptions {
+                    trigger_characters: Some(vec![":".to_string()]),
+                    ..Default::default()
+                }),
                 ..Default::default()
-            }),
+            },
             ..Default::default()
-        },
-        ..Default::default()
-    }));
+        }))
+        .await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -646,11 +650,13 @@ async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        disk_based_diagnostics_progress_token: Some(progress_token.into()),
-        disk_based_diagnostics_sources: vec!["disk".into()],
-        ..Default::default()
-    }));
+    let mut fake_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            disk_based_diagnostics_progress_token: Some(progress_token.into()),
+            disk_based_diagnostics_sources: vec!["disk".into()],
+            ..Default::default()
+        }))
+        .await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -769,11 +775,13 @@ async fn test_restarting_server_with_diagnostics_running(cx: &mut gpui::TestAppC
         },
         None,
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        disk_based_diagnostics_sources: vec!["disk".into()],
-        disk_based_diagnostics_progress_token: Some(progress_token.into()),
-        ..Default::default()
-    }));
+    let mut fake_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            disk_based_diagnostics_sources: vec!["disk".into()],
+            disk_based_diagnostics_progress_token: Some(progress_token.into()),
+            ..Default::default()
+        }))
+        .await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree("/dir", json!({ "a.rs": "" })).await;
@@ -848,10 +856,12 @@ async fn test_toggling_enable_language_server(
         },
         None,
     );
-    let mut fake_rust_servers = rust.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "rust-lsp",
-        ..Default::default()
-    }));
+    let mut fake_rust_servers = rust
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "rust-lsp",
+            ..Default::default()
+        }))
+        .await;
     let mut js = Language::new(
         LanguageConfig {
             name: Arc::from("JavaScript"),
@@ -860,10 +870,12 @@ async fn test_toggling_enable_language_server(
         },
         None,
     );
-    let mut fake_js_servers = js.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        name: "js-lsp",
-        ..Default::default()
-    }));
+    let mut fake_js_servers = js
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            name: "js-lsp",
+            ..Default::default()
+        }))
+        .await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree("/dir", json!({ "a.rs": "", "b.js": "" }))
@@ -969,10 +981,12 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        disk_based_diagnostics_sources: vec!["disk".into()],
-        ..Default::default()
-    }));
+    let mut fake_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            disk_based_diagnostics_sources: vec!["disk".into()],
+            ..Default::default()
+        }))
+        .await;
 
     let text = "
         fn a() { A }
@@ -1311,7 +1325,7 @@ async fn test_edits_from_lsp_with_past_version(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_servers = language.set_fake_lsp_adapter(Default::default()).await;
 
     let text = "
         fn a() {
@@ -1712,7 +1726,7 @@ async fn test_definition(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_servers = language.set_fake_lsp_adapter(Default::default()).await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -1811,7 +1825,7 @@ async fn test_completions_without_edit_ranges(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_typescript::language_typescript()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -1895,7 +1909,7 @@ async fn test_completions_with_carriage_returns(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_typescript::language_typescript()),
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -1948,7 +1962,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) {
         },
         None,
     );
-    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
+    let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(
@@ -2876,16 +2890,18 @@ async fn test_rename(cx: &mut gpui::TestAppContext) {
         },
         Some(tree_sitter_rust::language()),
     );
-    let mut fake_servers = language.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
-        capabilities: lsp::ServerCapabilities {
-            rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
-                prepare_provider: Some(true),
-                work_done_progress_options: Default::default(),
-            })),
+    let mut fake_servers = language
+        .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
+            capabilities: lsp::ServerCapabilities {
+                rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
+                    prepare_provider: Some(true),
+                    work_done_progress_options: Default::default(),
+                })),
+                ..Default::default()
+            },
             ..Default::default()
-        },
-        ..Default::default()
-    }));
+        }))
+        .await;
 
     let fs = FakeFs::new(cx.background());
     fs.insert_tree(

crates/project_symbols/src/project_symbols.rs 🔗

@@ -290,7 +290,9 @@ mod tests {
             },
             None,
         );
-        let mut fake_servers = language.set_fake_lsp_adapter(Arc::<FakeLspAdapter>::default());
+        let mut fake_servers = language
+            .set_fake_lsp_adapter(Arc::<FakeLspAdapter>::default())
+            .await;
 
         let fs = FakeFs::new(cx.background());
         fs.insert_tree("/dir", json!({ "test.rs": "" })).await;

crates/zed/src/languages/go.rs 🔗

@@ -324,7 +324,7 @@ mod tests {
             ("number".into(), Color::yellow().into()),
             ("property".into(), Color::white().into()),
         ]);
-        language.set_theme(theme.into());
+        language.set_theme(&theme);
 
         let grammar = language.grammar().unwrap();
         let highlight_function = grammar.highlight_id_for_name("function").unwrap();

crates/zed/src/languages/rust.rs 🔗

@@ -315,7 +315,7 @@ mod tests {
             ("property".into(), Color::white().into()),
         ]);
 
-        language.set_theme(theme.into());
+        language.set_theme(&theme);
 
         let highlight_function = grammar.highlight_id_for_name("function").unwrap();
         let highlight_type = grammar.highlight_id_for_name("type").unwrap();
@@ -394,7 +394,7 @@ mod tests {
             ("property".into(), Color::white().into()),
         ]);
 
-        language.set_theme(theme.into());
+        language.set_theme(&theme);
 
         let highlight_function = grammar.highlight_id_for_name("function").unwrap();
         let highlight_type = grammar.highlight_id_for_name("type").unwrap();

crates/zed/src/main.rs 🔗

@@ -217,7 +217,7 @@ fn main() {
         cx.observe_global::<Settings, _>({
             let languages = languages.clone();
             move |cx| {
-                languages.set_theme(cx.global::<Settings>().theme.editor.syntax.clone());
+                languages.set_theme(cx.global::<Settings>().theme.clone());
             }
         })
         .detach();
@@ -225,9 +225,7 @@ fn main() {
         cx.spawn({
             let languages = languages.clone();
             |cx| async move {
-                cx.read(|cx| {
-                    languages.set_theme(cx.global::<Settings>().theme.editor.syntax.clone())
-                });
+                cx.read(|cx| languages.set_theme(cx.global::<Settings>().theme.clone()));
                 init_languages.await;
             }
         })