lsp: Identify language servers by their configuration (#35270)
- **WIP: reorganize dispositions** - **Introduce a LocalToolchainStore trait and use it for LspAdapter methods** Closes #35782 Closes #27331 Release Notes: - Python: Improved propagation of a selected virtual environment into the LSP configuration. This should the make all language-related features such as Go to definition or Find all references more reliable. --------- Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: Lukas Wirth <lukas@zed.dev>
This commit is contained in:
parent
42ffa8900a
commit
b8a106632f
32 changed files with 1037 additions and 1085 deletions
|
@ -1571,6 +1571,7 @@ impl Buffer {
|
|||
diagnostics: diagnostics.iter().cloned().collect(),
|
||||
lamport_timestamp,
|
||||
};
|
||||
|
||||
self.apply_diagnostic_update(server_id, diagnostics, lamport_timestamp, cx);
|
||||
self.send_operation(op, true, cx);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
|
|||
use serde_json::Value;
|
||||
use settings::WorktreeId;
|
||||
use smol::future::FutureExt as _;
|
||||
use std::num::NonZeroU32;
|
||||
use std::{
|
||||
any::Any,
|
||||
ffi::OsStr,
|
||||
|
@ -59,7 +60,6 @@ use std::{
|
|||
atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst},
|
||||
},
|
||||
};
|
||||
use std::{num::NonZeroU32, sync::OnceLock};
|
||||
use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
|
||||
use task::RunnableTag;
|
||||
pub use task_context::{ContextLocation, ContextProvider, RunnableRange};
|
||||
|
@ -67,7 +67,9 @@ pub use text_diff::{
|
|||
DiffOptions, apply_diff_patch, line_diff, text_diff, text_diff_with_options, unified_diff,
|
||||
};
|
||||
use theme::SyntaxTheme;
|
||||
pub use toolchain::{LanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister};
|
||||
pub use toolchain::{
|
||||
LanguageToolchainStore, LocalLanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister,
|
||||
};
|
||||
use tree_sitter::{self, Query, QueryCursor, WasmStore, wasmtime};
|
||||
use util::serde::default_true;
|
||||
|
||||
|
@ -165,7 +167,6 @@ pub struct CachedLspAdapter {
|
|||
pub adapter: Arc<dyn LspAdapter>,
|
||||
pub reinstall_attempt_count: AtomicU64,
|
||||
cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>,
|
||||
manifest_name: OnceLock<Option<ManifestName>>,
|
||||
}
|
||||
|
||||
impl Debug for CachedLspAdapter {
|
||||
|
@ -201,7 +202,6 @@ impl CachedLspAdapter {
|
|||
adapter,
|
||||
cached_binary: Default::default(),
|
||||
reinstall_attempt_count: AtomicU64::new(0),
|
||||
manifest_name: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ impl CachedLspAdapter {
|
|||
pub async fn get_language_server_command(
|
||||
self: Arc<Self>,
|
||||
delegate: Arc<dyn LspAdapterDelegate>,
|
||||
toolchains: Arc<dyn LanguageToolchainStore>,
|
||||
toolchains: Option<Toolchain>,
|
||||
binary_options: LanguageServerBinaryOptions,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<LanguageServerBinary> {
|
||||
|
@ -281,12 +281,6 @@ impl CachedLspAdapter {
|
|||
.cloned()
|
||||
.unwrap_or_else(|| language_name.lsp_id())
|
||||
}
|
||||
|
||||
pub fn manifest_name(&self) -> Option<ManifestName> {
|
||||
self.manifest_name
|
||||
.get_or_init(|| self.adapter.manifest_name())
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines what gets sent out as a workspace folders content
|
||||
|
@ -327,7 +321,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
fn get_language_server_command<'a>(
|
||||
self: Arc<Self>,
|
||||
delegate: Arc<dyn LspAdapterDelegate>,
|
||||
toolchains: Arc<dyn LanguageToolchainStore>,
|
||||
toolchains: Option<Toolchain>,
|
||||
binary_options: LanguageServerBinaryOptions,
|
||||
mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
||||
cx: &'a mut AsyncApp,
|
||||
|
@ -402,7 +396,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
async fn check_if_user_installed(
|
||||
&self,
|
||||
_: &dyn LspAdapterDelegate,
|
||||
_: Arc<dyn LanguageToolchainStore>,
|
||||
_: Option<Toolchain>,
|
||||
_: &AsyncApp,
|
||||
) -> Option<LanguageServerBinary> {
|
||||
None
|
||||
|
@ -535,7 +529,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
self: Arc<Self>,
|
||||
_: &dyn Fs,
|
||||
_: &Arc<dyn LspAdapterDelegate>,
|
||||
_: Arc<dyn LanguageToolchainStore>,
|
||||
_: Option<Toolchain>,
|
||||
_cx: &mut AsyncApp,
|
||||
) -> Result<Value> {
|
||||
Ok(serde_json::json!({}))
|
||||
|
@ -555,7 +549,6 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
_target_language_server_id: LanguageServerName,
|
||||
_: &dyn Fs,
|
||||
_: &Arc<dyn LspAdapterDelegate>,
|
||||
_: Arc<dyn LanguageToolchainStore>,
|
||||
_cx: &mut AsyncApp,
|
||||
) -> Result<Option<Value>> {
|
||||
Ok(None)
|
||||
|
@ -594,10 +587,6 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
WorkspaceFoldersContent::SubprojectRoots
|
||||
}
|
||||
|
||||
fn manifest_name(&self) -> Option<ManifestName> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Method only implemented by the default JSON language server adapter.
|
||||
/// Used to provide dynamic reloading of the JSON schemas used to
|
||||
/// provide autocompletion and diagnostics in Zed setting and keybind
|
||||
|
@ -1108,6 +1097,7 @@ pub struct Language {
|
|||
pub(crate) grammar: Option<Arc<Grammar>>,
|
||||
pub(crate) context_provider: Option<Arc<dyn ContextProvider>>,
|
||||
pub(crate) toolchain: Option<Arc<dyn ToolchainLister>>,
|
||||
pub(crate) manifest_name: Option<ManifestName>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
|
@ -1318,6 +1308,7 @@ impl Language {
|
|||
}),
|
||||
context_provider: None,
|
||||
toolchain: None,
|
||||
manifest_name: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1331,6 +1322,10 @@ impl Language {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_manifest(mut self, name: Option<ManifestName>) -> Self {
|
||||
self.manifest_name = name;
|
||||
self
|
||||
}
|
||||
pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
|
||||
if let Some(query) = queries.highlights {
|
||||
self = self
|
||||
|
@ -1764,6 +1759,9 @@ impl Language {
|
|||
pub fn name(&self) -> LanguageName {
|
||||
self.config.name.clone()
|
||||
}
|
||||
pub fn manifest(&self) -> Option<&ManifestName> {
|
||||
self.manifest_name.as_ref()
|
||||
}
|
||||
|
||||
pub fn code_fence_block_name(&self) -> Arc<str> {
|
||||
self.config
|
||||
|
@ -2209,7 +2207,7 @@ impl LspAdapter for FakeLspAdapter {
|
|||
async fn check_if_user_installed(
|
||||
&self,
|
||||
_: &dyn LspAdapterDelegate,
|
||||
_: Arc<dyn LanguageToolchainStore>,
|
||||
_: Option<Toolchain>,
|
||||
_: &AsyncApp,
|
||||
) -> Option<LanguageServerBinary> {
|
||||
Some(self.language_server_binary.clone())
|
||||
|
@ -2218,7 +2216,7 @@ impl LspAdapter for FakeLspAdapter {
|
|||
fn get_language_server_command<'a>(
|
||||
self: Arc<Self>,
|
||||
_: Arc<dyn LspAdapterDelegate>,
|
||||
_: Arc<dyn LanguageToolchainStore>,
|
||||
_: Option<Toolchain>,
|
||||
_: LanguageServerBinaryOptions,
|
||||
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
||||
_: &'a mut AsyncApp,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
|
||||
LanguageServerName, LspAdapter, PLAIN_TEXT, ToolchainLister,
|
||||
LanguageServerName, LspAdapter, ManifestName, PLAIN_TEXT, ToolchainLister,
|
||||
language_settings::{
|
||||
AllLanguageSettingsContent, LanguageSettingsContent, all_language_settings,
|
||||
},
|
||||
|
@ -172,6 +172,7 @@ pub struct AvailableLanguage {
|
|||
hidden: bool,
|
||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
||||
loaded: bool,
|
||||
manifest_name: Option<ManifestName>,
|
||||
}
|
||||
|
||||
impl AvailableLanguage {
|
||||
|
@ -259,6 +260,7 @@ pub struct LoadedLanguage {
|
|||
pub queries: LanguageQueries,
|
||||
pub context_provider: Option<Arc<dyn ContextProvider>>,
|
||||
pub toolchain_provider: Option<Arc<dyn ToolchainLister>>,
|
||||
pub manifest_name: Option<ManifestName>,
|
||||
}
|
||||
|
||||
impl LanguageRegistry {
|
||||
|
@ -349,12 +351,14 @@ impl LanguageRegistry {
|
|||
config.grammar.clone(),
|
||||
config.matcher.clone(),
|
||||
config.hidden,
|
||||
None,
|
||||
Arc::new(move || {
|
||||
Ok(LoadedLanguage {
|
||||
config: config.clone(),
|
||||
queries: Default::default(),
|
||||
toolchain_provider: None,
|
||||
context_provider: None,
|
||||
manifest_name: None,
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
@ -487,6 +491,7 @@ impl LanguageRegistry {
|
|||
grammar_name: Option<Arc<str>>,
|
||||
matcher: LanguageMatcher,
|
||||
hidden: bool,
|
||||
manifest_name: Option<ManifestName>,
|
||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
||||
) {
|
||||
let state = &mut *self.state.write();
|
||||
|
@ -496,6 +501,7 @@ impl LanguageRegistry {
|
|||
existing_language.grammar = grammar_name;
|
||||
existing_language.matcher = matcher;
|
||||
existing_language.load = load;
|
||||
existing_language.manifest_name = manifest_name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -508,6 +514,7 @@ impl LanguageRegistry {
|
|||
load,
|
||||
hidden,
|
||||
loaded: false,
|
||||
manifest_name,
|
||||
});
|
||||
state.version += 1;
|
||||
state.reload_count += 1;
|
||||
|
@ -575,6 +582,7 @@ impl LanguageRegistry {
|
|||
grammar: language.config.grammar.clone(),
|
||||
matcher: language.config.matcher.clone(),
|
||||
hidden: language.config.hidden,
|
||||
manifest_name: None,
|
||||
load: Arc::new(|| Err(anyhow!("already loaded"))),
|
||||
loaded: true,
|
||||
});
|
||||
|
@ -914,10 +922,12 @@ impl LanguageRegistry {
|
|||
Language::new_with_id(id, loaded_language.config, grammar)
|
||||
.with_context_provider(loaded_language.context_provider)
|
||||
.with_toolchain_lister(loaded_language.toolchain_provider)
|
||||
.with_manifest(loaded_language.manifest_name)
|
||||
.with_queries(loaded_language.queries)
|
||||
} else {
|
||||
Ok(Language::new_with_id(id, loaded_language.config, None)
|
||||
.with_context_provider(loaded_language.context_provider)
|
||||
.with_manifest(loaded_language.manifest_name)
|
||||
.with_toolchain_lister(loaded_language.toolchain_provider))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,12 @@ impl Borrow<SharedString> for ManifestName {
|
|||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for ManifestName {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SharedString> for ManifestName {
|
||||
fn from(value: SharedString) -> Self {
|
||||
Self(value)
|
||||
|
|
|
@ -17,7 +17,7 @@ use settings::WorktreeId;
|
|||
use crate::{LanguageName, ManifestName};
|
||||
|
||||
/// Represents a single toolchain.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Eq)]
|
||||
pub struct Toolchain {
|
||||
/// User-facing label
|
||||
pub name: SharedString,
|
||||
|
@ -27,6 +27,14 @@ pub struct Toolchain {
|
|||
pub as_json: serde_json::Value,
|
||||
}
|
||||
|
||||
impl std::hash::Hash for Toolchain {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.name.hash(state);
|
||||
self.path.hash(state);
|
||||
self.language_name.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Toolchain {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// Do not use as_json for comparisons; it shouldn't impact equality, as it's not user-surfaced.
|
||||
|
@ -64,6 +72,29 @@ pub trait LanguageToolchainStore: Send + Sync + 'static {
|
|||
) -> Option<Toolchain>;
|
||||
}
|
||||
|
||||
pub trait LocalLanguageToolchainStore: Send + Sync + 'static {
|
||||
fn active_toolchain(
|
||||
self: Arc<Self>,
|
||||
worktree_id: WorktreeId,
|
||||
relative_path: &Arc<Path>,
|
||||
language_name: LanguageName,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Option<Toolchain>;
|
||||
}
|
||||
|
||||
#[async_trait(?Send )]
|
||||
impl<T: LocalLanguageToolchainStore> LanguageToolchainStore for T {
|
||||
async fn active_toolchain(
|
||||
self: Arc<Self>,
|
||||
worktree_id: WorktreeId,
|
||||
relative_path: Arc<Path>,
|
||||
language_name: LanguageName,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Option<Toolchain> {
|
||||
self.active_toolchain(worktree_id, &relative_path, language_name, cx)
|
||||
}
|
||||
}
|
||||
|
||||
type DefaultIndex = usize;
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ToolchainList {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue