Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 5 additions & 5 deletions demo/ThemingDemo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
Section("No theme (the default identity encoder)");
RenderAll(new ExpressionTemplate(textTemplate), events);

foreach (var (name, theme) in new (string, TemplateTheme)[]
foreach (var (name, theme) in new[]
{
("Code", TemplateTheme.Code),
("Grayscale", TemplateTheme.Grayscale),
Expand All @@ -45,11 +45,11 @@
})
{
Section($"TemplateTheme.{name}");
RenderAll(new ExpressionTemplate(textTemplate, theme: theme), events);
RenderAll(new ExpressionTemplate(textTemplate, encoder: TemplateOutputEncoder.Ansi(theme)), events);
}

Section("Level styling and alignment across Seq's level vocabulary — {@Level,-12:t4} {@Level}");
var levels = new ExpressionTemplate("{@Level,-12:t4} {@Level}\n", theme: TemplateTheme.Code);
var levels = new ExpressionTemplate("{@Level,-12:t4} {@Level}\n", encoder: TemplateOutputEncoder.Ansi(TemplateTheme.Code));
foreach (var spelling in new[] { "trace", "verbose", "dbug", "info", "notice", "warn", "eror", "fatal", "critical", "emerg", "alert", "panic", "OK" })
levels.Format(Event("-", level: spelling), Console.Out);

Expand All @@ -69,7 +69,7 @@
"{#end}" +
" {@Message}\n" +
"{@Exception}",
theme: melon);
encoder: TemplateOutputEncoder.Ansi(melon));

mel.Format(Event("Host listening at {ListenUri}",
new { ListenUri = "https://hello-world.local", SourceContext = "ThemingDemo.Program" }), Console.Out);
Expand All @@ -85,7 +85,7 @@

Section("Terminal safety: themed output strips event-derived control characters");
var hostile = Event("Deleting {Path}", new { Path = "\x1b[33;1mC:\\WINDOWS\x1b[0m" }, level: "Warning");
new ExpressionTemplate("[{@Level:u3}] {@Message}\n", theme: TemplateTheme.Code).Format(hostile, Console.Out);
new ExpressionTemplate("[{@Level:u3}] {@Message}\n", encoder: TemplateOutputEncoder.Ansi(TemplateTheme.Code)).Format(hostile, Console.Out);

