/// <summary>
        /// Given a list of packages, this function will print them in a table
        /// </summary>
        /// <param name="packages">The list of packages</param>
        /// <param name="printingTransitive">Whether the function is printing transitive packages information.</param>
        /// <param name="listPackageArgs">Command line options.</param>
        /// <param name="tableHasAutoReference">Flagged if an autoreference marker was printer</param>
        /// <returns>The table as a string</returns>
        internal static IEnumerable <FormattedCell> BuildPackagesTable(
            IEnumerable <InstalledPackageReference> packages,
            bool printingTransitive,
            ListPackageArgs listPackageArgs,
            ref bool tableHasAutoReference)
        {
            var autoReferenceFlagged = false;

            if (!packages.Any())
            {
                return(null);
            }

            packages = packages.OrderBy(p => p.Name);

            var headers = BuildTableHeaders(printingTransitive, listPackageArgs);

            var valueSelectors = new List <Func <InstalledPackageReference, object> >
            {
                p => new FormattedCell(p.Name),
                p => new FormattedCell(GetAutoReferenceMarker(p, printingTransitive, ref autoReferenceFlagged)),
            };

            // Include "Requested" version column for top level package list
            if (!printingTransitive)
            {
                valueSelectors.Add(p => new FormattedCell(p.OriginalRequestedVersion));
            }

            // "Resolved" version
            valueSelectors.Add(p => new FormattedCell(GetPackageVersion(p)));

            switch (listPackageArgs.ReportType)
            {
            case ReportType.Outdated:
                // "Latest" version
                valueSelectors.Add(p => new FormattedCell(GetPackageVersion(p, useLatest: true)));
                break;

            case ReportType.Deprecated:
                valueSelectors.Add(p => new FormattedCell(
                                       PrintDeprecationReasons(p.ResolvedPackageMetadata.GetDeprecationMetadataAsync().Result)));
                valueSelectors.Add(p => new FormattedCell(
                                       PrintAlternativePackage((p.ResolvedPackageMetadata.GetDeprecationMetadataAsync().Result)?.AlternatePackage)));
                break;

            case ReportType.Vulnerable:
                valueSelectors.Add(p => PrintVulnerabilitiesSeverities(p.ResolvedPackageMetadata.Vulnerabilities));
                valueSelectors.Add(p => PrintVulnerabilitiesAdvisoryUrls(p.ResolvedPackageMetadata.Vulnerabilities));
                break;
            }


            var tableToPrint = packages.ToStringTable(headers, valueSelectors.ToArray());

            tableHasAutoReference = autoReferenceFlagged;
            return(tableToPrint);
        }
            public void FiltersFrameworkPackagesCollectionWithOutdatedMetadata(
                bool includeTopLevelPositives,
                bool includeTransitivePositives)
            {
                // Arrange
                var packages         = new FrameworkPackages("net40");
                var topLevelPackages =
                    new List <InstalledPackageReference>
                {
                    ListPackageTestHelper.CreateInstalledPackageReference(resolvedPackageVersionString: "2.0.0",
                                                                          latestPackageVersionString: "2.0.0")
                };
                var transitivePackages =
                    new List <InstalledPackageReference>
                {
                    ListPackageTestHelper.CreateInstalledPackageReference(resolvedPackageVersionString: "2.0.0",
                                                                          latestPackageVersionString: "2.0.0")
                };

                if (includeTopLevelPositives)
                {
                    topLevelPackages.Add(ListPackageTestHelper.CreateInstalledPackageReference(
                                             resolvedPackageVersionString: "2.0.0", latestPackageVersionString: "3.0.0"));
                }

                if (includeTransitivePositives)
                {
                    transitivePackages.Add(ListPackageTestHelper.CreateInstalledPackageReference(
                                               resolvedPackageVersionString: "2.0.0", latestPackageVersionString: "3.0.0"));
                }

                packages.TopLevelPackages   = topLevelPackages;
                packages.TransitivePackages = transitivePackages;
                var allPackages = new List <FrameworkPackages> {
                    packages
                };
                var listPackageArgs = new ListPackageArgs(path: "", packageSources: Enumerable.Empty <PackageSource>(),
                                                          frameworks: Enumerable.Empty <string>(),
                                                          ReportType.Outdated,
                                                          includeTransitive: true, prerelease: false, highestPatch: false, highestMinor: false,
                                                          logger: new Mock <ILogger>().Object,
                                                          CancellationToken.None);

                // Act
                var isFilteredSetNonEmpty = ListPackageCommandRunner.FilterPackages(allPackages, listPackageArgs);

                // Assert
                Assert.Equal(includeTopLevelPositives || includeTransitivePositives, isFilteredSetNonEmpty);
                Assert.Equal(includeTopLevelPositives ? 1 : 0, allPackages.First().TopLevelPackages.Count());
                Assert.Equal(includeTransitivePositives ? 1 : 0, allPackages.First().TransitivePackages.Count());
            }
        /// <summary>
        /// Prepares the headers for the tables that will be printed
        /// </summary>
        /// <param name="printingTransitive">Whether the table is for transitive or not</param>
        /// <param name="listPackageArgs">Command line options</param>
        /// <returns></returns>
        internal static string[] BuildTableHeaders(bool printingTransitive, ListPackageArgs listPackageArgs)
        {
            var result = new List <string>();

            if (printingTransitive)
            {
                result.Add(Strings.ListPkg_TransitiveHeader);
                result.Add(string.Empty);
            }
            else
            {
                result.Add(Strings.ListPkg_TopLevelHeader);
                result.Add(string.Empty);
                result.Add(Strings.ListPkg_Requested);
            }

            result.Add(Strings.ListPkg_Resolved);

            switch (listPackageArgs.ReportType)
            {
            case ReportType.Outdated:
                result.Add(Strings.ListPkg_Latest);
                break;

            case ReportType.Deprecated:
                result.Add(Strings.ListPkg_DeprecationReasons);
                result.Add(Strings.ListPkg_DeprecationAlternative);
                break;

            case ReportType.Vulnerable:
                result.Add(Strings.ListPkg_VulnerabilitySeverity);
                result.Add(Strings.ListPkg_VulnerabilityAdvisoryUrl);
                break;
            }

            return(result.ToArray());
        }
        /// <summary>
        /// A function that prints all the package references of a project
        /// </summary>
        /// <param name="packages">A list of framework packages. Check <see cref="FrameworkPackages"/></param>
        /// <param name="projectName">The project name</param>
        /// <param name="listPackageArgs">Command line options</param>
        /// <param name="hasAutoReference">At least one discovered package is autoreference</param>
        internal static void PrintPackages(
            IEnumerable <FrameworkPackages> packages, string projectName, ListPackageArgs listPackageArgs, ref bool hasAutoReference)
        {
            switch (listPackageArgs.ReportType)
            {
            case ReportType.Outdated:
                Console.WriteLine(string.Format(Strings.ListPkg_ProjectUpdatesHeaderLog, projectName));
                break;

            case ReportType.Deprecated:
                Console.WriteLine(string.Format(Strings.ListPkg_ProjectDeprecationsHeaderLog, projectName));
                break;

            case ReportType.Vulnerable:
                Console.WriteLine(string.Format(Strings.ListPkg_ProjectVulnerabilitiesHeaderLog, projectName));
                break;

            case ReportType.Default:
                Console.WriteLine(string.Format(Strings.ListPkg_ProjectHeaderLog, projectName));
                break;
            }

            hasAutoReference = false;
            foreach (var frameworkPackages in packages)
            {
                var frameworkTopLevelPackages   = frameworkPackages.TopLevelPackages;
                var frameworkTransitivePackages = frameworkPackages.TransitivePackages;

                // If no packages exist for this framework, print the
                // appropriate message
                if (!frameworkTopLevelPackages.Any() && !frameworkTransitivePackages.Any())
                {
                    Console.ForegroundColor = ConsoleColor.Blue;

                    switch (listPackageArgs.ReportType)
                    {
                    case ReportType.Outdated:
                        Console.WriteLine(string.Format("   [{0}]: " + Strings.ListPkg_NoUpdatesForFramework, frameworkPackages.Framework));
                        break;

                    case ReportType.Deprecated:
                        Console.WriteLine(string.Format("   [{0}]: " + Strings.ListPkg_NoDeprecationsForFramework, frameworkPackages.Framework));
                        break;

                    case ReportType.Vulnerable:
                        Console.WriteLine(string.Format("   [{0}]: " + Strings.ListPkg_NoVulnerabilitiesForFramework, frameworkPackages.Framework));
                        break;

                    case ReportType.Default:
                        Console.WriteLine(string.Format("   [{0}]: " + Strings.ListPkg_NoPackagesForFramework, frameworkPackages.Framework));
                        break;
                    }

                    Console.ResetColor();
                }
                else
                {
                    // Print name of the framework
                    Console.ForegroundColor = ConsoleColor.Blue;
                    Console.WriteLine(string.Format("   [{0}]: ", frameworkPackages.Framework));
                    Console.ResetColor();

                    // Print top-level packages
                    if (frameworkTopLevelPackages.Any())
                    {
                        var tableHasAutoReference = false;
                        var tableToPrint          = BuildPackagesTable(
                            frameworkTopLevelPackages, printingTransitive: false, listPackageArgs, ref tableHasAutoReference);
                        if (tableToPrint != null)
                        {
                            PrintPackagesTable(tableToPrint);
                            hasAutoReference = hasAutoReference || tableHasAutoReference;
                        }
                    }

                    // Print transitive packages
                    if (listPackageArgs.IncludeTransitive && frameworkTransitivePackages.Any())
                    {
                        var tableHasAutoReference = false;
                        var tableToPrint          = BuildPackagesTable(
                            frameworkTransitivePackages, printingTransitive: true, listPackageArgs, ref tableHasAutoReference);
                        if (tableToPrint != null)
                        {
                            PrintPackagesTable(tableToPrint);
                            hasAutoReference = hasAutoReference || tableHasAutoReference;
                        }
                    }
                }
            }
        }