< Summary - Code Coverage

Information
Class: Plainquire.Filter.Swashbuckle.OpenApiParameterExtensions
Assembly: Plainquire.Filter.Swashbuckle
File(s): /home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter.Swashbuckle/Extensions/OpenApiParameterExtensions.cs
Tag: 74_23635074410
Line coverage
90%
Covered lines: 49
Uncovered lines: 5
Coverable lines: 54
Total lines: 113
Line coverage: 90.7%
Branch coverage
78%
Covered branches: 25
Total branches: 32
Branch coverage: 78.1%
Method coverage
100%
Covered methods: 7
Total methods: 7
Method coverage: 100%

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
IsEntityFilterParameter(...)50%22100%
IsEntityFilterSetParameter(...)50%22100%
ReplaceFilterParameters(...)100%1010100%
AddOriginalIndexExtensionIfMissing(...)80%101083.33%
GetOriginalIndex(...)62.5%8866.66%
ExpandToPropertyParameters(...)100%11100%
GetXmlDocumentationSummary(...)100%11100%

File(s)

/home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter.Swashbuckle/Extensions/OpenApiParameterExtensions.cs

#LineLine coverage
 1using LoxSmoke.DocXml;
 2using Microsoft.AspNetCore.Mvc.ApiExplorer;
 3using Microsoft.OpenApi;
 4using Plainquire.Filter.Abstractions;
 5using Plainquire.Filter.Swashbuckle.Models;
 6using Swashbuckle.AspNetCore.SwaggerGen;
 7using System;
 8using System.Collections.Generic;
 9using System.Diagnostics.CodeAnalysis;
 10using System.Linq;
 11using System.Reflection;
 12using System.Text.Json.Nodes;
 13
 14namespace Plainquire.Filter.Swashbuckle;
 15
 16internal static class OpenApiParameterExtensions
 17{
 18    private const string PARAMETER_INDEX_EXTENSION = "x-original-parameter-index";
 19    internal const string ENTITY_EXTENSION_PREFIX = "x-entity-filter-";
 20
 21    [SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract", Justification = "Paramet
 22    public static bool IsEntityFilterParameter(this ApiParameterDescription description)
 11323        => description.ParameterDescriptor != null && description.ParameterDescriptor.ParameterType.IsGenericEntityFilte
 24
 25    [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "Para
 26    public static bool IsEntityFilterSetParameter(this ApiParameterDescription description)
 8527        => description.ParameterDescriptor?.ParameterType.GetCustomAttribute<EntityFilterSetAttribute>() != null;
 28
 29    public static void ReplaceFilterParameters(this IList<IOpenApiParameter> parameters, List<FilterParameterReplaceInfo
 30    {
 4231        foreach (var replacement in parameterReplacements)
 32        {
 933            if (!replacement.Parameters.Any())
 34                continue;
 35
 936            var parameterIndex = parameters.IndexOf(replacement.Parameters[0]);
 37
 10838            foreach (var parameter in replacement.Parameters)
 4539                parameters.Remove(parameter);
 40
 941            var propertyParameters = replacement
 942                .EntityFilters
 943                .SelectMany(entityFilterType => entityFilterType
 944                    .GenericTypeArguments[0]
 945                    .ExpandToPropertyParameters(docXmlReaders)
 946                )
 947                .ToList();
 48
 6449            foreach (var parameter in propertyParameters)
 2350                parameters.Insert(parameterIndex++, parameter);
 51        }
 1252    }
 53
 54    public static void AddOriginalIndexExtensionIfMissing(this OpenApiOperation operation, OperationFilterContext contex
 55    {
 1256        if (operation.Parameters == null)
 057            return;
 58
 1259        var indexExtensionsAlreadyAdded = operation.Parameters.Any(p => p.Extensions?.ContainsKey(PARAMETER_INDEX_EXTENS
 1260        if (indexExtensionsAlreadyAdded)
 461            return;
 62
 26463        for (var index = 0; index < operation.Parameters.Count; index++)
 64        {
 12465            var parameter = operation.Parameters[index];
 12466            if (parameter is not IOpenApiExtensible openApiParameter)
 067                throw new InvalidOperationException("The OpenApiParameter must implement IOpenApiExtensible to be replac
 68
 12469            openApiParameter.Extensions ??= new Dictionary<string, IOpenApiExtension>(StringComparer.OrdinalIgnoreCase);
 12470            openApiParameter.Extensions.Add(PARAMETER_INDEX_EXTENSION, new JsonNodeExtension(JsonValue.Create(index)));
 71        }
 872    }
 73
 74    public static int GetOriginalIndex(this IOpenApiParameter parameter)
 75    {
 21476        if (parameter.Extensions == null)
 077            return -1;
 78
 21479        if (!parameter.Extensions.TryGetValue(PARAMETER_INDEX_EXTENSION, out var extension))
 880            return -1;
 81
 20682        if (extension is not JsonNodeExtension nodeExtension)
 083            throw new InvalidOperationException($"Extension '{PARAMETER_INDEX_EXTENSION}' must be of type {nameof(JsonNo
 84
 20685        if (nodeExtension.Node is not JsonValue jsonValue)
 086            throw new InvalidOperationException($"Value of extension '{PARAMETER_INDEX_EXTENSION}' must be of type {name
 87
 20688        return jsonValue.GetValue<int>();
 89    }
 90
 91    private static List<OpenApiParameter> ExpandToPropertyParameters(this Type filteredType, IReadOnlyCollection<DocXmlR
 92    {
 993        var filterableProperties = filteredType.GetFilterableProperties();
 994        var entityFilterAttribute = filteredType.GetCustomAttribute<EntityFilterAttribute>();
 95
 996        return filterableProperties
 997            .Select(property => new OpenApiParameter
 998            {
 999                Name = property.GetFilterParameterName(entityFilterAttribute?.Prefix),
 9100                Description = docXmlReaders.GetXmlDocumentationSummary(property),
 9101                Schema = new OpenApiSchema { Type = JsonSchemaType.String },
 9102                In = ParameterLocation.Query,
 9103                Extensions = new Dictionary<string, IOpenApiExtension>(StringComparer.OrdinalIgnoreCase)
 9104                {
 9105                    [ENTITY_EXTENSION_PREFIX + "property-type"] = new JsonNodeExtension(JsonValue.Create(property.Proper
 9106                }
 9107            })
 9108            .ToList();
 109    }
 110
 111    private static string? GetXmlDocumentationSummary(this IEnumerable<DocXmlReader> docXmlReaders, MemberInfo member)
 23112        => docXmlReaders.Select(x => x.GetMemberComment(member)).FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
 113}