Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement != operator for filtering #4494

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,4 @@ internal enum FilterOperator
/// Combine the following expressions with a logical OR.
/// </summary>
Or,

/// <summary>
/// Filter the following expression by the given property.
/// </summary>
Equals,
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ internal enum OperatorKind
/// </summary>
FilterEquals,

/// <summary>
/// Filter not equals operator.
/// </summary>
FilterNotEquals,

/// <summary>
/// Operator used for combining multiple filters with a logical OR.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ internal TreeNodeFilter(string filter)
/// FILTER_EXPR =
/// '(' FILTER_EXPR ')'
/// | TOKEN '=' TOKEN
/// | TOKEN '!=' TOKEN
/// | FILTER_EXPR OP FILTER_EXPR
/// | TOKEN
/// OP = '&amp;' | '|'
Expand Down Expand Up @@ -210,6 +211,13 @@ private static List<FilterExpression> ParseFilter(string filter)
isPropAllowed = false;
break;

case "!=":
operatorStack.Push(OperatorKind.FilterNotEquals);

isOperatorAllowed = false;
isPropAllowed = false;
break;

default:
expressionStack.Push(new ValueExpression(token));

Expand Down Expand Up @@ -311,14 +319,14 @@ private static void ProcessStackOperator(OperatorKind op, Stack<FilterExpression
{
OperatorKind.And => FilterOperator.And,
OperatorKind.Or => FilterOperator.Or,
OperatorKind.FilterEquals => FilterOperator.Equals,
_ => throw ApplicationStateGuard.Unreachable(),
};

expr.Push(new OperatorExpression(filter, subexprs));
break;

case OperatorKind.FilterEquals:
case OperatorKind.FilterNotEquals:
FilterExpression valueExpr = expr.Pop();
FilterExpression propExpr = expr.Pop();

Expand All @@ -328,7 +336,13 @@ private static void ProcessStackOperator(OperatorKind op, Stack<FilterExpression
throw new InvalidOperationException();
}

expr.Push(new PropertyExpression(propValueExpr, valueValueExpr));
FilterExpression filterExpression = new PropertyExpression(propValueExpr, valueValueExpr);
if (op == OperatorKind.FilterNotEquals)
{
filterExpression = new OperatorExpression(FilterOperator.Not, [filterExpression]);
}

expr.Push(filterExpression);
break;

default:
Expand Down Expand Up @@ -407,6 +421,25 @@ private static IEnumerable<string> TokenizeFilter(string filter)

break;

case '!':
if (i + 1 < filter.Length && filter[i + 1] == '=')
{
if (lastStringTokenBuilder.Length > 0)
{
yield return lastStringTokenBuilder.ToString();
lastStringTokenBuilder.Clear();
}

yield return "!=";
i++;
}
else
{
goto default;
}

break;

default:
lastStringTokenBuilder.Append(Regex.Escape(filter[i].ToString()));
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ public void Parameters_PropertyCheck()
Assert.IsFalse(filter.MatchesFilter("/ProjectB.UnitTests", new PropertyBag()));
}

[TestMethod]
public void Parameters_NegatedPropertyCheck()
{
TreeNodeFilter filter = new("/*.UnitTests[Tag!=Fast]");
Assert.IsFalse(filter.MatchesFilter("/ProjectB.UnitTests", new PropertyBag(new KeyValuePairStringProperty("Tag", "Fast"))));
Assert.IsTrue(filter.MatchesFilter("/ProjectB.UnitTests", new PropertyBag(new KeyValuePairStringProperty("Tag", "Slow"))));
Assert.IsTrue(filter.MatchesFilter("/ProjectB.UnitTests", new PropertyBag()));
}

[TestMethod]
public void Parameters_DisallowAtStart()
=> Assert.ThrowsException<InvalidOperationException>(() => _ = new TreeNodeFilter("/[Tag=Fast]"));
Expand Down