< Summary

Information
Class: DotNetApiDiff.Models.Configuration.MappingConfiguration
Assembly: DotNetApiDiff
File(s): /home/runner/work/dotnet-api-diff/dotnet-api-diff/src/DotNetApiDiff/Models/Configuration/MappingConfiguration.cs
Line coverage
100%
Covered lines: 61
Uncovered lines: 0
Coverable lines: 61
Total lines: 134
Line coverage: 100%
Branch coverage
100%
Covered branches: 28
Total branches: 28
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_NamespaceMappings()100%11100%
get_TypeMappings()100%11100%
get_AutoMapSameNameTypes()100%11100%
get_IgnoreCase()100%11100%
CreateDefault()100%11100%
IsValid()100%1212100%
HasCircularReferences()100%44100%
DetectCircular(...)100%1212100%

File(s)

/home/runner/work/dotnet-api-diff/dotnet-api-diff/src/DotNetApiDiff/Models/Configuration/MappingConfiguration.cs

#LineLine coverage
 1// Copyright DotNet API Diff Project Contributors - SPDX Identifier: MIT
 2using System.Text.Json.Serialization;
 3
 4namespace DotNetApiDiff.Models.Configuration;
 5
 6/// <summary>
 7/// Configuration for mapping namespaces and types between assemblies
 8/// </summary>
 9public class MappingConfiguration
 10{
 11    /// <summary>
 12    /// Dictionary mapping source namespaces to one or more target namespaces
 13    /// </summary>
 14    [JsonPropertyName("namespaceMappings")]
 50115    public Dictionary<string, List<string>> NamespaceMappings { get; set; } = new Dictionary<string, List<string>>();
 16
 17    /// <summary>
 18    /// Dictionary mapping source type names to target type names
 19    /// </summary>
 20    [JsonPropertyName("typeMappings")]
 41021    public Dictionary<string, string> TypeMappings { get; set; } = new Dictionary<string, string>();
 22
 23    /// <summary>
 24    /// Whether to automatically map types with the same name but different namespaces
 25    /// </summary>
 26    [JsonPropertyName("autoMapSameNameTypes")]
 33727    public bool AutoMapSameNameTypes { get; set; } = false;
 28
 29    /// <summary>
 30    /// Whether to ignore case when mapping types and namespaces
 31    /// </summary>
 32    [JsonPropertyName("ignoreCase")]
 35633    public bool IgnoreCase { get; set; } = false;
 34
 35    /// <summary>
 36    /// Creates a default mapping configuration
 37    /// </summary>
 38    /// <returns>A default mapping configuration</returns>
 39    public static MappingConfiguration CreateDefault()
 6540    {
 6541        return new MappingConfiguration
 6542        {
 6543            NamespaceMappings = new Dictionary<string, List<string>>(),
 6544            TypeMappings = new Dictionary<string, string>(),
 6545            AutoMapSameNameTypes = false,
 6546            IgnoreCase = false
 6547        };
 6548    }
 49
 50    /// <summary>
 51    /// Validates the mapping configuration
 52    /// </summary>
 53    /// <returns>True if valid, false otherwise</returns>
 54    public bool IsValid()
 3755    {
 56        // Check for empty keys or values in namespace mappings
 7157        if (NamespaceMappings.Any(kvp => string.IsNullOrWhiteSpace(kvp.Key) ||
 7158                                         kvp.Value == null ||
 7159                                         kvp.Value.Count == 0 ||
 7160                                         kvp.Value.Any(string.IsNullOrWhiteSpace)))
 461        {
 462            return false;
 63        }
 64
 65        // Check for empty keys or values in type mappings
 5766        if (TypeMappings.Any(kvp => string.IsNullOrWhiteSpace(kvp.Key) ||
 5767                                    string.IsNullOrWhiteSpace(kvp.Value)))
 268        {
 269            return false;
 70        }
 71
 72        // Check for circular references in namespace mappings
 3173        if (HasCircularReferences())
 274        {
 275            return false;
 76        }
 77
 2978        return true;
 3779    }
 80
 81    /// <summary>
 82    /// Checks if there are circular references in namespace mappings
 83    /// </summary>
 84    /// <returns>True if circular references exist, false otherwise</returns>
 85    private bool HasCircularReferences()
 3186    {
 3187        var visited = new HashSet<string>();
 3188        var recursionStack = new HashSet<string>();
 89
 14790        foreach (var source in NamespaceMappings.Keys)
 2891        {
 2892            if (DetectCircular(source, visited, recursionStack))
 293            {
 294                return true;
 95            }
 2696        }
 97
 2998        return false;
 3199    }
 100
 101    /// <summary>
 102    /// Helper method for circular reference detection using DFS
 103    /// </summary>
 104    private bool DetectCircular(string current, HashSet<string> visited, HashSet<string> recursionStack)
 32105    {
 32106        if (!visited.Contains(current))
 30107        {
 30108            visited.Add(current);
 30109            recursionStack.Add(current);
 110
 111            // If the current namespace maps to other namespaces
 30112            if (NamespaceMappings.TryGetValue(current, out var targets))
 30113            {
 148114                foreach (var target in targets)
 31115                {
 116                    // If target is in recursion stack, we have a cycle
 31117                    if (recursionStack.Contains(target))
 2118                    {
 2119                        return true;
 120                    }
 121
 122                    // If target is a source namespace and we detect a cycle in its mappings
 29123                    if (NamespaceMappings.ContainsKey(target) && DetectCircular(target, visited, recursionStack))
 2124                    {
 2125                        return true;
 126                    }
 27127                }
 26128            }
 26129        }
 130
 28131        recursionStack.Remove(current);
 28132        return false;
 32133    }
 134}