Skip to content

Commit c7dda76

Browse files
committed
CI
1 parent a16b094 commit c7dda76

17 files changed

+203
-85
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ calling a function will be undefined if:
147147
| :--- | :--- |
148148
| `Coalesce(p0, p1, ..pN)` | Returns the first defined, non-null argument. |
149149
| `Contains(s, t)` | Tests whether the string `s` contains the substring `t`. |
150+
| `ElementAt(x, i)` | Retrieves a property of `x` by name `i`, or array element of `x` by numeric index `i`. |
150151
| `EndsWith(s, t)` | Tests whether the string `s` ends with substring `t`. |
151152
| `IndexOf(s, t)` | Returns the first index of substring `t` in string `s`, or -1 if the substring does not appear. |
152153
| `IndexOfMatch(s, p)` | Returns the index of the first match of regular expression `p` in string `s`, or -1 if the regular expression does not match. |

src/Serilog.Expressions/Expressions/Ast/CallExpression.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,24 @@ namespace Serilog.Expressions.Ast
55
{
66
class CallExpression : Expression
77
{
8-
public CallExpression(string operatorName, params Expression[] operands)
8+
public CallExpression(bool ignoreCase, string operatorName, params Expression[] operands)
99
{
10+
IgnoreCase = ignoreCase;
1011
OperatorName = operatorName ?? throw new ArgumentNullException(nameof(operatorName));
1112
Operands = operands ?? throw new ArgumentNullException(nameof(operands));
1213
}
1314

15+
public bool IgnoreCase { get; }
16+
1417
public string OperatorName { get; }
1518

1619
public Expression[] Operands { get; }
1720

1821
public override string ToString()
1922
{
20-
return OperatorName + "(" + string.Join(", ", Operands.Select(o => o.ToString())) + ")";
23+
return OperatorName
24+
+ "(" + string.Join(", ", Operands.Select(o => o.ToString())) + ")"
25+
+ (IgnoreCase ? " ci" : "");
2126
}
2227
}
2328
}

src/Serilog.Expressions/Expressions/Compilation/Linq/Intrinsics.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.Linq;
45
using System.Text.RegularExpressions;
@@ -65,13 +66,13 @@ public static bool CoerceToScalarBoolean(LogEventPropertyValue value)
6566
return value;
6667
}
6768

