diff --git a/src/Readme.txt b/src/Readme.txt index 0da1dc5e..56ad9a4b 100644 --- a/src/Readme.txt +++ b/src/Readme.txt @@ -67,10 +67,11 @@ For further details take a look at LICENSE.txt. CHANGELOG -5.3.12.0 +5.4.0.0 * Fix: #699 Rounding crap score to full number * Fix: #700 Fixed handling of .netconfig files (sourceDirectories, reportTypes, plugins, assemblyFilters, etc.) + * Fix: #704 Improved handling of file filters 5.3.11.0 diff --git a/src/ReportGenerator.Core.Test/Parser/Filtering/DefaultFilterTest.cs b/src/ReportGenerator.Core.Test/Parser/Filtering/DefaultFilterTest.cs index 71002e5d..5e63d9cd 100644 --- a/src/ReportGenerator.Core.Test/Parser/Filtering/DefaultFilterTest.cs +++ b/src/ReportGenerator.Core.Test/Parser/Filtering/DefaultFilterTest.cs @@ -56,10 +56,10 @@ public void OnlyIncludesWithWildcards_NotMatchingElement_ElementIsNotAccepted() { IFilter filter = new DefaultFilter(new[] { "+Test*" }); - Assert.False(filter.IsElementIncludedInReport("PrefixTest"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("prefixtest"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("PrefixTest123"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("prefixtest123"), "Element is expected to be included."); + Assert.False(filter.IsElementIncludedInReport("PrefixTest"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("prefixtest"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("PrefixTest123"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("prefixtest123"), "Element is expected to be excluded."); Assert.True(filter.HasCustomFilters); } @@ -100,10 +100,50 @@ public void IncludesAndExcludesWithWildcards_NotMatchingElement_ElementIsNotAcce { IFilter filter = new DefaultFilter(new[] { "+Test*", "-Tes*" }); - Assert.False(filter.IsElementIncludedInReport("Test"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("test"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("PrefixTest123"), "Element is expected to be included."); - Assert.False(filter.IsElementIncludedInReport("prefixtest123"), "Element is expected to be included."); + Assert.False(filter.IsElementIncludedInReport("Test"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("test"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("PrefixTest123"), "Element is expected to be excluded."); + Assert.False(filter.IsElementIncludedInReport("prefixtest123"), "Element is expected to be excluded."); + Assert.True(filter.HasCustomFilters); + } + + [Fact] + public void LinuxPath_NoOsIndependantPathSeparator() + { + IFilter filter = new DefaultFilter(new[] { "+abc/def" }); + + Assert.True(filter.IsElementIncludedInReport("abc/def"), "Element is expected to be included."); + Assert.False(filter.IsElementIncludedInReport("abc\\def"), "Element is expected to be excluded."); + Assert.True(filter.HasCustomFilters); + } + + [Fact] + public void LinuxPath_OsIndependantPathSeparator() + { + IFilter filter = new DefaultFilter(new[] { "+abc/def" }, true); + + Assert.True(filter.IsElementIncludedInReport("abc/def"), "Element is expected to be included."); + Assert.True(filter.IsElementIncludedInReport("abc\\def"), "Element is expected to be included."); + Assert.True(filter.HasCustomFilters); + } + + [Fact] + public void WindowsPath_NoOsIndependantPathSeparator() + { + IFilter filter = new DefaultFilter(new[] { "+abc\\def" }); + + Assert.False(filter.IsElementIncludedInReport("abc/def"), "Element is expected to be excluded."); + Assert.True(filter.IsElementIncludedInReport("abc\\def"), "Element is expected to be included."); + Assert.True(filter.HasCustomFilters); + } + + [Fact] + public void WindowsPath_OsIndependantPathSeparator() + { + IFilter filter = new DefaultFilter(new[] { "+abc/def" }, true); + + Assert.True(filter.IsElementIncludedInReport("abc/def"), "Element is expected to be included."); + Assert.True(filter.IsElementIncludedInReport("abc\\def"), "Element is expected to be included."); Assert.True(filter.HasCustomFilters); } } diff --git a/src/ReportGenerator.Core/Parser/CoverageReportParser.cs b/src/ReportGenerator.Core/Parser/CoverageReportParser.cs index 4f848055..a69f76e6 100644 --- a/src/ReportGenerator.Core/Parser/CoverageReportParser.cs +++ b/src/ReportGenerator.Core/Parser/CoverageReportParser.cs @@ -181,7 +181,7 @@ public CoverageReportParser(IReportContext reportContext) this.sourceDirectories = reportContext.ReportConfiguration.SourceDirectories ?? throw new ArgumentNullException(nameof(reportContext.ReportConfiguration.SourceDirectories)); this.assemblyFilter = new DefaultFilter(reportContext.ReportConfiguration.AssemblyFilters); this.classFilter = new DefaultFilter(reportContext.ReportConfiguration.ClassFilters); - this.fileFilter = new DefaultFilter(reportContext.ReportConfiguration.FileFilters); + this.fileFilter = new DefaultFilter(reportContext.ReportConfiguration.FileFilters, true); } /// diff --git a/src/ReportGenerator.Core/Parser/Filtering/DefaultFilter.cs b/src/ReportGenerator.Core/Parser/Filtering/DefaultFilter.cs index 045f0339..c6823d69 100644 --- a/src/ReportGenerator.Core/Parser/Filtering/DefaultFilter.cs +++ b/src/ReportGenerator.Core/Parser/Filtering/DefaultFilter.cs @@ -28,6 +28,16 @@ public class DefaultFilter : IFilter /// /// The filters. public DefaultFilter(IEnumerable filters) + : this(filters, false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The filters. + /// Indicates whether filter thould be treated as paths and the operating system format should be ignored. + public DefaultFilter(IEnumerable filters, bool osIndependantPathSeparator) { if (filters == null) { @@ -36,12 +46,12 @@ public DefaultFilter(IEnumerable filters) this.excludeFilters = filters .Where(f => f.StartsWith("-", StringComparison.OrdinalIgnoreCase)) - .Select(f => CreateFilterRegex(f)) + .Select(f => CreateFilterRegex(f, osIndependantPathSeparator)) .ToArray(); this.includeFilters = filters .Where(f => f.StartsWith("+", StringComparison.OrdinalIgnoreCase)) - .Select(f => CreateFilterRegex(f)) + .Select(f => CreateFilterRegex(f, osIndependantPathSeparator)) .ToArray(); this.HasCustomFilters = this.excludeFilters.Length > 0 || this.includeFilters.Length > 0; @@ -50,7 +60,7 @@ public DefaultFilter(IEnumerable filters) { this.includeFilters = new[] { - CreateFilterRegex("+*") + CreateFilterRegex("+*", false) }; } } @@ -87,14 +97,23 @@ public bool IsElementIncludedInReport(string name) /// Special characters are escaped. Wildcards '*' are converted to '.*'. /// /// The filter. + /// Indicates whether filter thould be treated as paths and the operating system format should be ignored. /// The regular expression. - private static Regex CreateFilterRegex(string filter) + private static Regex CreateFilterRegex(string filter, bool osIndependantPathSeparator) { filter = filter.Substring(1); filter = filter.Replace("*", "$$$*"); filter = Regex.Escape(filter); filter = filter.Replace(@"\$\$\$\*", ".*"); + if (osIndependantPathSeparator) + { + filter = filter + .Replace("/", "$$$") + .Replace("\\", "$$$") + .Replace("$$$", @"[/\\]"); + } + return new Regex($"^{filter}$", RegexOptions.Compiled | RegexOptions.IgnoreCase); } }