refactor: fix roslyn analyzer warnings

- fix warnings across the code base
- exclude CA rules via .editorconfig as needed
- use newer version of `Microsoft.CodeAnalysis.NetAnalyzers`
recyclarr
Robert Dailey 3 years ago
parent 3d3c6f327d
commit bcbdc580ff

@ -83,7 +83,7 @@ dotnet_diagnostic.ca1027.severity = warning
dotnet_diagnostic.ca1028.severity = warning
dotnet_diagnostic.ca1030.severity = warning
dotnet_diagnostic.ca1031.severity = warning
dotnet_diagnostic.ca1032.severity = warning
dotnet_diagnostic.ca1032.severity = none
dotnet_diagnostic.ca1033.severity = warning
dotnet_diagnostic.ca1034.severity = warning
dotnet_diagnostic.ca1036.severity = none
@ -98,12 +98,12 @@ dotnet_diagnostic.ca1050.severity = suggestion
dotnet_diagnostic.ca1051.severity = none
dotnet_diagnostic.ca1052.severity = warning
dotnet_diagnostic.ca1054.severity = warning
dotnet_diagnostic.ca1055.severity = warning
dotnet_diagnostic.ca1056.severity = warning
dotnet_diagnostic.ca1055.severity = none
dotnet_diagnostic.ca1056.severity = none
dotnet_diagnostic.ca1058.severity = warning
dotnet_diagnostic.ca1060.severity = warning
dotnet_diagnostic.ca1061.severity = suggestion
dotnet_diagnostic.ca1062.severity = warning
dotnet_diagnostic.ca1062.severity = none
dotnet_diagnostic.ca1063.severity = warning
dotnet_diagnostic.ca1064.severity = warning
dotnet_diagnostic.ca1065.severity = warning
@ -113,7 +113,7 @@ dotnet_diagnostic.ca1068.severity = suggestion
dotnet_diagnostic.ca1069.severity = suggestion
dotnet_diagnostic.ca1070.severity = suggestion
dotnet_diagnostic.ca1200.severity = none
dotnet_diagnostic.ca1303.severity = warning
dotnet_diagnostic.ca1303.severity = none
dotnet_diagnostic.ca1304.severity = none
dotnet_diagnostic.ca1305.severity = none
dotnet_diagnostic.ca1307.severity = warning
@ -175,7 +175,7 @@ dotnet_diagnostic.ca1837.severity = suggestion
dotnet_diagnostic.ca1838.severity = none
dotnet_diagnostic.ca2000.severity = warning
dotnet_diagnostic.ca2002.severity = warning
dotnet_diagnostic.ca2007.severity = warning
dotnet_diagnostic.ca2007.severity = none
dotnet_diagnostic.ca2008.severity = warning
dotnet_diagnostic.ca2009.severity = suggestion
dotnet_diagnostic.ca2011.severity = suggestion
@ -202,7 +202,7 @@ dotnet_diagnostic.ca2217.severity = warning
dotnet_diagnostic.ca2219.severity = suggestion
dotnet_diagnostic.ca2225.severity = warning
dotnet_diagnostic.ca2226.severity = warning
dotnet_diagnostic.ca2227.severity = warning
dotnet_diagnostic.ca2227.severity = none
dotnet_diagnostic.ca2229.severity = none
dotnet_diagnostic.ca2231.severity = suggestion
dotnet_diagnostic.ca2234.severity = warning
@ -774,7 +774,7 @@ dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
file_header_template =
file_header_template =
# ReSharper properties
resharper_accessor_owner_body = expression_body
@ -1063,7 +1063,7 @@ resharper_remove_blank_lines_near_braces_in_declarations = true
resharper_remove_this_qualifier = true
resharper_requires_expression_braces = next_line
resharper_resx_attribute_indent = single_indent
resharper_resx_linebreak_before_elements =
resharper_resx_linebreak_before_elements =
resharper_resx_max_blank_lines_between_tags = 0
resharper_resx_max_line_length = 2147483647
resharper_resx_pi_attribute_style = do_not_touch
@ -1286,7 +1286,7 @@ resharper_xmldoc_wrap_lines = true
resharper_xmldoc_wrap_tags_and_pi = true
resharper_xmldoc_wrap_text = true
resharper_xml_attribute_indent = align_by_first_attribute
resharper_xml_linebreak_before_elements =
resharper_xml_linebreak_before_elements =
resharper_xml_max_blank_lines_between_tags = 2
resharper_xml_max_line_length = 120
resharper_xml_pi_attribute_style = do_not_touch

