| File: ApiCompatRunnerExtensions.cs | Web Access |
| Project: src\sdk\src\Compatibility\ApiCompat\Microsoft.DotNet.PackageValidation\Microsoft.DotNet.PackageValidation.csproj (Microsoft.DotNet.PackageValidation) |
// 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; using Microsoft.DotNet.ApiCompatibility.Logging; using Microsoft.DotNet.ApiCompatibility.Runner; using NuGet.ContentModel; using NuGet.Frameworks; namespace Microsoft.DotNet.PackageValidation { // ApiCompatRunner extension methods that are specific to package validation // and rely on NuGet API. internal static class ApiCompatRunnerExtensions { public static void QueueApiCompatFromContentItem(this IApiCompatRunner apiCompatRunner, ISuppressibleLog log, IReadOnlyList<ContentItem> leftContentItems, IReadOnlyList<ContentItem> rightContentItems, ApiCompatRunnerOptions options, Package leftPackage, Package? rightPackage = null) { Debug.Assert(leftContentItems.Count > 0); Debug.Assert(rightContentItems.Count > 0); // Don't enqueue duplicate items (if no right package is supplied and items match) if (rightPackage is null && leftContentItems.SequenceEqual(rightContentItems, ContentItemEqualityComparer.Instance)) { return; } // If a right hand side package is provided in addition to the left side, package validation runs in baseline comparison mode. // The assumption stands that the right hand side is "current" and has more information than the left, i.e. assembly references. // If the left package doesn't provide assembly references, fallback to the references from the right side if the TFMs are compatible. IEnumerable<string>? fallbackAssemblyReferences = null; if (rightPackage is not null && leftPackage.AssemblyReferences is null) { // Retrieve the left TFM and try to find the best assembly references from the right hand side package. if (leftContentItems[0].Properties.TryGetValue("tfm", out object? tfmObj) && tfmObj is NuGetFramework leftTargetFramework) { fallbackAssemblyReferences = rightPackage.FindBestAssemblyReferencesForFramework(leftTargetFramework); } // if we cannot find references for the left framework, then just use the same right references for the left assembly if (fallbackAssemblyReferences is null && rightContentItems[0].Properties.TryGetValue("tfm", out tfmObj) && tfmObj is NuGetFramework rightTargetFramework) { fallbackAssemblyReferences = rightPackage.FindBestAssemblyReferencesForFramework(rightTargetFramework); } } MetadataInformation[] left = new MetadataInformation[leftContentItems.Count]; for (int leftIndex = 0; leftIndex < leftContentItems.Count; leftIndex++) { left[leftIndex] = GetMetadataInformation(log, leftPackage, leftContentItems[leftIndex], displayString: options.IsBaselineComparison ? Resources.Baseline + " " + leftContentItems[leftIndex].Path : null, assemblyReferences: fallbackAssemblyReferences); } MetadataInformation[] right = new MetadataInformation[rightContentItems.Count]; for (int rightIndex = 0; rightIndex < rightContentItems.Count; rightIndex++) { right[rightIndex] = GetMetadataInformation(log, rightPackage ?? leftPackage, rightContentItems[rightIndex]); } apiCompatRunner.EnqueueWorkItem(new ApiCompatRunnerWorkItem(left, options, right)); } private static MetadataInformation GetMetadataInformation(ISuppressibleLog log, Package package, ContentItem item, string? displayString = null, IEnumerable<string>? assemblyReferences = null) { displayString ??= item.Path; // Don't pass assembly references to the work item if the TFM can't be retrieved. if (item.Properties.TryGetValue("tfm", out object? tfmObj) && tfmObj is NuGetFramework nuGetFramework) { // If assembly references are provided for the package, use those. if (package.AssemblyReferences is not null && package.AssemblyReferences.Count > 0) { // See if the package's assembly reference entries have the same target framework. if (!package.AssemblyReferences.TryGetValue(nuGetFramework, out assemblyReferences)) { log.LogWarning(new Suppression(DiagnosticIds.SearchDirectoriesNotFoundForTfm) { Target = displayString }, DiagnosticIds.SearchDirectoriesNotFoundForTfm, string.Format(Resources.MissingSearchDirectory, nuGetFramework.GetShortFolderName(), displayString)); } } } return new MetadataInformation(Path.GetFileName(item.Path), item.Path, package.PackagePath, assemblyReferences, displayString); } } }