| File: PackageSpecExtensions.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.ProjectModel\NuGet.ProjectModel.csproj (NuGet.ProjectModel) |
// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using NuGet.Frameworks; namespace NuGet.ProjectModel { public static class PackageSpecExtensions { /// <summary> /// Get the nearest framework available in the project. /// </summary> public static TargetFrameworkInformation GetTargetFramework(this PackageSpec project, NuGetFramework targetFramework) { var frameworkInfo = project.TargetFrameworks.FirstOrDefault(f => NuGetFramework.Comparer.Equals(targetFramework, f.FrameworkName)); if (frameworkInfo == null) { frameworkInfo = NuGetFrameworkUtility.GetNearest(project.TargetFrameworks, targetFramework, item => item.FrameworkName); } return frameworkInfo ?? new TargetFrameworkInformation(); } /// <summary> /// Get restore metadata framework. This is based on the project's target frameworks, then an /// exact match is found under restore metadata. /// </summary> public static ProjectRestoreMetadataFrameworkInfo GetRestoreMetadataFramework(this PackageSpec project, NuGetFramework targetFramework) { ProjectRestoreMetadataFrameworkInfo? frameworkInfo = null; var projectFrameworkInfo = GetTargetFramework(project, targetFramework); if (projectFrameworkInfo.FrameworkName != null) { frameworkInfo = project.RestoreMetadata?.TargetFrameworks .FirstOrDefault(f => f.FrameworkName.Equals(projectFrameworkInfo.FrameworkName)); } return frameworkInfo ?? new ProjectRestoreMetadataFrameworkInfo(); } /// <summary> /// Get the <see cref="TargetFrameworkInformation"/> for the given target alias. /// If there is not a match, null is returned. /// </summary> /// <param name="project">The project</param> /// <param name="targetAlias">The target alias to search for</param> /// <returns>The <see cref="TargetFrameworkInformation"/> if it exists, <see langword="null"/> otherwise. </returns> public static TargetFrameworkInformation? GetTargetFramework(this PackageSpec project, string? targetAlias) { foreach (var framework in project.TargetFrameworks.NoAllocEnumerate()) { if (string.Equals(framework.TargetAlias, targetAlias, StringComparison.OrdinalIgnoreCase)) { return framework; } } return null; } /// <summary> /// Get the <see cref="ProjectRestoreMetadataFrameworkInfo"/> for the given target alias. /// If there is not a match, null is returned. /// </summary> /// <param name="project">The project</param> /// <param name="targetAlias">The target alias to search for</param> /// <returns>The <see cref="ProjectRestoreMetadataFrameworkInfo"/> if it exists, <see langword="null"/> otherwise. </returns> public static ProjectRestoreMetadataFrameworkInfo? GetRestoreMetadataFramework(this PackageSpec project, string? targetAlias) { if (project.RestoreMetadata != null) { foreach (var framework in project.RestoreMetadata.TargetFrameworks.NoAllocEnumerate()) { if (string.Equals(framework.TargetAlias, targetAlias, StringComparison.OrdinalIgnoreCase)) { return framework; } } } return null; } /// <summary> /// Gets the nearest target framework within the project based on the given target framework and target alias. /// If multiple frameworks match, the target alias is used to disambiguate. /// If there are duplicates and no matching alias, then an empty TargetFrameworkInformation is returned. /// </summary> /// <param name="project">The project spec in question.</param> /// <param name="targetFramework">The pivot target framework.</param> /// <param name="targetAlias">The alias for disambiguation</param> public static TargetFrameworkInformation GetNearestTargetFramework(this PackageSpec project, NuGetFramework targetFramework, string? targetAlias) { TargetFrameworkInformation? result = null; List<TargetFrameworkInformation>? frameworks = null; FindMatchingFrameworks(project, targetFramework, ref result, ref frameworks); // We matched a single framework. if (result != null && frameworks == null) { return result; } // No exact match found, find the nearest if (result == null || frameworks == null) { var reducer = new FrameworkReducer(DefaultFrameworkNameProvider.Instance, DefaultCompatibilityProvider.Instance); NuGetFramework? mostCompatibleFramework = reducer.GetNearest(targetFramework, project.TargetFrameworks.Select(e => e.FrameworkName)); if (mostCompatibleFramework != null) { FindMatchingFrameworks(project, mostCompatibleFramework, ref result, ref frameworks); } } // We matched a single framework. if (result != null && frameworks == null) { return result; } // Multiple matchingFrameworks matched exactly, use target alias to disambiguate if (result != null && frameworks != null) { foreach (var framework in frameworks) { if (string.Equals(framework.TargetAlias, targetAlias, StringComparison.OrdinalIgnoreCase)) { return framework; } } } return new TargetFrameworkInformation(); static void FindMatchingFrameworks(PackageSpec project, NuGetFramework targetFramework, ref TargetFrameworkInformation? matchedFramework, ref List<TargetFrameworkInformation>? matchingFrameworks) { foreach (TargetFrameworkInformation framework in project.TargetFrameworks.NoAllocEnumerate()) { if (NuGetFramework.Comparer.Equals(targetFramework, framework.FrameworkName)) { // Result not being null means we have multiple matches. if (matchedFramework != null) { if (matchingFrameworks == null) { matchingFrameworks = [matchedFramework, framework]; } else { matchingFrameworks.Add(framework); } } matchedFramework = framework; } } } } } }