diff --git a/Themes/Controls.xaml b/Themes/Controls.xaml index 211e84c..75dc73f 100644 --- a/Themes/Controls.xaml +++ b/Themes/Controls.xaml @@ -654,31 +654,6 @@ - - - + + + + diff --git a/ytLive.Tests/ThemeResourceTests.cs b/ytLive.Tests/ThemeResourceTests.cs index dbd5bde..3ef9af1 100644 --- a/ytLive.Tests/ThemeResourceTests.cs +++ b/ytLive.Tests/ThemeResourceTests.cs @@ -46,6 +46,36 @@ public class ThemeResourceTests + string.Join("\n ", missing.Distinct())); } + [Fact] + public void A_dictionary_never_references_a_key_defined_later_in_itself() + { + // StaticResource resolves while the dictionary is being built, so a forward reference + // fails at load with "Cannot find resource named …" — exactly how the app refused to + // launch on 2026-10-30 (a BasedOn pointing at a style defined further down the file). + var root = System.IO.Path.GetDirectoryName(SourceAssert.RepoPath("App.xaml"))!; + var files = new[] { System.IO.Path.Combine(root, "App.xaml") } + .Concat(Directory.GetFiles(System.IO.Path.Combine(root, "Themes"), "*.xaml")); + + var forward = new List(); + foreach (var file in files) + { + var text = File.ReadAllText(file); + var definitions = Regex.Matches(text, @"x:Key=""([^""]+)""") + .ToDictionary(m => m.Groups[1].Value, m => m.Index, StringComparer.Ordinal); + + foreach (Match use in Regex.Matches(text, @"\{StaticResource ([^}]+)\}")) + { + var key = use.Groups[1].Value.Trim(); + if (!definitions.TryGetValue(key, out var defined)) continue; + if (defined > use.Index) + forward.Add($"{System.IO.Path.GetFileName(file)}: {key} used before it is defined"); + } + } + + Assert.True(forward.Count == 0, + "Forward StaticResource references fail at load:\n " + string.Join("\n ", forward.Distinct())); + } + private static HashSet KeysIn(string text) => Regex.Matches(text, @"x:Key=""([^""]+)""").Select(m => m.Groups[1].Value) .ToHashSet(StringComparer.Ordinal);