Section("TemplateOutputEncoder.Html: content is escaped; unsafe() passes markup through");
var htmlTemplate = new ExpressionTemplate(
Expand Down
16 changes: 7 additions & 9 deletions src/Seq.Syntax/Compatibility/V1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public static bool TryCompileExpression(
[MaybeNullWhen(false)] out CompiledExpression result,
[MaybeNullWhen(true)] out string error)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
if (nameResolver == null) throw new ArgumentNullException(nameof(nameResolver));
ArgumentNullException.ThrowIfNull(expression);
ArgumentNullException.ThrowIfNull(nameResolver);

var expressionParser = new ExpressionParser();
if (!expressionParser.TryParse(expression, out var root, out error))
{
Expand All @@ -64,14 +64,11 @@ public static bool TryParseTemplate(
string template,
CultureInfo? culture,
NameResolver? nameResolver,
TemplateTheme? theme,
TemplateOutputEncoder? encoder,
[MaybeNullWhen(false)] out ExpressionTemplate result,
[MaybeNullWhen(true)] out string error)
{
if (template == null) throw new ArgumentNullException(nameof(template));

var outputEncoder = ExpressionTemplate.CreateOutputEncoder(theme, encoder);
ArgumentNullException.ThrowIfNull(template);

var templateParser = new TemplateParser();
if (!templateParser.TryParse(template, out var parsed, out error))
Expand All @@ -84,12 +81,13 @@ public static bool TryParseTemplate(

var planned = TemplateLocalNameBinder.BindLocalValueNames(parsed);

encoder ??= TemplateOutputEncoder.Default;
result = new ExpressionTemplate(
TemplateCompiler.Compile(
planned,
culture,
TemplateFunctionNameResolver.Build(WithV1Functions(nameResolver), planned, outputEncoder.HasEscaper),
outputEncoder));
TemplateFunctionNameResolver.Build(WithV1Functions(nameResolver), planned, encoder.HasEscaper),
encoder));

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Seq.Syntax/Expressions/Compilation/Linq/EventIdHash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static class EventIdHash
/// Murmur32 by default, and we should probably head in the same direction here.</remarks>
public static uint Compute(string messageTemplate)
{
if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate));
ArgumentNullException.ThrowIfNull(messageTemplate);

// Jenkins one-at-a-time https://en.wikipedia.org/wiki/Jenkins_hash_function
unchecked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class LinqExpressionCompiler : SeqExpressionTransformer<ExpressionBody>
public static Evaluatable Compile(Expression expression, CultureInfo? formatProvider,
NameResolver nameResolver)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
ArgumentNullException.ThrowIfNull(expression);
var compiler = new LinqExpressionCompiler(formatProvider, nameResolver);
var body = compiler.Transform(expression);
return LX.Lambda<Evaluatable>(body, compiler.Context).Compile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public static Expression ReplaceParameters(LambdaExpression lambda, params Param

ParameterReplacementVisitor(ParameterExpression[] from, ParameterExpression[] to)
{
if (from == null) throw new ArgumentNullException(nameof(from));
if (to == null) throw new ArgumentNullException(nameof(to));
ArgumentNullException.ThrowIfNull(from);
ArgumentNullException.ThrowIfNull(to);
if (from.Length != to.Length) throw new InvalidOperationException("Mismatched parameter lists");
_from = from;
_to = to;
Expand Down
4 changes: 2 additions & 2 deletions src/Seq.Syntax/Expressions/Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ static class Operators

public static bool SameOperator(string op1, string op2)
{
if (op1 == null) throw new ArgumentNullException(nameof(op1));
if (op2 == null) throw new ArgumentNullException(nameof(op2));
ArgumentNullException.ThrowIfNull(op1);
ArgumentNullException.ThrowIfNull(op2);

return OperatorComparer.Equals(op1, op2);
}
Expand Down
11 changes: 4 additions & 7 deletions src/Seq.Syntax/Expressions/Parsing/Combinators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ public static TokenListParser<TKind, TResult> ChainModified<TKind, TResult, TOpe
TokenListParser<TKind, TModifier> modify,
Func<TOperator, TResult, TResult, TModifier, TResult> apply)
{
if (@operator == null)
throw new ArgumentNullException(nameof (@operator));
if (operand == null)
throw new ArgumentNullException(nameof (operand));
if (modify == null) throw new ArgumentNullException(nameof(modify));
if (apply == null)
throw new ArgumentNullException(nameof (apply));
ArgumentNullException.ThrowIfNull(@operator);
ArgumentNullException.ThrowIfNull(operand);
ArgumentNullException.ThrowIfNull(modify);
ArgumentNullException.ThrowIfNull(apply);

return input =>
{
Expand Down
2 changes: 1 addition & 1 deletion src/Seq.Syntax/Expressions/Parsing/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public Expression Parse(string expression)
public bool TryParse(string filterExpression,
[MaybeNullWhen(false)] out Expression root, [MaybeNullWhen(true)] out string error)
{
if (filterExpression == null) throw new ArgumentNullException(nameof(filterExpression));
ArgumentNullException.ThrowIfNull(filterExpression);

var tokenList = _tokenizer.TryTokenize(filterExpression);
if (!tokenList.HasValue)
Expand Down
6 changes: 3 additions & 3 deletions src/Seq.Syntax/Expressions/Parsing/ParserExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ static class ParserExtensions
{
public static TokenListParser<TTokenKind, TResult> SelectCatch<TTokenKind, TArg, TResult>(this TokenListParser<TTokenKind, TArg> parser, Func<TArg, TResult> trySelector, string errorMessage)
{
if (parser == null) throw new ArgumentNullException(nameof(parser));
if (trySelector == null) throw new ArgumentNullException(nameof(trySelector));
if (errorMessage == null) throw new ArgumentNullException(nameof(errorMessage));
ArgumentNullException.ThrowIfNull(parser);
ArgumentNullException.ThrowIfNull(trySelector);
ArgumentNullException.ThrowIfNull(errorMessage);

return input =>
{
Expand Down
12 changes: 6 additions & 6 deletions src/Seq.Syntax/Expressions/SeqExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static CompiledExpression Compile(string expression,
CultureInfo? formatProvider = null,
NameResolver? nameResolver = null)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
ArgumentNullException.ThrowIfNull(expression);
if (!TryCompileImpl(expression, formatProvider, nameResolver, out var filter, out var error))
throw new ArgumentException(error);

Expand All @@ -62,7 +62,7 @@ public static bool TryCompile(
// ReSharper disable once OutParameterValueIsAlwaysDiscarded.Global
[MaybeNullWhen(true)] out string error)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
ArgumentNullException.ThrowIfNull(expression);
return TryCompileImpl(expression, null, null, out result, out error);
}

Expand All @@ -85,8 +85,8 @@ public static bool TryCompile(string expression,
[MaybeNullWhen(false)] out CompiledExpression result,
[MaybeNullWhen(true)] out string error)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
if (nameResolver == null) throw new ArgumentNullException(nameof(nameResolver));
ArgumentNullException.ThrowIfNull(expression);
ArgumentNullException.ThrowIfNull(nameResolver);
return TryCompileImpl(expression, formatProvider, nameResolver, out result, out error);
}

Expand Down Expand Up @@ -118,7 +118,7 @@ static bool TryCompileImpl(string expression,
// ReSharper disable once UnusedMember.Global
public static string EscapeLikeExpressionContent(string text)
{
if (text == null) throw new ArgumentNullException(nameof(text));
ArgumentNullException.ThrowIfNull(text);
return EscapeStringContent(text)
.Replace("%", "%%")
.Replace("_", "__");
Expand All @@ -131,7 +131,7 @@ public static string EscapeLikeExpressionContent(string text)
/// <returns>The text with any special values escaped.</returns>
public static string EscapeStringContent(string text)
{
if (text == null) throw new ArgumentNullException(nameof(text));
ArgumentNullException.ThrowIfNull(text);
return text.Replace("'", "''");
}

Expand Down
2 changes: 1 addition & 1 deletion src/Seq.Syntax/Expressions/StaticMemberNameResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class StaticMemberNameResolver : NameResolver
/// <param name="type">A <see cref="Type"/> with public static members implementing runtime functions.</param>
public StaticMemberNameResolver(Type type)
{
if (type == null) throw new ArgumentNullException(nameof(type));
ArgumentNullException.ThrowIfNull(type);

_methods = type
.GetTypeInfo()
Expand Down
16 changes: 6 additions & 10 deletions src/Seq.Syntax/Templates/Encoding/TemplateOutputEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,9 @@
namespace Seq.Syntax.Templates.Encoding;

/// <summary>
/// Encodes template output. Template evaluation produces a sequence of runs, each classified by
/// a <see cref="TemplateThemeStyle"/> and as either <em>content</em> (event-derived text) or
/// <em>markup</em> (text the template author controls: literal template text, padding, and
/// <c>unsafe()</c> output). The theme, when present, delimits every run; the escaper, when
/// present, transforms content — and only content — before it is written.
/// Applies theming and/or content escaping to template output.
/// </summary>
public class TemplateOutputEncoder
public sealed class TemplateOutputEncoder
{
static readonly TemplateThemeStyle[] Styles = Enum.GetValues<TemplateThemeStyle>();

Expand All @@ -34,8 +30,8 @@ public class TemplateOutputEncoder
/// <summary>
/// Construct a <see cref="TemplateOutputEncoder"/>.
/// </summary>
/// <param name="theme">Optionally, a theme delimiting classified output runs.</param>
/// <param name="escaper">Optionally, an escaper applied to event-derived content.</param>
/// <param name="theme">If specified, inserts theming delimiters before and after template elements for output.</param>
/// <param name="escaper">If specified, applies escaping to content substituted into template holes.</param>
public TemplateOutputEncoder(TemplateTheme? theme = null, TemplateOutputEscaper? escaper = null)
{
Theme = theme;
Expand All @@ -55,9 +51,9 @@ public TemplateOutputEncoder(TemplateTheme? theme = null, TemplateOutputEscaper?
/// control characters or ANSI escape sequences into the terminal.
/// </summary>
/// <param name="theme">The theme to apply.</param>
public static TemplateOutputEncoder Ansi(TemplateTheme theme)
public static TemplateOutputEncoder Ansi(TemplateTheme? theme)
{
if (theme == null) throw new ArgumentNullException(nameof(theme));
ArgumentNullException.ThrowIfNull(theme);
return new TemplateOutputEncoder(theme, TemplateOutputEscaper.Terminal);
}

Expand Down
46 changes: 10 additions & 36 deletions src/Seq.Syntax/Templates/ExpressionTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using Seq.Syntax.Templates.Compilation.NameResolution;
using Seq.Syntax.Templates.Encoding;
using Seq.Syntax.Templates.Parsing;
using Seq.Syntax.Templates.Themes;
using System.Text.Json.Nodes;

// ReSharper disable MemberCanBePrivate.Global, UnusedMember.Global
Expand All @@ -45,8 +44,8 @@ public static bool TryParse(
[MaybeNullWhen(false)] out ExpressionTemplate result,
[MaybeNullWhen(true)] out string error)
{
if (template == null) throw new ArgumentNullException(nameof(template));
return TryParse(template, null, null, null, null, out result, out error);
ArgumentNullException.ThrowIfNull(template);
return TryParse(template, null, null, null, out result, out error);
}

/// <summary>
Expand All @@ -59,24 +58,17 @@ public static bool TryParse(
/// <param name="error">A description of the error, if unsuccessful.</param>
/// <param name="nameResolver">Optionally, a <see cref="NameResolver"/>
/// with which to resolve function names that appear in the template.</param>
/// <param name="theme">Optionally, a theme for ANSI terminal output; shorthand for
/// <c>encoder: TemplateOutputEncoder.Ansi(theme)</c>, and exclusive with <paramref name="encoder"/>.</param>
/// <param name="encoder">Optionally, an encoder applying a theme and/or escaper to template output.</param>
/// <returns><c langword="true">true</c> if the template was well-formed.</returns>
/// <exception cref="ArgumentException">Both <paramref name="theme"/> and <paramref name="encoder"/>
/// are supplied.</exception>
public static bool TryParse(
string template,
CultureInfo? culture,
NameResolver? nameResolver,
TemplateTheme? theme,
TemplateOutputEncoder? encoder,
[MaybeNullWhen(false)] out ExpressionTemplate result,
[MaybeNullWhen(true)] out string error)
{
if (template == null) throw new ArgumentNullException(nameof(template));

var outputEncoder = CreateOutputEncoder(theme, encoder);
ArgumentNullException.ThrowIfNull(template);

var templateParser = new TemplateParser();
if (!templateParser.TryParse(template, out var parsed, out error))
Expand All @@ -87,12 +79,13 @@ public static bool TryParse(

var planned = TemplateLocalNameBinder.BindLocalValueNames(parsed);

encoder ??= TemplateOutputEncoder.Default;
result = new ExpressionTemplate(
TemplateCompiler.Compile(
planned,
culture,
TemplateFunctionNameResolver.Build(nameResolver, planned, outputEncoder.HasEscaper),
outputEncoder));
TemplateFunctionNameResolver.Build(nameResolver, planned, encoder.HasEscaper),
encoder));

return true;
}
Expand All @@ -110,48 +103,29 @@ internal ExpressionTemplate(CompiledTemplate compiled)
/// embedded values.</param>
/// <param name="nameResolver">Optionally, a <see cref="NameResolver"/>
/// with which to resolve function names that appear in the template.</param>
/// <param name="theme">Optionally, a theme for ANSI terminal output; shorthand for
/// <c>encoder: TemplateOutputEncoder.Ansi(theme)</c>, and exclusive with <paramref name="encoder"/>.</param>
/// <param name="encoder">Optionally, an encoder applying a theme and/or escaper to template output.</param>
/// <exception cref="ArgumentException">Both <paramref name="theme"/> and <paramref name="encoder"/>
/// are supplied, or the template is malformed.</exception>
public ExpressionTemplate(
string template,
CultureInfo? culture = null,
NameResolver? nameResolver = null,
TemplateTheme? theme = null,
TemplateOutputEncoder? encoder = null)
{
if (template == null) throw new ArgumentNullException(nameof(template));

var outputEncoder = CreateOutputEncoder(theme, encoder);
ArgumentNullException.ThrowIfNull(template);

var templateParser = new TemplateParser();
if (!templateParser.TryParse(template, out var parsed, out var error))
throw new ArgumentException(error);

var planned = TemplateLocalNameBinder.BindLocalValueNames(parsed);

encoder ??= TemplateOutputEncoder.Default;
_compiled = TemplateCompiler.Compile(
planned,
culture,
TemplateFunctionNameResolver.Build(nameResolver, planned, outputEncoder.HasEscaper),
outputEncoder);
}

internal static TemplateOutputEncoder CreateOutputEncoder(TemplateTheme? theme, TemplateOutputEncoder? encoder)
{
if (theme != null && encoder != null)
throw new ArgumentException(
$"Supply either `theme` or `encoder`, but not both. A theme is combined with a custom escaper by constructing a {nameof(TemplateOutputEncoder)} directly.");

if (theme != null)
return TemplateOutputEncoder.Ansi(theme);

return encoder ?? TemplateOutputEncoder.Default;
TemplateFunctionNameResolver.Build(nameResolver, planned, encoder.HasEscaper),
encoder);
}


/// <summary>
/// Format <paramref name="eventJson"/> into <paramref name="output"/>.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Seq.Syntax/Templates/Parsing/TemplateParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public bool TryParse(
[MaybeNullWhen(false)] out Template parsed,
[MaybeNullWhen(true)] out string error)
{
if (template == null) throw new ArgumentNullException(nameof(template));
ArgumentNullException.ThrowIfNull(template);

var tokenList = _tokenizer.TryTokenize(template);
if (!tokenList.HasValue)
Expand Down
Loading
Loading