Fix issues with extension API that come up when moving Svelte into an extension (#9611)

We're doing it. Svelte support is moving into an extension. This PR
fixes some issues that came up along the way.

Notes

* extensions need to be able to retrieve the path the `node` binary
installed by Zed
* previously we were silently swallowing any errors that occurred while
loading a grammar
* npm commands ran by extensions weren't run in the right directory
* Tree-sitter's WASM stdlib didn't support a C function (`strncmp`)
needed by the Svelte parser's external scanner
* the way that LSP installation status was reported was unnecessarily
complex

Release Notes:

- Removed built-in support for the Svelte and Gleam languages, because
full support for those languages is now available via extensions. These
extensions will be suggested for download when you open a `.svelte` or
`.gleam` file.

---------

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-03-22 17:29:06 -07:00 committed by GitHub
parent 4459eacc98
commit 6ebe599c98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
70 changed files with 1278 additions and 1223 deletions

View file

@ -25,7 +25,7 @@ use sum_tree::Bias;
use text::{Point, Rope};
use theme::Theme;
use unicase::UniCase;
use util::{paths::PathExt, post_inc, ResultExt};
use util::{maybe, paths::PathExt, post_inc, ResultExt};
pub struct LanguageRegistry {
state: RwLock<LanguageRegistryState>,
@ -54,10 +54,9 @@ struct LanguageRegistryState {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LanguageServerBinaryStatus {
None,
CheckingForUpdate,
Downloading,
Downloaded,
Cached,
Failed { error: String },
}
@ -91,9 +90,10 @@ enum AvailableGrammar {
Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),
Loading(
#[allow(unused)] PathBuf,
Vec<oneshot::Sender<Result<tree_sitter::Language>>>,
Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,
),
Unloaded(PathBuf),
LoadFailed(Arc<anyhow::Error>),
}
#[derive(Debug)]
@ -213,7 +213,20 @@ impl LanguageRegistry {
.lsp_adapters
.entry(language_name)
.or_default()
.push(CachedLspAdapter::new(adapter));
.push(CachedLspAdapter::new(adapter, true));
}
pub fn register_secondary_lsp_adapter(
&self,
language_name: Arc<str>,
adapter: Arc<dyn LspAdapter>,
) {
self.state
.write()
.lsp_adapters
.entry(language_name)
.or_default()
.push(CachedLspAdapter::new(adapter, false));
}
#[cfg(any(feature = "test-support", test))]
@ -227,7 +240,7 @@ impl LanguageRegistry {
.lsp_adapters
.entry(language_name.into())
.or_default()
.push(CachedLspAdapter::new(Arc::new(adapter)));
.push(CachedLspAdapter::new(Arc::new(adapter), true));
self.fake_language_servers(language_name)
}
@ -578,6 +591,9 @@ impl LanguageRegistry {
if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
match grammar {
AvailableGrammar::LoadFailed(error) => {
tx.send(Err(error.clone())).ok();
}
AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
tx.send(Ok(grammar.clone())).ok();
}
@ -586,46 +602,47 @@ impl LanguageRegistry {
}
AvailableGrammar::Unloaded(wasm_path) => {
let this = self.clone();
let wasm_path = wasm_path.clone();
*grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
self.executor
.spawn({
let wasm_path = wasm_path.clone();
async move {
.spawn(async move {
let grammar_result = maybe!({
let wasm_bytes = std::fs::read(&wasm_path)?;
let grammar_name = wasm_path
.file_stem()
.and_then(OsStr::to_str)
.ok_or_else(|| anyhow!("invalid grammar filename"))?;
let grammar = PARSER.with(|parser| {
anyhow::Ok(PARSER.with(|parser| {
let mut parser = parser.borrow_mut();
let mut store = parser.take_wasm_store().unwrap();
let grammar = store.load_language(&grammar_name, &wasm_bytes);
parser.set_wasm_store(store).unwrap();
grammar
})?;
})?)
})
.map_err(Arc::new);
if let Some(AvailableGrammar::Loading(_, txs)) =
this.state.write().grammars.insert(
name,
AvailableGrammar::Loaded(wasm_path, grammar.clone()),
)
{
for tx in txs {
tx.send(Ok(grammar.clone())).ok();
}
let value = match &grammar_result {
Ok(grammar) => AvailableGrammar::Loaded(wasm_path, grammar.clone()),
Err(error) => AvailableGrammar::LoadFailed(error.clone()),
};
let old_value = this.state.write().grammars.insert(name, value);
if let Some(AvailableGrammar::Loading(_, txs)) = old_value {
for tx in txs {
tx.send(grammar_result.clone()).ok();
}
anyhow::Ok(())
}
})
.detach();
*grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
}
}
} else {
tx.send(Err(anyhow!("no such grammar {}", name))).ok();
tx.send(Err(Arc::new(anyhow!("no such grammar {}", name))))
.ok();
}
async move { rx.await? }
async move { rx.await?.map_err(|e| anyhow!(e)) }
}
pub fn to_vec(&self) -> Vec<Arc<Language>> {
@ -691,7 +708,7 @@ impl LanguageRegistry {
// the login shell to be set on our process.
login_shell_env_loaded.await;
let binary = adapter
let binary_result = adapter
.clone()
.get_language_server_command(
language.clone(),
@ -699,8 +716,11 @@ impl LanguageRegistry {
delegate.clone(),
&mut cx,
)
.await?;
.await;
delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None);
let binary = binary_result?;
let options = adapter
.adapter
.clone()