< Summary

Information
Class: NGql.Tool.SnippetRunner
Assembly: NGql.Tool
File(s): /home/runner/work/NGql/NGql/tools/Tool/SnippetRunner.cs
Line coverage
100%
Covered lines: 23
Uncovered lines: 0
Coverable lines: 23
Total lines: 61
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
CompileAndRun()100%44100%
IsMutation(...)100%11100%

File(s)

/home/runner/work/NGql/NGql/tools/Tool/SnippetRunner.cs

#LineLine coverage
 1using Microsoft.CodeAnalysis.CSharp.Scripting;
 2using Microsoft.CodeAnalysis.Scripting;
 3
 4using NGql.Core;
 5using NGql.Core.Builders;
 6
 7namespace NGql.Tool;
 8
 9/// <summary>
 10/// Compiles + evaluates a C# script snippet against the bundled NGql.Core, returning the
 11/// ToString() of the final expression's value.
 12/// </summary>
 13internal static class SnippetRunner
 14{
 315    private static readonly ScriptOptions Options = ScriptOptions.Default
 316        .WithReferences(
 317            typeof(QueryBuilder).Assembly,
 318            typeof(EnumValue).Assembly,
 319            typeof(Dictionary<,>).Assembly,
 320            typeof(System.Linq.Enumerable).Assembly,
 321            typeof(object).Assembly)
 322        .WithImports(
 323            "System",
 324            "System.Collections.Generic",
 325            "System.Linq",
 326            "NGql.Core",
 327            "NGql.Core.Builders");
 28
 29    public static async Task<SnippetResult> CompileAndRun(string snippet)
 30    {
 31        try
 32        {
 23433            var result = await CSharpScript.EvaluateAsync<object?>(snippet, Options);
 22234            return result is null
 22235                ? SnippetResult.Failed("snippet produced null — its final expression must yield a builder/object with To
 22236                : SnippetResult.Rendered(result.ToString() ?? string.Empty);
 37        }
 938        catch (CompilationErrorException ex)
 39        {
 940            return SnippetResult.Failed("compile error:\n" + string.Join('\n', ex.Diagnostics));
 41        }
 342        catch (Exception ex)
 43        {
 344            return SnippetResult.Failed($"runtime error: {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}");
 45        }
 23446    }
 47
 48    public static bool IsMutation(string rendered) =>
 6949        rendered.TrimStart().StartsWith("mutation ", StringComparison.Ordinal);
 50}
 51
 52/// <summary>
 53/// Outcome of compiling and evaluating a snippet: exactly one of <see cref="Output"/> (when
 54/// <see cref="Ok"/>) or <see cref="Error"/> carries text, so callers never need a null fallback.
 55/// </summary>
 56internal sealed record SnippetResult(bool Ok, string Output, string Error)
 57{
 58    public static SnippetResult Rendered(string output) => new(true, output, string.Empty);
 59
 60    public static SnippetResult Failed(string error) => new(false, string.Empty, error);
 61}