示例#1
0
        public static Generations Load(string generationsPath, bool useNetPlatform)
        {
            Generations result;
            string      cachePath = $"{generationsPath}:{useNetPlatform}";

            if (s_generationsCache.TryGetValue(cachePath, out result))
            {
                return(result);
            }

            result = new Generations(useNetPlatform);

            using (var fileStream = File.OpenRead(generationsPath))
                using (var streamReader = new StreamReader(fileStream))
                    using (var jsonReader = new JsonTextReader(streamReader))
                    {
                        var json = JToken.Load(jsonReader);

                        foreach (var generation in EachProperty(json["generations"]).Select(ReadGeneration))
                        {
                            if (useNetPlatform)
                            {
                                // net platform, dotnet, is 4.1 ahead of netstandard.  EG: netstandard1.0 = dotnet5.1, and so on.
                                generation.Version = new Version(generation.Version.Major + 4, generation.Version.Minor + 1, 0, 0);
                            }

                            result._generations.Add(generation);
                        }
                    }

            result._generations.Sort((g1, g2) => g1.Version.CompareTo(g2.Version));

            return(result);
        }
示例#2
0
        public static Generations Load(string generationsPath, bool useNetPlatform)
        {
            Generations result;
            string cachePath = $"{generationsPath}:{useNetPlatform}";

            if (s_generationsCache.TryGetValue(cachePath, out result))
                return result;

            result = new Generations(useNetPlatform);

            using (var fileStream = File.OpenRead(generationsPath))
            using (var streamReader = new StreamReader(fileStream))
            using (var jsonReader = new JsonTextReader(streamReader))
            {
                var json = JToken.Load(jsonReader);

                foreach (var generation in EachProperty(json["generations"]).Select(ReadGeneration))
                {
                    if (useNetPlatform)
                    {
                        // net platform, dotnet, is 4.1 ahead of netstandard.  EG: netstandard1.0 = dotnet5.1, and so on.
                        generation.Version = new Version(generation.Version.Major + 4, generation.Version.Minor + 1, 0, 0);
                    }

                    result._generations.Add(generation);
                }
            }

            result._generations.Sort((g1, g2) => g1.Version.CompareTo(g2.Version));

            return result;
        }
