Enable more analyser rules as errors

Also deduplicates a bit of code inside of SeasonPathParser and adds some more tests
This commit is contained in:
Bond_009 2024-08-01 17:17:10 +02:00
parent 623f9f6d8a
commit 0a0de6708e
5 changed files with 66 additions and 45 deletions

View File

@ -24,6 +24,8 @@ namespace Emby.Naming.TV
"stagione" "stagione"
}; };
private static readonly char[] _splitChars = ['.', '_', ' ', '-'];
/// <summary> /// <summary>
/// Attempts to parse season number from path. /// Attempts to parse season number from path.
/// </summary> /// </summary>
@ -83,14 +85,9 @@ namespace Emby.Naming.TV
} }
} }
if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase)) if (TryGetSeasonNumberFromPart(filename, out int seasonNumber))
{ {
var testFilename = filename.AsSpan().Slice(1); return (seasonNumber, true);
if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return (val, true);
}
} }
// Look for one of the season folder names // Look for one of the season folder names
@ -108,10 +105,10 @@ namespace Emby.Naming.TV
} }
} }
var parts = filename.Split(new[] { '.', '_', ' ', '-' }, StringSplitOptions.RemoveEmptyEntries); var parts = filename.Split(_splitChars, StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts) foreach (var part in parts)
{ {
if (TryGetSeasonNumberFromPart(part, out int seasonNumber)) if (TryGetSeasonNumberFromPart(part, out seasonNumber))
{ {
return (seasonNumber, true); return (seasonNumber, true);
} }

View File

@ -1304,7 +1304,7 @@ namespace MediaBrowser.Model.Dlna
// Check audio codec // Check audio codec
MediaStream? selectedAudioStream = null; MediaStream? selectedAudioStream = null;
if (candidateAudioStreams.Any()) if (candidateAudioStreams.Count != 0)
{ {
selectedAudioStream = candidateAudioStreams.FirstOrDefault(audioStream => directPlayProfile.SupportsAudioCodec(audioStream.Codec)); selectedAudioStream = candidateAudioStreams.FirstOrDefault(audioStream => directPlayProfile.SupportsAudioCodec(audioStream.Codec));
if (selectedAudioStream is null) if (selectedAudioStream is null)

View File

@ -105,6 +105,28 @@
<Rule Id="CA1851" Action="Error" /> <Rule Id="CA1851" Action="Error" />
<!-- error on CA1854: Prefer a 'TryGetValue' call over a Dictionary indexer access guarded by a 'ContainsKey' check to avoid double lookup --> <!-- error on CA1854: Prefer a 'TryGetValue' call over a Dictionary indexer access guarded by a 'ContainsKey' check to avoid double lookup -->
<Rule Id="CA1854" Action="Error" /> <Rule Id="CA1854" Action="Error" />
<!-- error on CA1860: Avoid using 'Enumerable.Any()' extension method -->
<Rule Id="CA1860" Action="Error" />
<!-- error on CA1862: Use the 'StringComparison' method overloads to perform case-insensitive string comparisons -->
<Rule Id="CA1862" Action="Error" />
<!-- error on CA1863: Use 'CompositeFormat' -->
<Rule Id="CA1863" Action="Error" />
<!-- error on CA1864: Prefer the 'IDictionary.TryAdd(TKey, TValue)' method -->
<Rule Id="CA1864" Action="Error" />
<!-- error on CA1865-CA1867: Use 'string.Method(char)' instead of 'string.Method(string)' for string with single char -->
<Rule Id="CA1865" Action="Error" />
<Rule Id="CA1866" Action="Error" />
<Rule Id="CA1867" Action="Error" />
<!-- error on CA1868: Unnecessary call to 'Contains' for sets -->
<Rule Id="CA1868" Action="Error" />
<!-- error on CA1869: Cache and reuse 'JsonSerializerOptions' instances -->
<Rule Id="CA1869" Action="Error" />
<!-- error on CA1870: Use a cached 'SearchValues' instance -->
<Rule Id="CA1870" Action="Error" />
<!-- error on CA1871: Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull' -->
<Rule Id="CA1871" Action="Error" />
<!-- error on CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' -->
<Rule Id="CA1872" Action="Error" />
<!-- error on CA2016: Forward the CancellationToken parameter to methods that take one <!-- error on CA2016: Forward the CancellationToken parameter to methods that take one
or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token --> or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token -->
<Rule Id="CA2016" Action="Error" /> <Rule Id="CA2016" Action="Error" />

View File

@ -1,35 +0,0 @@
using Emby.Naming.TV;
using Xunit;
namespace Jellyfin.Naming.Tests.TV
{
public class SeasonFolderTests
{
[Theory]
[InlineData("/Drive/Season 1", 1, true)]
[InlineData("/Drive/Season 2", 2, true)]
[InlineData("/Drive/Season 02", 2, true)]
[InlineData("/Drive/Seinfeld/S02", 2, true)]
[InlineData("/Drive/Seinfeld/2", 2, true)]
[InlineData("/Drive/Season 2009", 2009, true)]
[InlineData("/Drive/Season1", 1, true)]
[InlineData("The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH", 4, true)]
[InlineData("/Drive/Season 7 (2016)", 7, false)]
[InlineData("/Drive/Staffel 7 (2016)", 7, false)]
[InlineData("/Drive/Stagione 7 (2016)", 7, false)]
[InlineData("/Drive/Season (8)", null, false)]
[InlineData("/Drive/3.Staffel", 3, false)]
[InlineData("/Drive/s06e05", null, false)]
[InlineData("/Drive/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv", null, false)]
[InlineData("/Drive/extras", 0, true)]
[InlineData("/Drive/specials", 0, true)]
public void GetSeasonNumberFromPathTest(string path, int? seasonNumber, bool isSeasonDirectory)
{
var result = SeasonPathParser.Parse(path, true, true);
Assert.Equal(result.SeasonNumber is not null, result.Success);
Assert.Equal(result.SeasonNumber, seasonNumber);
Assert.Equal(isSeasonDirectory, result.IsSeasonFolder);
}
}
}

View File

@ -0,0 +1,37 @@
using Emby.Naming.TV;
using Xunit;
namespace Jellyfin.Naming.Tests.TV;
public class SeasonPathParserTests
{
[Theory]
[InlineData("/Drive/Season 1", 1, true)]
[InlineData("/Drive/s1", 1, true)]
[InlineData("/Drive/S1", 1, true)]
[InlineData("/Drive/Season 2", 2, true)]
[InlineData("/Drive/Season 02", 2, true)]
[InlineData("/Drive/Seinfeld/S02", 2, true)]
[InlineData("/Drive/Seinfeld/2", 2, true)]
[InlineData("/Drive/Seinfeld - S02", 2, true)]
[InlineData("/Drive/Season 2009", 2009, true)]
[InlineData("/Drive/Season1", 1, true)]
[InlineData("The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH", 4, true)]
[InlineData("/Drive/Season 7 (2016)", 7, false)]
[InlineData("/Drive/Staffel 7 (2016)", 7, false)]
[InlineData("/Drive/Stagione 7 (2016)", 7, false)]
[InlineData("/Drive/Season (8)", null, false)]
[InlineData("/Drive/3.Staffel", 3, false)]
[InlineData("/Drive/s06e05", null, false)]
[InlineData("/Drive/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv", null, false)]
[InlineData("/Drive/extras", 0, true)]
[InlineData("/Drive/specials", 0, true)]
public void GetSeasonNumberFromPathTest(string path, int? seasonNumber, bool isSeasonDirectory)
{
var result = SeasonPathParser.Parse(path, true, true);
Assert.Equal(result.SeasonNumber is not null, result.Success);
Assert.Equal(result.SeasonNumber, seasonNumber);
Assert.Equal(isSeasonDirectory, result.IsSeasonFolder);
}
}