debugger/extensions: Revert changes to extension store related to language config (#30225)
Revert #29945 Release Notes: - N/A --------- Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
20387f24aa
commit
b091581e4b
@ -1,12 +1,11 @@
|
|||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cmp::Reverse,
|
|
||||||
ops::Not,
|
ops::Not,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use collections::{HashMap, HashSet};
|
|
||||||
use dap::{
|
use dap::{
|
||||||
DapRegistry, DebugRequest,
|
DapRegistry, DebugRequest,
|
||||||
adapters::{DebugAdapterName, DebugTaskDefinition},
|
adapters::{DebugAdapterName, DebugTaskDefinition},
|
||||||
@ -192,25 +191,22 @@ impl NewSessionModal {
|
|||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Option<ui::DropdownMenu> {
|
) -> Option<ui::DropdownMenu> {
|
||||||
let workspace = self.workspace.clone();
|
let workspace = self.workspace.clone();
|
||||||
let language_registry = self
|
|
||||||
.workspace
|
|
||||||
.update(cx, |this, _| this.app_state().languages.clone())
|
|
||||||
.ok()?;
|
|
||||||
let weak = cx.weak_entity();
|
let weak = cx.weak_entity();
|
||||||
let label = self
|
let label = self
|
||||||
.debugger
|
.debugger
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|d| d.0.clone())
|
.map(|d| d.0.clone())
|
||||||
.unwrap_or_else(|| SELECT_DEBUGGER_LABEL.clone());
|
.unwrap_or_else(|| SELECT_DEBUGGER_LABEL.clone());
|
||||||
let active_buffer_language_name =
|
let active_buffer_language = self
|
||||||
self.task_contexts
|
.task_contexts
|
||||||
.active_item_context
|
.active_item_context
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|item| {
|
.and_then(|item| {
|
||||||
item.1
|
item.1
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|location| location.buffer.read(cx).language()?.name().into())
|
.and_then(|location| location.buffer.read(cx).language())
|
||||||
});
|
})
|
||||||
|
.cloned();
|
||||||
DropdownMenu::new(
|
DropdownMenu::new(
|
||||||
"dap-adapter-picker",
|
"dap-adapter-picker",
|
||||||
label,
|
label,
|
||||||
@ -229,42 +225,19 @@ impl NewSessionModal {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let available_languages = language_registry.language_names();
|
|
||||||
let mut debugger_to_languages = HashMap::default();
|
|
||||||
for language in available_languages {
|
|
||||||
let Some(language) =
|
|
||||||
language_registry.available_language_for_name(language.as_str())
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
language.config().debuggers.iter().for_each(|adapter| {
|
|
||||||
debugger_to_languages
|
|
||||||
.entry(adapter.clone())
|
|
||||||
.or_insert_with(HashSet::default)
|
|
||||||
.insert(language.name());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let mut available_adapters = workspace
|
let mut available_adapters = workspace
|
||||||
.update(cx, |_, cx| DapRegistry::global(cx).enumerate_adapters())
|
.update(cx, |_, cx| DapRegistry::global(cx).enumerate_adapters())
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
if let Some(language) = active_buffer_language {
|
||||||
available_adapters.sort_by_key(|name| {
|
available_adapters.sort_by_key(|adapter| {
|
||||||
let languages_for_debugger = debugger_to_languages.get(name.as_ref());
|
language
|
||||||
let languages_count =
|
.config()
|
||||||
languages_for_debugger.map_or(0, |languages| languages.len());
|
.debuggers
|
||||||
let contains_language_of_active_buffer = languages_for_debugger
|
.get_index_of(adapter.0.as_ref())
|
||||||
.zip(active_buffer_language_name.as_ref())
|
.unwrap_or(usize::MAX)
|
||||||
.map_or(false, |(languages, active_buffer_language)| {
|
});
|
||||||
languages.contains(active_buffer_language)
|
}
|
||||||
});
|
|
||||||
|
|
||||||
(
|
|
||||||
Reverse(contains_language_of_active_buffer),
|
|
||||||
Reverse(languages_count),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
for adapter in available_adapters.into_iter() {
|
for adapter in available_adapters.into_iter() {
|
||||||
menu = menu.entry(adapter.0.clone(), None, setter_for_name(adapter.clone()));
|
menu = menu.entry(adapter.0.clone(), None, setter_for_name(adapter.clone()));
|
||||||
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use gpui::{App, Global, ReadGlobal, SharedString, Task};
|
use gpui::{App, Global, ReadGlobal, SharedString, Task};
|
||||||
use language::{BinaryStatus, LanguageConfig, LanguageName, LoadedLanguage};
|
use language::{BinaryStatus, LanguageMatcher, LanguageName, LoadedLanguage};
|
||||||
use lsp::LanguageServerName;
|
use lsp::LanguageServerName;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
@ -224,7 +224,10 @@ impl ExtensionGrammarProxy for ExtensionHostProxy {
|
|||||||
pub trait ExtensionLanguageProxy: Send + Sync + 'static {
|
pub trait ExtensionLanguageProxy: Send + Sync + 'static {
|
||||||
fn register_language(
|
fn register_language(
|
||||||
&self,
|
&self,
|
||||||
config: LanguageConfig,
|
language: LanguageName,
|
||||||
|
grammar: Option<Arc<str>>,
|
||||||
|
matcher: LanguageMatcher,
|
||||||
|
hidden: bool,
|
||||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -238,14 +241,17 @@ pub trait ExtensionLanguageProxy: Send + Sync + 'static {
|
|||||||
impl ExtensionLanguageProxy for ExtensionHostProxy {
|
impl ExtensionLanguageProxy for ExtensionHostProxy {
|
||||||
fn register_language(
|
fn register_language(
|
||||||
&self,
|
&self,
|
||||||
language: LanguageConfig,
|
language: LanguageName,
|
||||||
|
grammar: Option<Arc<str>>,
|
||||||
|
matcher: LanguageMatcher,
|
||||||
|
hidden: bool,
|
||||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
||||||
) {
|
) {
|
||||||
let Some(proxy) = self.language_proxy.read().clone() else {
|
let Some(proxy) = self.language_proxy.read().clone() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
proxy.register_language(language, load)
|
proxy.register_language(language, grammar, matcher, hidden, load)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_languages(
|
fn remove_languages(
|
||||||
|
@ -34,7 +34,8 @@ use gpui::{
|
|||||||
};
|
};
|
||||||
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
|
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
|
||||||
use language::{
|
use language::{
|
||||||
LanguageConfig, LanguageName, LanguageQueries, LoadedLanguage, QUERY_FILENAME_PREFIXES, Rope,
|
LanguageConfig, LanguageMatcher, LanguageName, LanguageQueries, LoadedLanguage,
|
||||||
|
QUERY_FILENAME_PREFIXES, Rope,
|
||||||
};
|
};
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use project::ContextProviderWithTasks;
|
use project::ContextProviderWithTasks;
|
||||||
@ -139,7 +140,7 @@ struct GlobalExtensionStore(Entity<ExtensionStore>);
|
|||||||
|
|
||||||
impl Global for GlobalExtensionStore {}
|
impl Global for GlobalExtensionStore {}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Default)]
|
#[derive(Debug, Deserialize, Serialize, Default, PartialEq, Eq)]
|
||||||
pub struct ExtensionIndex {
|
pub struct ExtensionIndex {
|
||||||
pub extensions: BTreeMap<Arc<str>, ExtensionIndexEntry>,
|
pub extensions: BTreeMap<Arc<str>, ExtensionIndexEntry>,
|
||||||
pub themes: BTreeMap<Arc<str>, ExtensionIndexThemeEntry>,
|
pub themes: BTreeMap<Arc<str>, ExtensionIndexThemeEntry>,
|
||||||
@ -166,12 +167,13 @@ pub struct ExtensionIndexIconThemeEntry {
|
|||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)]
|
||||||
pub struct ExtensionIndexLanguageEntry {
|
pub struct ExtensionIndexLanguageEntry {
|
||||||
pub extension: Arc<str>,
|
pub extension: Arc<str>,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
#[serde(skip)]
|
pub matcher: LanguageMatcher,
|
||||||
pub config: LanguageConfig,
|
pub hidden: bool,
|
||||||
|
pub grammar: Option<Arc<str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
actions!(zed, [ReloadExtensions]);
|
actions!(zed, [ReloadExtensions]);
|
||||||
@ -1181,8 +1183,44 @@ impl ExtensionStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.proxy.register_grammars(grammars_to_add);
|
self.proxy.register_grammars(grammars_to_add);
|
||||||
|
let languages_to_add = new_index
|
||||||
|
.languages
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|(_, entry)| extensions_to_load.contains(&entry.extension))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for (language_name, language) in languages_to_add {
|
||||||
|
let mut language_path = self.installed_dir.clone();
|
||||||
|
language_path.extend([
|
||||||
|
Path::new(language.extension.as_ref()),
|
||||||
|
language.path.as_path(),
|
||||||
|
]);
|
||||||
|
self.proxy.register_language(
|
||||||
|
language_name.clone(),
|
||||||
|
language.grammar.clone(),
|
||||||
|
language.matcher.clone(),
|
||||||
|
language.hidden,
|
||||||
|
Arc::new(move || {
|
||||||
|
let config = std::fs::read_to_string(language_path.join("config.toml"))?;
|
||||||
|
let config: LanguageConfig = ::toml::from_str(&config)?;
|
||||||
|
let queries = load_plugin_queries(&language_path);
|
||||||
|
let context_provider =
|
||||||
|
std::fs::read_to_string(language_path.join("tasks.json"))
|
||||||
|
.ok()
|
||||||
|
.and_then(|contents| {
|
||||||
|
let definitions =
|
||||||
|
serde_json_lenient::from_str(&contents).log_err()?;
|
||||||
|
Some(Arc::new(ContextProviderWithTasks::new(definitions)) as Arc<_>)
|
||||||
|
});
|
||||||
|
|
||||||
let installed_dir = self.installed_dir.clone();
|
Ok(LoadedLanguage {
|
||||||
|
config,
|
||||||
|
queries,
|
||||||
|
context_provider,
|
||||||
|
toolchain_provider: None,
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let fs = self.fs.clone();
|
let fs = self.fs.clone();
|
||||||
let wasm_host = self.wasm_host.clone();
|
let wasm_host = self.wasm_host.clone();
|
||||||
@ -1192,60 +1230,11 @@ impl ExtensionStore {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|name| new_index.extensions.get(name).cloned())
|
.filter_map(|name| new_index.extensions.get(name).cloned())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
self.extension_index = new_index;
|
||||||
|
cx.notify();
|
||||||
|
cx.emit(Event::ExtensionsUpdated);
|
||||||
|
|
||||||
cx.spawn(async move |this, cx| {
|
cx.spawn(async move |this, cx| {
|
||||||
let languages_to_add = new_index
|
|
||||||
.languages
|
|
||||||
.iter_mut()
|
|
||||||
.filter(|(_, entry)| extensions_to_load.contains(&entry.extension))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
for (_, language) in languages_to_add {
|
|
||||||
let mut language_path = installed_dir.clone();
|
|
||||||
language_path.extend([
|
|
||||||
Path::new(language.extension.as_ref()),
|
|
||||||
language.path.as_path(),
|
|
||||||
]);
|
|
||||||
let Some(config) = fs.load(&language_path.join("config.toml")).await.ok() else {
|
|
||||||
log::error!("Could not load config.toml in {:?}", language_path);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let Some(config) = ::toml::from_str::<LanguageConfig>(&config).ok() else {
|
|
||||||
log::error!(
|
|
||||||
"Could not parse language config.toml in {:?}",
|
|
||||||
language_path
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
language.config = config.clone();
|
|
||||||
proxy.register_language(
|
|
||||||
language.config.clone(),
|
|
||||||
Arc::new(move || {
|
|
||||||
let queries = load_plugin_queries(&language_path);
|
|
||||||
let context_provider =
|
|
||||||
std::fs::read_to_string(language_path.join("tasks.json"))
|
|
||||||
.ok()
|
|
||||||
.and_then(|contents| {
|
|
||||||
let definitions =
|
|
||||||
serde_json_lenient::from_str(&contents).log_err()?;
|
|
||||||
Some(Arc::new(ContextProviderWithTasks::new(definitions))
|
|
||||||
as Arc<_>)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(LoadedLanguage {
|
|
||||||
config: config.clone(),
|
|
||||||
queries,
|
|
||||||
context_provider,
|
|
||||||
toolchain_provider: None,
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.update(cx, |this, cx| {
|
|
||||||
this.extension_index = new_index;
|
|
||||||
cx.notify();
|
|
||||||
cx.emit(Event::ExtensionsUpdated);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
cx.background_spawn({
|
cx.background_spawn({
|
||||||
let fs = fs.clone();
|
let fs = fs.clone();
|
||||||
async move {
|
async move {
|
||||||
@ -1448,7 +1437,9 @@ impl ExtensionStore {
|
|||||||
ExtensionIndexLanguageEntry {
|
ExtensionIndexLanguageEntry {
|
||||||
extension: extension_id.clone(),
|
extension: extension_id.clone(),
|
||||||
path: relative_path,
|
path: relative_path,
|
||||||
config,
|
matcher: config.matcher,
|
||||||
|
hidden: config.hidden,
|
||||||
|
grammar: config.grammar,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use fs::{FakeFs, Fs, RealFs};
|
|||||||
use futures::{AsyncReadExt, StreamExt, io::BufReader};
|
use futures::{AsyncReadExt, StreamExt, io::BufReader};
|
||||||
use gpui::{AppContext as _, SemanticVersion, SharedString, TestAppContext};
|
use gpui::{AppContext as _, SemanticVersion, SharedString, TestAppContext};
|
||||||
use http_client::{FakeHttpClient, Response};
|
use http_client::{FakeHttpClient, Response};
|
||||||
use language::{BinaryStatus, LanguageConfig, LanguageMatcher, LanguageRegistry};
|
use language::{BinaryStatus, LanguageMatcher, LanguageRegistry};
|
||||||
use lsp::LanguageServerName;
|
use lsp::LanguageServerName;
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@ -206,14 +206,11 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
ExtensionIndexLanguageEntry {
|
ExtensionIndexLanguageEntry {
|
||||||
extension: "zed-ruby".into(),
|
extension: "zed-ruby".into(),
|
||||||
path: "languages/erb".into(),
|
path: "languages/erb".into(),
|
||||||
config: LanguageConfig {
|
grammar: Some("embedded_template".into()),
|
||||||
grammar: Some("embedded_template".into()),
|
hidden: false,
|
||||||
hidden: false,
|
matcher: LanguageMatcher {
|
||||||
matcher: LanguageMatcher {
|
path_suffixes: vec!["erb".into()],
|
||||||
path_suffixes: vec!["erb".into()],
|
first_line_pattern: None,
|
||||||
first_line_pattern: None,
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -222,14 +219,11 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
ExtensionIndexLanguageEntry {
|
ExtensionIndexLanguageEntry {
|
||||||
extension: "zed-ruby".into(),
|
extension: "zed-ruby".into(),
|
||||||
path: "languages/ruby".into(),
|
path: "languages/ruby".into(),
|
||||||
config: LanguageConfig {
|
grammar: Some("ruby".into()),
|
||||||
grammar: Some("ruby".into()),
|
hidden: false,
|
||||||
hidden: false,
|
matcher: LanguageMatcher {
|
||||||
matcher: LanguageMatcher {
|
path_suffixes: vec!["rb".into()],
|
||||||
path_suffixes: vec!["rb".into()],
|
first_line_pattern: None,
|
||||||
first_line_pattern: None,
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -301,18 +295,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
index.languages.iter().zip(expected_index.languages.iter())
|
index.languages.iter().zip(expected_index.languages.iter())
|
||||||
{
|
{
|
||||||
assert_eq!(actual_key, expected_key);
|
assert_eq!(actual_key, expected_key);
|
||||||
assert_eq!(
|
assert_eq!(actual_language.grammar, expected_language.grammar);
|
||||||
actual_language.config.grammar,
|
assert_eq!(actual_language.matcher, expected_language.matcher);
|
||||||
expected_language.config.grammar
|
assert_eq!(actual_language.hidden, expected_language.hidden);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.matcher,
|
|
||||||
expected_language.config.matcher
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.hidden,
|
|
||||||
expected_language.config.hidden
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
assert_eq!(index.themes, expected_index.themes);
|
assert_eq!(index.themes, expected_index.themes);
|
||||||
|
|
||||||
@ -405,18 +390,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
index.languages.iter().zip(expected_index.languages.iter())
|
index.languages.iter().zip(expected_index.languages.iter())
|
||||||
{
|
{
|
||||||
assert_eq!(actual_key, expected_key);
|
assert_eq!(actual_key, expected_key);
|
||||||
assert_eq!(
|
assert_eq!(actual_language.grammar, expected_language.grammar);
|
||||||
actual_language.config.grammar,
|
assert_eq!(actual_language.matcher, expected_language.matcher);
|
||||||
expected_language.config.grammar
|
assert_eq!(actual_language.hidden, expected_language.hidden);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.matcher,
|
|
||||||
expected_language.config.matcher
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.hidden,
|
|
||||||
expected_language.config.hidden
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(index.extensions, expected_index.extensions);
|
assert_eq!(index.extensions, expected_index.extensions);
|
||||||
@ -470,18 +446,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
.zip(expected_index.languages.iter())
|
.zip(expected_index.languages.iter())
|
||||||
{
|
{
|
||||||
assert_eq!(actual_key, expected_key);
|
assert_eq!(actual_key, expected_key);
|
||||||
assert_eq!(
|
assert_eq!(actual_language.grammar, expected_language.grammar);
|
||||||
actual_language.config.grammar,
|
assert_eq!(actual_language.matcher, expected_language.matcher);
|
||||||
expected_language.config.grammar
|
assert_eq!(actual_language.hidden, expected_language.hidden);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.matcher,
|
|
||||||
expected_language.config.matcher
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.hidden,
|
|
||||||
expected_language.config.hidden
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -534,18 +501,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
|
|||||||
.zip(expected_index.languages.iter())
|
.zip(expected_index.languages.iter())
|
||||||
{
|
{
|
||||||
assert_eq!(actual_key, expected_key);
|
assert_eq!(actual_key, expected_key);
|
||||||
assert_eq!(
|
assert_eq!(actual_language.grammar, expected_language.grammar);
|
||||||
actual_language.config.grammar,
|
assert_eq!(actual_language.matcher, expected_language.matcher);
|
||||||
expected_language.config.grammar
|
assert_eq!(actual_language.hidden, expected_language.hidden);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.matcher,
|
|
||||||
expected_language.config.matcher
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
actual_language.config.hidden,
|
|
||||||
expected_language.config.hidden
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(language_registry.language_names(), ["Plain Text"]);
|
assert_eq!(language_registry.language_names(), ["Plain Text"]);
|
||||||
|
@ -149,7 +149,10 @@ impl HeadlessExtensionStore {
|
|||||||
config.grammar = None;
|
config.grammar = None;
|
||||||
|
|
||||||
this.proxy.register_language(
|
this.proxy.register_language(
|
||||||
config.clone(),
|
config.name.clone(),
|
||||||
|
None,
|
||||||
|
config.matcher.clone(),
|
||||||
|
config.hidden,
|
||||||
Arc::new(move || {
|
Arc::new(move || {
|
||||||
Ok(LoadedLanguage {
|
Ok(LoadedLanguage {
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
|
@ -666,7 +666,7 @@ pub struct CodeLabel {
|
|||||||
pub filter_range: Range<usize>,
|
pub filter_range: Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, Serialize, Debug)]
|
#[derive(Clone, Deserialize, JsonSchema)]
|
||||||
pub struct LanguageConfig {
|
pub struct LanguageConfig {
|
||||||
/// Human-readable name of the language.
|
/// Human-readable name of the language.
|
||||||
pub name: LanguageName,
|
pub name: LanguageName,
|
||||||
@ -694,20 +694,12 @@ pub struct LanguageConfig {
|
|||||||
pub auto_indent_on_paste: Option<bool>,
|
pub auto_indent_on_paste: Option<bool>,
|
||||||
/// A regex that is used to determine whether the indentation level should be
|
/// A regex that is used to determine whether the indentation level should be
|
||||||
/// increased in the following line.
|
/// increased in the following line.
|
||||||
#[serde(
|
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||||
default,
|
|
||||||
deserialize_with = "deserialize_regex",
|
|
||||||
serialize_with = "serialize_regex"
|
|
||||||
)]
|
|
||||||
#[schemars(schema_with = "regex_json_schema")]
|
#[schemars(schema_with = "regex_json_schema")]
|
||||||
pub increase_indent_pattern: Option<Regex>,
|
pub increase_indent_pattern: Option<Regex>,
|
||||||
/// A regex that is used to determine whether the indentation level should be
|
/// A regex that is used to determine whether the indentation level should be
|
||||||
/// decreased in the following line.
|
/// decreased in the following line.
|
||||||
#[serde(
|
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||||
default,
|
|
||||||
deserialize_with = "deserialize_regex",
|
|
||||||
serialize_with = "serialize_regex"
|
|
||||||
)]
|
|
||||||
#[schemars(schema_with = "regex_json_schema")]
|
#[schemars(schema_with = "regex_json_schema")]
|
||||||
pub decrease_indent_pattern: Option<Regex>,
|
pub decrease_indent_pattern: Option<Regex>,
|
||||||
/// A list of characters that trigger the automatic insertion of a closing
|
/// A list of characters that trigger the automatic insertion of a closing
|
||||||
@ -762,7 +754,7 @@ pub struct LanguageConfig {
|
|||||||
pub completion_query_characters: HashSet<char>,
|
pub completion_query_characters: HashSet<char>,
|
||||||
/// A list of preferred debuggers for this language.
|
/// A list of preferred debuggers for this language.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub debuggers: IndexSet<String>,
|
pub debuggers: IndexSet<SharedString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
|
||||||
@ -781,7 +773,7 @@ pub struct LanguageMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The configuration for JSX tag auto-closing.
|
/// The configuration for JSX tag auto-closing.
|
||||||
#[derive(Clone, Deserialize, JsonSchema, Serialize, Debug)]
|
#[derive(Clone, Deserialize, JsonSchema)]
|
||||||
pub struct JsxTagAutoCloseConfig {
|
pub struct JsxTagAutoCloseConfig {
|
||||||
/// The name of the node for a opening tag
|
/// The name of the node for a opening tag
|
||||||
pub open_tag_node_name: String,
|
pub open_tag_node_name: String,
|
||||||
@ -822,7 +814,7 @@ pub struct LanguageScope {
|
|||||||
override_id: Option<u32>,
|
override_id: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default, Debug, JsonSchema, Serialize)]
|
#[derive(Clone, Deserialize, Default, Debug, JsonSchema)]
|
||||||
pub struct LanguageConfigOverride {
|
pub struct LanguageConfigOverride {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub line_comments: Override<Vec<Arc<str>>>,
|
pub line_comments: Override<Vec<Arc<str>>>,
|
||||||
@ -949,7 +941,7 @@ pub struct FakeLspAdapter {
|
|||||||
///
|
///
|
||||||
/// This struct includes settings for defining which pairs of characters are considered brackets and
|
/// This struct includes settings for defining which pairs of characters are considered brackets and
|
||||||
/// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
|
/// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
|
||||||
#[derive(Clone, Debug, Default, JsonSchema, Serialize)]
|
#[derive(Clone, Debug, Default, JsonSchema)]
|
||||||
pub struct BracketPairConfig {
|
pub struct BracketPairConfig {
|
||||||
/// A list of character pairs that should be treated as brackets in the context of a given language.
|
/// A list of character pairs that should be treated as brackets in the context of a given language.
|
||||||
pub pairs: Vec<BracketPair>,
|
pub pairs: Vec<BracketPair>,
|
||||||
@ -999,7 +991,7 @@ impl<'de> Deserialize<'de> for BracketPairConfig {
|
|||||||
|
|
||||||
/// Describes a single bracket pair and how an editor should react to e.g. inserting
|
/// Describes a single bracket pair and how an editor should react to e.g. inserting
|
||||||
/// an opening bracket or to a newline character insertion in between `start` and `end` characters.
|
/// an opening bracket or to a newline character insertion in between `start` and `end` characters.
|
||||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema, Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
|
||||||
pub struct BracketPair {
|
pub struct BracketPair {
|
||||||
/// Starting substring for a bracket.
|
/// Starting substring for a bracket.
|
||||||
pub start: String,
|
pub start: String,
|
||||||
|
@ -145,24 +145,25 @@ pub enum BinaryStatus {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AvailableLanguage {
|
pub struct AvailableLanguage {
|
||||||
id: LanguageId,
|
id: LanguageId,
|
||||||
config: LanguageConfig,
|
name: LanguageName,
|
||||||
|
grammar: Option<Arc<str>>,
|
||||||
|
matcher: LanguageMatcher,
|
||||||
|
hidden: bool,
|
||||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
||||||
loaded: bool,
|
loaded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AvailableLanguage {
|
impl AvailableLanguage {
|
||||||
pub fn name(&self) -> LanguageName {
|
pub fn name(&self) -> LanguageName {
|
||||||
self.config.name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn matcher(&self) -> &LanguageMatcher {
|
pub fn matcher(&self) -> &LanguageMatcher {
|
||||||
&self.config.matcher
|
&self.matcher
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hidden(&self) -> bool {
|
pub fn hidden(&self) -> bool {
|
||||||
self.config.hidden
|
self.hidden
|
||||||
}
|
|
||||||
pub fn config(&self) -> &LanguageConfig {
|
|
||||||
&self.config
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +327,10 @@ impl LanguageRegistry {
|
|||||||
#[cfg(any(feature = "test-support", test))]
|
#[cfg(any(feature = "test-support", test))]
|
||||||
pub fn register_test_language(&self, config: LanguageConfig) {
|
pub fn register_test_language(&self, config: LanguageConfig) {
|
||||||
self.register_language(
|
self.register_language(
|
||||||
config.clone(),
|
config.name.clone(),
|
||||||
|
config.grammar.clone(),
|
||||||
|
config.matcher.clone(),
|
||||||
|
config.hidden,
|
||||||
Arc::new(move || {
|
Arc::new(move || {
|
||||||
Ok(LoadedLanguage {
|
Ok(LoadedLanguage {
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
@ -485,14 +489,18 @@ impl LanguageRegistry {
|
|||||||
/// Adds a language to the registry, which can be loaded if needed.
|
/// Adds a language to the registry, which can be loaded if needed.
|
||||||
pub fn register_language(
|
pub fn register_language(
|
||||||
&self,
|
&self,
|
||||||
config: LanguageConfig,
|
name: LanguageName,
|
||||||
|
grammar_name: Option<Arc<str>>,
|
||||||
|
matcher: LanguageMatcher,
|
||||||
|
hidden: bool,
|
||||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
|
||||||
) {
|
) {
|
||||||
let state = &mut *self.state.write();
|
let state = &mut *self.state.write();
|
||||||
|
|
||||||
for existing_language in &mut state.available_languages {
|
for existing_language in &mut state.available_languages {
|
||||||
if existing_language.config.name == config.name {
|
if existing_language.name == name {
|
||||||
existing_language.config = config;
|
existing_language.grammar = grammar_name;
|
||||||
|
existing_language.matcher = matcher;
|
||||||
existing_language.load = load;
|
existing_language.load = load;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -500,8 +508,11 @@ impl LanguageRegistry {
|
|||||||
|
|
||||||
state.available_languages.push(AvailableLanguage {
|
state.available_languages.push(AvailableLanguage {
|
||||||
id: LanguageId::new(),
|
id: LanguageId::new(),
|
||||||
config,
|
name,
|
||||||
|
grammar: grammar_name,
|
||||||
|
matcher,
|
||||||
load,
|
load,
|
||||||
|
hidden,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
});
|
});
|
||||||
state.version += 1;
|
state.version += 1;
|
||||||
@ -547,7 +558,7 @@ impl LanguageRegistry {
|
|||||||
let mut result = state
|
let mut result = state
|
||||||
.available_languages
|
.available_languages
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|l| l.loaded.not().then_some(l.config.name.to_string()))
|
.filter_map(|l| l.loaded.not().then_some(l.name.to_string()))
|
||||||
.chain(state.languages.iter().map(|l| l.config.name.to_string()))
|
.chain(state.languages.iter().map(|l| l.config.name.to_string()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
|
result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
|
||||||
@ -566,7 +577,10 @@ impl LanguageRegistry {
|
|||||||
let mut state = self.state.write();
|
let mut state = self.state.write();
|
||||||
state.available_languages.push(AvailableLanguage {
|
state.available_languages.push(AvailableLanguage {
|
||||||
id: language.id,
|
id: language.id,
|
||||||
config: language.config.clone(),
|
name: language.name(),
|
||||||
|
grammar: language.config.grammar.clone(),
|
||||||
|
matcher: language.config.matcher.clone(),
|
||||||
|
hidden: language.config.hidden,
|
||||||
load: Arc::new(|| Err(anyhow!("already loaded"))),
|
load: Arc::new(|| Err(anyhow!("already loaded"))),
|
||||||
loaded: true,
|
loaded: true,
|
||||||
});
|
});
|
||||||
@ -635,7 +649,7 @@ impl LanguageRegistry {
|
|||||||
state
|
state
|
||||||
.available_languages
|
.available_languages
|
||||||
.iter()
|
.iter()
|
||||||
.find(|l| l.config.name.0.as_ref() == name)
|
.find(|l| l.name.0.as_ref() == name)
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,11 +766,8 @@ impl LanguageRegistry {
|
|||||||
let current_match_type = best_language_match
|
let current_match_type = best_language_match
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(LanguageMatchPrecedence::default(), |(_, score)| *score);
|
.map_or(LanguageMatchPrecedence::default(), |(_, score)| *score);
|
||||||
let language_score = callback(
|
let language_score =
|
||||||
&language.config.name,
|
callback(&language.name, &language.matcher, current_match_type);
|
||||||
&language.config.matcher,
|
|
||||||
current_match_type,
|
|
||||||
);
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
language_score.is_none_or(|new_score| new_score > current_match_type),
|
language_score.is_none_or(|new_score| new_score > current_match_type),
|
||||||
"Matching callback should only return a better match than the current one"
|
"Matching callback should only return a better match than the current one"
|
||||||
@ -804,7 +815,7 @@ impl LanguageRegistry {
|
|||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
|
|
||||||
let id = language.id;
|
let id = language.id;
|
||||||
let name = language.config.name.clone();
|
let name = language.name.clone();
|
||||||
let language_load = language.load.clone();
|
let language_load = language.load.clone();
|
||||||
|
|
||||||
self.executor
|
self.executor
|
||||||
@ -1120,7 +1131,7 @@ impl LanguageRegistryState {
|
|||||||
self.languages
|
self.languages
|
||||||
.retain(|language| !languages_to_remove.contains(&language.name()));
|
.retain(|language| !languages_to_remove.contains(&language.name()));
|
||||||
self.available_languages
|
self.available_languages
|
||||||
.retain(|language| !languages_to_remove.contains(&language.config.name));
|
.retain(|language| !languages_to_remove.contains(&language.name));
|
||||||
self.grammars
|
self.grammars
|
||||||
.retain(|name, _| !grammars_to_remove.contains(name));
|
.retain(|name, _| !grammars_to_remove.contains(name));
|
||||||
self.version += 1;
|
self.version += 1;
|
||||||
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy};
|
use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy};
|
||||||
use language::{LanguageConfig, LanguageName, LanguageRegistry, LoadedLanguage};
|
use language::{LanguageMatcher, LanguageName, LanguageRegistry, LoadedLanguage};
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
extension_host_proxy: Arc<ExtensionHostProxy>,
|
extension_host_proxy: Arc<ExtensionHostProxy>,
|
||||||
@ -31,10 +31,14 @@ impl ExtensionGrammarProxy for LanguageServerRegistryProxy {
|
|||||||
impl ExtensionLanguageProxy for LanguageServerRegistryProxy {
|
impl ExtensionLanguageProxy for LanguageServerRegistryProxy {
|
||||||
fn register_language(
|
fn register_language(
|
||||||
&self,
|
&self,
|
||||||
language: LanguageConfig,
|
language: LanguageName,
|
||||||
|
grammar: Option<Arc<str>>,
|
||||||
|
matcher: LanguageMatcher,
|
||||||
|
hidden: bool,
|
||||||
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
|
||||||
) {
|
) {
|
||||||
self.language_registry.register_language(language, load);
|
self.language_registry
|
||||||
|
.register_language(language, grammar, matcher, hidden, load);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_languages(
|
fn remove_languages(
|
||||||
|
@ -325,7 +325,10 @@ fn register_language(
|
|||||||
languages.register_lsp_adapter(config.name.clone(), adapter);
|
languages.register_lsp_adapter(config.name.clone(), adapter);
|
||||||
}
|
}
|
||||||
languages.register_language(
|
languages.register_language(
|
||||||
config.clone(),
|
config.name.clone(),
|
||||||
|
config.grammar.clone(),
|
||||||
|
config.matcher.clone(),
|
||||||
|
config.hidden,
|
||||||
Arc::new(move || {
|
Arc::new(move || {
|
||||||
Ok(LoadedLanguage {
|
Ok(LoadedLanguage {
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user