Factor out construction of font-related JSON schemas (#15341)

Marshall Bowers created

This PR factors out the construction of the font-related JSON schemas,
as they were used in multiple places.

Release Notes:

- N/A

Change summary

Cargo.lock                               |  1 
crates/settings/src/json_schema.rs       | 37 +++++++++++++++++++++++++
crates/settings/src/settings.rs          |  4 --
crates/settings/src/settings_store.rs    |  8 +----
crates/terminal/Cargo.toml               |  2 -
crates/terminal/src/terminal_settings.rs | 36 ++-----------------------
crates/theme/src/settings.rs             | 28 +------------------
7 files changed, 44 insertions(+), 72 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -10814,7 +10814,6 @@ dependencies = [
  "schemars",
  "serde",
  "serde_derive",
- "serde_json",
  "settings",
  "smol",
  "sysinfo",

crates/settings/src/json_schema.rs 🔗

@@ -1,4 +1,39 @@
-use schemars::schema::{RootSchema, Schema};
+use schemars::schema::{ArrayValidation, InstanceType, RootSchema, Schema, SchemaObject};
+use serde_json::Value;
+
+pub struct SettingsJsonSchemaParams<'a> {
+    pub staff_mode: bool,
+    pub language_names: &'a [String],
+    pub font_names: &'a [String],
+}
+
+impl<'a> SettingsJsonSchemaParams<'a> {
+    pub fn font_family_schema(&self) -> Schema {
+        let available_fonts: Vec<_> = self.font_names.iter().cloned().map(Value::String).collect();
+
+        SchemaObject {
+            instance_type: Some(InstanceType::String.into()),
+            enum_values: Some(available_fonts),
+            ..Default::default()
+        }
+        .into()
+    }
+
+    pub fn font_fallback_schema(&self) -> Schema {
+        SchemaObject {
+            instance_type: Some(InstanceType::Array.into()),
+            array: Some(Box::new(ArrayValidation {
+                items: Some(schemars::schema::SingleOrVec::Single(Box::new(
+                    self.font_family_schema(),
+                ))),
+                unique_items: Some(true),
+                ..Default::default()
+            })),
+            ..Default::default()
+        }
+        .into()
+    }
+}
 
 type PropertyName<'a> = &'a str;
 type ReferencePath<'a> = &'a str;

crates/settings/src/settings.rs 🔗

@@ -13,9 +13,7 @@ pub use editable_setting_control::*;
 pub use json_schema::*;
 pub use keymap_file::KeymapFile;
 pub use settings_file::*;
-pub use settings_store::{
-    Settings, SettingsJsonSchemaParams, SettingsLocation, SettingsSources, SettingsStore,
-};
+pub use settings_store::{Settings, SettingsLocation, SettingsSources, SettingsStore};
 
 #[derive(RustEmbed)]
 #[folder = "../../assets"]

crates/settings/src/settings_store.rs 🔗

@@ -17,6 +17,8 @@ use std::{
 };
 use util::{merge_non_null_json_value_into, RangeExt, ResultExt as _};
 
+use crate::SettingsJsonSchemaParams;
+
 /// A value that can be defined as a user setting.
 ///
 /// Settings can be loaded from a combination of multiple JSON files.
@@ -146,12 +148,6 @@ pub struct SettingsLocation<'a> {
     pub path: &'a Path,
 }
 