@ -10,6 +10,7 @@
https://youtrack.jetbrains.com/issue/RIDER-55142
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
-->
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<GitVersionBaseDirectory>$(MSBuildThisFileDirectory)</GitVersionBaseDirectory>
</PropertyGroup>
@ -21,6 +22,7 @@
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Condition=" '$(DisableNbgv)' != 'true' " />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" />
</ItemGroup>
<ItemGroup Condition="$(ProjectName.EndsWith('.Tests'))">

@ -18,11 +18,14 @@
<PackageReference Update="CliFx" Version="2.*" />
<PackageReference Update="Flurl.Http" Version="3.*" />
<PackageReference Update="Flurl" Version="3.*" />
<PackageReference Update="Nerdbank.GitVersioning" Version="3.*">
<PrivateAssets>true</PrivateAssets>
</PackageReference>
<PackageReference Update="JetBrains.Annotations" Version="*">
<PrivateAssets>true</PrivateAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Update="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.*">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Update="Nerdbank.GitVersioning" Version="3.*">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Update="Serilog.Sinks.Console" Version="3.*" />
<PackageReference Update="Serilog" Version="2.*" />

@ -15,11 +15,11 @@ namespace Trash.Tests.Command
{
}
public class StubCommand : IServiceCommand
private class StubCommand : IServiceCommand
{
public bool Preview => false;
public bool Debug => false;
public List<string>? Config => null;
public ICollection<string>? Config => null;
public string CacheStoragePath => "";
}

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
@ -24,11 +23,6 @@ namespace Trash.Tests.Config
private TextReader GetResourceData(string file)
{
var testData = new ResourceDataReader(typeof(ConfigurationLoaderTest), "Data");
if (testData == null)
{
throw new InvalidOperationException("TestData object has not been created yet");
}
return new StringReader(testData.ReadData(file));
}

@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Linq;
using Common;
using FluentAssertions;
using NSubstitute;
using NUnit.Framework;
using Serilog;
using Serilog.Sinks.TestCorrelator;
@ -31,8 +30,10 @@ namespace Trash.Tests.Sonarr.ReleaseProfile
.MinimumLevel.Debug()
.CreateLogger();
Config = Substitute.For<SonarrConfiguration>();
Config.ReleaseProfiles.Add(new ReleaseProfileConfig());
Config = new SonarrConfiguration
{
ReleaseProfiles = new[] {new ReleaseProfileConfig()}
};
GuideParser = new ReleaseProfileGuideParser(logger);
}

@ -16,7 +16,6 @@ namespace Trash.Tests.Sonarr
public ISonarrCommand Args { get; } = Substitute.For<ISonarrCommand>();
public IReleaseProfileGuideParser Parser { get; } = Substitute.For<IReleaseProfileGuideParser>();
public ISonarrApi Api { get; } = Substitute.For<ISonarrApi>();
public SonarrConfiguration Config { get; } = Substitute.For<SonarrConfiguration>();
public ILogger Logger { get; } = Substitute.For<ILogger>();
}
@ -26,7 +25,7 @@ namespace Trash.Tests.Sonarr
var context = new Context();
var logic = new ReleaseProfileUpdater(context.Logger, context.Parser, context.Api);
logic.Process(context.Args, context.Config);
logic.Process(context.Args, new SonarrConfiguration());
context.Parser.DidNotReceive().GetMarkdownData(Arg.Any<ReleaseProfileType>());
}
@ -37,12 +36,15 @@ namespace Trash.Tests.Sonarr
var context = new Context();
context.Parser.GetMarkdownData(ReleaseProfileType.Anime).Returns("theMarkdown");
context.Config.ReleaseProfiles.Add(new ReleaseProfileConfig {Type = ReleaseProfileType.Anime});
var config = new SonarrConfiguration
{
ReleaseProfiles = new[] {new ReleaseProfileConfig {Type = ReleaseProfileType.Anime}}
};
var logic = new ReleaseProfileUpdater(context.Logger, context.Parser, context.Api);
logic.Process(context.Args, context.Config);
logic.Process(context.Args, config);
context.Parser.Received().ParseMarkdown(context.Config.ReleaseProfiles[0], "theMarkdown");
context.Parser.Received().ParseMarkdown(config.ReleaseProfiles[0], "theMarkdown");
}
}
}

