< Summary - Kestrun — Combined Coverage

Information
Class: PowerShellAttributes
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/OpenApi/PowerShellAttributes.cs
Tag: Kestrun/Kestrun@ca54e35c77799b76774b3805b6f075cdbc0c5fbe
Line coverage
85%
Covered lines: 57
Uncovered lines: 10
Coverable lines: 67
Total lines: 214
Line coverage: 85%
Branch coverage
69%
Covered branches: 50
Total branches: 72
Branch coverage: 69.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 12/12/2025 - 17:27:19 Line coverage: 4.4% (3/68) Branch coverage: 2.7% (2/72) Total lines: 215 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd01/08/2026 - 02:20:28 Line coverage: 83.5% (56/67) Branch coverage: 68% (49/72) Total lines: 214 Tag: Kestrun/Kestrun@4bc17b7e465c315de6386907c417e44fcb0fd3eb01/14/2026 - 07:55:07 Line coverage: 85% (57/67) Branch coverage: 69.4% (50/72) Total lines: 214 Tag: Kestrun/Kestrun@13bd81d8920e7e63e39aafdd188e7d766641ad35 12/12/2025 - 17:27:19 Line coverage: 4.4% (3/68) Branch coverage: 2.7% (2/72) Total lines: 215 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd01/08/2026 - 02:20:28 Line coverage: 83.5% (56/67) Branch coverage: 68% (49/72) Total lines: 214 Tag: Kestrun/Kestrun@4bc17b7e465c315de6386907c417e44fcb0fd3eb01/14/2026 - 07:55:07 Line coverage: 85% (57/67) Branch coverage: 69.4% (50/72) Total lines: 214 Tag: Kestrun/Kestrun@13bd81d8920e7e63e39aafdd188e7d766641ad35

Metrics

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/OpenApi/PowerShellAttributes.cs

