public static async Task <CrawlerResults> CrawlAsync(NuGetFeed feed, PackageIdentity packageId) { ArgumentNullException.ThrowIfNull(feed); ArgumentNullException.ThrowIfNull(packageId); var crawler = new AssemblyCrawler(); using var reader = await feed.GetPackageAsync(packageId).ConfigureAwait(false); foreach (var packagePath in reader.GetFiles()) { #pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task await using var assemblyStream = reader.GetStream(packagePath); await using var memoryStream = new MemoryStream(); #pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task await assemblyStream.CopyToAsync(memoryStream).ConfigureAwait(false); memoryStream.Position = 0; using var env = new HostEnvironment(); var assembly = env.LoadAssemblyFrom(packagePath, memoryStream); if (assembly is null) { continue; } crawler.Crawl(assembly); } return(crawler.CreateResults()); }
public async Task RunAsync(Func <AnalyzeResult, Task> receiver) { var framework = NuGetFramework.ParseFolder(_tfmSelector.DetermineTargetTfmValue()); var platforms = _options.Platform.Select(p => p.ToString().ToLowerInvariant()).ToImmutableList(); async void Receiver(AssemblyResult result) { _logger.LogInformation(Resources.BinaryAnalysisProcessedAssemblyMessageFormat, result.AssemblyName); foreach (var r in CreateUaResults(result).ToList()) { await receiver(r).ConfigureAwait(false); } } var catalog = await CatalogService.LoadCatalogAsync().ConfigureAwait(false); var apiByGuid = catalog.GetAllApis().ToDictionary(a => a.UniqueId); var availabilityContext = ApiAvailabilityContext.Create(catalog); var platformContext = PlatformAnnotationContext.Create(availabilityContext, framework.GetShortFolderName()); foreach (var api in catalog.GetAllApis()) { var forwardedApi = catalog.GetForwardedApi(api); if (forwardedApi is not null) { apiByGuid[api.UniqueId] = forwardedApi.Value; } } var apiAvailability = new ConcurrentDictionary <ApiModel, ApiAvailability>(); using var resultSink = new BlockingCollection <AssemblyResult>(); var resultSinkTask = Task.Run(() => { foreach (var result in resultSink.GetConsumingEnumerable()) { Receiver(result); } }); var filePaths = AssemblyFileSet.Create(_options.Content.ToList()); Parallel.ForEach(filePaths, filePath => { using var env = new HostEnvironment(); var assembly = env.LoadAssemblyFrom(filePath); var assemblyName = assembly is not null ? assembly.Name.Value : Path.GetFileName(filePath); if (assembly is null) { var result = new AssemblyResult(assemblyName, Resources.BinaryAnalysisInvalidAssemblyMessage, Array.Empty <ApiResult>()); resultSink.Add(result); } else { var assemblyTfm = assembly.GetTargetFrameworkMoniker(); var assemblyFramework = string.IsNullOrEmpty(assemblyTfm) ? null : NuGetFramework.Parse(assemblyTfm); var crawler = new AssemblyCrawler(); crawler.Crawl(assembly); var crawlerResults = crawler.CreateResults(); var apiResults = new List <ApiResult>(); var frameworkResultBuilder = new List <FrameworkResult>(); var platformResultBuilder = new List <PlatformResult?>(platforms.Count); foreach (var apiKey in crawlerResults.Data.Keys) { if (apiByGuid.TryGetValue(apiKey.Id, out var api)) { var availability = apiAvailability.GetOrAdd(api, a => availabilityContext.GetAvailability(a)); frameworkResultBuilder.Clear(); AnalyzeAvailability(availability, framework, out AvailabilityResult availabilityResult, out ApiFrameworkAvailability? info); var obsoletionResult = AnalyzeObsoletion(availabilityContext, assemblyFramework, api, info); AnalyzePlatformSupport(platforms, platformContext, frameworkResultBuilder, platformResultBuilder !, api, framework !, availabilityResult, info, obsoletionResult); var apiResult = new ApiResult(api, frameworkResultBuilder.ToArray()); apiResults.Add(apiResult); }