示例#3
0
        public static Generations Load(string generationsPath)
        {
            Generations result;
            if (s_generationsCache.TryGetValue(generationsPath, out result))
                return result;

            result = new Generations();

            using (var fileStream = File.OpenRead(generationsPath))
            using (var streamReader = new StreamReader(fileStream))
            using (var jsonReader = new JsonTextReader(streamReader))
            {
                var json = JToken.Load(jsonReader);

                foreach (var generation in EachProperty(json["generations"]).Select(ReadGeneration))
                {
                    result._generations.Add(generation);
                }
            }

            result._generations.Sort((g1, g2) => g1.Version.CompareTo(g2.Version));

            return result;
        }
        /* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks,
         * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */
        public override bool Execute()
        {
            if (null == Dependencies)
            {
                Log.LogError("Dependencies argument must be specified");
                return(false);
            }
            if (null == FrameworkListsPath)
            {
                Log.LogError("FrameworkListsPath argument must be specified");
                return(false);
            }

            // Retrieve the list of generation dependency group TFM's
            var dependencyGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetFramework")).Select(dg => new
            {
                Framework    = NuGetFramework.Parse(dg.Key),
                Dependencies = dg.ToArray()
            });

            List <ITaskItem> addedDependencies = new List <ITaskItem>();

            // Exclude any non-portable frameworks that already have specific dependency groups.
            var frameworksToExclude = dependencyGroups.Select(dg => dg.Framework).Where(fx => !FrameworkUtilities.IsGenerationMoniker(fx));

            // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package
            PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray();
            var           packagePaths = packageItems.Select(pi => pi.TargetPath);
            var           targetFrameworksWithPlaceHolders = packageItems.Where(pi => NuGetAssetResolver.IsPlaceholder(pi.TargetPath)).Select(pi => pi.TargetFramework);

            NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths);

            foreach (var portableDependencyGroup in dependencyGroups.Where(dg => FrameworkUtilities.IsGenerationMoniker(dg.Framework)))
            {
                // Determine inbox frameworks for this generation that don't already have explicit groups
                HashSet <NuGetFramework> inboxFrameworksList = new HashSet <NuGetFramework>(
                    Frameworks.GetAlllInboxFrameworks(FrameworkListsPath)
                    .Where(fx => !fx.IsPCL)
                    .Where(fx => Generations.DetermineGenerationForFramework(fx, UseNetPlatform) >= portableDependencyGroup.Framework.Version &&
                           !frameworksToExclude.Any(exFx => exFx.Framework == fx.Framework && exFx.Version <= fx.Version)));

                // Check for assets which have a ref, but not a lib asset. If we have any of these, then they are actually not supported frameworks
                // and we should not include them.
                inboxFrameworksList.RemoveWhere(inboxFx => !IsSupported(inboxFx, resolver));

                // Only add the lowest version for a particular inbox framework.  EG if both net45 and net46 are supported by this generation,
                //        only add net45
                inboxFrameworksList.RemoveWhere(fx => inboxFrameworksList.Any(otherFx => (otherFx.Framework.Equals(fx.Framework)) && (otherFx.Version < fx.Version)));

                // Create dependency items for each inbox framework.
                foreach (var framework in inboxFrameworksList)
                {
                    bool addedDependencyToFramework = false;
                    foreach (ITaskItem dependency in portableDependencyGroup.Dependencies)
                    {
                        string version = GetVersion(dependency);

                        if (!Frameworks.IsInbox(FrameworkListsPath, framework, dependency.ItemSpec, version))
                        {
                            addedDependencyToFramework = true;
                            AddDependency(addedDependencies, new TaskItem(dependency), framework, portableDependencyGroup.Framework);
                        }
                    }
                    if (!addedDependencyToFramework)
                    {
                        AddDependency(addedDependencies, new TaskItem("_._"), framework, portableDependencyGroup.Framework);
                    }
                }
            }

            // Collapse frameworks
            // For any dependency with a targetframework, if there is another target framework which is compatible and older, remove this dependency.

            // Get all Dependencies which are not in a portable dependency group so that we can collapse the frameworks.  If we include
            // the portable frameworks, then we'll end up collapsing to those.
            List <NuGetFramework> allDependencyGroups = new List <NuGetFramework>();

            allDependencyGroups.AddRange(Dependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) &&
                                                                                                                                !FrameworkUtilities.IsGenerationMoniker(a) &&
                                                                                                                                !FrameworkUtilities.IsPortableMoniker(a)));
            allDependencyGroups.AddRange(addedDependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) &&
                                                                                                                                     !FrameworkUtilities.IsGenerationMoniker(a) &&
                                                                                                                                     !FrameworkUtilities.IsPortableMoniker(a)));

            List <NuGetFramework> collapsedDependencyGroups = FrameworkUtilities.ReduceDownwards(allDependencyGroups).ToList <NuGetFramework>();

            // Get the list of dependency groups that we collapsed down so that we can add them back if they contained different dependencies than what is present in the collapsed group.

            /* TODO: Look into NuGet's sorting algorithm, they may have a bug (fixed in this line). They were not including version in the sort.
             *       See ReduceCore in https://github.com/NuGet/NuGet.Client/blob/23ea68b91a439fcfd7f94bcd01bcdee2e8adae92/src/NuGet.Core/NuGet.Frameworks/FrameworkReducer.cs */
            IEnumerable <NuGetFramework> removedDependencyGroups = allDependencyGroups.Where(d => !collapsedDependencyGroups.Contains(d))?.OrderBy(f => f.Framework, StringComparer.OrdinalIgnoreCase).ThenBy(f => f.Version);

            foreach (NuGetFramework removedDependencyGroup in removedDependencyGroups)
            {
                // always recalculate collapsedDependencyGroups in case we added an item in a previous iteration.  Dependency groups are sorted, so this should be additive and we shouldn't need to restart the collapse / add back cycle
                var nearest = FrameworkUtilities.GetNearest(removedDependencyGroup, collapsedDependencyGroups.ToArray());

                // gather the dependencies for this dependency group and the calculated "nearest" dependency group
                var nearestDependencies = addedDependencies.Where(d => nearest.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString());
                var currentDependencies = addedDependencies.Where(d => removedDependencyGroup.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString());

                // The nearest dependency group's dependencies are different than this dependency group's dependencies
                if (nearestDependencies.Count() != currentDependencies.Count())
                {
                    // ignore if dependency is a placeholder
                    if (currentDependencies.Count() > 0)
                    {
                        if (!NuGetAssetResolver.IsPlaceholder(currentDependencies.First().ToString()))
                        {
                            collapsedDependencyGroups.Add(removedDependencyGroup);
                        }
                    }
                    else
                    {
                        collapsedDependencyGroups.Add(removedDependencyGroup);
                    }
                }
                // identical dependency count between current and nearest, and the count is > 0
                else if (nearestDependencies.Count() > 0)
                {
                    if (!currentDependencies.SequenceEqual(nearestDependencies, new DependencyITaskItemComparer()))
                    {
                        collapsedDependencyGroups.Add(removedDependencyGroup);
                    }
                }
            }


            List <ITaskItem> collapsedDependencies = new List <ITaskItem>();

            foreach (ITaskItem dependency in addedDependencies)
            {
                if (collapsedDependencyGroups.Contains(NuGetFramework.Parse(dependency.GetMetadata("TargetFramework"))))
                {
                    collapsedDependencies.Add(dependency);
                }
            }
            TrimmedDependencies = collapsedDependencies.ToArray();

            return(!Log.HasLoggedErrors);
        }
