/// <summary>
        ///     Build and return a list of Sarif Result list from the find characterstics results
        /// </summary>
        /// <param name="purl"> </param>
        /// <param name="results"> </param>
        /// <returns> </returns>
        private static List <SarifResult> GetSarifResults(PackageURL purl, Dictionary <string, AnalyzeResult?> analysisResult, Options opts)
        {
            List <SarifResult> sarifResults = new List <SarifResult>();

            if (analysisResult.HasAtLeastOneNonNullValue())
            {
                foreach (var key in analysisResult.Keys)
                {
                    var metadata = analysisResult?[key]?.Metadata;

                    foreach (var result in metadata?.Matches ?? new List <MatchRecord>())
                    {
                        var individualResult = new SarifResult()
                        {
                            Message = new Message()
                            {
                                Text = result.RuleDescription,
                                Id   = result.RuleId
                            },
                            Kind      = ResultKind.Informational,
                            Level     = opts.SarifLevel,
                            Locations = SarifOutputBuilder.BuildPurlLocation(purl),
                            Rule      = new ReportingDescriptorReference()
                            {
                                Id = result.RuleId
                            },
                        };

                        individualResult.SetProperty("Severity", result.Severity);
                        individualResult.SetProperty("Confidence", result.Confidence);

                        individualResult.Locations.Add(new CodeAnalysis.Sarif.Location()
                        {
                            PhysicalLocation = new PhysicalLocation()
                            {
                                Address = new Address()
                                {
                                    FullyQualifiedName = result.FileName
                                },
                                Region = new Region()
                                {
                                    StartLine      = result.StartLocationLine,
                                    EndLine        = result.EndLocationLine,
                                    StartColumn    = result.StartLocationColumn,
                                    EndColumn      = result.EndLocationColumn,
                                    SourceLanguage = result.Language,
                                    Snippet        = new ArtifactContent()
                                    {
                                        Text     = result.Excerpt,
                                        Rendered = new MultiformatMessageString(result.Excerpt, $"`{result.Excerpt}`", null)
                                    }
                                }
                            }
                        });

                        sarifResults.Add(individualResult);
                    }
                }
            }
            return(sarifResults);
        }
        public async Task <List <Dictionary <string, AnalyzeResult?> > > RunAsync(Options options)
        {
            // select output destination and format
            SelectOutput(options.OutputFile);
            IOutputBuilder outputBuilder = SelectFormat(options.Format);

            var finalResults = new List <Dictionary <string, AnalyzeResult?> >();

            if (options.Targets is IList <string> targetList && targetList.Count > 0)
            {
                foreach (var target in targetList)
                {
                    try
                    {
                        if (target.StartsWith("pkg:"))
                        {
                            var    purl = new PackageURL(target);
                            string downloadDirectory = options.DownloadDirectory == "." ? Directory.GetCurrentDirectory() : options.DownloadDirectory;
                            var    analysisResult    = await AnalyzePackage(options, purl,
                                                                            downloadDirectory,
                                                                            options.UseCache == true);

                            AppendOutput(outputBuilder, purl, analysisResult, options);
                            finalResults.Add(analysisResult);
                        }
                        else if (Directory.Exists(target))
                        {
                            var analysisResult = await AnalyzeDirectory(options, target);

                            if (analysisResult != null)
                            {
                                var analysisResults = new Dictionary <string, AnalyzeResult?>()
                                {
                                    { target, analysisResult }
                                };
                                var purl = new PackageURL("generic", target);
                                AppendOutput(outputBuilder, purl, analysisResults, options);
                            }
                            finalResults.Add(new Dictionary <string, AnalyzeResult?>()
                            {
                                { target, analysisResult }
                            });
                        }
                        else if (File.Exists(target))
                        {
                            var analysisResult = await AnalyzeFile(options, target);

                            if (analysisResult != null)
                            {
                                var analysisResults = new Dictionary <string, AnalyzeResult?>()
                                {
                                    { target, analysisResult }
                                };
                                var purl = new PackageURL("generic", target);
                                AppendOutput(outputBuilder, purl, analysisResults, options);
                            }
                            finalResults.Add(new Dictionary <string, AnalyzeResult?>()
                            {
                                { target, analysisResult }
                            });
                        }
                        else
                        {
                            Logger.Warn("Package or file identifier was invalid.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Warn(ex, "Error processing {0}: {1}", target, ex.Message);
                    }
                }
                outputBuilder.PrintOutput();
            }

            RestoreOutput();
            return(finalResults);
        }
        /// <summary>
        ///     Analyze a package by downloading it first.
        /// </summary>
        /// <param name="purl"> The package-url of the package to analyze. </param>
        /// <returns> List of tags identified </returns>
        public async Task <Dictionary <string, AnalyzeResult?> > AnalyzePackage(Options options, PackageURL purl,
                                                                                string?targetDirectoryName,
                                                                                bool doCaching = false)
        {
            Logger.Trace("AnalyzePackage({0})", purl.ToString());

            var analysisResults = new Dictionary <string, AnalyzeResult?>();

            var packageDownloader = new PackageDownloader(purl, targetDirectoryName, doCaching);
            // ensure that the cache directory has the required package, download it otherwise
            var directoryNames = await packageDownloader.DownloadPackageLocalCopy(purl,
                                                                                  false,
                                                                                  true);

            if (directoryNames.Count > 0)
            {
                foreach (var directoryName in directoryNames)
                {
                    var singleResult = await AnalyzeDirectory(options, directoryName);

                    analysisResults[directoryName] = singleResult;
                }
            }
            else
            {
                Logger.Warn("Error downloading {0}.", purl.ToString());
            }
            packageDownloader.ClearPackageLocalCopyIfNoCaching();
            return(analysisResults);
        }