diff --git a/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/OperatorExpression.cs b/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/OperatorExpression.cs index cf5409e595..0333f7e048 100644 --- a/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/OperatorExpression.cs +++ b/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/OperatorExpression.cs @@ -4,9 +4,9 @@ namespace Microsoft.Testing.Platform.Requests; // Allows to express an expression A & B or A | B -internal sealed class OperatorExpression(FilterOperator op, IReadOnlyCollection subExpressions) : FilterExpression +internal sealed class OperatorExpression(FilterOperator op, IReadOnlyList subExpressions) : FilterExpression { public FilterOperator Op { get; } = op; - public IReadOnlyCollection SubExpressions { get; } = subExpressions; + public IReadOnlyList SubExpressions { get; } = subExpressions; } diff --git a/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/TreeNodeFilter.cs b/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/TreeNodeFilter.cs index da7178a629..c10e2bb94c 100644 --- a/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/TreeNodeFilter.cs +++ b/src/Platform/Microsoft.Testing.Platform/Requests/TreeNodeFilter/TreeNodeFilter.cs @@ -542,10 +542,60 @@ private static bool MatchFilterPattern( int endFragmentIndex, PropertyBag properties) { +#if NET8_0_OR_GREATER + return MatchFilterPattern( + filterExpression, + testNodeFullPath.AsSpan(startFragmentIndex, endFragmentIndex - startFragmentIndex), + properties); +#else string str = testNodeFullPath[startFragmentIndex..endFragmentIndex]; return MatchFilterPattern(filterExpression, str, properties); +#endif } +#if NET8_0_OR_GREATER + private static bool MatchFilterPattern( + FilterExpression filterExpression, + ReadOnlySpan testNodeFragment, + PropertyBag properties) + { + switch (filterExpression) + { + case ValueExpression vExpr: + return vExpr.Regex.IsMatch(testNodeFragment); + case OperatorExpression { Op: FilterOperator.Or, SubExpressions: var subexprs }: + foreach (FilterExpression expr in subexprs) + { + if (MatchFilterPattern(expr, testNodeFragment, properties)) + { + return true; + } + } + + return false; + case OperatorExpression { Op: FilterOperator.And, SubExpressions: var subexprs }: + foreach (FilterExpression expr in subexprs) + { + if (!MatchFilterPattern(expr, testNodeFragment, properties)) + { + return false; + } + } + + return true; + case OperatorExpression { Op: FilterOperator.Not, SubExpressions: var subexprs }: + return !MatchFilterPattern(subexprs.Single(), testNodeFragment, properties); + case ValueAndPropertyExpression { Value: var valueExpr, Properties: var propExpr }: + return MatchFilterPattern(valueExpr, testNodeFragment, properties) + && MatchProperties(propExpr, properties); + case NopExpression: + return true; + default: + throw ApplicationStateGuard.Unreachable(); + } + } +#endif + private static bool MatchFilterPattern( FilterExpression filterExpression, string testNodeFragment,