示例#5
0
        private void LoadSupport()
        {
            _frameworks = new Dictionary <NuGetFramework, ValidationFramework>();

            // determine which TxM:RIDs should be considered for support based on Frameworks item
            foreach (var framework in Frameworks)
            {
                NuGetFramework fx;
                try
                {
                    fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework.");
                    continue;
                }

                string runtimeIdList = framework.GetMetadata("RuntimeIDs");

                if (_frameworks.ContainsKey(fx))
                {
                    Log.LogError($"Framework {fx} has been listed in Frameworks more than once.");
                    continue;
                }

                _frameworks[fx] = new ValidationFramework(fx);

                if (!String.IsNullOrWhiteSpace(runtimeIdList))
                {
                    _frameworks[fx].RuntimeIds = runtimeIdList.Split(';');
                }
            }

            // keep a list of explicitly listed supported frameworks so that we can check for conflicts.
            HashSet <NuGetFramework> explicitlySupportedFrameworks = new HashSet <NuGetFramework>();

            // determine what version should be supported based on SupportedFramework items
            foreach (var supportedFramework in SupportedFrameworks)
            {
                NuGetFramework fx;
                string         fxString           = supportedFramework.ItemSpec;
                bool           isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']';
                if (isExclusiveVersion)
                {
                    fxString = fxString.Substring(1, fxString.Length - 2);
                }

                try
                {
                    fx = FrameworkUtilities.ParseNormalized(fxString);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework.");
                    continue;
                }

                Version supportedVersion;
                string  version = supportedFramework.GetMetadata("Version");
                try
                {
                    supportedVersion = Version.Parse(version);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}");
                    continue;
                }

                ValidationFramework validationFramework = null;
                if (!_frameworks.TryGetValue(fx, out validationFramework))
                {
                    Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation.");
                    continue;
                }


                if (explicitlySupportedFrameworks.Contains(fx))
                {
                    if (validationFramework.SupportedVersion != supportedVersion)
                    {
                        Log.LogError($"Framework {fx} has been listed in SupportedFrameworks more than once with different versions {validationFramework.SupportedVersion} and {supportedVersion}.  Framework should only be listed once with the expected API version for that platform.");
                    }
                    continue;
                }
                explicitlySupportedFrameworks.Add(fx);

                validationFramework.SupportedVersion = supportedVersion;

                if (!isExclusiveVersion)
                {
                    // find all frameworks of higher version, sorted by version ascending
                    var higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version);

                    foreach (var higherFramework in higherFrameworks)
                    {
                        if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion)
                        {
                            // found an higher framework version a higher API version, stop applying this supported version
                            break;
                        }

                        higherFramework.SupportedVersion = supportedVersion;
                    }
                }
            }


            // determine which Frameworks should support inbox
            _frameworkSet = FrameworkSet.Load(FrameworkListsPath);
            foreach (IEnumerable <Framework> inboxFxGroup in _frameworkSet.Frameworks.Values)
            {
                foreach (Framework inboxFx in inboxFxGroup)
                {
                    // get currently supported version to see if we have OOB'ed it
                    Version inboxVersion = null;
                    inboxFx.Assemblies.TryGetValue(ContractName, out inboxVersion);

                    if (inboxVersion != null)
                    {
                        NuGetFramework      fx = FrameworkUtilities.ParseNormalized(inboxFx.ShortName);
                        ValidationFramework validationFramework = null;
                        if (_frameworks.TryGetValue(fx, out validationFramework))
                        {
                            Version supportedVersion = validationFramework.SupportedVersion;

                            if (supportedVersion != null &&
                                (supportedVersion.Major > inboxVersion.Major ||
                                 (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor)))
                            {
                                // Higher major.minor
                                Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}.  Assuming out of box.");
                                continue;
                            }
                            else if (supportedVersion != null && supportedVersion < inboxVersion)
                            {
                                // Lower version
                                Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}");
                            }

                            // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item
                        }

                        if (validationFramework == null)
                        {
                            // we may not be explicitly validating for this framework so add it to validate inbox assets.
                            _frameworks[fx] = validationFramework = new ValidationFramework(fx)
                            {
                                SupportedVersion = inboxVersion
                            };
                        }

                        validationFramework.IsInbox = true;
                    }
                }
            }

            // for every framework we know about, also validate it's generation to ensure it can
            // be targeted by PCL.  Even if a package only supports a single framework we still
            // want to include a portable reference assembly.  This allows 3rd parties to add
            // their own implementation via a lineup/runtime.json.

            // only consider frameworks that support the contract at a specific version
            var portableFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != s_maxVersion).ToArray();

            var genVersionSuppression = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet <string>();
            Dictionary <NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary <NuGetFramework, ValidationFramework>();

            foreach (var framework in portableFrameworks)
            {
                NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(framework.Framework, UseNetPlatform));
                Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {framework.SupportedVersion} since it is supported by {framework.Framework}");

                ValidationFramework existingGeneration = null;
                if (generationsToValidate.TryGetValue(generation, out existingGeneration))
                {
                    if (!VersionUtility.IsCompatibleApiVersion(framework.SupportedVersion, existingGeneration.SupportedVersion) && !genVersionSuppression.Contains(framework.Framework.ToString()))
                    {
                        Log.LogError($"Framework {framework.Framework} supports {ContractName} at {framework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}");
                    }
                }
                else
                {
                    generationsToValidate.Add(generation, new ValidationFramework(generation)
                    {
                        SupportedVersion = framework.SupportedVersion
                    });
                }
            }

            foreach (var generation in generationsToValidate)
            {
                _frameworks.Add(generation.Key, generation.Value);
            }

            // for every generation supported explcitly in implementation, ensure
            // it can be targeted by PCL.
            foreach (var packageGroup in _resolver.GetAllRuntimeItems())
            {
                var allGenerationalImplementations = packageGroup.Value
                                                     .Where(contentGroup => FrameworkUtilities.IsGenerationMoniker(contentGroup.Properties[PropertyNames.TargetFrameworkMoniker] as NuGetFramework))
                                                     .SelectMany(contentGroup => contentGroup.Items.Select(item => _targetPathToPackageItem[AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageGroup.Key, item.Path)]));

                foreach (var generationalImplementation in allGenerationalImplementations)
                {
                    NuGetFramework generation = generationalImplementation.TargetFramework;
                    if (_frameworks.ContainsKey(generation))
                    {
                        continue;
                    }

                    Version supportedVersion = generationalImplementation.Version;

                    Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {supportedVersion} since it is supported by {generationalImplementation.TargetPath}");

                    _frameworks.Add(generation, new ValidationFramework(generation)
                    {
                        SupportedVersion = supportedVersion
                    });
                }
            }
        }
