Пример #1
0
 private static FrameworkSet GetInboxFrameworks(string frameworkListsPath)
 {
     if (s_inboxFrameworks == null)
     {
         s_inboxFrameworks = FrameworkSet.Load(frameworkListsPath);
     }
     return(s_inboxFrameworks);
 }
Пример #2
0
        public static bool IsInbox(string frameworkListsPath, NuGetFramework framework, string assemblyName, string assemblyVersion)
        {
            if (framework.Framework == FrameworkConstants.FrameworkIdentifiers.UAP ||
                (framework.Framework == FrameworkConstants.FrameworkIdentifiers.NetCore && framework.Version >= FrameworkConstants.CommonFrameworks.NetCore50.Version))
            {
                // UAP & netcore50 or higher are completely OOB, despite being compatible with netcore4x which has inbox assemblies
                return(false);
            }

            // if no version is specified just use 0.0.0.0 to evaluate for any version of the contract
            Version      version = FrameworkUtilities.Ensure4PartVersion(assemblyVersion);
            FrameworkSet fxs     = GetInboxFrameworks(frameworkListsPath);

            Version latestLegacyVersion = null;

            fxs.LastNonSemanticVersions.TryGetValue(assemblyName, out latestLegacyVersion);

            foreach (var fxVersions in fxs.Frameworks.Values)
            {
                // Get the nearest compatible framework from this set of frameworks.
                var nearest = FrameworkUtilities.GetNearest(framework, fxVersions.Select(fx => NuGetFramework.Parse(fx.ShortName)).ToArray());
                // If there are not compatible frameworks in the current framework set, there is not going to be a match.
                if (nearest == null)
                {
                    continue;
                }

                // don't allow PCL to specify inbox for non-PCL framework.
                if (nearest.IsPCL != framework.IsPCL)
                {
                    continue;
                }

                // find the first version (if any) that supports this contract
                foreach (var fxVersion in fxVersions)
                {
                    Version supportedVersion;
                    if (fxVersion.Assemblies.TryGetValue(assemblyName, out supportedVersion))
                    {
                        if (supportedVersion >= version)
                        {
                            return(true);
                        }

                        // new versions represent API surface via major.minor only, so consider
                        // a contract as supported so long as the latest legacy version is supported
                        // and this contract's major.minor match the latest legacy version.
                        if (supportedVersion == latestLegacyVersion &&
                            version.Major == latestLegacyVersion.Major && version.Minor == latestLegacyVersion.Minor)
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Пример #3
0
        public static bool IsInbox(string frameworkListsPath, string framework, string assemblyName, string assemblyVersion)
        {
            // if no version is specified just use 0.0.0.0 to evaluate for any version of the contract
            Version      version = FrameworkUtilities.Ensure4PartVersion(String.IsNullOrEmpty(assemblyVersion) ? new Version(0, 0, 0, 0) : new Version(assemblyVersion));
            FrameworkSet fxs     = GetInboxFrameworks(frameworkListsPath);

            Version latestLegacyVersion = null;

            fxs.LastNonSemanticVersions.TryGetValue(assemblyName, out latestLegacyVersion);

            foreach (var fxVersions in fxs.Frameworks.Values)
            {
                // Get the nearest compatible framework from this set of frameworks.
                var nearest = FrameworkUtilities.GetNearest(NuGetFramework.Parse(framework), fxVersions.Select(fx => NuGetFramework.Parse(fx.ShortName)).ToArray());
                // If there are not compatible frameworks in the current framework set, there is not going to be a match.
                if (nearest == null)
                {
                    continue;
                }
                var origFramework = NuGetFramework.Parse(framework);
                // if the nearest compatible frameworks version is greater than the version of the framework we are looking for, this is not going to be a match.
                if (nearest.Version > origFramework.Version)
                {
                    continue;
                }
                // find the first version (if any) that supports this contract
                foreach (var fxVersion in fxVersions)
                {
                    Version supportedVersion;
                    if (fxVersion.Assemblies.TryGetValue(assemblyName, out supportedVersion))
                    {
                        if (supportedVersion >= version)
                        {
                            return(true);
                        }

                        // new versions represent API surface via major.minor only, so consider
                        // a contract as supported so long as the latest legacy version is supported
                        // and this contract's major.minor match the latest legacy version.
                        if (supportedVersion == latestLegacyVersion &&
                            version.Major == latestLegacyVersion.Major && version.Minor == latestLegacyVersion.Minor)
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Пример #4
0
        public static string[] GetInboxFrameworksList(string frameworkListsPath, string assemblyName, string assemblyVersion, ILog log)
        {
            // if no version is specified just use 0.0.0.0 to evaluate for any version of the contract
            Version version = String.IsNullOrEmpty(assemblyVersion) ? new Version(0, 0, 0, 0) : new Version(assemblyVersion);

            FrameworkSet fxs = GetInboxFrameworks(frameworkListsPath);

            Version latestLegacyVersion = null;

            fxs.LastNonSemanticVersions.TryGetValue(assemblyName, out latestLegacyVersion);

            List <string> inboxIds = new List <string>();

            foreach (var fxVersions in fxs.Frameworks.Values)
            {
                // find the first version (if any) that supports this contract
                foreach (var fxVersion in fxVersions)
                {
                    Version supportedVersion;
                    if (fxVersion.Assemblies.TryGetValue(assemblyName, out supportedVersion))
                    {
                        if (supportedVersion >= version)
                        {
                            if (log != null)
                            {
                                log.LogMessage(LogImportance.Low, "inbox on {0}", fxVersion.ShortName);
                            }
                            inboxIds.Add(fxVersion.ShortName);
                            break;
                        }

                        // new versions represent API surface via major.minor only, so consider
                        // a contract as supported so long as the latest legacy version is supported
                        // and this contract's major.minor match the latest legacy version.
                        if (supportedVersion == latestLegacyVersion &&
                            version.Major == latestLegacyVersion.Major && version.Minor == latestLegacyVersion.Minor)
                        {
                            if (log != null)
                            {
                                log.LogMessage(LogImportance.Low, "Considering {0},Version={1} inbox on {2}, since it only differs in revsion.build from {3}", assemblyName, assemblyVersion, fxVersion.ShortName, latestLegacyVersion);
                            }
                            inboxIds.Add(fxVersion.ShortName);
                            break;
                        }
                    }
                }
            }
            return(inboxIds.ToArray());
        }
Пример #5
0
        public static FrameworkSet Load(string frameworkListsPath)
        {
            FrameworkSet result;

            if (s_frameworkSetCache.TryGetValue(frameworkListsPath, out result))
            {
                return(result);
            }

            result = new FrameworkSet();

            foreach (string fxDir in Directory.EnumerateDirectories(frameworkListsPath))
            {
                string    targetName = Path.GetFileName(fxDir);
                Framework framework  = new Framework(targetName);
                foreach (string frameworkListPath in Directory.EnumerateFiles(fxDir, "*.xml"))
                {
                    AddAssembliesFromFrameworkList(framework.Assemblies, frameworkListPath);
                }

                SortedSet <Framework> frameworkVersions = null;
                string fxId = framework.FrameworkName.Identifier;

                if (fxId == FrameworkConstants.FrameworkIdentifiers.Portable)
                {
                    // portable doesn't have version relationships, use the entire TFM
                    fxId = framework.FrameworkName.ToString();
                }

                if (!result.Frameworks.TryGetValue(fxId, out frameworkVersions))
                {
                    frameworkVersions = new SortedSet <Framework>();
                }

                frameworkVersions.Add(framework);

                result.Frameworks[fxId] = frameworkVersions;
            }

            string lastNonSemanticVersionsListPath = Path.Combine(frameworkListsPath, LastNonSemanticVersionsFileName);

            AddAssembliesFromFrameworkList(result.LastNonSemanticVersions, lastNonSemanticVersionsListPath);

            lock (s_frameworkSetCacheLock)
            {
                s_frameworkSetCache[frameworkListsPath] = result;
            }
            return(result);
        }
Пример #6
0
        internal static IEnumerable <NuGetFramework> GetAlllInboxFrameworks(string frameworkListsPath)
        {
            FrameworkSet fxs = FrameworkSet.Load(frameworkListsPath);

            return(fxs.Frameworks.SelectMany(fxList => fxList.Value).Select(fx => NuGetFramework.Parse(fx.ShortName)));
        }
Пример #7
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
                    });
                }
            }
        }
Пример #8
0
        private void LoadFrameworks()
        {
            _frameworks = new Dictionary <NuGetFramework, string[]>(NuGetFramework.Comparer);

            // load the specified frameworks
            foreach (var framework in Frameworks)
            {
                var runtimeIds = framework.GetMetadata("RuntimeIDs")?.Split(';');

                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;
                }

                _frameworks.Add(fx, runtimeIds);
            }

            // inspect any TFMs explicitly targeted
            var fileFrameworks = _targetPathToPackageItem.Values.Select(f => f.TargetFramework).Distinct(NuGetFramework.Comparer).Where(f => f != null);

            foreach (var fileFramework in fileFrameworks)
            {
                if (!_frameworks.ContainsKey(fileFramework))
                {
                    _frameworks.Add(fileFramework, s_noRids);
                }
            }

            // inspect any TFMs inbox
            var frameworkData   = FrameworkSet.Load(FrameworkListsPath);
            var inboxFrameworks = frameworkData.Frameworks.SelectMany(f => f.Value)
                                  .Where(fx => fx.Assemblies.ContainsKey(PackageId))
                                  .Select(fx => NuGetFramework.Parse(fx.FrameworkName.FullName));

            foreach (var inboxFramework in inboxFrameworks)
            {
                if (!_frameworks.ContainsKey(inboxFramework))
                {
                    _frameworks.Add(inboxFramework, s_noRids);
                }
            }

            // inspect for derived TFMs
            var expander = new FrameworkExpander();

            foreach (var framework in _frameworks.Keys.ToArray())
            {
                var derivedFxs = expander.Expand(framework);

                foreach (var derivedFx in derivedFxs)
                {
                    if (derivedFx.IsDesktop() && derivedFx.HasProfile)
                    {
                        // skip desktop profiles
                        continue;
                    }

                    if (derivedFx.Version.Major == 0 && derivedFx.Version.Minor == 0)
                    {
                        // skip unversioned frameworks
                        continue;
                    }

                    if (s_ignoredFrameworks.Contains(derivedFx.Framework))
                    {
                        continue;
                    }

                    if (!_frameworks.ContainsKey(derivedFx))
                    {
                        _frameworks.Add(derivedFx, s_noRids);
                    }
                }
            }
        }
Пример #9
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);
            }
        }