@ -2,7 +2,8 @@
namespace Trash.Cache
{
public class CacheObjectNameAttribute : Attribute
[AttributeUsage(AttributeTargets.Class)]
public sealed class CacheObjectNameAttribute : Attribute
{
public CacheObjectNameAttribute(string name)
{

@ -6,7 +6,7 @@ namespace Trash.Command
{
bool Preview { get; }
bool Debug { get; }
List<string>? Config { get; }
ICollection<string>? Config { get; }
string CacheStoragePath { get; }
}
}

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using CliFx;
@ -67,7 +67,8 @@ namespace Trash.Command
[CommandOption("config", 'c', Description =
"One or more YAML config files to use. All configs will be used and settings are additive. " +
"If not specified, the script will look for `trash.yml` in the same directory as the executable.")]
public List<string> Config { get; [UsedImplicitly] set; } = new() {AppPaths.DefaultConfigPath};
public ICollection<string> Config { get; [UsedImplicitly] set; } =
new List<string> {AppPaths.DefaultConfigPath};
public abstract string CacheStoragePath { get; }

@ -1,16 +1,16 @@
using System;
using System;
namespace Trash.Config
{
public class ConfigurationException : Exception
{
public ConfigurationException(string propertyName, Type type)
public ConfigurationException(string propertyName, Type deserializableType)
{
PropertyName = propertyName;
Type = type;
DeserializableType = deserializableType;
}
public string PropertyName { get; }
public Type Type { get; }
public Type DeserializableType { get; }
}
}

@ -1,9 +1,14 @@
using System.Text.RegularExpressions;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
namespace Trash.Extensions
{
public static class RegexExtensions
{
[SuppressMessage("Design", "CA1021:Avoid out parameters",
Justification =
"The out param has a very specific design purpose. It's to allow regex match expressions " +
"to be executed inside an if condition while also providing match output variable.")]
public static bool Match(this Regex re, string strToCheck, out Match match)
{
match = re.Match(strToCheck);

@ -1,4 +1,4 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
using Autofac;
using CliFx;
using Trash.Command;

@ -7,6 +7,6 @@ namespace Trash.Radarr.Api
public interface IRadarrApi
{
Task<List<RadarrQualityDefinitionItem>> GetQualityDefinition();
Task<List<RadarrQualityDefinitionItem>> UpdateQualityDefinition(List<RadarrQualityDefinitionItem> newQuality);
Task<IList<RadarrQualityDefinitionItem>> UpdateQualityDefinition(IList<RadarrQualityDefinitionItem> newQuality);
}
}

@ -24,8 +24,8 @@ namespace Trash.Radarr.Api
.GetJsonAsync<List<RadarrQualityDefinitionItem>>();
}
public async Task<List<RadarrQualityDefinitionItem>> UpdateQualityDefinition(
List<RadarrQualityDefinitionItem> newQuality)
public async Task<IList<RadarrQualityDefinitionItem>> UpdateQualityDefinition(
IList<RadarrQualityDefinitionItem> newQuality)
{
return await BaseUrl()
.AppendPathSegment("qualityDefinition/update")

@ -8,12 +8,12 @@ namespace Trash.Sonarr.Api
public interface ISonarrApi
{
Task<Version> GetVersion();
Task<List<SonarrTag>> GetTags();
Task<IList<SonarrTag>> GetTags();
Task<SonarrTag> CreateTag(string tag);
Task<List<SonarrReleaseProfile>> GetReleaseProfiles();
Task<IList<SonarrReleaseProfile>> GetReleaseProfiles();
Task UpdateReleaseProfile(SonarrReleaseProfile profileToUpdate);
Task<SonarrReleaseProfile> CreateReleaseProfile(SonarrReleaseProfile newProfile);
Task<List<SonarrQualityDefinitionItem>> GetQualityDefinition();
Task<List<SonarrQualityDefinitionItem>> UpdateQualityDefinition(List<SonarrQualityDefinitionItem> newQuality);
Task<IReadOnlyCollection<SonarrQualityDefinitionItem>> GetQualityDefinition();
Task<IList<SonarrQualityDefinitionItem>> UpdateQualityDefinition(IReadOnlyCollection<SonarrQualityDefinitionItem> newQuality);
}
}

@ -28,9 +28,9 @@ namespace Trash.Sonarr.Api.Objects
public string Name { get; set; } = "";
public string Required { get; set; } = "";
public string Ignored { get; set; } = "";
public List<SonarrPreferredTerm> Preferred { get; set; } = new();
public IReadOnlyCollection<SonarrPreferredTerm> Preferred { get; set; } = new List<SonarrPreferredTerm>();
public bool IncludePreferredWhenRenaming { get; set; }
public int IndexerId { get; set; }
public List<int> Tags { get; set; } = new();
public IReadOnlyCollection<int> Tags { get; set; } = new List<int>();
}
}

@ -25,7 +25,7 @@ namespace Trash.Sonarr.Api
return new Version(data.version);
}
public async Task<List<SonarrTag>> GetTags()
public async Task<IList<SonarrTag>> GetTags()
{
return await BaseUrl()
.AppendPathSegment("tag")
@ -40,7 +40,7 @@ namespace Trash.Sonarr.Api
.ReceiveJson<SonarrTag>();
}
public async Task<List<SonarrReleaseProfile>> GetReleaseProfiles()
public async Task<IList<SonarrReleaseProfile>> GetReleaseProfiles()
{
return await BaseUrl()
.AppendPathSegment("releaseprofile")
@ -62,15 +62,15 @@ namespace Trash.Sonarr.Api
.ReceiveJson<SonarrReleaseProfile>();
}
public async Task<List<SonarrQualityDefinitionItem>> GetQualityDefinition()
public async Task<IReadOnlyCollection<SonarrQualityDefinitionItem>> GetQualityDefinition()
{
return await BaseUrl()
.AppendPathSegment("qualitydefinition")
.GetJsonAsync<List<SonarrQualityDefinitionItem>>();
}
public async Task<List<SonarrQualityDefinitionItem>> UpdateQualityDefinition(
List<SonarrQualityDefinitionItem> newQuality)
public async Task<IList<SonarrQualityDefinitionItem>> UpdateQualityDefinition(
IReadOnlyCollection<SonarrQualityDefinitionItem> newQuality)
{
return await BaseUrl()
.AppendPathSegment("qualityDefinition/update")

@ -14,15 +14,15 @@ namespace Trash.Sonarr.ReleaseProfile
_config = config;
}
public List<string> Required => _config.Filter.IncludeOptional
public IEnumerable<string> Required => _config.Filter.IncludeOptional
? _profileData.Required.Concat(_profileData.Optional.Required).ToList()
: _profileData.Required;
public List<string> Ignored => _config.Filter.IncludeOptional
public IEnumerable<string> Ignored => _config.Filter.IncludeOptional
? _profileData.Ignored.Concat(_profileData.Optional.Ignored).ToList()
: _profileData.Ignored;
public Dictionary<int, List<string>> Preferred => _config.Filter.IncludeOptional
public IDictionary<int, List<string>> Preferred => _config.Filter.IncludeOptional
? _profileData.Preferred
.Union(_profileData.Optional.Preferred)
.GroupBy(kvp => kvp.Key)