示例#6
0
        private void LoadSupport()
        {
            _frameworks = new Dictionary <NuGetFramework, ValidationFramework>();

            // determine which TxM:RIDs should be considered for support based on Frameworks item
            foreach (var framework in Frameworks)
            {
                NuGetFramework fx;
                try
                {
                    fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework.");
                    continue;
                }

                string runtimeIdList = framework.GetMetadata("RuntimeIDs");

                if (_frameworks.ContainsKey(fx))
                {
                    Log.LogError($"Framework {fx} has been listed in Frameworks more than once.");
                    continue;
                }

                _frameworks[fx] = new ValidationFramework(fx);

                if (!String.IsNullOrWhiteSpace(runtimeIdList))
                {
                    _frameworks[fx].RuntimeIds = runtimeIdList.Split(';');
                }
            }

            // keep a list of explicitly listed supported frameworks so that we can check for conflicts.
            HashSet <NuGetFramework> explicitlySupportedFrameworks = new HashSet <NuGetFramework>();

            // determine what version should be supported based on SupportedFramework items
            foreach (var supportedFramework in SupportedFrameworks)
            {
                NuGetFramework fx;
                string         fxString           = supportedFramework.ItemSpec;
                bool           isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']';
                if (isExclusiveVersion)
                {
                    fxString = fxString.Substring(1, fxString.Length - 2);
                }

                try
                {
                    fx = FrameworkUtilities.ParseNormalized(fxString);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}");
                    continue;
                }

                if (fx.Equals(NuGetFramework.UnsupportedFramework))
                {
                    Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework.");
                    continue;
                }

                Version supportedVersion;
                string  version = supportedFramework.GetMetadata("Version");
                try
                {
                    supportedVersion = Version.Parse(version);
                }
                catch (Exception ex)
                {
                    Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}");
                    continue;
                }

                ValidationFramework validationFramework = null;
                if (!_frameworks.TryGetValue(fx, out validationFramework))
                {
                    Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation.");
                    continue;
                }


                if (explicitlySupportedFrameworks.Contains(fx))
                {
                    if (supportedVersion <= validationFramework.SupportedVersion)
                    {
                        // if we've already picked up a higher/equal version, prefer it
                        continue;
                    }
                }
                else
                {
                    explicitlySupportedFrameworks.Add(fx);
                }

                validationFramework.SupportedVersion = supportedVersion;

                if (!isExclusiveVersion)
                {
                    // find all frameworks of higher version, sorted by version ascending
                    IEnumerable <ValidationFramework> higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version);

                    // netcore50 is the last `netcore` framework, after that we use `uap`
                    if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetCore)
                    {
                        var uapFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == FrameworkConstants.FrameworkIdentifiers.UAP).OrderBy(vf => vf.Framework.Version);
                        higherFrameworks = higherFrameworks.Concat(uapFrameworks);
                    }


                    foreach (var higherFramework in higherFrameworks)
                    {
                        if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion)
                        {
                            // found an higher framework version a higher API version, stop applying this supported version
                            break;
                        }

                        higherFramework.SupportedVersion = supportedVersion;
                    }
                }
            }


            // determine which Frameworks should support inbox
            _frameworkSet = FrameworkSet.Load(FrameworkListsPath);
            foreach (IEnumerable <Framework> inboxFxGroup in _frameworkSet.Frameworks.Values)
            {
                foreach (Framework inboxFx in inboxFxGroup)
                {
                    // get currently supported version to see if we have OOB'ed it
                    Version inboxVersion = null;
                    inboxFx.Assemblies.TryGetValue(ContractName, out inboxVersion);

                    if (inboxVersion != null)
                    {
                        NuGetFramework      fx = FrameworkUtilities.ParseNormalized(inboxFx.ShortName);
                        ValidationFramework validationFramework = null;
                        if (_frameworks.TryGetValue(fx, out validationFramework))
                        {
                            Version supportedVersion = validationFramework.SupportedVersion;

                            if (supportedVersion != null &&
                                (supportedVersion.Major > inboxVersion.Major ||
                                 (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor)))
                            {
                                // Higher major.minor
                                Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}.  Assuming out of box.");
                                continue;
                            }
                            else if (supportedVersion != null && supportedVersion < inboxVersion && inboxVersion != s_maxVersion)
                            {
                                // Lower version
                                Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}");
                            }

                            // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item
                        }

                        if (validationFramework == null)
                        {
                            // we may not be explicitly validating for this framework so add it to validate inbox assets.
                            _frameworks[fx] = validationFramework = new ValidationFramework(fx)
                            {
                                SupportedVersion = inboxVersion
                            };
                        }

                        validationFramework.IsInbox = true;
                    }
                }
            }

            // for every framework we know about, also infer it's netstandard version to ensure it can
            // be targeted by PCL.  Even if a package only supports a single framework we still
            // want to include a portable reference assembly.  This allows 3rd parties to add
            // their own implementation via a lineup/runtime.json.

            // only consider frameworks that support the contract at a specific version
            var inferFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != s_maxVersion).ToArray();

            var genVersionSuppression       = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet <string>();
            var inferNETStandardSuppression = GetSuppressionValues(Suppression.SuppressNETStandardInference) ?? new HashSet <string>();
            Dictionary <NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary <NuGetFramework, ValidationFramework>();

            foreach (var inferFramework in inferFrameworks)
            {
                var inferFrameworkMoniker = inferFramework.Framework.ToString();
                if (inferNETStandardSuppression.Contains(inferFrameworkMoniker))
                {
                    continue;
                }

                NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(inferFramework.Framework, UseNetPlatform));
                Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {inferFramework.SupportedVersion} since it is supported by {inferFrameworkMoniker}");

                ValidationFramework existingGeneration = null;
                if (generationsToValidate.TryGetValue(generation, out existingGeneration))
                {
                    // the netstandard version should be the minimum version supported by all platforms that support that netstandard version.
                    if (inferFramework.SupportedVersion < existingGeneration.SupportedVersion)
                    {
                        Log.LogMessage($"Framework {inferFramework.Framework} supports {ContractName} at {inferFramework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}.  Lowering the version supported by {generation.GetShortFolderName()}.");
                        existingGeneration.SupportedVersion = inferFramework.SupportedVersion;
                    }
                }
                else
                {
                    generationsToValidate.Add(generation, new ValidationFramework(generation)
                    {
                        SupportedVersion = inferFramework.SupportedVersion
                    });
                }
            }

            foreach (var generation in generationsToValidate)
            {
                _frameworks.Add(generation.Key, generation.Value);
            }
        }
        public override bool Execute()
        {
            if (String.IsNullOrEmpty(PackageTargetFramework))
            {
                Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework is not defined");
                return(true);
            }

            NuGetFramework fx = null;

            try
            {
                fx = NuGetFramework.Parse(PackageTargetFramework);
            }
            catch (Exception ex)
            {
                Log.LogError($"Could not parse PackageTargetFramework {PackageTargetFramework}. {ex}");
                return(false);
            }

            Version assemblyVersion = null;

            if (!Version.TryParse(AssemblyVersion, out assemblyVersion))
            {
                Log.LogError($"Could not parse AssemblyVersion {AssemblyVersion}.");
                return(false);
            }

            if (UseNetPlatform)
            {
                if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetStandard)
                {
                    Log.LogError($"Validating for legacy 'dotnet' moniker but package targets new 'netstandard' moniker.");
                    return(false);
                }
                else if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetPlatform)
                {
                    Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetPlatform}");
                    return(true);
                }
            }
            else
            {
                if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetPlatform)
                {
                    if (fx.Version > new Version(5, 0))
                    {
                        NuGetFramework netstandardFx = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.NetStandard, new Version(fx.Version.Major - 4, fx.Version.Minor - 1));
                        Log.LogError($"{fx.GetShortFolderName()} is no longer supported please update to {netstandardFx.GetShortFolderName()}.  Validating as {netstandardFx.GetShortFolderName()}.");
                        // update to netstandard so that we can get the right number of errors
                        fx = netstandardFx;
                    }
                    else
                    {
                        Log.LogError($"Invalid framework version {fx.GetShortFolderName()} please update to appropriate netstandard version.");
                        // update to nestandard so that we'll do the actual calculation
                        fx = FrameworkConstants.CommonFrameworks.NetStandard;
                    }
                }


                if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetStandard)
                {
                    Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetStandard}");
                    return(true);
                }
            }

            _generations = Generations.Load(GenerationDefinitionsFile, UseNetPlatform);

            Dictionary <string, string> candidateRefs = CandidateReferences.ToDictionary(r => r.GetMetadata("FileName"), r => r.GetMetadata("FullPath"));

            Version idealGeneration = _generations.DetermineGenerationFromSeeds(AssemblyName, assemblyVersion, Log) ?? new Version(0, 0, 0, 0);

            if (idealGeneration > fx.Version)
            {
                Log.LogError($"Assembly {AssemblyName}, Version={assemblyVersion} is generation {idealGeneration} based on the seed data in {GenerationDefinitionsFile} which is greater than project generation {fx.Version}.");
            }

            HashSet <string> ignoredRefs = null;

            if (IgnoredReferences != null)
            {
                ignoredRefs = new HashSet <string>(IgnoredReferences.Select(ir => ir.ItemSpec), StringComparer.OrdinalIgnoreCase);
            }

            Version defaultGeneration = UseNetPlatform ? FrameworkConstants.CommonFrameworks.DotNet.Version : FrameworkConstants.CommonFrameworks.NetStandard.Version;

            foreach (var reference in DirectReferences)
            {
                string path = reference.GetMetadata("FullPath");

                // workaround issue where portable targeting pack design time facades
                // include dangling refs and refs to higher versions of contracts than
                // exist in the targeting pack.
                if (path.IndexOf(".NETPortable", StringComparison.OrdinalIgnoreCase) != -1 &&
                    designTimeFacades.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }

                if (ignoredRefs != null && ignoredRefs.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }

                if (!File.Exists(path))
                {
                    Log.LogError($"Reference {path} does not exist.");
                    continue;
                }

                var dependencyGeneration = _generations.DetermineGenerationFromFile(path, Log, candidateRefs: candidateRefs, ignoredRefs: ignoredRefs) ?? defaultGeneration;

                if (dependencyGeneration > fx.Version)
                {
                    Log.LogError($"Dependency {path} is generation {dependencyGeneration} which is greater than project generation {fx.Version}.");
                }

                if (dependencyGeneration > idealGeneration)
                {
                    idealGeneration = dependencyGeneration;
                }
            }

            if (fx.Version > idealGeneration)
            {
                Log.LogMessage(LogImportance.Low, $"Generation {fx.Version} is higher than the ideal miniumum {idealGeneration}.");
            }


            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            if (String.IsNullOrEmpty(PackageTargetFramework))
            {
                Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework is not defined");
                return true;
            }

            NuGetFramework fx = null;
            try
            {
                fx = NuGetFramework.Parse(PackageTargetFramework);
            }
            catch(Exception ex)
            {
                Log.LogError($"Could not parse PackageTargetFramework {PackageTargetFramework}. {ex}");
                return false;
            }

            Version assemblyVersion = null;
            if (!Version.TryParse(AssemblyVersion, out assemblyVersion))
            {
                Log.LogError($"Could not parse AssemblyVersion {AssemblyVersion}.");
                return false;
            }

            if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetPlatform)
            {
                Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetPlatform}");
                return true;
            }

            _generations = Generations.Load(GenerationDefinitionsFile);

            Dictionary<string, string> candidateRefs = CandidateReferences.ToDictionary(r => r.GetMetadata("FileName"), r => r.GetMetadata("FullPath"));

            Version idealGeneration = _generations.DetermineGenerationFromSeeds(AssemblyName, assemblyVersion, Log) ?? new Version(0, 0, 0, 0);
            if (idealGeneration > fx.Version)
            {
                Log.LogError($"Assembly {AssemblyName}, Version={assemblyVersion} is generation {idealGeneration} based on the seed data in {GenerationDefinitionsFile} which is greater than project generation {fx.Version}.");
            }

            HashSet<string> ignoredRefs = null;

            if (IgnoredReferences != null)
            {
                ignoredRefs = new HashSet<string>(IgnoredReferences.Select(ir => ir.ItemSpec), StringComparer.OrdinalIgnoreCase);
            }

            foreach (var reference in DirectReferences)
            {
                string path = reference.GetMetadata("FullPath");

                // workaround issue where portable targeting pack design time facades
                // include dangling refs and refs to higher versions of contracts than 
                // exist in the targeting pack.
                if (path.IndexOf(".NETPortable", StringComparison.OrdinalIgnoreCase) != -1 &&
                    designTimeFacades.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }

                if (ignoredRefs != null && ignoredRefs.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }
                
                if (!File.Exists(path))
                {
                    Log.LogError($"Reference {path} does not exist.");
                    continue;
                }

                var dependencyGeneration = _generations.DetermineGenerationFromFile(path, Log, candidateRefs: candidateRefs, ignoredRefs: ignoredRefs) ?? FrameworkConstants.CommonFrameworks.DotNet.Version;

                if (dependencyGeneration > fx.Version)
                {
                    Log.LogError($"Dependency {path} is generation {dependencyGeneration} which is greater than project generation {fx.Version}.");
                }
                
                if (dependencyGeneration > idealGeneration)
                {
                    idealGeneration = dependencyGeneration;
                }
            }

            if (fx.Version > idealGeneration)
            {
                Log.LogMessage(LogImportance.Low, $"Generation {fx.Version} is higher than the ideal miniumum {idealGeneration}.");
            }


            return !Log.HasLoggedErrors;
        }
