Allow extensions to define more of the methods in the LspAdapter trait (#9554)

Our goal is to extract Svelte support into an extension, since we've
seen problems with the Tree-sitter Svelte parser crashing due to bugs in
the external scanner. In order to do this, we need a couple more
capabilities in LSP extensions:

* [x] `initialization_options` - programmatically controlling the JSON
initialization params sent to the language server
* [x] `prettier_plugins` - statically specifying a list of prettier
plugins that apply for a given language.
* [x] `npm_install_package`

Release Notes:

- N/A

---------

Co-authored-by: Marshall <marshall@zed.dev>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
Max Brunsfeld 2024-03-20 12:47:04 -07:00 committed by GitHub
parent 0ce5cdc48f
commit d699b8e104
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 318 additions and 208 deletions

View file

@ -92,4 +92,37 @@ impl LspAdapter for ExtensionLspAdapter {
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
None
}
async fn initialization_options(
self: Arc<Self>,
delegate: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
let delegate = delegate.clone();
let json_options = self
.extension
.call({
let this = self.clone();
|extension, store| {
async move {
let resource = store.data_mut().table().push(delegate)?;
let options = extension
.call_language_server_initialization_options(
store,
&this.config,
resource,
)
.await?
.map_err(|e| anyhow!("{}", e))?;
anyhow::Ok(options)
}
.boxed()
}
})
.await?;
Ok(if let Some(json_options) = json_options {
serde_json::from_str(&json_options)?
} else {
None
})
}
}

View file

@ -307,6 +307,46 @@ impl wit::ExtensionImports for WasmState {
.map_err(|err| err.to_string()))
}
async fn npm_package_installed_version(
&mut self,
package_name: String,
) -> wasmtime::Result<Result<Option<String>, String>> {
async fn inner(
this: &mut WasmState,
package_name: String,
) -> anyhow::Result<Option<String>> {
this.host
.node_runtime
.npm_package_installed_version(&this.host.work_dir, &package_name)
.await
}
Ok(inner(self, package_name)
.await
.map_err(|err| err.to_string()))
}
async fn npm_install_package(
&mut self,
package_name: String,
version: String,
) -> wasmtime::Result<Result<(), String>> {
async fn inner(
this: &mut WasmState,
package_name: String,
version: String,
) -> anyhow::Result<()> {
this.host
.node_runtime
.npm_install_packages(&this.host.work_dir, &[(&package_name, &version)])
.await
}
Ok(inner(self, package_name, version)
.await
.map_err(|err| err.to_string()))
}
async fn latest_github_release(
&mut self,
repo: String,