Fix language too

This commit is contained in:
Conrad Irwin
2025-09-15 22:41:34 -06:00
parent 231870e1cc
commit 93c129beb8
6 changed files with 356 additions and 643 deletions

View File

@@ -1,6 +1,5 @@
use super::*;
use crate::Buffer;
use crate::language_settings::{AllLanguageSettingsContent, LanguageSettingsContent};
use clock::ReplicaId;
use collections::BTreeMap;
use futures::FutureExt as _;
@@ -11,6 +10,7 @@ use proto::deserialize_operation;
use rand::prelude::*;
use regex::RegexBuilder;
use settings::SettingsStore;
use settings::{AllLanguageSettingsContent, LanguageSettingsContent};
use std::collections::BTreeSet;
use std::{
env,

View File

@@ -1,14 +1,11 @@
use crate::{
CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
LanguageServerName, LspAdapter, ManifestName, PLAIN_TEXT, ToolchainLister,
language_settings::{
AllLanguageSettingsContent, LanguageSettingsContent, all_language_settings,
},
task_context::ContextProvider,
with_parser,
language_settings::all_language_settings, task_context::ContextProvider, with_parser,
};
use anyhow::{Context as _, Result, anyhow};
use collections::{FxHashMap, HashMap, HashSet, hash_map};
use settings::{AllLanguageSettingsContent, LanguageSettingsContent};
use futures::{
Future,
@@ -1175,7 +1172,7 @@ impl LanguageRegistryState {
language.set_theme(theme.syntax());
}
self.language_settings.languages.0.insert(
language.name(),
language.name().0,
LanguageSettingsContent {
tab_size: language.config.tab_size,
hard_tabs: language.config.hard_tabs,

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,7 @@ pub struct AllLanguageSettingsContent {
/// Settings for associating file extensions and filenames
/// with languages.
#[serde(default)]
pub file_types: HashMap<SharedString, Vec<String>>,
pub file_types: HashMap<Arc<str>, Vec<String>>,
}
/// The settings for enabling/disabling features.
@@ -37,13 +37,13 @@ pub struct AllLanguageSettingsContent {
#[serde(rename_all = "snake_case")]
pub struct FeaturesContent {
/// Determines which edit prediction provider to use.
pub edit_prediction_provider: Option<EditPredictionProviderContent>,
pub edit_prediction_provider: Option<EditPredictionProvider>,
}
/// The provider that supplies edit predictions.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum EditPredictionProviderContent {
pub enum EditPredictionProvider {
None,
#[default]
Copilot,
@@ -62,7 +62,7 @@ pub struct EditPredictionSettingsContent {
/// The mode used to display edit predictions in the buffer.
/// Provider support required.
#[serde(default)]
pub mode: EditPredictionsModeContent,
pub mode: EditPredictionsMode,
/// Settings specific to GitHub Copilot.
#[serde(default)]
pub copilot: CopilotSettingsContent,
@@ -98,7 +98,7 @@ pub struct CopilotSettingsContent {
/// The mode in which edit predictions should be displayed.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum EditPredictionsModeContent {
pub enum EditPredictionsMode {
/// If provider supports it, display inline when holding modifier key (e.g., alt).
/// Otherwise, eager preview is used.
#[serde(alias = "auto")]
@@ -112,7 +112,7 @@ pub enum EditPredictionsModeContent {
/// Controls the soft-wrapping behavior in the editor.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SoftWrapContent {
pub enum SoftWrap {
/// Prefer a single line generally, unless an overly long line is encountered.
None,
/// Deprecated: use None instead. Left to avoid breaking existing users' configs.
@@ -144,7 +144,7 @@ pub struct LanguageSettingsContent {
///
/// Default: none
#[serde(default)]
pub soft_wrap: Option<SoftWrapContent>,
pub soft_wrap: Option<SoftWrap>,
/// The column at which to soft-wrap lines, for buffers where soft-wrap
/// is enabled.
///
@@ -166,7 +166,7 @@ pub struct LanguageSettingsContent {
pub wrap_guides: Option<Vec<usize>>,
/// Indent guide related settings.
#[serde(default)]
pub indent_guides: Option<IndentGuideSettingsContent>,
pub indent_guides: Option<IndentGuideSettings>,
/// Whether or not to perform a buffer format before saving.
///
/// Default: on
@@ -379,6 +379,8 @@ pub struct JsxTagAutoCloseSettings {
}
/// The settings for inlay hints.
/// todo(settings_refactor) the fields of this struct should likely be optional,
/// and a similar struct exposed from the language crate.
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
pub struct InlayHintSettings {
/// Global switch to toggle hints on and off.
@@ -437,6 +439,54 @@ pub struct InlayHintSettings {
pub toggle_on_modifiers_press: Option<Modifiers>,
}
impl InlayHintSettings {
/// Returns the kinds of inlay hints that are enabled based on the settings.
pub fn enabled_inlay_hint_kinds(&self) -> HashSet<Option<InlayHintKind>> {
let mut kinds = HashSet::default();
if self.show_type_hints {
kinds.insert(Some(InlayHintKind::Type));
}
if self.show_parameter_hints {
kinds.insert(Some(InlayHintKind::Parameter));
}
if self.show_other_hints {
kinds.insert(None);
}
kinds
}
}
/// The kind of an inlay hint.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum InlayHintKind {
/// An inlay hint for a type.
Type,
/// An inlay hint for a parameter.
Parameter,
}
impl InlayHintKind {
/// Returns the [`InlayHintKind`] from the given name.
///
/// Returns `None` if `name` does not match any of the expected
/// string representations.
pub fn from_name(name: &str) -> Option<Self> {
match name {
"type" => Some(InlayHintKind::Type),
"parameter" => Some(InlayHintKind::Parameter),
_ => None,
}
}
/// Returns the name of this [`InlayHintKind`].
pub fn name(&self) -> &'static str {
match self {
InlayHintKind::Type => "type",
InlayHintKind::Parameter => "parameter",
}
}
}
fn edit_debounce_ms() -> u64 {
700
}
@@ -775,7 +825,7 @@ pub enum Formatter {
/// The settings for indent guides.
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct IndentGuideSettingsContent {
pub struct IndentGuideSettings {
/// Whether to display indent guides in the editor.
///
/// Default: true
@@ -881,3 +931,47 @@ pub enum IndentGuideBackgroundColoring {
/// Use a different color for each indentation level.
IndentAware,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_formatter_deserialization() {
let raw_auto = "{\"formatter\": \"auto\"}";
let settings: LanguageSettingsContent = serde_json::from_str(raw_auto).unwrap();
assert_eq!(settings.formatter, Some(SelectedFormatter::Auto));
let raw = "{\"formatter\": \"language_server\"}";
let settings: LanguageSettingsContent = serde_json::from_str(raw).unwrap();
assert_eq!(
settings.formatter,
Some(SelectedFormatter::List(FormatterList::Single(
Formatter::LanguageServer { name: None }
)))
);
let raw = "{\"formatter\": [{\"language_server\": {\"name\": null}}]}";
let settings: LanguageSettingsContent = serde_json::from_str(raw).unwrap();
assert_eq!(
settings.formatter,
Some(SelectedFormatter::List(FormatterList::Vec(vec![
Formatter::LanguageServer { name: None }
])))
);
let raw = "{\"formatter\": [{\"language_server\": {\"name\": null}}, \"prettier\"]}";
let settings: LanguageSettingsContent = serde_json::from_str(raw).unwrap();
assert_eq!(
settings.formatter,
Some(SelectedFormatter::List(FormatterList::Vec(vec![
Formatter::LanguageServer { name: None },
Formatter::Prettier
])))
);
}
#[test]
fn test_formatter_deserialization_invalid() {
let raw_auto = "{\"formatter\": {}}";
let result: Result<LanguageSettingsContent, _> = serde_json::from_str(raw_auto);
assert!(result.is_err());
}
}

View File

@@ -186,7 +186,7 @@ struct SettingValue<T> {
trait AnySettingValue: 'static + Send + Sync {
fn setting_type_name(&self) -> &'static str;
fn from_file(&self, s: &SettingsContent, cx: &mut App) -> Option<Box<dyn Any>>;
fn from_default(&self, s: &SettingsContent, cx: &mut App) -> Option<Box<dyn Any>>;
fn refine(&self, value: &mut dyn Any, s: &[&SettingsContent], cx: &mut App);
fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any;
@@ -279,7 +279,7 @@ impl SettingsStore {
}
let Some(mut value) = T::from_default(&self.default_settings, cx) else {
panic!(
"{}::from_file return None for default.json",
"{}::from_default return None for default.json",
type_name::<T>()
)
};
@@ -387,7 +387,7 @@ impl SettingsStore {
cx: &mut App,
update: impl FnOnce(&mut SettingsContent),
) {
let mut content = self.user_settings.as_ref().unwrap().content.clone();
let mut content = self.user_settings.clone().unwrap_or_default().content;
update(&mut content);
let new_text = serde_json::to_string(&UserSettingsContent {
content,
@@ -864,7 +864,9 @@ impl SettingsStore {
for setting_value in self.setting_values.values_mut() {
// If the global settings file changed, reload the global value for the field.
if changed_local_path.is_none() {
let mut value = setting_value.from_file(&self.default_settings, cx).unwrap();
let mut value = setting_value
.from_default(&self.default_settings, cx)
.unwrap();
setting_value.refine(value.as_mut(), &refinements, cx);
setting_value.set_global_value(value);
}
@@ -896,7 +898,9 @@ impl SettingsStore {
continue;
}
let mut value = setting_value.from_file(&self.default_settings, cx).unwrap();
let mut value = setting_value
.from_default(&self.default_settings, cx)
.unwrap();
setting_value.refine(value.as_mut(), &refinements, cx);
setting_value.refine(value.as_mut(), &project_settings_stack, cx);
setting_value.set_local_value(*root_id, directory_path.clone(), value);
@@ -980,7 +984,7 @@ impl Debug for SettingsStore {
}
impl<T: Settings> AnySettingValue for SettingValue<T> {
fn from_file(&self, s: &SettingsContent, cx: &mut App) -> Option<Box<dyn Any>> {
fn from_default(&self, s: &SettingsContent, cx: &mut App) -> Option<Box<dyn Any>> {
T::from_default(s, cx).map(|result| Box::new(result) as _)
}

View File

@@ -798,6 +798,7 @@ fn font_fallbacks_from_settings(
impl settings::Settings for ThemeSettings {
fn from_default(content: &settings::SettingsContent, cx: &mut App) -> Option<Self> {
let content = &content.theme;
dbg!(&content);
let themes = ThemeRegistry::default_global(cx);
let system_appearance = SystemAppearance::default_global(cx);
let theme_selection: ThemeSelection = content.theme.clone()?.into();
@@ -832,7 +833,7 @@ impl settings::Settings for ThemeSettings {
.get_icon_theme(icon_theme_selection.icon_theme(*system_appearance))
.ok()?,
icon_theme_selection: Some(icon_theme_selection),
ui_density: content.ui_density?.into(),
ui_density: content.ui_density.unwrap_or_default().into(),
unnecessary_code_fade: content.unnecessary_code_fade?,
};