diff --git a/README.md b/README.md index 7d078c9..87aed36 100644 --- a/README.md +++ b/README.md @@ -387,7 +387,7 @@ User-defined functions are supplied through an instance of `NameResolver`: ```csharp var myFunctions = new StaticMemberNameResolver(typeof(MyFunctions)); -var expr = SerilogExpression.Compile("IsHello(User.Name)", nameResolver: customSerilogFunctions); +var expr = SerilogExpression.Compile("IsHello(User.Name)", nameResolver: myFunctions); // Filter events based on whether `User.Name` is `'Hello'` :-) ``` diff --git a/appveyor.yml b/appveyor.yml index b81b089..396eae9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: xIn2Dlahvk1QLaFAazCkjSc83UC1Uv5jeMeyA2NDDiLeHZwFqMm5da6nHEzm6ks5 + secure: AcMGMnsJdQe1+SQwf+9VpRqcKNw93zr96OlxAEmPob52vqxDNH844SmdYidGX0cL skip_symbols: true on: branch: /^(main|dev)$/ diff --git a/src/Serilog.Expressions/Serilog.Expressions.csproj b/src/Serilog.Expressions/Serilog.Expressions.csproj index 238042a..545cac6 100644 --- a/src/Serilog.Expressions/Serilog.Expressions.csproj +++ b/src/Serilog.Expressions/Serilog.Expressions.csproj @@ -3,7 +3,7 @@ An embeddable mini-language for filtering, enriching, and formatting Serilog events, ideal for use with JSON or XML configuration. - 3.4.1 + 3.5.0 Serilog Contributors netstandard2.0;netstandard2.1;net5.0 true @@ -17,7 +17,7 @@ - + diff --git a/src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs b/src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs index 1049d96..1457032 100644 --- a/src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs +++ b/src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs @@ -22,7 +22,7 @@ class CompiledRepetition : CompiledTemplate { readonly Evaluatable _enumerable; readonly string? _keyOrElementName; - readonly string? _valueName; + readonly string? _valueOrIndexName; readonly CompiledTemplate _body; readonly CompiledTemplate? _delimiter; readonly CompiledTemplate? _alternative; @@ -30,14 +30,14 @@ class CompiledRepetition : CompiledTemplate public CompiledRepetition( Evaluatable enumerable, string? keyOrElementName, - string? valueName, + string? valueOrIndexName, CompiledTemplate body, CompiledTemplate? delimiter, CompiledTemplate? alternative) { _enumerable = enumerable; _keyOrElementName = keyOrElementName; - _valueName = valueName; + _valueOrIndexName = valueOrIndexName; _body = body; _delimiter = delimiter; _alternative = alternative; @@ -52,29 +52,32 @@ public override void Evaluate(EvaluationContext ctx, TextWriter output) return; } - if (enumerable is SequenceValue sv) + if (enumerable is SequenceValue sequence) { - if (sv.Elements.Count == 0) + if (sequence.Elements.Count == 0) { _alternative?.Evaluate(ctx, output); return; } - var first = true; - foreach (var element in sv.Elements) + for (var i = 0; i < sequence.Elements.Count; ++i) { - if (element == null) - continue; // Should have been invalid but Serilog didn't check and so this does occur in the wild. + // Null elements should have been invalid but Serilog didn't check, and so this does occur in the wild. + var element = sequence.Elements[i] ?? new ScalarValue(null); - if (first) - first = false; - else + if (i != 0) + { _delimiter?.Evaluate(ctx, output); + } var local = _keyOrElementName != null - ? new(ctx.LogEvent, Locals.Set(ctx.Locals, _keyOrElementName, element)) + ? new EvaluationContext(ctx.LogEvent, Locals.Set(ctx.Locals, _keyOrElementName, element)) : ctx; + local = _valueOrIndexName != null + ? new EvaluationContext(local.LogEvent, Locals.Set(local.Locals, _valueOrIndexName, new ScalarValue(i))) + : local; + _body.Evaluate(local, output); } @@ -101,8 +104,8 @@ public override void Evaluate(EvaluationContext ctx, TextWriter output) ? new(ctx.LogEvent, Locals.Set(ctx.Locals, _keyOrElementName, new ScalarValue(member.Name))) : ctx; - local = _valueName != null - ? new(local.LogEvent, Locals.Set(local.Locals, _valueName, member.Value)) + local = _valueOrIndexName != null + ? new(local.LogEvent, Locals.Set(local.Locals, _valueOrIndexName, member.Value)) : local; _body.Evaluate(local, output); @@ -129,8 +132,8 @@ public override void Evaluate(EvaluationContext ctx, TextWriter output) ? new(ctx.LogEvent, Locals.Set(ctx.Locals, _keyOrElementName, element.Key)) : ctx; - local = _valueName != null - ? new(local.LogEvent, Locals.Set(local.Locals, _valueName, element.Value)) + local = _valueOrIndexName != null + ? new(local.LogEvent, Locals.Set(local.Locals, _valueOrIndexName, element.Value)) : local; _body.Evaluate(local, output); diff --git a/src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameResolver.cs b/src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameBinder.cs similarity index 97% rename from src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameResolver.cs rename to src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameBinder.cs index 60bdb57..cf8683c 100644 --- a/src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameResolver.cs +++ b/src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameBinder.cs @@ -76,7 +76,7 @@ Template Transform(Repetition rep, Stack locals) locals.Pop(); return new Repetition( - rep.Enumerable, + ExpressionLocalNameBinder.BindLocalValueNames(rep.Enumerable, locals), rep.BindingNames, body, rep.Delimiter != null ? Transform(rep.Delimiter, locals) : null, diff --git a/test/Serilog.Expressions.Tests/Cases/template-evaluation-cases.asv b/test/Serilog.Expressions.Tests/Cases/template-evaluation-cases.asv index 5df712a..6c30df5 100644 --- a/test/Serilog.Expressions.Tests/Cases/template-evaluation-cases.asv +++ b/test/Serilog.Expressions.Tests/Cases/template-evaluation-cases.asv @@ -23,8 +23,10 @@ A{#if false}B{#else if false}C{#else if true}D{#else}E{#end} ⇶ AD A{#if false}B{#else if true}C{#end} ⇶ AC {#if true}A{#if false}B{#else}C{#end}D{#end} ⇶ ACD {#each a in [1,2,3]}<{a}>{#delimit},{#end} ⇶ <1>,<2>,<3> +{#each a, i in [1,2,3]}<{a}>({i}){#delimit},{#end} ⇶ <1>(0),<2>(1),<3>(2) {#each a in {x: 1, y: 2}}{a}{#end} ⇶ xy {#each a, b in {x: 1, y: 2}}{a}.{b}{#end} ⇶ x.1y.2 +{#each a, b in {x: {y: 'z'}}}{#each c, d in b}A: {a}, C: {c}, D: {d}{#end}{#end} ⇶ A: x, C: y, D: z {#if true}A{#each a in [1]}B{a}{#end}C{#end}D ⇶ AB1CD {#each a in []}{a}!{#else}none{#end} ⇶ none Culture-specific {42.34} ⇶ Culture-specific 42,34