< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Utilities.PsScriptBlockValidation
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Utilities/PsScriptBlockValidation.cs
Tag: Kestrun/Kestrun@ca54e35c77799b76774b3805b6f075cdbc0c5fbe
Line coverage
93%
Covered lines: 29
Uncovered lines: 2
Coverable lines: 31
Total lines: 94
Line coverage: 93.5%
Branch coverage
81%
Covered branches: 36
Total branches: 44
Branch coverage: 81.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 12/26/2025 - 18:43:06 Line coverage: 0% (0/31) Branch coverage: 0% (0/44) Total lines: 94 Tag: Kestrun/Kestrun@66a9a3a4461391825b9a1ffc8190f76adb1bb67f01/08/2026 - 08:19:25 Line coverage: 93.5% (29/31) Branch coverage: 81.8% (36/44) Total lines: 94 Tag: Kestrun/Kestrun@6ab94ca7560634c2ac58b36c2b98e2a9b1bf305d 12/26/2025 - 18:43:06 Line coverage: 0% (0/31) Branch coverage: 0% (0/44) Total lines: 94 Tag: Kestrun/Kestrun@66a9a3a4461391825b9a1ffc8190f76adb1bb67f01/08/2026 - 08:19:25 Line coverage: 93.5% (29/31) Branch coverage: 81.8% (36/44) Total lines: 94 Tag: Kestrun/Kestrun@6ab94ca7560634c2ac58b36c2b98e2a9b1bf305d

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
HasParamAndNothingAfterParam_Ast(...)70.83%252490%
IsParamLast(...)100%1414100%
IsParamLast(...)83.33%66100%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Utilities/PsScriptBlockValidation.cs

#LineLine coverage
 1using System.Management.Automation;
 2using System.Management.Automation.Language;
 3
 4namespace Kestrun.Utilities;
 5
 6/// <summary>
 7/// Utilities for validating PowerShell ScriptBlocks.
 8/// </summary>
 9internal static class PsScriptBlockValidation
 10{
 11    /// <summary>
 12    /// Checks if the provided PowerShell script text contains only a param() block
 13    /// and nothing else (no executable statements).
 14    /// </summary>
 15    /// <param name="scriptText">The PowerShell script text to validate.</param>
 16    /// <param name="error">Output error message if validation fails.</param>
 17    /// <returns>True if the script contains only a param() block; otherwise, false.</returns>
 18    internal static bool HasParamAndNothingAfterParam_Ast(string scriptText, out string? error)
 19    {
 1020        error = null;
 21
 1022        var ast = Parser.ParseInput(scriptText, out var tokens, out var errors);
 23
 1024        if (errors.Length > 0)
 25        {
 226            error = "Parse error: " + string.Join("; ", errors.Select(e => e.Message));
 127            return false;
 28        }
 29
 930        if (ast is not ScriptBlockAst sbAst)
 31        {
 032            error = "Not a ScriptBlockAst.";
 033            return false;
 34        }
 35
 36        // Find param block
 937        var paramAst = sbAst.ParamBlock;
 938        if (paramAst is null)
 39        {
 240            error = "No param() block found.";
 241            return false;
 42        }
 43
 44        // Any executable statements in Begin/Process/End blocks?
 745        var hasAnyStatements =
 746            (sbAst.BeginBlock?.Statements?.Count ?? 0) > 0 ||
 747            (sbAst.ProcessBlock?.Statements?.Count ?? 0) > 0 ||
 748            (sbAst.EndBlock?.Statements?.Count ?? 0) > 0;
 49
 750        if (hasAnyStatements)
 51        {
 352            error = "Statements found after param().";
 353            return false;
 54        }
 55
 456        return true;
 57    }
 58
 59    /// <summary>
 60    /// Checks if the param() block is the last element in the ScriptBlock AST.
 61    /// </summary>
 62    /// <param name="sbAst">The ScriptBlock AST to check.</param>
 63    /// <returns>True if the param() block is the last element; otherwise, false.</returns>
 64    internal static bool IsParamLast(ScriptBlockAst sbAst)
 65    {
 1166        if (sbAst.ParamBlock is null)
 67        {
 468            return false;
 69        }
 70
 71        // Collect all executable statements in all blocks
 772        var allStatements =
 773            (sbAst.BeginBlock?.Statements ?? Enumerable.Empty<StatementAst>())
 774            .Concat(sbAst.ProcessBlock?.Statements ?? Enumerable.Empty<StatementAst>())
 775            .Concat(sbAst.EndBlock?.Statements ?? Enumerable.Empty<StatementAst>());
 76
 77        // param() must be the last executable element, so no statements should exist
 778        return !allStatements.Any();
 79    }
 80
 81    /// <summary>
 82    /// Checks if the provided PowerShell ScriptBlock has the param() block as the last element.
 83    /// </summary>
 84    /// <param name="scriptBlock">The PowerShell ScriptBlock to check.</param>
 85    /// <returns>True if the param() block is the last element; otherwise, false.</returns>
 86    internal static bool IsParamLast(ScriptBlock scriptBlock)
 87    {
 788        var ast = scriptBlock?.Ast;
 89
 790        return ast is FunctionDefinitionAst funcDefAst
 791            ? IsParamLast(funcDefAst.Body)
 792            : ast is ScriptBlockAst sbAst && IsParamLast(sbAst);
 93    }
 94}