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

@ -90,17 +90,16 @@ impl LspAdapter for AstroLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true,
"typescript": {
"tsdk": "node_modules/typescript/lib",
}
}))
}
fn prettier_plugins(&self) -> &[&'static str] {
&["prettier-plugin-astro"]
})))
}
}

View file

@ -16,6 +16,7 @@ brackets = [
word_characters = ["#", "$", "-"]
scope_opt_in_language_servers = ["tailwindcss-language-server"]
prettier_parser_name = "astro"
prettier_plugins = ["prettier-plugin-astro"]
[overrides.string]
word_characters = ["-"]

View file

@ -91,10 +91,13 @@ impl LspAdapter for CssLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true
}))
})))
}
}

View file

@ -188,10 +188,13 @@ impl LspAdapter for DenoLspAdapter {
})
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true,
}))
})))
}
fn language_ids(&self) -> HashMap<String, String> {

View file

@ -189,8 +189,11 @@ impl super::LspAdapter for GoLspAdapter {
})
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"usePlaceholders": true,
"hints": {
"assignVariableTypes": true,
@ -201,7 +204,7 @@ impl super::LspAdapter for GoLspAdapter {
"parameterNames": true,
"rangeVariableTypes": true
}
}))
})))
}
async fn label_for_completion(

View file

@ -91,10 +91,13 @@ impl LspAdapter for HtmlLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true
}))
})))
}
}

View file

@ -143,10 +143,13 @@ impl LspAdapter for JsonLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true
}))
})))
}
fn workspace_configuration(&self, _workspace_root: &Path, cx: &mut AppContext) -> Value {

View file

@ -97,24 +97,9 @@ impl LspAdapter for IntelephenseLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
async fn label_for_completion(
&self,
_item: &lsp::CompletionItem,
_language: &Arc<language::Language>,
) -> Option<language::CodeLabel> {
None
}
fn initialization_options(&self) -> Option<serde_json::Value> {
None
}
fn language_ids(&self) -> HashMap<String, String> {
HashMap::from_iter([("PHP".into(), "php".into())])
}
fn prettier_plugins(&self) -> &[&'static str] {
&["@prettier/plugin-php"]
}
}
async fn get_cached_server_binary(

View file

@ -15,3 +15,4 @@ collapsed_placeholder = "/* ... */"
word_characters = ["$"]
scope_opt_in_language_servers = ["tailwindcss-language-server"]
prettier_parser_name = "php"
prettier_plugins = ["@prettier/plugin-php"]

View file

@ -88,10 +88,6 @@ impl LspAdapter for PrismaLspAdapter {
) -> Option<LanguageServerBinary> {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
None
}
}
async fn get_cached_server_binary(

View file

@ -93,12 +93,15 @@ impl LspAdapter for PurescriptLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"purescript": {
"addSpagoSources": true
}
}))
})))
}
fn language_ids(&self) -> HashMap<String, String> {

View file

@ -90,7 +90,10 @@ impl LspAdapter for SvelteLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
let config = json!({
"inlayHints": {
"parameterNames": {
@ -116,17 +119,13 @@ impl LspAdapter for SvelteLspAdapter {
}
});
Some(json!({
Ok(Some(json!({
"provideFormatter": true,
"configuration": {
"typescript": config,
"javascript": config
}
}))
}
fn prettier_plugins(&self) -> &[&'static str] {
&["prettier-plugin-svelte"]
})))
}
}

View file

@ -15,6 +15,7 @@ brackets = [
]
scope_opt_in_language_servers = ["tailwindcss-language-server"]
prettier_parser_name = "svelte"
prettier_plugins = ["prettier-plugin-svelte"]
[overrides.string]
word_characters = ["-"]

View file

@ -92,8 +92,11 @@ impl LspAdapter for TailwindLspAdapter {
get_cached_server_binary(container_dir, &*self.node).await
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true,
"userLanguages": {
"html": "html",
@ -101,7 +104,7 @@ impl LspAdapter for TailwindLspAdapter {
"javascript": "javascript",
"typescriptreact": "typescriptreact",
},
}))
})))
}
fn workspace_configuration(&self, _workspace_root: &Path, _: &mut AppContext) -> Value {
@ -126,10 +129,6 @@ impl LspAdapter for TailwindLspAdapter {
("PHP".to_string(), "php".to_string()),
])
}
fn prettier_plugins(&self) -> &[&'static str] {
&["prettier-plugin-tailwindcss"]
}
}
async fn get_cached_server_binary(

View file

@ -164,8 +164,11 @@ impl LspAdapter for TypeScriptLspAdapter {
})
}
fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
Ok(Some(json!({
"provideFormatter": true,
"tsserver": {
"path": "node_modules/typescript/lib",
@ -180,7 +183,7 @@ impl LspAdapter for TypeScriptLspAdapter {
"includeInlayFunctionLikeReturnTypeHints": true,
"includeInlayEnumMemberValueHints": true,
}
}))
})))
}
fn language_ids(&self) -> HashMap<String, String> {
@ -367,18 +370,6 @@ impl LspAdapter for EsLintLspAdapter {
) -> Option<LanguageServerBinary> {
get_cached_eslint_server_binary(container_dir, &*self.node).await
}
async fn label_for_completion(
&self,
_item: &lsp::CompletionItem,
_language: &Arc<language::Language>,
) -> Option<language::CodeLabel> {
None
}
fn initialization_options(&self) -> Option<serde_json::Value> {
None
}
}
async fn get_cached_eslint_server_binary(

View file

@ -5,7 +5,6 @@ pub use language::*;
use lsp::{CodeActionKind, LanguageServerBinary};
use node_runtime::NodeRuntime;
use parking_lot::Mutex;
use serde_json::Value;
use smol::fs::{self};
use std::{
any::Any,
@ -56,17 +55,20 @@ impl super::LspAdapter for VueLspAdapter {
ts_version: self.node.npm_package_latest_version("typescript").await?,
}) as Box<_>)
}
fn initialization_options(&self) -> Option<Value> {
async fn initialization_options(
self: Arc<Self>,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
let typescript_sdk_path = self.typescript_install_path.lock();
let typescript_sdk_path = typescript_sdk_path
.as_ref()
.expect("initialization_options called without a container_dir for typescript");
Some(serde_json::json!({
Ok(Some(serde_json::json!({
"typescript": {
"tsdk": typescript_sdk_path
}
}))
})))
}
fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
// REFACTOR is explicitly disabled, as vue-lsp does not adhere to LSP protocol for code actions with these - it