예제 #1
0
    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());
    }
예제 #2
0
        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);
                        }