@ -38,26 +38,23 @@ namespace Trash.Sonarr.ReleaseProfile
// If category is preferred, we also require a score
(CurrentCategory.Value != TermCategory.Preferred || Score != null);
public List<string> IgnoredTerms
=> TermsAreOptional.Value ? Profile.Optional.Ignored : Profile.Ignored;
public ICollection<string> IgnoredTerms
=> TermsAreOptional.Value ? GetProfile().Optional.Ignored : GetProfile().Ignored;
public List<string> RequiredTerms
=> TermsAreOptional.Value ? Profile.Optional.Required : Profile.Required;
public ICollection<string> RequiredTerms
=> TermsAreOptional.Value ? GetProfile().Optional.Required : GetProfile().Required;
public Dictionary<int, List<string>> PreferredTerms
=> TermsAreOptional.Value ? Profile.Optional.Preferred : Profile.Preferred;
public IDictionary<int, List<string>> PreferredTerms
=> TermsAreOptional.Value ? GetProfile().Optional.Preferred : GetProfile().Preferred;
public ProfileData Profile
public ProfileData GetProfile()
{
get
if (ProfileName == null)
{
if (ProfileName == null)
{
throw new NullReferenceException();
}
return Results.GetOrCreate(ProfileName);
throw new NullReferenceException();
}
return Results.GetOrCreate(ProfileName);
}
public void ResetParserState()

