diff --git a/src/Common.Tests/Extensions/DictionaryExtensionsTest.cs b/src/Common.Tests/Extensions/DictionaryExtensionsTest.cs index bab1fd76..d72252b7 100644 --- a/src/Common.Tests/Extensions/DictionaryExtensionsTest.cs +++ b/src/Common.Tests/Extensions/DictionaryExtensionsTest.cs @@ -14,30 +14,50 @@ namespace Common.Tests.Extensions } [Test] - public void GetOrCreate_ItemExists_ReturnExistingItem() + public void Create_item_if_none_exists() + { + var dict = new Dictionary(); + var theValue = dict.GetOrCreate(100); + dict.Should().HaveCount(1); + dict.Should().Contain(100, theValue); + } + + [Test] + public void Return_default_if_no_item_exists() { var sample = new MySampleValue(); var dict = new Dictionary {{100, sample}}; - var theValue = dict.GetOrCreate(100); - dict.Should().HaveCount(1); - dict.Should().Contain(100, sample); - dict.Should().ContainValue(theValue); - theValue.Should().Be(sample); + var theValue = dict.GetOrDefault(200); + + dict.Should().HaveCount(1).And.Contain(100, sample); + theValue.Should().BeNull(); } [Test] - public void GetOrCreate_NoItemExists_ItIsCreated() + public void Return_existing_item_if_exists_not_create() { - var dict = new Dictionary(); + var sample = new MySampleValue(); + var dict = new Dictionary {{100, sample}}; + var theValue = dict.GetOrCreate(100); dict.Should().HaveCount(1); - dict.Should().Contain(100, theValue); + dict.Should().Contain(100, sample); + dict.Should().ContainValue(theValue); + theValue.Should().Be(sample); } [Test] - public void GetOrDefault_ItemExists_ReturnExistingItem() + public void Return_existing_item_if_it_exists_not_default() { + var sample = new MySampleValue(); + var dict = new Dictionary {{100, sample}}; + + var theValue = dict.GetOrDefault(100); + + // Ensure the container hasn't been mutated + dict.Should().HaveCount(1).And.Contain(100, sample); + theValue.Should().Be(sample); } } } diff --git a/src/Common/Extensions/FluentValidationExtensions.cs b/src/Common/Extensions/FluentValidationExtensions.cs index 75af48a6..186a87a5 100644 --- a/src/Common/Extensions/FluentValidationExtensions.cs +++ b/src/Common/Extensions/FluentValidationExtensions.cs @@ -20,7 +20,7 @@ namespace Common.Extensions return ruleBuilder.SetAsyncValidator(adapter); } - private class NullableChildValidatorAdaptor : ChildValidatorAdaptor, + private sealed class NullableChildValidatorAdaptor : ChildValidatorAdaptor, IPropertyValidator, IAsyncPropertyValidator { public NullableChildValidatorAdaptor(IValidator validator, Type validatorType) diff --git a/src/Common/Extensions/LinqExtensions.cs b/src/Common/Extensions/LinqExtensions.cs deleted file mode 100644 index e5e0dd8e..00000000 --- a/src/Common/Extensions/LinqExtensions.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Common.Extensions -{ - internal static class LinqExtensions - { - internal static IEnumerable FullOuterGroupJoin( - this IEnumerable a, - IEnumerable b, - Func selectKeyA, - Func selectKeyB, - Func, IEnumerable, TKey, TResult> projection, - IEqualityComparer? cmp = null) - { - cmp ??= EqualityComparer.Default; - var alookup = a.ToLookup(selectKeyA, cmp); - var blookup = b.ToLookup(selectKeyB, cmp); - - var keys = new HashSet(alookup.Select(p => p.Key), cmp); - keys.UnionWith(blookup.Select(p => p.Key)); - - var join = from key in keys - let xa = alookup[key] - let xb = blookup[key] - select projection(xa, xb, key); - - return join; - } - - internal static IEnumerable FullOuterJoin( - this IEnumerable a, - IEnumerable b, - Func selectKeyA, - Func selectKeyB, - Func projection, - TA? defaultA = default, - TB? defaultB = default, - IEqualityComparer? cmp = null) - { - cmp ??= EqualityComparer.Default; - var alookup = a.ToLookup(selectKeyA, cmp); - var blookup = b.ToLookup(selectKeyB, cmp); - - var keys = new HashSet(alookup.Select(p => p.Key), cmp); - keys.UnionWith(blookup.Select(p => p.Key)); - - var join = from key in keys - from xa in alookup[key].DefaultIfEmpty(defaultA) - from xb in blookup[key].DefaultIfEmpty(defaultB) - select projection(xa, xb, key); - - return join; - } - } -} diff --git a/src/Common/Extensions/RxExtensions.cs b/src/Common/Extensions/RxExtensions.cs index 21bd9248..fe7ff1bf 100644 --- a/src/Common/Extensions/RxExtensions.cs +++ b/src/Common/Extensions/RxExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Reactive.Disposables; using System.Reactive.Linq; -using System.Threading; using Serilog; namespace Common.Extensions @@ -13,31 +12,31 @@ namespace Common.Extensions opName ??= "IObservable"; log.Debug("{OpName}: Observable obtained on Thread: {ThreadId}", opName, - Thread.CurrentThread.ManagedThreadId); + Environment.CurrentManagedThreadId); return Observable.Create(obs => { log.Debug("{OpName}: Subscribed to on Thread: {ThreadId}", opName, - Thread.CurrentThread.ManagedThreadId); + Environment.CurrentManagedThreadId); try { var subscription = source .Do( x => log.Debug("{OpName}: OnNext({Result}) on Thread: {ThreadId}", opName, x, - Thread.CurrentThread.ManagedThreadId), + Environment.CurrentManagedThreadId), ex => log.Debug("{OpName}: OnError({Result}) on Thread: {ThreadId}", opName, ex.Message, - Thread.CurrentThread.ManagedThreadId), + Environment.CurrentManagedThreadId), () => log.Debug("{OpName}: OnCompleted() on Thread: {ThreadId}", opName, - Thread.CurrentThread.ManagedThreadId)) + Environment.CurrentManagedThreadId)) .Subscribe(obs); return new CompositeDisposable( subscription, Disposable.Create(() => log.Debug( "{OpName}: Cleaned up on Thread: {ThreadId}", opName, - Thread.CurrentThread.ManagedThreadId))); + Environment.CurrentManagedThreadId))); } finally { diff --git a/src/Common/YamlDotNet/ValidatingDeserializer.cs b/src/Common/YamlDotNet/ValidatingDeserializer.cs index b88fefb5..c45755be 100644 --- a/src/Common/YamlDotNet/ValidatingDeserializer.cs +++ b/src/Common/YamlDotNet/ValidatingDeserializer.cs @@ -14,10 +14,10 @@ namespace Common.YamlDotNet _nodeDeserializer = nodeDeserializer; } - public bool Deserialize(IParser parser, Type expectedType, + public bool Deserialize(IParser reader, Type expectedType, Func nestedObjectDeserializer, out object? value) { - if (!_nodeDeserializer.Deserialize(parser, expectedType, nestedObjectDeserializer, out value) || + if (!_nodeDeserializer.Deserialize(reader, expectedType, nestedObjectDeserializer, out value) || value == null) { return false; @@ -31,12 +31,12 @@ namespace Common.YamlDotNet } catch (ValidationException e) { - if (parser.Current == null) + if (reader.Current == null) { throw; } - throw new YamlException(parser.Current.Start, parser.Current.End, e.Message); + throw new YamlException(reader.Current.Start, reader.Current.End, e.Message); } return true; diff --git a/src/Common/YamlDotNet/YamlDotNetExtensions.cs b/src/Common/YamlDotNet/YamlDotNetExtensions.cs index 34ef716e..f008c6ea 100644 --- a/src/Common/YamlDotNet/YamlDotNetExtensions.cs +++ b/src/Common/YamlDotNet/YamlDotNetExtensions.cs @@ -21,7 +21,7 @@ namespace Common.YamlDotNet } [UsedImplicitly(ImplicitUseTargetFlags.Members)] - private class RootExtractor + private sealed class RootExtractor where T : class { public T? RootObject { get; } diff --git a/src/Common/YamlDotNet/YamlNullableEnumTypeConverter.cs b/src/Common/YamlDotNet/YamlNullableEnumTypeConverter.cs index 99dca28c..7d89bc6d 100644 --- a/src/Common/YamlDotNet/YamlNullableEnumTypeConverter.cs +++ b/src/Common/YamlDotNet/YamlNullableEnumTypeConverter.cs @@ -19,13 +19,10 @@ namespace Common.YamlDotNet type = Nullable.GetUnderlyingType(type) ?? throw new ArgumentException("Expected nullable enum type for ReadYaml"); - if (parser.Accept(out var @event)) + if (parser.Accept(out var @event) && NodeIsNull(@event)) { - if (NodeIsNull(@event)) - { - parser.SkipThisAndNestedEvents(); - return null; - } + parser.SkipThisAndNestedEvents(); + return null; } var scalar = parser.Consume(); @@ -35,7 +32,7 @@ namespace Common.YamlDotNet } catch (Exception ex) { - throw new Exception($"Invalid value: \"{scalar.Value}\" for {type.Name}", ex); + throw new YamlException($"Invalid value: \"{scalar.Value}\" for {type.Name}", ex); } } @@ -44,12 +41,14 @@ namespace Common.YamlDotNet type = Nullable.GetUnderlyingType(type) ?? throw new ArgumentException("Expected nullable enum type for WriteYaml"); - if (value != null) + if (value == null) { - var toWrite = Enum.GetName(type, value) ?? - throw new InvalidOperationException($"Invalid value {value} for enum: {type}"); - emitter.Emit(new Scalar(null!, null!, toWrite, ScalarStyle.Any, true, false)); + return; } + + var toWrite = Enum.GetName(type, value) ?? + throw new InvalidOperationException($"Invalid value {value} for enum: {type}"); + emitter.Emit(new Scalar(null!, null!, toWrite, ScalarStyle.Any, true, false)); } private static bool NodeIsNull(NodeEvent nodeEvent) @@ -61,13 +60,13 @@ namespace Common.YamlDotNet return true; } - if (nodeEvent is Scalar scalar && scalar.Style == ScalarStyle.Plain) + if (nodeEvent is not Scalar {Style: ScalarStyle.Plain} scalar) { - var value = scalar.Value; - return value is "" or "~" or "null" or "Null" or "NULL"; + return false; } - return false; + var value = scalar.Value; + return value is "" or "~" or "null" or "Null" or "NULL"; } } } diff --git a/src/Trash.Tests/CompositionRootTest.cs b/src/Trash.Tests/CompositionRootTest.cs index 77ed9efa..8c6149d3 100644 --- a/src/Trash.Tests/CompositionRootTest.cs +++ b/src/Trash.Tests/CompositionRootTest.cs @@ -1,9 +1,8 @@ -using System; using System.Collections; using System.Linq; -using System.Reflection; using Autofac; -using CliFx; +using Autofac.Core; +using FluentAssertions; using NUnit.Framework; namespace Trash.Tests @@ -12,29 +11,31 @@ namespace Trash.Tests [Parallelizable(ParallelScope.All)] public class CompositionRootTest { - private class ConcreteTypeEnumerator : IEnumerable + private sealed class ConcreteTypeEnumerator : IEnumerable { - private readonly Assembly _asm; + private readonly IContainer _container; public ConcreteTypeEnumerator() { - _asm = Assembly.GetAssembly(typeof(CompositionRoot)) ?? throw new NullReferenceException(); + _container = CompositionRoot.Setup(); } public IEnumerator GetEnumerator() { - return _asm.DefinedTypes - .Where(t => t.GetInterfaces().Contains(typeof(T)) && !t.IsAbstract) + return _container.ComponentRegistry.Registrations + .SelectMany(x => x.Services) + .OfType() .GetEnumerator(); } } - [TestCaseSource(typeof(ConcreteTypeEnumerator))] - public void Resolve_ICommandConcreteClasses(Type concreteCmd) + [TestCaseSource(typeof(ConcreteTypeEnumerator))] + public void Resolve_ICommandConcreteClasses(Service service) { - var builder = new ContainerBuilder(); - var container = CompositionRoot.Setup(builder); - container.Resolve(concreteCmd); + using var container = CompositionRoot.Setup(); + container.Invoking(c => c.ResolveService(service)) + .Should().NotThrow() + .And.NotBeNull(); } } } diff --git a/src/Trash/Command/SonarrCommand.cs b/src/Trash/Command/SonarrCommand.cs index 0082da0e..f945d2f5 100644 --- a/src/Trash/Command/SonarrCommand.cs +++ b/src/Trash/Command/SonarrCommand.cs @@ -38,8 +38,6 @@ namespace Trash.Command _qualityUpdaterFactory = qualityUpdaterFactory; } - // todo: Add options to exclude parts of YAML on the fly? - public override string CacheStoragePath { get; } = Path.Combine(AppPaths.AppDataPath, "cache", "sonarr"); diff --git a/src/Trash/CompositionRoot.cs b/src/Trash/CompositionRoot.cs index 01fa9b80..ef9a2363 100644 --- a/src/Trash/CompositionRoot.cs +++ b/src/Trash/CompositionRoot.cs @@ -70,8 +70,8 @@ namespace Trash .As() .SingleInstance(); - builder.Register(c => c.Resolve().ActiveCommand) - .As(); + builder.Register(c => new Lazy( + () => c.Resolve().ActiveCommand)); } public static IContainer Setup() @@ -96,7 +96,6 @@ namespace Trash builder.Register(_ => AutoMapperConfig.Setup()).SingleInstance(); - // builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); return builder.Build(); } } diff --git a/src/Trash/Config/ConfigurationException.cs b/src/Trash/Config/ConfigurationException.cs index aee050eb..a14f1aa0 100644 --- a/src/Trash/Config/ConfigurationException.cs +++ b/src/Trash/Config/ConfigurationException.cs @@ -1,13 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text; using FluentValidation.Results; namespace Trash.Config { + [Serializable] public class ConfigurationException : Exception { + protected ConfigurationException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + private ConfigurationException(string propertyName, Type deserializableType, IEnumerable messages) { PropertyName = propertyName; @@ -26,9 +33,9 @@ namespace Trash.Config { } - public IReadOnlyCollection ErrorMessages { get; } - public string PropertyName { get; } - public Type DeserializableType { get; } + public IReadOnlyCollection ErrorMessages { get; } = new List(); + public string PropertyName { get; } = ""; + public Type DeserializableType { get; } = default!; public override string Message => BuildMessage(); diff --git a/src/Trash/Config/ConfigurationLoader.cs b/src/Trash/Config/ConfigurationLoader.cs index 2e64325e..10b632cb 100644 --- a/src/Trash/Config/ConfigurationLoader.cs +++ b/src/Trash/Config/ConfigurationLoader.cs @@ -37,9 +37,9 @@ namespace Trash.Config .Build(); } - public IEnumerable Load(string configPath, string configSection) + public IEnumerable Load(string propertyName, string configSection) { - using var stream = _fileSystem.File.OpenText(configPath); + using var stream = _fileSystem.File.OpenText(propertyName); return LoadFromStream(stream, configSection); } @@ -53,24 +53,20 @@ namespace Trash.Config var validConfigs = new List(); while (parser.TryConsume(out var key)) { - if (key.Value == configSection) + if (key.Value != configSection) { - var configs = (List?) _deserializer.Deserialize>(parser); - if (configs != null) - { - foreach (var config in configs) - { - var result = _validator.Validate(config); - if (result is {IsValid: false}) - { - throw new ConfigurationException(configSection, typeof(T), result.Errors); - } + parser.SkipThisAndNestedEvents(); + continue; + } - validConfigs.Add(config); - } - } + var configs = _deserializer.Deserialize?>(parser); + if (configs == null) + { + parser.SkipThisAndNestedEvents(); + continue; } + ValidateConfigs(configSection, configs, validConfigs); parser.SkipThisAndNestedEvents(); } @@ -82,6 +78,20 @@ namespace Trash.Config return validConfigs; } + private void ValidateConfigs(string configSection, IEnumerable configs, ICollection validConfigs) + { + foreach (var config in configs) + { + var result = _validator.Validate(config); + if (result is {IsValid: false}) + { + throw new ConfigurationException(configSection, typeof(T), result.Errors); + } + + validConfigs.Add(config); + } + } + public IEnumerable LoadMany(IEnumerable configFiles, string configSection) { foreach (var config in configFiles.SelectMany(file => Load(file, configSection))) diff --git a/src/TrashLib.Tests/Radarr/CustomFormat/CachePersisterTest.cs b/src/TrashLib.Tests/Radarr/CustomFormat/CachePersisterTest.cs index 69cc4423..e99279a4 100644 --- a/src/TrashLib.Tests/Radarr/CustomFormat/CachePersisterTest.cs +++ b/src/TrashLib.Tests/Radarr/CustomFormat/CachePersisterTest.cs @@ -20,17 +20,16 @@ namespace TrashLib.Tests.Radarr.CustomFormat { public Context() { - Log = Substitute.For(); + var log = Substitute.For(); ServiceCache = Substitute.For(); - Persister = new CachePersister(Log, ServiceCache); + Persister = new CachePersister(log, ServiceCache); } public CachePersister Persister { get; } - public ILogger Log { get; } public IServiceCache ServiceCache { get; } } - private ProcessedCustomFormatData QuickMakeCf(string cfName, string trashId, int cfId) + private static ProcessedCustomFormatData QuickMakeCf(string cfName, string trashId, int cfId) { return new ProcessedCustomFormatData(cfName, trashId, new JObject()) { diff --git a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/PersistenceSteps/CustomFormatApiPersistenceStepTest.cs b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/PersistenceSteps/CustomFormatApiPersistenceStepTest.cs index 8858e65c..5ac82bf5 100644 --- a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/PersistenceSteps/CustomFormatApiPersistenceStepTest.cs +++ b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/PersistenceSteps/CustomFormatApiPersistenceStepTest.cs @@ -14,7 +14,7 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.PersistenceSteps [Parallelizable(ParallelScope.All)] public class CustomFormatApiPersistenceStepTest { - private ProcessedCustomFormatData QuickMakeCf(string cfName, string trashId, int cfId) + private static ProcessedCustomFormatData QuickMakeCf(string cfName, string trashId, int cfId) { return new ProcessedCustomFormatData(cfName, trashId, new JObject()) { diff --git a/src/TrashLib/Config/ServerInfo.cs b/src/TrashLib/Config/ServerInfo.cs index a6f1ac37..0157b9e0 100644 --- a/src/TrashLib/Config/ServerInfo.cs +++ b/src/TrashLib/Config/ServerInfo.cs @@ -7,22 +7,23 @@ namespace TrashLib.Config { internal class ServerInfo : IServerInfo { - private readonly string _apiKey; - private readonly string _baseUrl; + private readonly IConfigurationProvider _config; private readonly ILogger _log; - public ServerInfo(string baseUrl, string apiKey, ILogger log) + public ServerInfo(IConfigurationProvider config, ILogger log) { - _baseUrl = baseUrl; - _apiKey = apiKey; + _config = config; _log = log; } public IFlurlRequest BuildRequest() { - return _baseUrl + var apiKey = _config.ActiveConfiguration.ApiKey; + var baseUrl = _config.ActiveConfiguration.BaseUrl; + + return baseUrl .AppendPathSegment("api/v3") - .SetQueryParams(new {apikey = _apiKey}) + .SetQueryParams(new {apikey = apiKey}) .SanitizedLogging(_log); } } diff --git a/src/TrashLib/Radarr/RadarrAutofacModule.cs b/src/TrashLib/Radarr/RadarrAutofacModule.cs index efc18a30..6d601fed 100644 --- a/src/TrashLib/Radarr/RadarrAutofacModule.cs +++ b/src/TrashLib/Radarr/RadarrAutofacModule.cs @@ -1,6 +1,5 @@ using Autofac; using Autofac.Extras.AggregateService; -using Serilog; using TrashLib.Config; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat; @@ -25,13 +24,7 @@ namespace TrashLib.Radarr // Configuration builder.RegisterType().As(); - builder.Register(c => - { - var config = c.Resolve().ActiveConfiguration; - var log = c.Resolve(); - return new ServerInfo(config.BaseUrl, config.ApiKey, log); - }) - .As(); + builder.RegisterType().As(); // Quality Definition Support builder.RegisterType().As(); @@ -43,9 +36,9 @@ namespace TrashLib.Radarr builder.RegisterType().As(); // Guide Processor - builder.RegisterType() - .As< - IGuideProcessor>(); // todo: register as singleton to avoid parsing guide multiple times when using 2 or more instances in config + + // todo: register as singleton to avoid parsing guide multiple times when using 2 or more instances in config + builder.RegisterType().As(); builder.RegisterAggregateService(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/TrashUpdater.sln.DotSettings b/src/TrashUpdater.sln.DotSettings index b88769e4..af23c5cd 100644 --- a/src/TrashUpdater.sln.DotSettings +++ b/src/TrashUpdater.sln.DotSettings @@ -4,9 +4,111 @@ &lt;/profile&gt;</IDEA_SETTINGS></Profile> True - <?xml version="1.0" encoding="utf-16"?><Profile name="TrashUpdaterCleanup"><CSReorderTypeMembers>True</CSReorderTypeMembers><XMLReformatCode>True</XMLReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" /><RemoveCodeRedundanciesVB>True</RemoveCodeRedundanciesVB><Xaml.RedundantFreezeAttribute>True</Xaml.RedundantFreezeAttribute><Xaml.RemoveRedundantModifiersAttribute>True</Xaml.RemoveRedundantModifiersAttribute><Xaml.RemoveRedundantNameAttribute>True</Xaml.RemoveRedundantNameAttribute><Xaml.RemoveRedundantResource>True</Xaml.RemoveRedundantResource><Xaml.RemoveRedundantCollectionProperty>True</Xaml.RemoveRedundantCollectionProperty><Xaml.RemoveRedundantAttachedPropertySetter>True</Xaml.RemoveRedundantAttachedPropertySetter><Xaml.RemoveRedundantStyledValue>True</Xaml.RemoveRedundantStyledValue><Xaml.RemoveRedundantNamespaceAlias>True</Xaml.RemoveRedundantNamespaceAlias><Xaml.RemoveForbiddenResourceName>True</Xaml.RemoveForbiddenResourceName><Xaml.RemoveRedundantGridDefinitionsAttribute>True</Xaml.RemoveRedundantGridDefinitionsAttribute><Xaml.RemoveRedundantGridSpanAttribut>True</Xaml.RemoveRedundantGridSpanAttribut><Xaml.RemoveRedundantUpdateSourceTriggerAttribute>True</Xaml.RemoveRedundantUpdateSourceTriggerAttribute><Xaml.RemoveRedundantBindingModeAttribute>True</Xaml.RemoveRedundantBindingModeAttribute><HtmlReformatCode>True</HtmlReformatCode><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><CppAddOverrideSpecifier>True</CppAddOverrideSpecifier><CppAddTypenameTemplateKeywords>True</CppAddTypenameTemplateKeywords><CppReplaceImportDirective>True</CppReplaceImportDirective><CppRemoveElseKeyword>True</CppRemoveElseKeyword><CppShortenQualifiedName>True</CppShortenQualifiedName><CppDeleteRedundantSpecifier>True</CppDeleteRedundantSpecifier><CppRemoveStatement>True</CppRemoveStatement><CppDeleteRedundantTypenameTemplateKeywords>True</CppDeleteRedundantTypenameTemplateKeywords><CppCStyleToStaticCastDescriptor>True</CppCStyleToStaticCastDescriptor><CppReplaceExpressionWithBooleanConst>True</CppReplaceExpressionWithBooleanConst><CppMakeIfConstexpr>True</CppMakeIfConstexpr><CppMakePostfixOperatorPrefix>True</CppMakePostfixOperatorPrefix><CppChangeSmartPointerToMakeFunction>True</CppChangeSmartPointerToMakeFunction><CppReplaceThrowWithRethrowFix>True</CppReplaceThrowWithRethrowFix><CppReplaceExpressionWithNullptr>True</CppReplaceExpressionWithNullptr><CppSortMemberInitializers>True</CppSortMemberInitializers><CppReformatCode>True</CppReformatCode><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><VBReformatCode>True</VBReformatCode><VBFormatDocComments>True</VBFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><IDEA_SETTINGS>&lt;profile version="1.0"&gt; + <?xml version="1.0" encoding="utf-16"?><Profile name="RecyclarrCleanup"><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" /><CppAddOverrideSpecifier>True</CppAddOverrideSpecifier><CppReplaceImportDirective>True</CppReplaceImportDirective><CppSortMemberInitializers>True</CppSortMemberInitializers><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><IDEA_SETTINGS>&lt;profile version="1.0"&gt; + &lt;option name="myName" value="RecyclarrCleanup" /&gt; + &lt;inspection_tool class="ES6ShorthandObjectProperty" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSArrowFunctionBracesCanBeRemoved" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSPrimitiveTypeWrapperUsage" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSRemoveUnnecessaryParentheses" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSUnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="TypeScriptExplicitMemberType" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryContinueJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelOnBreakStatementJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelOnContinueStatementJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryReturnJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; +&lt;/profile&gt;</IDEA_SETTINGS><CSShortenReferences>True</CSShortenReferences><CSUpdateFileHeader>True</CSUpdateFileHeader><RIDER_SETTINGS>&lt;profile&gt; + &lt;Language id="CSS"&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="EditorConfig"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="HTML"&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="Ini"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JSON"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JavaScript"&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="Markdown"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Properties"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="RELAX-NG"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="SQL"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="XML"&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="yaml"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; +&lt;/profile&gt;</RIDER_SETTINGS><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CppCodeStyleCleanupDescriptor ArrangeAuto="False" ArrangeBraces="False" ArrangeCVQualifiers="False" ArrangeFunctionDeclarations="False" ArrangeNestedNamespaces="False" ArrangeOverridingFunctions="False" ArrangeSlashesInIncludeDirectives="False" ArrangeTypeAliases="False" SortIncludeDirectives="False" SortMemberInitializers="False" /><CppRemoveCastDescriptor>False</CppRemoveCastDescriptor><CppTypeTraitAliasDescriptor>False</CppTypeTraitAliasDescriptor><CppReplaceTieWithStructuredBindingDescriptor>False</CppReplaceTieWithStructuredBindingDescriptor></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="TrashUpdaterCleanup"><XMLReformatCode>True</XMLReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" /><RemoveCodeRedundanciesVB>True</RemoveCodeRedundanciesVB><Xaml.RedundantFreezeAttribute>True</Xaml.RedundantFreezeAttribute><Xaml.RemoveRedundantModifiersAttribute>True</Xaml.RemoveRedundantModifiersAttribute><Xaml.RemoveRedundantNameAttribute>True</Xaml.RemoveRedundantNameAttribute><Xaml.RemoveRedundantResource>True</Xaml.RemoveRedundantResource><Xaml.RemoveRedundantCollectionProperty>True</Xaml.RemoveRedundantCollectionProperty><Xaml.RemoveRedundantAttachedPropertySetter>True</Xaml.RemoveRedundantAttachedPropertySetter><Xaml.RemoveRedundantStyledValue>True</Xaml.RemoveRedundantStyledValue><Xaml.RemoveRedundantNamespaceAlias>True</Xaml.RemoveRedundantNamespaceAlias><Xaml.RemoveForbiddenResourceName>True</Xaml.RemoveForbiddenResourceName><Xaml.RemoveRedundantGridDefinitionsAttribute>True</Xaml.RemoveRedundantGridDefinitionsAttribute><Xaml.RemoveRedundantGridSpanAttribut>True</Xaml.RemoveRedundantGridSpanAttribut><Xaml.RemoveRedundantUpdateSourceTriggerAttribute>True</Xaml.RemoveRedundantUpdateSourceTriggerAttribute><Xaml.RemoveRedundantBindingModeAttribute>True</Xaml.RemoveRedundantBindingModeAttribute><HtmlReformatCode>True</HtmlReformatCode><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><CppAddOverrideSpecifier>True</CppAddOverrideSpecifier><CppAddTypenameTemplateKeywords>True</CppAddTypenameTemplateKeywords><CppReplaceImportDirective>True</CppReplaceImportDirective><CppRemoveElseKeyword>True</CppRemoveElseKeyword><CppShortenQualifiedName>True</CppShortenQualifiedName><CppDeleteRedundantSpecifier>True</CppDeleteRedundantSpecifier><CppRemoveStatement>True</CppRemoveStatement><CppDeleteRedundantTypenameTemplateKeywords>True</CppDeleteRedundantTypenameTemplateKeywords><CppCStyleToStaticCastDescriptor>True</CppCStyleToStaticCastDescriptor><CppReplaceExpressionWithBooleanConst>True</CppReplaceExpressionWithBooleanConst><CppMakeIfConstexpr>True</CppMakeIfConstexpr><CppMakePostfixOperatorPrefix>True</CppMakePostfixOperatorPrefix><CppChangeSmartPointerToMakeFunction>True</CppChangeSmartPointerToMakeFunction><CppReplaceThrowWithRethrowFix>True</CppReplaceThrowWithRethrowFix><CppReplaceExpressionWithNullptr>True</CppReplaceExpressionWithNullptr><CppSortMemberInitializers>True</CppSortMemberInitializers><CppReformatCode>True</CppReformatCode><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><VBReformatCode>True</VBReformatCode><VBFormatDocComments>True</VBFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><IDEA_SETTINGS>&lt;profile version="1.0"&gt; &lt;option name="myName" value="TrashUpdaterCleanup" /&gt; -&lt;/profile&gt;</IDEA_SETTINGS><CSShortenReferences>True</CSShortenReferences><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> +&lt;/profile&gt;</IDEA_SETTINGS><CSShortenReferences>True</CSShortenReferences><CSUpdateFileHeader>True</CSUpdateFileHeader><RIDER_SETTINGS>&lt;profile&gt; + &lt;Language id="CSS"&gt; + &lt;Rearrange&gt;true&lt;/Rearrange&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="EditorConfig"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="HTML"&gt; + &lt;Rearrange&gt;true&lt;/Rearrange&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;OptimizeImports&gt;true&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="Ini"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JSON"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JavaScript"&gt; + &lt;Rearrange&gt;true&lt;/Rearrange&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;OptimizeImports&gt;true&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="Markdown"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Properties"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="RELAX-NG"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="SQL"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="XML"&gt; + &lt;Rearrange&gt;true&lt;/Rearrange&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;OptimizeImports&gt;true&lt;/OptimizeImports&gt; + &lt;/Language&gt; + &lt;Language id="yaml"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; +&lt;/profile&gt;</RIDER_SETTINGS></Profile> TrashUpdaterCleanup True True