| File: Rules\RuleRunner.cs | Web Access |
| Project: src\sdk\src\Compatibility\ApiCompat\Microsoft.DotNet.ApiCompatibility\Microsoft.DotNet.ApiCompatibility.csproj (Microsoft.DotNet.ApiCompatibility) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using Microsoft.DotNet.ApiCompatibility.Mapping; namespace Microsoft.DotNet.ApiCompatibility.Rules { /// <summary> /// Rule runner that exposes functionality to initialize rules and run element mapper objects. /// </summary> public class RuleRunner(IRuleFactory ruleFactory, IRuleContext context) : IRuleRunner { /// <inheritdoc /> public void InitializeRules(IRuleSettings settings) { // Instantiate the rules but don't invoke anything on them as they register themselves on "events" inside their constructor. _ = ruleFactory.CreateRules(settings, context); } /// <inheritdoc /> public IEnumerable<CompatDifference> Run<T>(IElementMapper<T> mapper) { List<CompatDifference> differences = []; int rightLength = mapper.Right.Length; for (int rightIndex = 0; rightIndex < rightLength; rightIndex++) { if (mapper is AssemblyMapper am) { // Ignore assembly mappings which are null on both sides, i.e. when different assembly identities are marked as compatible. if (am.Left == null && am.Right[rightIndex] == null) continue; /* Some assembly symbol actions need to know if the passed in assembly is the only one being visited. This is true if the assembly set only contains a single assembly or if there is no assembly set and the assembly mapper is directly visited. */ bool containsSingleAssembly = am.ContainingAssemblySet == null || am.ContainingAssemblySet.AssemblyCount < 2; context.RunOnAssemblySymbolActions(am.Left?.Element, am.Right[rightIndex]?.Element, am.Left?.MetadataInformation ?? MetadataInformation.DefaultLeft, am.Right[rightIndex]?.MetadataInformation ?? MetadataInformation.DefaultRight, containsSingleAssembly, differences); } else if (mapper is TypeMapper tm) { if (tm.ShouldDiffElement(rightIndex)) { context.RunOnTypeSymbolActions(tm.Left, tm.Right[rightIndex], tm.ContainingNamespace.ContainingAssembly.Left?.MetadataInformation ?? MetadataInformation.DefaultLeft, tm.ContainingNamespace.ContainingAssembly.Right[rightIndex]?.MetadataInformation ?? MetadataInformation.DefaultRight, differences); } } else if (mapper is MemberMapper mm) { if (mm.ShouldDiffElement(rightIndex)) { // ContainingType Left and Right cannot be null, as otherwise, the above condition would be false. Debug.Assert(mm.ContainingType.Left != null); Debug.Assert(mm.ContainingType.Right[rightIndex] != null); context.RunOnMemberSymbolActions( mm.Left, mm.Right[rightIndex], mm.ContainingType.Left!, mm.ContainingType.Right[rightIndex]!, mm.ContainingType.ContainingNamespace.ContainingAssembly.Left?.MetadataInformation ?? MetadataInformation.DefaultLeft, mm.ContainingType.ContainingNamespace.ContainingAssembly.Right[rightIndex]?.MetadataInformation ?? MetadataInformation.DefaultRight, differences); } } else { throw new ArgumentOutOfRangeException(nameof(mapper)); } } return differences; } } }