internal static IVsProjectRestoreInfo Build(IEnumerable <IProjectVersionedValue <IProjectSubscriptionUpdate> > updates,
                                                    UnconfiguredProject project)
        {
            Requires.NotNull(updates, nameof(updates));
            Requires.NotNull(project, nameof(project));

            // if none of the underlying subscriptions have any changes
            if (!updates.Any(u => u.Value.ProjectChanges.Any(c => c.Value.Difference.AnyChanges)))
            {
                return(null);
            }

            string baseIntermediatePath     = null;
            string originalTargetFrameworks = null;
            var    targetFrameworks         = new TargetFrameworks();
            var    toolReferences           = new ReferenceItems();

            foreach (IProjectVersionedValue <IProjectSubscriptionUpdate> update in updates)
            {
                var nugetRestoreChanges = update.Value.ProjectChanges[NuGetRestore.SchemaName];
                baseIntermediatePath = baseIntermediatePath ??
                                       nugetRestoreChanges.After.Properties[NuGetRestore.BaseIntermediateOutputPathProperty];
                originalTargetFrameworks = originalTargetFrameworks ??
                                           nugetRestoreChanges.After.Properties[NuGetRestore.TargetFrameworksProperty];
                bool noTargetFramework =
                    !update.Value.ProjectConfiguration.Dimensions.TryGetValue(NuGetRestore.TargetFrameworkProperty, out string targetFramework) &&
                    !nugetRestoreChanges.After.Properties.TryGetValue(NuGetRestore.TargetFrameworkProperty, out targetFramework);

                if (noTargetFramework || string.IsNullOrEmpty(targetFramework))
                {
                    TraceUtilities.TraceWarning("Unable to find TargetFramework Property");
                    continue;
                }

                if (!targetFrameworks.Contains(targetFramework))
                {
                    var projectReferencesChanges = update.Value.ProjectChanges[ProjectReference.SchemaName];
                    var packageReferencesChanges = update.Value.ProjectChanges[PackageReference.SchemaName];

                    targetFrameworks.Add(new TargetFrameworkInfo
                    {
                        TargetFrameworkMoniker = targetFramework,
                        ProjectReferences      = GetProjectReferences(projectReferencesChanges.After.Items, project),
                        PackageReferences      = GetReferences(packageReferencesChanges.After.Items),
                        Properties             = GetProperties(nugetRestoreChanges.After.Properties)
                    });
                }

                var toolReferencesChanges = update.Value.ProjectChanges[DotNetCliToolReference.SchemaName];
                foreach (var item in toolReferencesChanges.After.Items)
                {
                    if (!toolReferences.Contains(item.Key))
                    {
                        toolReferences.Add(GetReferenceItem(item));
                    }
                }
            }

            // return nominate restore information if any target framework entries are found
            return(targetFrameworks.Any()
                ? new ProjectRestoreInfo
            {
                BaseIntermediatePath = baseIntermediatePath,
                OriginalTargetFrameworks = originalTargetFrameworks,
                TargetFrameworks = targetFrameworks,
                ToolReferences = toolReferences
            }
                : null);
        }
        internal static IVsProjectRestoreInfo Build(IEnumerable <IProjectVersionedValue <IProjectSubscriptionUpdate> > updates)
        {
            Requires.NotNull(updates, nameof(updates));

            // if none of the underlying subscriptions have any changes
            if (!updates.Any(u => u.Value.ProjectChanges.Any(c => c.Value.Difference.AnyChanges)))
            {
                return(null);
            }

            string msbuildProjectExtensionsPath = null;
            string originalTargetFrameworks     = null;
            var    targetFrameworks             = new TargetFrameworks();
            var    toolReferences = new ReferenceItems();

            foreach (IProjectVersionedValue <IProjectSubscriptionUpdate> update in updates)
            {
                IProjectChangeDescription nugetRestoreChanges = update.Value.ProjectChanges[NuGetRestore.SchemaName];
                msbuildProjectExtensionsPath = msbuildProjectExtensionsPath ??
                                               nugetRestoreChanges.After.Properties[NuGetRestore.MSBuildProjectExtensionsPathProperty];
                originalTargetFrameworks = originalTargetFrameworks ??
                                           nugetRestoreChanges.After.Properties[NuGetRestore.TargetFrameworksProperty];
                bool noTargetFramework =
                    !update.Value.ProjectConfiguration.Dimensions.TryGetValue(NuGetRestore.TargetFrameworkProperty, out string targetFramework) &&
                    !nugetRestoreChanges.After.Properties.TryGetValue(NuGetRestore.TargetFrameworkProperty, out targetFramework);

                if (noTargetFramework || string.IsNullOrEmpty(targetFramework))
                {
                    TraceUtilities.TraceWarning("Unable to find TargetFramework Property");
                    continue;
                }

                if (!targetFrameworks.Contains(targetFramework))
                {
                    IProjectChangeDescription projectReferencesChanges = update.Value.ProjectChanges[ProjectReference.SchemaName];
                    IProjectChangeDescription packageReferencesChanges = update.Value.ProjectChanges[PackageReference.SchemaName];

                    targetFrameworks.Add(new TargetFrameworkInfo
                    {
                        TargetFrameworkMoniker = targetFramework,
                        ProjectReferences      = GetProjectReferences(projectReferencesChanges.After.Items),
                        PackageReferences      = GetReferences(packageReferencesChanges.After.Items),
                        Properties             = GetProperties(nugetRestoreChanges.After.Properties)
                    });
                }

                IProjectChangeDescription toolReferencesChanges = update.Value.ProjectChanges[DotNetCliToolReference.SchemaName];
                foreach (KeyValuePair <string, IImmutableDictionary <string, string> > item in toolReferencesChanges.After.Items)
                {
                    if (!toolReferences.Contains(item.Key))
                    {
                        toolReferences.Add(GetReferenceItem(item));
                    }
                }
            }

            // return nominate restore information if any target framework entries are found
            return(targetFrameworks.Any()
                ? new ProjectRestoreInfo
            {
                // NOTE: We pass MSBuildProjectExtensionsPath as BaseIntermediatePath instead of using
                // BaseIntermediateOutputPath. This is because NuGet switched from using BaseIntermediateOutputPath
                // to MSBuildProjectExtensionsPath, since the value of BaseIntermediateOutputPath is often set too
                // late (after *.g.props files would need to have been imported from it). Instead of modifying the
                // IVsProjectRestoreInfo interface or introducing something like IVsProjectRestoreInfo with an
                // MSBuildProjectExtensionsPath property, we opted to leave the interface the same but change the
                // meaning of its BaseIntermediatePath property. See
                // https://github.com/dotnet/project-system/issues/3466for for details.
                BaseIntermediatePath = msbuildProjectExtensionsPath,
                OriginalTargetFrameworks = originalTargetFrameworks,
                TargetFrameworks = targetFrameworks,
                ToolReferences = toolReferences
            }
                : null);
        }