diff --git a/Terminal.Gui/Configuration/ConfigProperty.cs b/Terminal.Gui/Configuration/ConfigProperty.cs index 2418268cf..0c4a41682 100644 --- a/Terminal.Gui/Configuration/ConfigProperty.cs +++ b/Terminal.Gui/Configuration/ConfigProperty.cs @@ -41,7 +41,7 @@ public class ConfigProperty { if (PropertyInfo?.GetValue (null) is { }) { - PropertyInfo?.SetValue (null, DeepMemberwiseCopy (PropertyValue, PropertyInfo?.GetValue (null))); + PropertyInfo?.SetValue (null, DeepMemberWiseCopy (PropertyValue, PropertyInfo?.GetValue (null))); } } catch (TargetInvocationException tie) @@ -82,9 +82,9 @@ public class ConfigProperty /// public static string GetJsonPropertyName (PropertyInfo pi) { - var jpna = pi.GetCustomAttribute (typeof (JsonPropertyNameAttribute)) as JsonPropertyNameAttribute; + var attr = pi.GetCustomAttribute (typeof (JsonPropertyNameAttribute)) as JsonPropertyNameAttribute; - return jpna?.Name ?? pi.Name; + return attr?.Name ?? pi.Name; } /// @@ -118,7 +118,7 @@ public class ConfigProperty if (PropertyValue is { }) { - PropertyValue = DeepMemberwiseCopy (source, PropertyValue); + PropertyValue = DeepMemberWiseCopy (source, PropertyValue); } else { diff --git a/Terminal.Gui/Configuration/ConfigurationManager.cs b/Terminal.Gui/Configuration/ConfigurationManager.cs index 2dbd2ba44..f72cdd775 100644 --- a/Terminal.Gui/Configuration/ConfigurationManager.cs +++ b/Terminal.Gui/Configuration/ConfigurationManager.cs @@ -2,6 +2,7 @@ global using CM = Terminal.Gui.ConfigurationManager; using System.Collections; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Encodings.Web; using System.Text.Json; @@ -33,19 +34,19 @@ namespace Terminal.Gui; /// Settings are applied using the following precedence (higher precedence settings overwrite lower precedence /// settings): /// -/// 1. Application configuration found in the users's home directory (~/.tui/appname.config.json) -- +/// 1. Application configuration found in the users' home directory (~/.tui/appname.config.json) -- /// Highest precedence /// /// /// 2. Application configuration found in the directory the app was launched from ( /// ./.tui/appname.config.json). /// -/// 3. Application configuration found in the applications's resources (Resources/config.json). +/// 3. Application configuration found in the applications' resources (Resources/config.json). /// 4. Global configuration found in the user's home directory (~/.tui/config.json). /// 5. Global configuration found in the directory the app was launched from (./.tui/config.json). /// /// 6. Global configuration in Terminal.Gui.dll's resources (Terminal.Gui.Resources.config.json) -- -/// Lowest Precidence. +/// Lowest Precedence. /// /// public static class ConfigurationManager @@ -82,8 +83,10 @@ public static class ConfigurationManager /// to get and set the property's value. /// /// Is until is called. + [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "")] internal static Dictionary? _allConfigProperties; + [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "")] internal static readonly JsonSerializerOptions _serializerOptions = new () { ReadCommentHandling = JsonCommentHandling.Skip, @@ -104,8 +107,10 @@ public static class ConfigurationManager Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; - internal static StringBuilder jsonErrors = new (); + [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "")] + internal static StringBuilder _jsonErrors = new (); + [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "")] private static readonly string _configFilename = "config.json"; /// The backing property for . @@ -280,7 +285,7 @@ public static class ConfigurationManager public static void OnApplied () { Debug.WriteLine ("ConfigurationManager.OnApplied()"); - Applied?.Invoke (null, new ConfigurationManagerEventArgs ()); + Applied?.Invoke (null, new ()); // TODO: Refactor ConfigurationManager to not use an event handler for this. // Instead, have it call a method on any class appropriately attributed @@ -294,18 +299,18 @@ public static class ConfigurationManager public static void OnUpdated () { Debug.WriteLine (@"ConfigurationManager.OnApplied()"); - Updated?.Invoke (null, new ConfigurationManagerEventArgs ()); + Updated?.Invoke (null, new ()); } /// Prints any Json deserialization errors that occurred during deserialization to the console. public static void PrintJsonErrors () { - if (jsonErrors.Length > 0) + if (_jsonErrors.Length > 0) { Console.WriteLine ( @"Terminal.Gui ConfigurationManager encountered the following errors while deserializing configuration files:" ); - Console.WriteLine (jsonErrors.ToString ()); + Console.WriteLine (_jsonErrors.ToString ()); } } @@ -326,9 +331,9 @@ public static class ConfigurationManager ClearJsonErrors (); - Settings = new SettingsScope (); + Settings = new (); ThemeManager.Reset (); - AppSettings = new AppScope (); + AppSettings = new (); // To enable some unit tests, we only load from resources if the flag is set if (Locations.HasFlag (ConfigLocations.DefaultOnly)) @@ -350,23 +355,20 @@ public static class ConfigurationManager internal static void AddJsonError (string error) { Debug.WriteLine ($"ConfigurationManager: {error}"); - jsonErrors.AppendLine (error); + _jsonErrors.AppendLine (error); } /// /// System.Text.Json does not support copying a deserialized object to an existing instance. To work around this, - /// we implement a 'deep, memberwise copy' method. + /// we implement a 'deep, member-wise copy' method. /// /// TOOD: When System.Text.Json implements `PopulateObject` revisit https://github.com/dotnet/corefx/issues/37627 /// /// /// updated from - internal static object? DeepMemberwiseCopy (object? source, object? destination) + internal static object? DeepMemberWiseCopy (object? source, object? destination) { - if (destination is null) - { - throw new ArgumentNullException (nameof (destination)); - } + ArgumentNullException.ThrowIfNull (destination); if (source is null) { @@ -406,7 +408,7 @@ public static class ConfigurationManager if (((IDictionary)destination).Contains (srcKey)) { ((IDictionary)destination) [srcKey] = - DeepMemberwiseCopy (((IDictionary)source) [srcKey], ((IDictionary)destination) [srcKey]); + DeepMemberWiseCopy (((IDictionary)source) [srcKey], ((IDictionary)destination) [srcKey]); } else { @@ -438,7 +440,7 @@ public static class ConfigurationManager if (destVal is { }) { // Recurse - destProp.SetValue (destination, DeepMemberwiseCopy (sourceVal, destVal)); + destProp.SetValue (destination, DeepMemberWiseCopy (sourceVal, destVal)); } else { @@ -478,7 +480,7 @@ public static class ConfigurationManager throw new InvalidOperationException ("Initialize must be called first."); } - Settings = new SettingsScope (); + Settings = new (); ThemeManager.GetHardCodedDefaults (); AppSettings?.RetrieveValues (); @@ -494,7 +496,7 @@ public static class ConfigurationManager /// internal static void Initialize () { - _allConfigProperties = new Dictionary (); + _allConfigProperties = new (); _settings = null; Dictionary classesWithConfigProps = new (StringComparer.InvariantCultureIgnoreCase); @@ -549,18 +551,18 @@ public static class ConfigurationManager scp.OmitClassName ? ConfigProperty.GetJsonPropertyName (p) : $"{p.DeclaringType?.Name}.{p.Name}", - new ConfigProperty { PropertyInfo = p, PropertyValue = null } + new() { PropertyInfo = p, PropertyValue = null } ); } else { - throw new Exception ( - $"Property { - p.Name - } in class { - p.DeclaringType?.Name - } is not static. All SerializableConfigurationProperty properties must be static." - ); + throw new ( + $"Property { + p.Name + } in class { + p.DeclaringType?.Name + } is not static. All SerializableConfigurationProperty properties must be static." + ); } } } @@ -576,7 +578,7 @@ public static class ConfigurationManager //_allConfigProperties.ToList ().ForEach (x => Debug.WriteLine ($" Property: {x.Key}")); - AppSettings = new AppScope (); + AppSettings = new (); } /// Creates a JSON document with the configuration specified. @@ -602,5 +604,5 @@ public static class ConfigurationManager return stream; } - private static void ClearJsonErrors () { jsonErrors.Clear (); } + private static void ClearJsonErrors () { _jsonErrors.Clear (); } } diff --git a/Terminal.sln.DotSettings b/Terminal.sln.DotSettings index ef874a7ca..d04aeb7c3 100644 --- a/Terminal.sln.DotSettings +++ b/Terminal.sln.DotSettings @@ -383,6 +383,9 @@ True True False + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> True True True diff --git a/UnitTests/Configuration/ConfigurationMangerTests.cs b/UnitTests/Configuration/ConfigurationMangerTests.cs index c238ad5fb..6d3273847 100644 --- a/UnitTests/Configuration/ConfigurationMangerTests.cs +++ b/UnitTests/Configuration/ConfigurationMangerTests.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Text.Json; using static Terminal.Gui.ConfigurationManager; +#pragma warning disable IDE1006 namespace Terminal.Gui.ConfigurationTests; @@ -41,68 +42,69 @@ public class ConfigurationManagerTests Assert.True (fired); Applied -= ConfigurationManager_Applied; + Reset (); } [Fact] - public void DeepMemberwiseCopyTest () + public void DeepMemberWiseCopyTest () { // Value types var stringDest = "Destination"; var stringSrc = "Source"; - object stringCopy = DeepMemberwiseCopy (stringSrc, stringDest); + object stringCopy = DeepMemberWiseCopy (stringSrc, stringDest); Assert.Equal (stringSrc, stringCopy); stringDest = "Destination"; stringSrc = "Destination"; - stringCopy = DeepMemberwiseCopy (stringSrc, stringDest); + stringCopy = DeepMemberWiseCopy (stringSrc, stringDest); Assert.Equal (stringSrc, stringCopy); stringDest = "Destination"; stringSrc = null; - stringCopy = DeepMemberwiseCopy (stringSrc, stringDest); + stringCopy = DeepMemberWiseCopy (stringSrc, stringDest); Assert.Equal (stringSrc, stringCopy); stringDest = "Destination"; stringSrc = string.Empty; - stringCopy = DeepMemberwiseCopy (stringSrc, stringDest); + stringCopy = DeepMemberWiseCopy (stringSrc, stringDest); Assert.Equal (stringSrc, stringCopy); var boolDest = true; var boolSrc = false; - object boolCopy = DeepMemberwiseCopy (boolSrc, boolDest); + object boolCopy = DeepMemberWiseCopy (boolSrc, boolDest); Assert.Equal (boolSrc, boolCopy); boolDest = false; boolSrc = true; - boolCopy = DeepMemberwiseCopy (boolSrc, boolDest); + boolCopy = DeepMemberWiseCopy (boolSrc, boolDest); Assert.Equal (boolSrc, boolCopy); boolDest = true; boolSrc = true; - boolCopy = DeepMemberwiseCopy (boolSrc, boolDest); + boolCopy = DeepMemberWiseCopy (boolSrc, boolDest); Assert.Equal (boolSrc, boolCopy); boolDest = false; boolSrc = false; - boolCopy = DeepMemberwiseCopy (boolSrc, boolDest); + boolCopy = DeepMemberWiseCopy (boolSrc, boolDest); Assert.Equal (boolSrc, boolCopy); // Structs var attrDest = new Attribute (Color.Black); var attrSrc = new Attribute (Color.White); - object attrCopy = DeepMemberwiseCopy (attrSrc, attrDest); + object attrCopy = DeepMemberWiseCopy (attrSrc, attrDest); Assert.Equal (attrSrc, attrCopy); // Classes var colorschemeDest = new ColorScheme { Disabled = new Attribute (Color.Black) }; var colorschemeSrc = new ColorScheme { Disabled = new Attribute (Color.White) }; - object colorschemeCopy = DeepMemberwiseCopy (colorschemeSrc, colorschemeDest); + object colorschemeCopy = DeepMemberWiseCopy (colorschemeSrc, colorschemeDest); Assert.Equal (colorschemeSrc, colorschemeCopy); // Dictionaries Dictionary dictDest = new () { { "Disabled", new Attribute (Color.Black) } }; Dictionary dictSrc = new () { { "Disabled", new Attribute (Color.White) } }; - Dictionary dictCopy = (Dictionary)DeepMemberwiseCopy (dictSrc, dictDest); + Dictionary dictCopy = (Dictionary)DeepMemberWiseCopy (dictSrc, dictDest); Assert.Equal (dictSrc, dictCopy); dictDest = new Dictionary { { "Disabled", new Attribute (Color.Black) } }; @@ -111,7 +113,7 @@ public class ConfigurationManagerTests { { "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) } }; - dictCopy = (Dictionary)DeepMemberwiseCopy (dictSrc, dictDest); + dictCopy = (Dictionary)DeepMemberWiseCopy (dictSrc, dictDest); Assert.Equal (dictSrc, dictCopy); // src adds an item @@ -121,7 +123,7 @@ public class ConfigurationManagerTests { { "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) } }; - dictCopy = (Dictionary)DeepMemberwiseCopy (dictSrc, dictDest); + dictCopy = (Dictionary)DeepMemberWiseCopy (dictSrc, dictDest); Assert.Equal (2, dictCopy.Count); Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]); Assert.Equal (dictSrc ["Normal"], dictCopy ["Normal"]); @@ -132,7 +134,7 @@ public class ConfigurationManagerTests { "Disabled", new Attribute (Color.Black) }, { "Normal", new Attribute (Color.White) } }; dictSrc = new Dictionary { { "Disabled", new Attribute (Color.White) } }; - dictCopy = (Dictionary)DeepMemberwiseCopy (dictSrc, dictDest); + dictCopy = (Dictionary)DeepMemberWiseCopy (dictSrc, dictDest); Assert.Equal (2, dictCopy.Count); Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]); Assert.Equal (dictDest ["Normal"], dictCopy ["Normal"]); @@ -176,6 +178,7 @@ public class ConfigurationManagerTests Assert.True (fired); Updated -= ConfigurationManager_Updated; + Reset (); } [Fact] @@ -264,6 +267,7 @@ public class ConfigurationManagerTests Assert.Equal (KeyCode.PageDown | KeyCode.CtrlMask, Application.AlternateForwardKey.KeyCode); Assert.Equal (KeyCode.PageUp | KeyCode.CtrlMask, Application.AlternateBackwardKey.KeyCode); Assert.False (Application.IsMouseDisabled); + Reset (); } [Fact] @@ -376,7 +380,7 @@ public class ConfigurationManagerTests Assert.NotEmpty (Settings); - // test that all ConfigProperites have our attribute + // test that all ConfigProperties have our attribute Assert.All ( Settings, item => Assert.NotEmpty ( @@ -408,7 +412,7 @@ public class ConfigurationManagerTests [Fact] public void TestConfigPropertyOmitClassName () { - // Color.ColorShemes is serialzied as "ColorSchemes", not "Colors.ColorSchemes" + // Color.ColorSchemes is serialized as "ColorSchemes", not "Colors.ColorSchemes" PropertyInfo pi = typeof (Colors).GetProperty ("ColorSchemes"); var scp = (SerializableConfigurationProperty)pi.GetCustomAttribute (typeof (SerializableConfigurationProperty)); Assert.True (scp.Scope == typeof (ThemeScope)); @@ -537,7 +541,7 @@ public class ConfigurationManagerTests Settings.Update ("{}}", "test"); - Assert.NotEqual (0, jsonErrors.Length); + Assert.NotEqual (0, _jsonErrors.Length); Application.Shutdown (); @@ -621,7 +625,7 @@ public class ConfigurationManagerTests jsonException = Assert.Throws (() => Settings.Update (json, "test")); Assert.Equal ("Both Foreground and Background colors must be provided.", jsonException.Message); - // Unknown proeprty + // Unknown property json = @" { ""Unknown"" : ""Not known"" @@ -630,7 +634,7 @@ public class ConfigurationManagerTests jsonException = Assert.Throws (() => Settings.Update (json, "test")); Assert.StartsWith ("Unknown property", jsonException.Message); - Assert.Equal (0, jsonErrors.Length); + Assert.Equal (0, _jsonErrors.Length); ThrowOnJsonErrors = false; } @@ -813,6 +817,7 @@ public class ConfigurationManagerTests Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"].Normal.Foreground); Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background); + Reset (); } [Fact] diff --git a/UnitTests/Configuration/ThemeScopeTests.cs b/UnitTests/Configuration/ThemeScopeTests.cs index 900676c5a..3da7f881a 100644 --- a/UnitTests/Configuration/ThemeScopeTests.cs +++ b/UnitTests/Configuration/ThemeScopeTests.cs @@ -35,6 +35,7 @@ public class ThemeScopeTests ThemeManager.Themes! [ThemeManager.SelectedTheme]!.Apply (); Assert.Equal (Dialog.ButtonAlignments.Right, Dialog.DefaultButtonAlignment); + Reset (); } [Fact] diff --git a/UnitTests/Configuration/ThemeTests.cs b/UnitTests/Configuration/ThemeTests.cs index e467b7ce4..f7d8c732f 100644 --- a/UnitTests/Configuration/ThemeTests.cs +++ b/UnitTests/Configuration/ThemeTests.cs @@ -27,6 +27,8 @@ public class ThemeTests Themes! [ThemeManager.SelectedTheme]!.Apply (); Assert.Equal (LineStyle.Double, FrameView.DefaultBorderStyle); + + Reset (); } [Fact] @@ -68,6 +70,7 @@ public class ThemeTests // remove test ColorScheme from Colors to avoid failures on others unit tests with ColorScheme Colors.ColorSchemes.Remove ("test"); Assert.Equal (5, Colors.ColorSchemes.Count); + Reset (); } [Fact] @@ -84,6 +87,7 @@ public class ThemeTests Dialog.ButtonAlignments.Right, (Dialog.ButtonAlignments)deserialized ["Dialog.DefaultButtonAlignment"].PropertyValue ); + Reset (); } [Fact] @@ -132,6 +136,7 @@ public class ThemeTests colorSchemes = (Dictionary)theme ["ColorSchemes"].PropertyValue; Assert.Equal (colorSchemes ["Test"].Normal, colorScheme.Normal); Assert.Equal (colorSchemes ["Test"].Focus, colorScheme.Focus); + Reset (); } [Fact] @@ -186,5 +191,6 @@ public class ThemeTests Assert.Equal (new Color (Color.BrightBlue), colorSchemes ["Test"].Normal.Background); Assert.Equal (new Color (Color.Cyan), colorSchemes ["Test"].Focus.Foreground); Assert.Equal (new Color (Color.BrightCyan), colorSchemes ["Test"].Focus.Background); + Reset (); } } diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index 88d7ec978..5842b3a38 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -86,6 +86,7 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute Responder.Instances.Clear (); } #endif + ConfigurationManager.Reset (); } }