ensure that builtin basedpyright will override the extension

This commit is contained in:
Cole Miller 2025-07-30 17:13:36 -04:00
parent 573eb8e25d
commit 182e16d3b3
5 changed files with 51 additions and 140 deletions

View file

@ -615,6 +615,11 @@ pub trait LspAdapter: 'static + Send + Sync {
"Not implemented for this adapter. This method should only be called on the default JSON language server adapter" "Not implemented for this adapter. This method should only be called on the default JSON language server adapter"
); );
} }
/// True for the extension adapter and false otherwise.
fn is_extension(&self) -> bool {
false
}
} }
async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>( async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>(
@ -2273,6 +2278,10 @@ impl LspAdapter for FakeLspAdapter {
let label_for_completion = self.label_for_completion.as_ref()?; let label_for_completion = self.label_for_completion.as_ref()?;
label_for_completion(item, language) label_for_completion(item, language)
} }
fn is_extension(&self) -> bool {
false
}
} }
fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) { fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) {

View file

@ -370,14 +370,23 @@ impl LanguageRegistry {
pub fn register_available_lsp_adapter( pub fn register_available_lsp_adapter(
&self, &self,
name: LanguageServerName, name: LanguageServerName,
load: impl Fn() -> Arc<dyn LspAdapter> + 'static + Send + Sync, adapter: Arc<dyn LspAdapter>,
) { ) {
self.state.write().available_lsp_adapters.insert( let mut state = self.state.write();
if adapter.is_extension()
&& let Some(existing_adapter) = state.all_lsp_adapters.get(&name)
&& !existing_adapter.adapter.is_extension()
{
log::warn!(
"not registering extension-provided language server {name:?}, since a builtin language server exists with that name",
);
return;
}
state.available_lsp_adapters.insert(
name, name,
Arc::new(move || { Arc::new(move || CachedLspAdapter::new(adapter.clone())),
let lsp_adapter = load();
CachedLspAdapter::new(lsp_adapter)
}),
); );
} }
@ -392,47 +401,29 @@ impl LanguageRegistry {
Some(load_lsp_adapter()) Some(load_lsp_adapter())
} }
pub fn register_lsp_adapter( pub fn register_lsp_adapter(&self, language_name: LanguageName, adapter: Arc<dyn LspAdapter>) {
&self,
language_name: LanguageName,
adapter: Arc<dyn LspAdapter>,
) -> Arc<CachedLspAdapter> {
let cached = CachedLspAdapter::new(adapter);
let mut state = self.state.write(); let mut state = self.state.write();
if adapter.is_extension()
&& let Some(existing_adapter) = state.all_lsp_adapters.get(&adapter.name())
&& !existing_adapter.adapter.is_extension()
{
log::warn!(
"not registering extension-provided language server {:?} for language {language_name:?}, since a builtin language server exists with that name",
adapter.name(),
);
return;
}
let cached = CachedLspAdapter::new(adapter);
state state
.lsp_adapters .lsp_adapters
.entry(language_name) .entry(language_name.clone())
.or_default() .or_default()
.push(cached.clone()); .push(cached.clone());
state state
.all_lsp_adapters .all_lsp_adapters
.insert(cached.name.clone(), cached.clone()); .insert(cached.name.clone(), cached.clone());
cached
}
pub fn get_or_register_lsp_adapter(
&self,
language_name: LanguageName,
server_name: LanguageServerName,
build_adapter: impl FnOnce() -> Arc<dyn LspAdapter> + 'static,
) -> Arc<CachedLspAdapter> {
let registered = self
.state
.write()
.lsp_adapters
.entry(language_name.clone())
.or_default()
.iter()
.find(|cached_adapter| cached_adapter.name == server_name)
.cloned();
if let Some(found) = registered {
found
} else {
let adapter = build_adapter();
self.register_lsp_adapter(language_name, adapter)
}
} }
/// Register a fake language server and adapter /// Register a fake language server and adapter

View file

@ -397,6 +397,10 @@ impl LspAdapter for ExtensionLspAdapter {
Ok(labels_from_extension(labels, language)) Ok(labels_from_extension(labels, language))
} }
fn is_extension(&self) -> bool {
true
}
} }
fn labels_from_extension( fn labels_from_extension(

View file

@ -265,29 +265,18 @@ pub fn init(languages: Arc<LanguageRegistry>, node: NodeRuntime, cx: &mut App) {
// ``` // ```
languages.register_available_lsp_adapter( languages.register_available_lsp_adapter(
LanguageServerName("tailwindcss-language-server".into()), LanguageServerName("tailwindcss-language-server".into()),
{ tailwind_adapter.clone(),
let adapter = tailwind_adapter.clone();
move || adapter.clone()
},
); );
languages.register_available_lsp_adapter(LanguageServerName("eslint".into()), { languages.register_available_lsp_adapter(
let adapter = eslint_adapter.clone(); LanguageServerName("eslint".into()),
move || adapter.clone() eslint_adapter.clone(),
}); );
languages.register_available_lsp_adapter(LanguageServerName("vtsls".into()), { languages.register_available_lsp_adapter(LanguageServerName("vtsls".into()), vtsls_adapter);
let adapter = vtsls_adapter.clone();
move || adapter.clone()
});
languages.register_available_lsp_adapter( languages.register_available_lsp_adapter(
LanguageServerName("typescript-language-server".into()), LanguageServerName("typescript-language-server".into()),
{ typescript_lsp_adapter,
let adapter = typescript_lsp_adapter.clone();
move || adapter.clone()
},
); );
languages.register_available_lsp_adapter(python_lsp_adapter.name(), move || { languages.register_available_lsp_adapter(python_lsp_adapter.name(), python_lsp_adapter);
python_lsp_adapter.clone()
});
// Register Tailwind for the existing languages that should have it by default. // Register Tailwind for the existing languages that should have it by default.
// //

View file

@ -81,7 +81,6 @@ use sha2::{Digest, Sha256};
use smol::channel::Sender; use smol::channel::Sender;
use snippet::Snippet; use snippet::Snippet;
use std::{ use std::{
any::Any,
borrow::Cow, borrow::Cow,
cell::RefCell, cell::RefCell,
cmp::{Ordering, Reverse}, cmp::{Ordering, Reverse},
@ -12227,87 +12226,6 @@ fn glob_literal_prefix(glob: &Path) -> PathBuf {
.collect() .collect()
} }
pub struct SshLspAdapter {
name: LanguageServerName,
binary: LanguageServerBinary,
initialization_options: Option<String>,
code_action_kinds: Option<Vec<CodeActionKind>>,
}
impl SshLspAdapter {
pub fn new(
name: LanguageServerName,
binary: LanguageServerBinary,
initialization_options: Option<String>,
code_action_kinds: Option<String>,
) -> Self {
Self {
name,
binary,
initialization_options,
code_action_kinds: code_action_kinds
.as_ref()
.and_then(|c| serde_json::from_str(c).ok()),
}
}
}
#[async_trait(?Send)]
impl LspAdapter for SshLspAdapter {
fn name(&self) -> LanguageServerName {
self.name.clone()
}
async fn initialization_options(
self: Arc<Self>,
_: &dyn Fs,
_: &Arc<dyn LspAdapterDelegate>,
) -> Result<Option<serde_json::Value>> {
let Some(options) = &self.initialization_options else {
return Ok(None);
};
let result = serde_json::from_str(options)?;
Ok(result)
}
fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
self.code_action_kinds.clone()
}
async fn check_if_user_installed(
&self,
_: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncApp,
) -> Option<LanguageServerBinary> {
Some(self.binary.clone())
}
async fn cached_server_binary(
&self,
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
None
}
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
}
async fn fetch_server_binary(
&self,
_: Box<dyn 'static + Send + Any>,
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary> {
anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
}
}
pub fn language_server_settings<'a>( pub fn language_server_settings<'a>(
delegate: &'a dyn LspAdapterDelegate, delegate: &'a dyn LspAdapterDelegate,
language: &LanguageServerName, language: &LanguageServerName,