<commit_before>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols.SymbolTree;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.IncrementalCaches;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.SolutionSize;
using Microsoft.CodeAnalysis.Storage;

namespace AnalyzerRunner
{
    internal class IncrementalAnalyzerRunner
    {
        private readonly Options _options;

        public IncrementalAnalyzerRunner(Options options)
        {
            _options = options;
        }

        public bool HasAnalyzers => _options.IncrementalAnalyzerNames.Any();

        internal async Task RunAsync(Workspace workspace, CancellationToken cancellationToken)
        {
            if (!HasAnalyzers)
            {
                return;
            }

            workspace.Options = workspace.Options
                .WithChangedOption(StorageOptions.SolutionSizeThreshold, _options.UsePersistentStorage ? 0 : int.MaxValue)
                .WithChangedOption(RuntimeOptions.FullSolutionAnalysis, _options.FullSolutionAnalysis)
                .WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.CSharp, _options.FullSolutionAnalysis)
                .WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.VisualBasic, _options.FullSolutionAnalysis);

            if (!string.IsNullOrEmpty(_options.ProfileRoot))
            {
                ProfileOptimization.StartProfile(nameof(IIncrementalAnalyzer));
            }

            var exportProvider = (IMefHostExportProvider)workspace.Services.HostServices;

            var solutionSizeTracker = exportProvider.GetExports<ISolutionSizeTracker>().Single().Value;

            // This will return the tracker, since it's a singleton.
            var analyzer = ((IIncrementalAnalyzerProvider)solutionSizeTracker).CreateIncrementalAnalyzer(workspace);
            await analyzer.NewSolutionSnapshotAsync(workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);

            var solutionCrawlerRegistrationService = (SolutionCrawlerRegistrationService)workspace.Services.GetRequiredService<ISolutionCrawlerRegistrationService>();
            solutionCrawlerRegistrationService.Register(workspace);
            solutionCrawlerRegistrationService.WaitUntilCompletion_ForTestingPurposesOnly(workspace, ImmutableArray.Create(analyzer));

            var size = solutionSizeTracker.GetSolutionSize(workspace, workspace.CurrentSolution.Id);
            Console.WriteLine("Current solution size:\t" + size);

            if (_options.UsePersistentStorage)
            {
                if (size <= 0)
                {
                    throw new InvalidOperationException("Solution size is too small; persistent storage is disabled.");
                }

                var persistentStorageService = workspace.Services.GetRequiredService<IPersistentStorageService>();
                var persistentStorage = persistentStorageService.GetStorage(workspace.CurrentSolution);
                if (persistentStorage is NoOpPersistentStorage)
                {
                    throw new InvalidOperationException("Benchmark is not configured to use persistent storage.");
                }
            }

            var incrementalAnalyzerProviders = exportProvider.GetExports<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>();
<commit_msg>Wait 5 seconds after getting the solution size<commit_after>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols.SymbolTree;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.IncrementalCaches;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.SolutionSize;
using Microsoft.CodeAnalysis.Storage;

namespace AnalyzerRunner
{
    internal class IncrementalAnalyzerRunner
    {
        private readonly Options _options;

        public IncrementalAnalyzerRunner(Options options)
        {
            _options = options;
        }

        public bool HasAnalyzers => _options.IncrementalAnalyzerNames.Any();

        internal async Task RunAsync(Workspace workspace, CancellationToken cancellationToken)
        {
            if (!HasAnalyzers)
            {
                return;
            }

            workspace.Options = workspace.Options
                .WithChangedOption(StorageOptions.SolutionSizeThreshold, _options.UsePersistentStorage ? 0 : int.MaxValue)
                .WithChangedOption(RuntimeOptions.FullSolutionAnalysis, _options.FullSolutionAnalysis)
                .WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.CSharp, _options.FullSolutionAnalysis)
                .WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.VisualBasic, _options.FullSolutionAnalysis);

            if (!string.IsNullOrEmpty(_options.ProfileRoot))
            {
                ProfileOptimization.StartProfile(nameof(IIncrementalAnalyzer));
            }

            var exportProvider = (IMefHostExportProvider)workspace.Services.HostServices;

            var solutionSizeTracker = exportProvider.GetExports<ISolutionSizeTracker>().Single().Value;

            // This will return the tracker, since it's a singleton.
            var analyzer = ((IIncrementalAnalyzerProvider)solutionSizeTracker).CreateIncrementalAnalyzer(workspace);
            await analyzer.NewSolutionSnapshotAsync(workspace.CurrentSolution, cancellationToken).ConfigureAwait(false);

            var solutionCrawlerRegistrationService = (SolutionCrawlerRegistrationService)workspace.Services.GetRequiredService<ISolutionCrawlerRegistrationService>();
            solutionCrawlerRegistrationService.Register(workspace);
            solutionCrawlerRegistrationService.WaitUntilCompletion_ForTestingPurposesOnly(workspace, ImmutableArray.Create(analyzer));

            var size = solutionSizeTracker.GetSolutionSize(workspace, workspace.CurrentSolution.Id);
            Console.WriteLine("Current solution size:\t" + size);

            if (_options.UsePersistentStorage)
            {
                if (size <= 0)
                {
                    throw new InvalidOperationException("Solution size is too small; persistent storage is disabled.");
                }

                var persistentStorageService = workspace.Services.GetRequiredService<IPersistentStorageService>();
                var persistentStorage = persistentStorageService.GetStorage(workspace.CurrentSolution);
                if (persistentStorage is NoOpPersistentStorage)
                {
                    throw new InvalidOperationException("Benchmark is not configured to use persistent storage.");
                }
            }

            Console.WriteLine("Pausing 5 seconds before continuing analysis...");
            await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);

            var incrementalAnalyzerProviders = exportProvider.GetExports<IIncrementalAnalyzerProvider, IncrementalAnalyzerProviderMetadata>();

{'fraction_non_alphanumeric': 0.06925137099859711, 'fraction_numerical': 0.0014028822854227777, 'mean_word_length': 3.2389189189189187, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2555477', 'n_tokens_mistral': 1871, 'n_tokens_neox': 1751, 'n_words': 361}