From 82dd96369302f60a9c83a2d54d021458f82bcd36 Mon Sep 17 00:00:00 2001 From: Tim <63202655+sarsapar1lla@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:52:09 +0100 Subject: [PATCH] Add: validation of bundled themes in build workflow (#11627) * Add: xtask to check themes for validation warnings * Update: tidied up runtime paths * Update: test build workflow * Update: address clippy lints * Revert: only trigger workflow on push to master branch * Add: Theme::from_keys factory method to construct theme from Toml keys * Update: returning validation failures in Loader.load method * Update: commented out invalid keys from affected themes * Update: correct invalid keys so that valid styles still applied * Update: include default and base16_default themes in check * Update: renamed validation_failures to load_errors * Update: introduce load_with_warnings helper function and centralise logging of theme warnings * Update: use consistent naming throughout --- .github/workflows/build.yml | 4 ++ helix-view/src/theme.rs | 116 ++++++++++++++++++------------- runtime/themes/autumn.toml | 6 +- runtime/themes/emacs.toml | 3 +- runtime/themes/flatwhite.toml | 7 +- runtime/themes/kanagawa.toml | 3 +- runtime/themes/monokai.toml | 3 +- runtime/themes/monokai_aqua.toml | 9 ++- runtime/themes/zed_onedark.toml | 3 +- xtask/src/main.rs | 7 ++ xtask/src/path.rs | 10 ++- xtask/src/theme_check.rs | 33 +++++++++ 12 files changed, 143 insertions(+), 61 deletions(-) create mode 100644 xtask/src/theme_check.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93fcb9816..c9f198d0c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + - name: Install stable toolchain uses: dtolnay/rust-toolchain@1.70 @@ -107,6 +108,9 @@ jobs: - name: Validate queries run: cargo xtask query-check + - name: Validate themes + run: cargo xtask theme-check + - name: Generate docs run: cargo xtask docgen diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 4acc56648..9dc326444 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -53,20 +53,34 @@ impl Loader { /// Loads a theme searching directories in priority order. pub fn load(&self, name: &str) -> Result { + let (theme, warnings) = self.load_with_warnings(name)?; + + for warning in warnings { + warn!("Theme '{}': {}", name, warning); + } + + Ok(theme) + } + + /// Loads a theme searching directories in priority order, returning any warnings + pub fn load_with_warnings(&self, name: &str) -> Result<(Theme, Vec)> { if name == "default" { - return Ok(self.default()); + return Ok((self.default(), Vec::new())); } if name == "base16_default" { - return Ok(self.base16_default()); + return Ok((self.base16_default(), Vec::new())); } let mut visited_paths = HashSet::new(); - let theme = self.load_theme(name, &mut visited_paths).map(Theme::from)?; + let (theme, warnings) = self + .load_theme(name, &mut visited_paths) + .map(Theme::from_toml)?; - Ok(Theme { + let theme = Theme { name: name.into(), ..theme - }) + }; + Ok((theme, warnings)) } /// Recursively load a theme, merging with any inherited parent themes. @@ -87,10 +101,7 @@ impl Loader { let theme_toml = if let Some(parent_theme_name) = inherits { let parent_theme_name = parent_theme_name.as_str().ok_or_else(|| { - anyhow!( - "Theme: expected 'inherits' to be a string: {}", - parent_theme_name - ) + anyhow!("Expected 'inherits' to be a string: {}", parent_theme_name) })?; let parent_theme_toml = match parent_theme_name { @@ -181,9 +192,9 @@ impl Loader { }) .ok_or_else(|| { if cycle_found { - anyhow!("Theme: cycle found in inheriting: {}", name) + anyhow!("Cycle found in inheriting: {}", name) } else { - anyhow!("Theme: file not found for: {}", name) + anyhow!("File not found for: {}", name) } }) } @@ -220,19 +231,11 @@ pub struct Theme { impl From for Theme { fn from(value: Value) -> Self { - if let Value::Table(table) = value { - let (styles, scopes, highlights) = build_theme_values(table); - - Self { - styles, - scopes, - highlights, - ..Default::default() - } - } else { - warn!("Expected theme TOML value to be a table, found {:?}", value); - Default::default() + let (theme, warnings) = Theme::from_toml(value); + for warning in warnings { + warn!("{}", warning); } + theme } } @@ -242,31 +245,29 @@ impl<'de> Deserialize<'de> for Theme { D: Deserializer<'de>, { let values = Map::::deserialize(deserializer)?; - - let (styles, scopes, highlights) = build_theme_values(values); - - Ok(Self { - styles, - scopes, - highlights, - ..Default::default() - }) + let (theme, warnings) = Theme::from_keys(values); + for warning in warnings { + warn!("{}", warning); + } + Ok(theme) } } fn build_theme_values( mut values: Map, -) -> (HashMap, Vec, Vec