-pub struct SettingsJsonSchemaParams<'a> {
-    pub staff_mode: bool,
-    pub language_names: &'a [String],
-    pub font_names: &'a [String],
-}
-
 /// A set of strongly-typed setting values defined via multiple JSON files.
 pub struct SettingsStore {
     setting_values: HashMap<TypeId, Box<dyn AnySettingValue>>,

crates/terminal/Cargo.toml 🔗

@@ -12,7 +12,6 @@ workspace = true
 path = "src/terminal.rs"
 doctest = false
 
-
 [dependencies]
 alacritty_terminal = { git = "https://github.com/alacritty/alacritty", rev = "cacdb5bb3b72bad2c729227537979d95af75978f" }
 anyhow.workspace = true
@@ -25,7 +24,6 @@ release_channel.workspace = true
 schemars.workspace = true
 serde.workspace = true
 serde_derive.workspace = true
-serde_json.workspace = true
 settings.workspace = true
 sysinfo.workspace = true
 smol.workspace = true

crates/terminal/src/terminal_settings.rs 🔗

@@ -2,13 +2,8 @@ use collections::HashMap;
 use gpui::{
     px, AbsoluteLength, AppContext, FontFallbacks, FontFeatures, FontWeight, Pixels, SharedString,
 };
-use schemars::{
-    gen::SchemaGenerator,
-    schema::{ArrayValidation, InstanceType, RootSchema, SchemaObject},
-    JsonSchema,
-};
+use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
 use serde_derive::{Deserialize, Serialize};
-use serde_json::Value;
 use settings::{add_references_to_properties, SettingsJsonSchemaParams, SettingsSources};
 use std::path::PathBuf;
 use task::Shell;
@@ -202,34 +197,9 @@ impl settings::Settings for TerminalSettings {
         _: &AppContext,
     ) -> RootSchema {
         let mut root_schema = generator.root_schema_for::<Self::FileContent>();
-        let available_fonts: Vec<_> = params
-            .font_names
-            .iter()
-            .cloned()
-            .map(Value::String)
-            .collect();
-
-        let font_family_schema = SchemaObject {
-            instance_type: Some(InstanceType::String.into()),
-            enum_values: Some(available_fonts),
-            ..Default::default()
-        };
-
-        let font_fallback_schema = SchemaObject {
-            instance_type: Some(InstanceType::Array.into()),
-            array: Some(Box::new(ArrayValidation {
-                items: Some(schemars::schema::SingleOrVec::Single(Box::new(
-                    font_family_schema.clone().into(),
-                ))),
-                unique_items: Some(true),
-                ..Default::default()
-            })),
-            ..Default::default()
-        };
-
         root_schema.definitions.extend([
-            ("FontFamilies".into(), font_family_schema.into()),
-            ("FontFallbacks".into(), font_fallback_schema.into()),
+            ("FontFamilies".into(), params.font_family_schema()),
+            ("FontFallbacks".into(), params.font_fallback_schema()),
         ]);
 
         add_references_to_properties(

crates/theme/src/settings.rs 🔗

@@ -7,7 +7,6 @@ use gpui::{
     Subscription, ViewContext, WindowContext,
 };
 use refineable::Refineable;
-use schemars::schema::ArrayValidation;
 use schemars::{
     gen::SchemaGenerator,
     schema::{InstanceType, Schema, SchemaObject},
@@ -620,33 +619,10 @@ impl settings::Settings for ThemeSettings {
             ..Default::default()
         };
 
-        let available_fonts = params
-            .font_names
-            .iter()
-            .cloned()
-            .map(Value::String)
-            .collect::<Vec<_>>();
-        let font_family_schema = SchemaObject {
-            instance_type: Some(InstanceType::String.into()),
-            enum_values: Some(available_fonts),
-            ..Default::default()
-        };
-        let font_fallback_schema = SchemaObject {
-            instance_type: Some(InstanceType::Array.into()),
-            array: Some(Box::new(ArrayValidation {
-                items: Some(schemars::schema::SingleOrVec::Single(Box::new(
-                    font_family_schema.clone().into(),
-                ))),
-                unique_items: Some(true),
-                ..Default::default()
-            })),
-            ..Default::default()
-        };
-
         root_schema.definitions.extend([
             ("ThemeName".into(), theme_name_schema.into()),
-            ("FontFamilies".into(), font_family_schema.into()),
-            ("FontFallbacks".into(), font_fallback_schema.into()),
+            ("FontFamilies".into(), params.font_family_schema()),
+            ("FontFallbacks".into(), params.font_fallback_schema()),
         ]);
 
         add_references_to_properties(