68-
public static LogEventPropertyValue? TryGetStructurePropertyValue(LogEventPropertyValue maybeStructure, string name)
69+
public static LogEventPropertyValue? TryGetStructurePropertyValue(StringComparison sc, LogEventPropertyValue maybeStructure, string name)
6970
{
7071
if (maybeStructure is StructureValue sv)
7172
{
7273
foreach (var prop in sv.Properties)
7374
{
74-
if (prop.Name == name)
75+
if (prop.Name.Equals(name, sc))
7576
{
7677
return prop.Value;
7778
}

src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ protected override ExpressionBody Transform(CallExpression lx)
5656
{
5757
if (!OperatorMethods.TryGetValue(lx.OperatorName, out var m))
5858
throw new ArgumentException($"The function name `{lx.OperatorName}` was not recognised.");
59-
60-
if (m.GetParameters().Length != lx.Operands.Length)
61-
throw new ArgumentException($"The function `{lx.OperatorName}` requires {m.GetParameters().Length} arguments.");
6259

63-
var operands = lx.Operands.Select(Transform).ToArray();
60+
var parameterCount = m.GetParameters().Count(pi => pi.ParameterType == typeof(LogEventPropertyValue));
61+
if (parameterCount != lx.Operands.Length)
62+
throw new ArgumentException($"The function `{lx.OperatorName}` requires {parameterCount} arguments.");
63+
64+
var operands = lx.Operands.Select(Transform).ToList();
6465

6566
// `and` and `or` short-circuit to save execution time; unlike the earlier Serilog.Filters.Expressions, nothing else does.
6667
if (Operators.SameOperator(lx.OperatorName, Operators.RuntimeOpAnd))
@@ -69,6 +70,9 @@ protected override ExpressionBody Transform(CallExpression lx)
6970
if (Operators.SameOperator(lx.OperatorName, Operators.RuntimeOpOr))
7071
return CompileLogical(LX.OrElse, operands[0], operands[1]);
7172

73+
if (m.GetParameters().Any(pi => pi.ParameterType == typeof(StringComparison)))
74+
operands.Insert(0, LX.Constant(lx.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
75+
7276
return LX.Call(m, operands);
7377
}
7478

@@ -86,7 +90,7 @@ static ExpressionBody CompileLogical(Func<ExpressionBody, ExpressionBody, Expres
8690
protected override ExpressionBody Transform(AccessorExpression spx)
8791
{
8892
var recv = Transform(spx.Receiver);
89-
return LX.Call(TryGetStructurePropertyValueMethod, recv, LX.Constant(spx.MemberName, typeof(string)));
93+
return LX.Call(TryGetStructurePropertyValueMethod, LX.Constant(StringComparison.OrdinalIgnoreCase), recv, LX.Constant(spx.MemberName, typeof(string)));
9094
}
9195

9296
protected override ExpressionBody Transform(ConstantExpression cx)
@@ -189,7 +193,7 @@ protected override ExpressionBody Transform(ObjectExpression ox)
189193

190194
protected override ExpressionBody Transform(IndexerExpression ix)
191195
{
192-
return Transform(new CallExpression(Operators.RuntimeOpElementAt, ix.Receiver, ix.Index));
196+
return Transform(new CallExpression(false, Operators.OpElementAt, ix.Receiver, ix.Index));
193197
}
194198

195199
protected override ExpressionBody Transform(IndexOfMatchExpression mx)

src/Serilog.Expressions/Expressions/Compilation/Text/LikeSyntaxTransformer.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,30 @@ protected override Expression Transform(CallExpression lx)
2222
return base.Transform(lx);
2323

2424
if (Operators.SameOperator(lx.OperatorName, Operators.IntermediateOpLike))
25-
return TryCompileLikeExpression(lx.Operands[0], lx.Operands[1]);
25+
return TryCompileLikeExpression(lx.IgnoreCase, lx.Operands[0], lx.Operands[1]);
2626

2727
if (Operators.SameOperator(lx.OperatorName, Operators.IntermediateOpNotLike))
2828
return new CallExpression(
29+
false,
2930
Operators.RuntimeOpStrictNot,
30-
TryCompileLikeExpression(lx.Operands[0], lx.Operands[1]));
31+
TryCompileLikeExpression(lx.IgnoreCase, lx.Operands[0], lx.Operands[1]));
3132

3233
return base.Transform(lx);
3334
}
3435

35-
Expression TryCompileLikeExpression(Expression corpus, Expression like)
36+
Expression TryCompileLikeExpression(bool ignoreCase, Expression corpus, Expression like)
3637
{
3738
if (like is ConstantExpression cx &&
3839
cx.Constant is ScalarValue scalar &&
3940
scalar.Value is string s)
4041
{
4142
var regex = LikeToRegex(s);
42-
var compiled = new Regex(regex, RegexOptions.Compiled | RegexOptions.ExplicitCapture, TimeSpan.FromMilliseconds(100));
43+
var opts = RegexOptions.Compiled | RegexOptions.ExplicitCapture;
44+
if (ignoreCase)
45+
opts |= RegexOptions.IgnoreCase;
46+
var compiled = new Regex(regex, opts, TimeSpan.FromMilliseconds(100));
4347
var indexof = new IndexOfMatchExpression(Transform(corpus), compiled);
44-
return new CallExpression(Operators.RuntimeOpNotEqual, indexof, new ConstantExpression(new ScalarValue(-1)));
48+
return new CallExpression(ignoreCase, Operators.RuntimeOpNotEqual, indexof, new ConstantExpression(new ScalarValue(-1)));
4549
}
4650

4751
SelfLog.WriteLine($"Serilog.Expressions: `like` requires a constant string argument; found ${like}.");

src/Serilog.Expressions/Expressions/Compilation/Text/TextMatchingTransformer.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,28 @@ protected override Expression Transform(CallExpression lx)
2222
return base.Transform(lx);
2323

2424
if (Operators.SameOperator(lx.OperatorName, Operators.OpIndexOfMatch))
25-
return TryCompileIndexOfMatch(lx.Operands[0], lx.Operands[1]);
25+
return TryCompileIndexOfMatch(lx.IgnoreCase, lx.Operands[0], lx.Operands[1]);
2626

2727
if (Operators.SameOperator(lx.OperatorName, Operators.OpIsMatch))
2828
return new CallExpression(
29+
false,
2930
Operators.RuntimeOpNotEqual,
30-
TryCompileIndexOfMatch(lx.Operands[0], lx.Operands[1]),
31+
TryCompileIndexOfMatch(lx.IgnoreCase, lx.Operands[0], lx.Operands[1]),
3132
new ConstantExpression(new ScalarValue(-1)));
3233

3334
return base.Transform(lx);
3435
}
3536

36-
Expression TryCompileIndexOfMatch(Expression corpus, Expression regex)
37+
Expression TryCompileIndexOfMatch(bool ignoreCase, Expression corpus, Expression regex)
3738
{
3839
if (regex is ConstantExpression cx &&
3940
cx.Constant is ScalarValue scalar &&
4041
scalar.Value is string s)
4142
{
42-
var compiled = new Regex(s, RegexOptions.Compiled | RegexOptions.ExplicitCapture, TimeSpan.FromMilliseconds(100));
43+
var opts = RegexOptions.Compiled | RegexOptions.ExplicitCapture;
44+
if (ignoreCase)
45+
opts |= RegexOptions.IgnoreCase;
46+
var compiled = new Regex(s, opts, TimeSpan.FromMilliseconds(100));
4347
return new IndexOfMatchExpression(Transform(corpus), compiled);
4448
}
4549

src/Serilog.Expressions/Expressions/Compilation/Transformations/IdentityTransformer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ protected override Expression Transform(CallExpression lx)
2525
if (!any)
2626
return lx;
2727

28-
return new CallExpression(lx.OperatorName, operands.ToArray());
28+
return new CallExpression(lx.IgnoreCase, lx.OperatorName, operands.ToArray());
2929
}
3030

3131
protected override Expression Transform(ConstantExpression cx)

src/Serilog.Expressions/Expressions/Compilation/Variadics/VariadicCallRewriter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ protected override Expression Transform(CallExpression lx)
2121
.Select(Transform)
2222
.Concat(new[] {new AmbientPropertyExpression(BuiltInProperty.Undefined, true)})
2323
.ToArray();
24-
return new CallExpression(lx.OperatorName, operands);
24+
return new CallExpression(lx.IgnoreCase, lx.OperatorName, operands);
2525
}
2626

2727
if (Operators.SameOperator(lx.OperatorName, Operators.OpCoalesce))
@@ -33,8 +33,8 @@ protected override Expression Transform(CallExpression lx)
3333
if (lx.Operands.Length > 2)
3434
{
3535
var first = Transform(lx.Operands.First());
36-
return new CallExpression(lx.OperatorName, first,
37-
Transform(new CallExpression(lx.OperatorName, lx.Operands.Skip(1).ToArray())));
36+
return new CallExpression(false, lx.OperatorName, first,
37+
Transform(new CallExpression(false, lx.OperatorName, lx.Operands.Skip(1).ToArray())));
3838
}
3939
}
4040

src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardComprehensionTransformer.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,16 @@ public static Expression Expand(Expression root)
1515

1616
protected override Expression Transform(CallExpression lx)
1717
{
18-
var target = lx;
19-
20-
if (!Operators.WildcardComparators.Contains(target.OperatorName) || target.Operands.Length != 2)
18+
if (!Operators.WildcardComparators.Contains(lx.OperatorName) || lx.Operands.Length != 2)
2119
return base.Transform(lx);
2220

23-
var lhsIs = WildcardSearch.FindElementAtWildcard(target.Operands[0]);
24-
var rhsIs = WildcardSearch.FindElementAtWildcard(target.Operands[1]);
21+
var lhsIs = WildcardSearch.FindElementAtWildcard(lx.Operands[0]);
22+
var rhsIs = WildcardSearch.FindElementAtWildcard(lx.Operands[1]);
2523
if (lhsIs != null && rhsIs != null || lhsIs == null && rhsIs == null)
2624
return base.Transform(lx); // N/A, or invalid
2725

28-
var wildcardPath = lhsIs != null ? target.Operands[0] : target.Operands[1];
29-
var comparand = lhsIs != null ? target.Operands[1] : target.Operands[0];
26+
var wildcardPath = lhsIs != null ? lx.Operands[0] : lx.Operands[1];
27+
var comparand = lhsIs != null ? lx.Operands[1] : lx.Operands[0];
3028
var indexer = lhsIs ?? rhsIs!;
3129

3230
var px = new ParameterExpression("p" + _nextParameter++);
@@ -36,12 +34,12 @@ protected override Expression Transform(CallExpression lx)
3634
var wc = ((IndexerWildcardExpression)indexer.Index).Wildcard;
3735

3836
var comparisonArgs = lhsIs != null ? new[] { nestedComparand, comparand } : new[] { comparand, nestedComparand };
39-
var body = new CallExpression(target.OperatorName, comparisonArgs);
37+
var body = new CallExpression(lx.IgnoreCase, lx.OperatorName, comparisonArgs);
4038

4139
var lambda = new LambdaExpression(new[] { px }, body);
4240

4341
var op = Operators.ToRuntimeWildcardOperator(wc);
44-
var call = new CallExpression(op, coll, lambda);
42+
var call = new CallExpression(false, op, coll, lambda);
4543
return Transform(call);
4644
}
4745
}

src/Serilog.Expressions/Expressions/Operators.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ static class Operators
1616

1717
public const string OpCoalesce = "Coalesce";
1818
public const string OpContains = "Contains";
19+
public const string OpElementAt = "ElementAt";
1920
public const string OpEndsWith = "EndsWith";
2021
public const string OpIndexOf = "IndexOf";
2122
public const string OpIndexOfMatch = "IndexOfMatch";
@@ -48,7 +49,6 @@ static class Operators
4849
public const string RuntimeOpNotEqual = "_Internal_NotEqual";
4950
public const string RuntimeOpNegate = "_Internal_Negate";
5051
public const string RuntimeOpNot = "_Internal_Not";
51-
public const string RuntimeOpElementAt = "_Internal_ElementAt";
5252
public const string RuntimeOpAny = "_Internal_Any";
5353
public const string RuntimeOpAll = "_Internal_All";
5454
public const string RuntimeOpIsNull = "_Internal_IsNull";

0 commit comments

Comments
 (0)