/// <summary> /// Finds all expansions using the mapping provider /// </summary> private IEnumerable <NuGetFramework> ExpandInternal(NuGetFramework framework) { // check the framework directly, this includes profiles which the range doesn't return IEnumerable <NuGetFramework> directlyEquivalent = null; if (_mappings.TryGetEquivalentFrameworks(framework, out directlyEquivalent)) { foreach (var eqFw in directlyEquivalent) { yield return(eqFw); } } // 0.0 through the current framework FrameworkRange frameworkRange = new FrameworkRange( new NuGetFramework(framework.Framework, new Version(0, 0), framework.Profile, framework.Platform, framework.PlatformVersion), framework); IEnumerable <NuGetFramework> equivalent = null; if (_mappings.TryGetEquivalentFrameworks(frameworkRange, out equivalent)) { foreach (var eqFw in equivalent) { yield return(eqFw); } } // find all possible sub set frameworks if no profile is used if (!framework.HasProfile) { IEnumerable <string> subSetFrameworks = null; if (_mappings.TryGetSubSetFrameworks(framework.Framework, out subSetFrameworks)) { foreach (var subFramework in subSetFrameworks) { // clone the framework but use the sub framework instead yield return(new NuGetFramework(subFramework, framework.Version, framework.Profile, framework.Platform, framework.PlatformVersion)); } } } // explicit compatiblity mappings IEnumerable <FrameworkRange> ranges = null; if (_mappings.TryGetCompatibilityMappings(framework, out ranges)) { foreach (var range in ranges) { yield return(range.Min); if (!range.Min.Equals(range.Max)) { yield return(range.Max); } } } yield break; }
/// <summary> /// Remove duplicates found in the equivalence mappings. /// </summary> public IEnumerable <NuGetFramework> ReduceEquivalent(IEnumerable <NuGetFramework> frameworks) { // order first so we get consistent results for equivalent frameworks var input = frameworks .OrderBy(f => f, new FrameworkPrecedenceSorter(_mappings, true)) .ThenByDescending(f => f, new NuGetFrameworkSorter()) .ToArray(); var duplicates = new HashSet <NuGetFramework>(); foreach (var framework in input) { if (duplicates.Contains(framework)) { continue; } yield return(framework); duplicates.Add(framework); IEnumerable <NuGetFramework> eqFrameworks; if (_mappings.TryGetEquivalentFrameworks(framework, out eqFrameworks)) { foreach (var eqFramework in eqFrameworks) { duplicates.Add(eqFramework); } } } }
/// <summary> /// Find all equivalent frameworks, and their equivalent frameworks. /// Example: /// Mappings: /// A <‒> B /// B <‒> C /// C <‒> D /// For A we need to find B, C, and D so we must retrieve equivalent frameworks for A, B, and C /// also as we discover them. /// </summary> private IEnumerable <NuGetFramework> GetEquivalentFrameworksClosure(NuGetFramework framework) { // add the current framework to the seen list to avoid returning it later var seen = new HashSet <NuGetFramework>() { framework }; var toExpand = new Stack <NuGetFramework>(); toExpand.Push(framework); while (toExpand.Count > 0) { var frameworkToExpand = toExpand.Pop(); IEnumerable <NuGetFramework> compatibleFrameworks = null; if (_mappings.TryGetEquivalentFrameworks(frameworkToExpand, out compatibleFrameworks)) { foreach (var curFramework in compatibleFrameworks) { if (seen.Add(curFramework)) { yield return(curFramework); toExpand.Push(curFramework); } } } } yield break; }
/// <summary> /// Remove duplicates found in the equivalence mappings. /// </summary> public IEnumerable <NuGetFramework> Reduce(IEnumerable <NuGetFramework> frameworks) { // order first so we get consistent results for equivalent frameworks var input = frameworks.OrderBy(f => f.DotNetFrameworkName, StringComparer.OrdinalIgnoreCase).ToArray(); var comparer = new NuGetFrameworkFullComparer(); for (var i = 0; i < input.Length; i++) { var dupe = false; IEnumerable <NuGetFramework> eqFrameworks = null; if (!_mappings.TryGetEquivalentFrameworks(input[i], out eqFrameworks)) { eqFrameworks = new List <NuGetFramework>() { input[i] }; } for (var j = i + 1; !dupe && j < input.Length; j++) { dupe = eqFrameworks.Contains(input[j], comparer); } if (!dupe) { yield return(input[i]); } } yield break; }