示例#9
0
        /* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks,
         * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */
        public override bool Execute()
        {
            if (null == Dependencies)
            {
                Log.LogError("Dependencies argument must be specified");
                return(false);
            }
            if (null == FrameworkListsPath)
            {
                Log.LogError("FrameworkListsPath argument must be specified");
                return(false);
            }

            // Retrieve the list of generation dependency group TFM's
            Dictionary <string, IEnumerable <ITaskItem> > portableDependencyGroups = new Dictionary <string, IEnumerable <ITaskItem> >();

            foreach (ITaskItem dependency in Dependencies)
            {
                string framework = dependency.GetMetadata("TargetFramework");
                if (framework != null && FrameworkUtilities.IsGenerationMoniker(framework) && !portableDependencyGroups.ContainsKey(framework))
                {
                    portableDependencyGroups.Add(framework, Dependencies.Where(d => d.GetMetadata("TargetFramework") == framework));
                }
            }

            List <ITaskItem> addedDependencies     = new List <ITaskItem>();
            List <string>    placeHolderFrameworks = new List <string>();

            var frameworksToExclude = TrimFrameworks?.Select(fx => NuGetFramework.Parse(fx))?.ToArray() ?? new NuGetFramework[0];

            // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package
            PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray();
            var           packagePaths = packageItems.Select(pi => pi.TargetPath);
            var           targetFrameworksWithPlaceHolders = packageItems.Where(pi => NuGetAssetResolver.IsPlaceholder(pi.TargetPath)).Select(pi => pi.TargetFramework);

            NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths);

            foreach (string portableDependency in portableDependencyGroups.Keys)
            {
                NuGetFramework portableDependencyFramework = NuGetFramework.Parse(portableDependency);

                // Determine inbox frameworks for this generations dependencies as a whole
                HashSet <NuGetFramework> inboxFrameworksList = new HashSet <NuGetFramework>();

                foreach (NuGetFramework inboxFramework in Frameworks.GetAlllInboxFrameworks(FrameworkListsPath))
                {
                    if (Generations.DetermineGenerationForFramework(inboxFramework, UseNetPlatform) >= portableDependencyFramework.Version &&
                        !frameworksToExclude.Contains(inboxFramework))
                    {
                        inboxFrameworksList.Add(inboxFramework);
                    }
                }

                // Only add the lowest version for a particular inbox framework.  EG if both net45 and net46 are supported by this generation,
                //        only add net45
                inboxFrameworksList.RemoveWhere(fx => inboxFrameworksList.Any(otherFx => (otherFx.Framework.Equals(fx.Framework)) && (otherFx.Version < fx.Version)));

                // Check for assets which have a ref, but not a lib asset. If we have any of these, then they are actually not supported frameworks
                // and we should not include them.
                inboxFrameworksList.RemoveWhere(inboxFx => !IsSupported(inboxFx, resolver));

                // Remove the frameworks which have placeholders.
                inboxFrameworksList.RemoveWhere(fx => targetFrameworksWithPlaceHolders.Any(tfx => tfx != null && fx.DotNetFrameworkName == tfx.DotNetFrameworkName));

                // Create dependency items for each inbox framework.
                foreach (string framework in inboxFrameworksList.Select(fx => fx.GetShortFolderName()))
                {
                    bool addedDependencyToFramework = false;
                    foreach (ITaskItem dependency in portableDependencyGroups[portableDependency])
                    {
                        // If we don't have the AssemblyVersion metadata (4 part version string), fall back and use Version (3 part version string)
                        string version = dependency.GetMetadata("AssemblyVersion");
                        if (string.IsNullOrEmpty(version))
                        {
                            version = dependency.GetMetadata("Version");

                            int prereleaseIndex = version.IndexOf('-');
                            if (prereleaseIndex != -1)
                            {
                                version = version.Substring(0, prereleaseIndex);
                            }
                        }
                        if (!Frameworks.IsInbox(FrameworkListsPath, framework, dependency.ItemSpec, version))
                        {
                            addedDependencyToFramework = true;
                            TaskItem dependencyItem = new TaskItem(dependency);
                            dependencyItem.SetMetadata("TargetFramework", framework);
                            // "Generation" is not required metadata, we just include it because it can be useful for debugging.
                            dependencyItem.SetMetadata("Generation", portableDependency);
                            addedDependencies.Add(dependencyItem);
                        }
                    }
                    if (!addedDependencyToFramework)
                    {
                        TaskItem dependencyItem = new TaskItem("_._");
                        dependencyItem.SetMetadata("TargetFramework", framework);
                        // "Generation" is not required metadata, we just include it because it can be useful for debugging.
                        dependencyItem.SetMetadata("Generation", portableDependency);
                        addedDependencies.Add(dependencyItem);
                        placeHolderFrameworks.Add(framework);
                    }
                }
            }

            // Collapse frameworks
            // For any dependency with a targetframework, if there is another target framework which is compatible and older, remove this dependency.

            // Get all Dependencies which are not in a portable dependency group so that we can collapse the frameworks.  If we include
            // the portable frameworks, then we'll end up collapsing to those.
            List <NuGetFramework> allDependencyGroups = new List <NuGetFramework>();

            allDependencyGroups.AddRange(Dependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) &&
                                                                                                                                !FrameworkUtilities.IsGenerationMoniker(a) &&
                                                                                                                                !FrameworkUtilities.IsPortableMoniker(a)));
            allDependencyGroups.AddRange(addedDependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) &&
                                                                                                                                     !FrameworkUtilities.IsGenerationMoniker(a) &&
                                                                                                                                     !FrameworkUtilities.IsPortableMoniker(a)));

            List <NuGetFramework> collapsedDependencyGroups = FrameworkUtilities.ReduceDownwards(allDependencyGroups).ToList <NuGetFramework>();

            // Get the list of dependency groups that we collapsed down so that we can add them back if they contained different dependencies than what is present in the collapsed group.

            /* TODO: Look into NuGet's sorting algorithm, they may have a bug (fixed in this line). They were not including version in the sort.
             *       See ReduceCore in https://github.com/NuGet/NuGet.Client/blob/23ea68b91a439fcfd7f94bcd01bcdee2e8adae92/src/NuGet.Core/NuGet.Frameworks/FrameworkReducer.cs */
            IEnumerable <NuGetFramework> removedDependencyGroups = allDependencyGroups.Where(d => !collapsedDependencyGroups.Contains(d))?.OrderBy(f => f.Framework, StringComparer.OrdinalIgnoreCase).ThenBy(f => f.Version);

            foreach (NuGetFramework removedDependencyGroup in removedDependencyGroups)
            {
                // always recalculate collapsedDependencyGroups in case we added an item in a previous iteration.  Dependency groups are sorted, so this should be additive and we shouldn't need to restart the collapse / add back cycle
                var nearest = FrameworkUtilities.GetNearest(removedDependencyGroup, collapsedDependencyGroups.ToArray());

                // gather the dependencies for this dependency group and the calculated "nearest" dependency group
                var nearestDependencies = addedDependencies.Where(d => nearest.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString());
                var currentDependencies = addedDependencies.Where(d => removedDependencyGroup.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString());

                // The nearest dependency group's dependencies are different than this dependency group's dependencies
                if (nearestDependencies.Count() != currentDependencies.Count())
                {
                    // ignore if dependency is a placeholder
                    if (currentDependencies.Count() > 0)
                    {
                        if (!NuGetAssetResolver.IsPlaceholder(currentDependencies.First().ToString()))
                        {
                            collapsedDependencyGroups.Add(removedDependencyGroup);
                        }
                    }
                    else
                    {
                        collapsedDependencyGroups.Add(removedDependencyGroup);
                    }
                }
                // identical dependency count between current and nearest, and the count is > 0
                else if (nearestDependencies.Count() > 0)
                {
                    if (!currentDependencies.SequenceEqual(nearestDependencies, new DependencyITaskItemComparer()))
                    {
                        collapsedDependencyGroups.Add(removedDependencyGroup);
                    }
                }
            }


            List <ITaskItem> collapsedDependencies = new List <ITaskItem>();

            foreach (ITaskItem dependency in addedDependencies)
            {
                if (collapsedDependencyGroups.Contains(NuGetFramework.Parse(dependency.GetMetadata("TargetFramework"))))
                {
                    collapsedDependencies.Add(dependency);
                }
            }
            TrimmedDependencies = collapsedDependencies.ToArray();

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            if (String.IsNullOrEmpty(PackageTargetFramework))
            {
                Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework is not defined");
                return true;
            }

            NuGetFramework fx = null;
            try
            {
                fx = NuGetFramework.Parse(PackageTargetFramework);
            }
            catch(Exception ex)
            {
                Log.LogError($"Could not parse PackageTargetFramework {PackageTargetFramework}. {ex}");
                return false;
            }

            Version assemblyVersion = null;
            if (!Version.TryParse(AssemblyVersion, out assemblyVersion))
            {
                Log.LogError($"Could not parse AssemblyVersion {AssemblyVersion}.");
                return false;
            }

            if (UseNetPlatform)
            {
                if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetStandard)
                {
                    Log.LogError($"Validating for legacy 'dotnet' moniker but package targets new 'netstandard' moniker.");
                    return false;
                }
                else if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetPlatform)
                {
                    Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetPlatform}");
                    return true;
                }
            }
            else
            {
                if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetPlatform)
                {
                    if (fx.Version > new Version(5, 0))
                    {
                        NuGetFramework netstandardFx = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.NetStandard, new Version(fx.Version.Major - 4, fx.Version.Minor - 1));
                        Log.LogError($"{fx.GetShortFolderName()} is no longer supported please update to {netstandardFx.GetShortFolderName()}.  Validating as {netstandardFx.GetShortFolderName()}.");
                        // update to netstandard so that we can get the right number of errors
                        fx = netstandardFx;
                    }
                    else
                    {
                        Log.LogError($"Invalid framework version {fx.GetShortFolderName()} please update to appropriate netstandard version.");
                        // update to nestandard so that we'll do the actual calculation
                        fx = FrameworkConstants.CommonFrameworks.NetStandard;
                    }
                }


                if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetStandard)
                {
                    Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetStandard}");
                    return true;
                }
            }

            _generations = Generations.Load(GenerationDefinitionsFile, UseNetPlatform);

            Dictionary<string, string> candidateRefs = CandidateReferences.ToDictionary(r => r.GetMetadata("FileName"), r => r.GetMetadata("FullPath"));

            Version idealGeneration = _generations.DetermineGenerationFromSeeds(AssemblyName, assemblyVersion, Log) ?? new Version(0, 0, 0, 0);
            if (idealGeneration > fx.Version)
            {
                Log.LogError($"Assembly {AssemblyName}, Version={assemblyVersion} is generation {idealGeneration} based on the seed data in {GenerationDefinitionsFile} which is greater than project generation {fx.Version}.");
            }

            HashSet<string> ignoredRefs = null;

            if (IgnoredReferences != null)
            {
                ignoredRefs = new HashSet<string>(IgnoredReferences.Select(ir => ir.ItemSpec), StringComparer.OrdinalIgnoreCase);
            }

            Version defaultGeneration = UseNetPlatform ? FrameworkConstants.CommonFrameworks.DotNet.Version : FrameworkConstants.CommonFrameworks.NetStandard.Version;

            foreach (var reference in DirectReferences)
            {
                string path = reference.GetMetadata("FullPath");

                // workaround issue where portable targeting pack design time facades
                // include dangling refs and refs to higher versions of contracts than 
                // exist in the targeting pack.
                if (path.IndexOf(".NETPortable", StringComparison.OrdinalIgnoreCase) != -1 &&
                    designTimeFacades.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }

                if (ignoredRefs != null && ignoredRefs.Contains(Path.GetFileNameWithoutExtension(path)))
                {
                    continue;
                }
                
                if (!File.Exists(path))
                {
                    Log.LogError($"Reference {path} does not exist.");
                    continue;
                }

                var dependencyGeneration = _generations.DetermineGenerationFromFile(path, Log, candidateRefs: candidateRefs, ignoredRefs: ignoredRefs) ?? defaultGeneration;

                if (dependencyGeneration > fx.Version)
                {
                    Log.LogError($"Dependency {path} is generation {dependencyGeneration} which is greater than project generation {fx.Version}.");
                }
                
                if (dependencyGeneration > idealGeneration)
                {
                    idealGeneration = dependencyGeneration;
                }
            }

            if (fx.Version > idealGeneration)
            {
                Log.LogMessage(LogImportance.Low, $"Generation {fx.Version} is higher than the ideal miniumum {idealGeneration}.");
            }


            return !Log.HasLoggedErrors;
        }