#LineLine coverage
 1
 2using System.Management.Automation;
 3using System.Management.Automation.Internal;
 4using System.Reflection;
 5using System.Text.Json.Nodes;
 6using Kestrun.OpenApi;
 7using Microsoft.OpenApi;
 8
 9internal static class PowerShellAttributes
 10{
 11    /// <summary>
 12    /// Applies PowerShell CmdletMetadataAttribute validations to an OpenAPI schema.
 13    /// </summary>
 14    /// <param name="attr">The CmdletMetadataAttribute to apply.</param>
 15    /// <param name="schema">The OpenAPI schema to modify.</param>
 16    internal static void ApplyPowerShellAttribute(CmdletMetadataAttribute attr, OpenApiSchema schema)
 17    {
 618        _ = attr switch
 619        {
 120            ValidateRangeAttribute a => ApplyValidateRangeAttribute(a, schema),
 621
 122            ValidateLengthAttribute a => ApplyValidateLengthAttribute(a, schema),
 623
 124            ValidateSetAttribute a => ApplyValidateSetAttribute(a.ValidValues, schema),
 625
 126            ValidatePatternAttribute a => ApplyValidatePatternAttribute(a, schema),
 627
 128            ValidateCountAttribute a => ApplyValidateCountAttribute(a, schema),
 629
 030            ValidateNotNullOrEmptyAttribute => ApplyNotNullOrEmpty(schema),
 031            ValidateNotNullAttribute => ApplyNotNull(schema),
 132            ValidateNotNullOrWhiteSpaceAttribute => ApplyNotNullOrWhiteSpace(schema),
 033            _ => null
 634        };
 035    }
 36
 37    /// <summary>
 38    /// Applies PowerShell validation attributes declared on a property to the specified schema.
 39    /// </summary>
 40    /// <param name="p">The property info to inspect for validation attributes.</param>
 41    /// <param name="s">The OpenAPI schema to apply constraints to.</param>
 42    internal static void ApplyPowerShellAttributes(PropertyInfo p, IOpenApiSchema s)
 43    {
 15644        if (s is not OpenApiSchema sc)
 45        {
 46            // constraints only applicable on a concrete schema, not a $ref proxy
 847            return;
 48        }
 49
 50        // Only pick PowerShell cmdlet metadata / validation attributes;
 51        // no magic string on Type.Name needed.
 30852        foreach (var attr in p.GetCustomAttributes<CmdletMetadataAttribute>(inherit: false))
 53        {
 654            ApplyPowerShellAttribute(attr, sc);
 55        }
 14856    }
 57
 58    /// <summary>
 59    /// Applies a ValidateRangeAttribute to an OpenApiSchema.
 60    /// </summary>
 61    /// <param name="attr">The ValidateRangeAttribute to apply.</param>
 62    /// <param name="schema">The OpenApiSchema to modify.</param>
 63    /// <returns>Returns always null.</returns>
 64    private static object? ApplyValidateRangeAttribute(ValidateRangeAttribute attr, OpenApiSchema schema)
 65    {
 166        var min = attr.MinRange;
 167        var max = attr.MaxRange;
 168        if (min is not null)
 69        {
 170            schema.Minimum = min.ToString();
 71        }
 172        if (max is not null)
 73        {
 174            schema.Maximum = max.ToString();
 75        }
 176        return null;
 77    }
 78
 79    /// <summary>
 80    /// Applies a ValidateLengthAttribute to an OpenApiSchema.
 81    /// </summary>
 82    /// <param name="attr">The ValidateLengthAttribute to apply.</param>
 83    /// <param name="schema">The OpenApiSchema to modify.</param>
 84    /// <returns>Returns always null.</returns>
 85    private static object? ApplyValidateLengthAttribute(ValidateLengthAttribute attr, OpenApiSchema schema)
 86    {
 187        var minLen = attr.MinLength;
 188        var maxLen = attr.MaxLength;
 189        if (minLen >= 0)
 90        {
 191            schema.MinLength = minLen;
 92        }
 193        if (maxLen >= 0)
 94        {
 195            schema.MaxLength = maxLen;
 96        }
 197        return null;
 98    }
 99
 100    /// <summary>
 101    /// Applies a ValidateSetAttribute to an OpenApiSchema.
 102    /// </summary>
 103    /// <param name="validValues">The list of valid values to apply.</param>
 104    /// <param name="sc">The OpenApiSchema to modify.</param>
 105    /// <returns>Returns always null.</returns>
 106    internal static object? ApplyValidateSetAttribute(IList<string> validValues, OpenApiSchema sc)
 107    {
 1108        if (validValues is not null)
 109        {
 1110            var list = new List<JsonNode>();
 6111            foreach (var node in validValues.Select(OpenApiJsonNodeFactory.ToNode))
 112            {
 2113                if (node is not null)
 114                {
 2115                    list.Add(node);
 116                }
 117            }
 118
 1119            if (list.Count > 0)
 120            {
 1121                var existing = sc.Enum?.ToList() ?? [];
 1122                existing.AddRange(list);
 1123                sc.Enum = existing;
 124            }
 125        }
 1126        return null;
 127    }
 128
 129    /// <summary>
 130    /// Applies a ValidatePatternAttribute to an OpenApiSchema.
 131    /// </summary>
 132    /// <param name="attr">The ValidatePatternAttribute to apply.</param>
 133    /// <param name="sc">The OpenApiSchema to modify.</param>
 134    /// <returns>Returns always null.</returns>
 135    private static object? ApplyValidatePatternAttribute(ValidatePatternAttribute attr, OpenApiSchema sc)
 136    {
 1137        if (string.IsNullOrWhiteSpace(sc.Pattern))
 138        {
 1139            sc.Pattern = attr.RegexPattern;
 140        }
 1141        return null;
 142    }
 143
 144    /// <summary>
 145    /// Applies a ValidateCountAttribute to an OpenApiSchema.
 146    /// </summary>
 147    /// <param name="attr">The ValidateCountAttribute to apply.</param>
 148    /// <param name="sc">The OpenApiSchema to modify.</param>
 149    /// <returns>Returns always null.</returns>
 150    private static object? ApplyValidateCountAttribute(ValidateCountAttribute attr, OpenApiSchema sc)
 151    {
 1152        if (attr.MinLength >= 0)
 153        {
 1154            sc.MinItems = attr.MinLength;
 155        }
 156
 1157        if (attr.MaxLength >= 0)
 158        {
 1159            sc.MaxItems = attr.MaxLength;
 160        }
 1161        return null;
 162    }
 163
 164    /// <summary>
 165    /// Applies a ValidateNotNullOrEmptyAttribute to an OpenApiSchema.
 166    /// </summary>
 167    /// <param name="sc">The OpenApiSchema to modify.</param>
 168    /// <returns>Returns always null.</returns>
 169    internal static object? ApplyNotNullOrEmpty(OpenApiSchema sc)
 170    {
 171        // string → minLength >= 1
 0172        if (sc.Type == JsonSchemaType.String && (sc.MinLength is null or < 1))
 173        {
 0174            sc.MinLength = 1;
 175        }
 176
 177        // array → minItems >= 1
 0178        if (sc.Type == JsonSchemaType.Array && (sc.MinItems is null or < 1))
 179        {
 0180            sc.MinItems = 1;
 181        }
 182
 0183        return null;
 184    }
 185
 186    /// <summary>
 187    /// Applies a ValidateNotNullOrWhiteSpaceAttribute to an OpenApiSchema.
 188    /// </summary>
 189    /// <param name="sc">The OpenApiSchema to modify.</param>
 190    /// <returns>Returns always null.</returns>
 191    internal static object? ApplyNotNullOrWhiteSpace(OpenApiSchema sc)
 192    {
 1193        if (sc.Type == JsonSchemaType.String)
 194        {
 1195            if (sc.MinLength is null or < 1)
 196            {
 1197                sc.MinLength = 1;
 198            }
 1199            if (string.IsNullOrEmpty(sc.Pattern))
 200            {
 201                // No existing pattern → just require a non-whitespace character
 1202                sc.Pattern = @"\S";
 203            }
 204        }
 1205        return null;
 206    }
 207
 208    /// <summary>
 209    /// Applies a ValidateNotNullAttribute to an OpenApiSchema.
 210    /// </summary>
 211    /// <param name="schema">The OpenApiSchema to modify.</param>
 212    /// <returns>Returns always null.</returns>
 0213    internal static object? ApplyNotNull(OpenApiSchema schema) => ApplyNotNullOrEmpty(schema);
 214}