@ -4,16 +4,16 @@ namespace Trash.Sonarr.ReleaseProfile
{
public class ProfileDataOptional
{
public List<string> Required { get; init; } = new();
public List<string> Ignored { get; init; } = new();
public Dictionary<int, List<string>> Preferred { get; init; } = new();
public ICollection<string> Required { get; init; } = new List<string>();
public ICollection<string> Ignored { get; init; } = new List<string>();
public IDictionary<int, List<string>> Preferred { get; init; } = new Dictionary<int, List<string>>();
}
public class ProfileData
{
public List<string> Required { get; init; } = new();
public List<string> Ignored { get; init; } = new();
public Dictionary<int, List<string>> Preferred { get; init; } = new();
public ICollection<string> Required { get; init; } = new List<string>();
public ICollection<string> Ignored { get; init; } = new List<string>();
public IDictionary<int, List<string>> Preferred { get; init; } = new Dictionary<int, List<string>>();
// We use 'null' here to represent no explicit mention of the "include preferred" string
// found in the markdown. We use this to control whether or not the corresponding profile

@ -206,9 +206,9 @@ namespace Trash.Sonarr.ReleaseProfile
// run the IsSkippableLine() check.
if (line.ContainsIgnoreCase("include preferred"))
{
state.Profile.IncludePreferredWhenRenaming = !line.ContainsIgnoreCase("not");
state.GetProfile().IncludePreferredWhenRenaming = !line.ContainsIgnoreCase("not");
Log.Debug(" - 'Include Preferred' found [Value: {IncludePreferredWhenRenaming}] [Line: {Line}]",
state.Profile.IncludePreferredWhenRenaming, line);
state.GetProfile().IncludePreferredWhenRenaming, line);
return;
}

@ -44,7 +44,7 @@ namespace Trash.Sonarr.ReleaseProfile
Console.WriteLine("");
}
static void PrintTerms(string title, IReadOnlyCollection<string> terms)
static void PrintTerms(string title, ICollection<string> terms)
{
if (terms.Count == 0)
{

@ -10,7 +10,7 @@ namespace Trash.Sonarr
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]
public class SonarrConfiguration : BaseConfiguration
{
public List<ReleaseProfileConfig> ReleaseProfiles { get; set; } = new();
public IList<ReleaseProfileConfig> ReleaseProfiles { get; set; } = new List<ReleaseProfileConfig>();
public SonarrQualityDefinitionType? QualityDefinition { get; init; }
public override string BuildUrl()
@ -27,7 +27,7 @@ namespace Trash.Sonarr
public ReleaseProfileType Type { get; init; }
public bool StrictNegativeScores { get; init; }
public SonarrProfileFilterConfig Filter { get; init; } = new();
public List<string> Tags { get; init; } = new();
public ICollection<string> Tags { get; init; } = new List<string>();
}
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]

@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{305C2AC5
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{18CF1FCA-7983-4423-8B7E-4A830108C624}"

Loading…
Cancel
Save