private async Task SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result)
        {
            using (var stream = await DirectStream.GetAsync(streamName, CancellationToken).ConfigureAwait(false))
            {
                using (var writer = new ObjectWriter(stream))
                {
                    DiagnosticResultSerializer.Serialize(writer, result, CancellationToken);
                }

                await stream.FlushAsync(CancellationToken).ConfigureAwait(false);
            }
        }
        private async Task SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result)
        {
            using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_SerializeDiagnosticResultAsync, GetResultLogInfo, result, CancellationToken))
            using (var stream = await DirectStream.GetAsync(streamName, CancellationToken).ConfigureAwait(false))
            {
                using (var writer = new ObjectWriter(stream))
                {
                    DiagnosticResultSerializer.Serialize(writer, result, CancellationToken);
                }

                await stream.FlushAsync(CancellationToken).ConfigureAwait(false);
            }
        }
Example #3
0
        private async Task SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
        {
            using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_SerializeDiagnosticResultAsync, GetResultLogInfo, result, cancellationToken))
                using (var stream = await DirectStream.GetAsync(streamName, cancellationToken).ConfigureAwait(false))
                {
                    using (var writer = new ObjectWriter(stream))
                    {
                        var info = DiagnosticResultSerializer.Serialize(writer, result, cancellationToken);

                        // save log for debugging
                        Log(TraceEventType.Information, $"diagnostics: {info.diagnostics}, telemetry: {info.telemetry}, exceptions: {info.exceptions}");
                    }

                    await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
                }
        }
Example #4
0
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            bool reportSuppressedDiagnostics,
            bool logAnalyzerExecutionTime,
            CancellationToken cancellationToken)
        {
            // flag that controls concurrency
            var useConcurrent = true;

            // get original compilation
            var compilation = await _project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // fork compilation with concurrent build. this is okay since WithAnalyzers will fork compilation
            // anyway to attach event queue. this should make compiling compilation concurrent and make things
            // faster
            compilation = compilation.WithOptions(compilation.Options.WithConcurrentBuild(useConcurrent));

            // TODO: can we support analyzerExceptionFilter in remote host?
            //       right now, host doesn't support watson, we might try to use new NonFatal watson API?
            var analyzerOptions = new CompilationWithAnalyzersOptions(
                options: new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, _project.Solution),
                onAnalyzerException: OnAnalyzerException,
                analyzerExceptionFilter: null,
                concurrentAnalysis: useConcurrent,
                logAnalyzerExecutionTime: logAnalyzerExecutionTime,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var analyzerDriver = compilation.WithAnalyzers(analyzers, analyzerOptions);

            // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
            var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

            // record performance if tracker is available
            if (_performanceTracker != null)
            {
                // +1 to include project itself
                _performanceTracker.AddSnapshot(analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(), _project.DocumentIds.Count + 1);
            }

            var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken);

            return(DiagnosticAnalysisResultMap.Create(
                       builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                       analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                       _exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray())));
        }
        public async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeAsync(CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
        {
            var remoteHostClient = await project.Solution.Workspace.Services.GetService <IRemoteHostClientService>().GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);

            if (remoteHostClient == null)
            {
                // remote host is not running. this can happen if remote host is disabled.
                return(await InProcCodeAnalysisDiagnosticAnalyzerExecutor.Instance.AnalyzeAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
            }

            var outOfProcResult = await AnalyzeOutOfProcAsync(remoteHostClient, analyzerDriver, project, cancellationToken).ConfigureAwait(false);

            // make sure things are not cancelled
            cancellationToken.ThrowIfCancellationRequested();

            return(DiagnosticAnalysisResultMap.Create(outOfProcResult.AnalysisResult, outOfProcResult.TelemetryInfo));
        }
Example #6
0
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            OptionSet options,
            bool reportSuppressedDiagnostics,
            bool logAnalyzerExecutionTime,
            CancellationToken cancellationToken)
        {
            // flag that controls concurrency
            var useConcurrent = true;

            // get original compilation
            var compilation = await _project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // fork compilation with concurrent build. this is okay since WithAnalyzers will fork compilation
            // anyway to attach event queue. this should make compiling compilation concurrent and make things
            // faster
            compilation = compilation.WithOptions(compilation.Options.WithConcurrentBuild(useConcurrent));

            // We need this to fork soluton, otherwise, option is cached at document.
            // all this can go away once we do this - https://github.com/dotnet/roslyn/issues/19284
            using (var temporaryWorksapce = new TemporaryWorkspace(_project.Solution))
            {
                // TODO: can we support analyzerExceptionFilter in remote host?
                //       right now, host doesn't support watson, we might try to use new NonFatal watson API?
                var analyzerOptions = new CompilationWithAnalyzersOptions(
                    options: new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, MergeOptions(_project.Solution.Options, options), temporaryWorksapce.CurrentSolution),
                    onAnalyzerException: OnAnalyzerException,
                    analyzerExceptionFilter: null,
                    concurrentAnalysis: useConcurrent,
                    logAnalyzerExecutionTime: logAnalyzerExecutionTime,
                    reportSuppressedDiagnostics: reportSuppressedDiagnostics);

                var analyzerDriver = compilation.WithAnalyzers(analyzers, analyzerOptions);

                // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
                var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken);

                return(DiagnosticAnalysisResultMap.Create(
                           builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                           analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                           _exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray())));
            }
        }
Example #7
0
        public static DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> ReadDiagnosticAnalysisResults(
            ObjectReader reader, IDictionary <string, DiagnosticAnalyzer> analyzerMap, Project project, VersionStamp version, CancellationToken cancellationToken)
        {
            var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            var analysisCount = reader.ReadInt32();

            for (var i = 0; i < analysisCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];

                var syntaxLocalMap   = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                var semanticLocalMap = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                var nonLocalMap      = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);

                var others = diagnosticDataSerializer.ReadDiagnosticData(reader, project, document: null, cancellationToken);

                var analysisResult = DiagnosticAnalysisResult.Create(
                    project,
                    version,
                    syntaxLocalMap,
                    semanticLocalMap,
                    nonLocalMap,
                    others.NullToEmpty(),
                    documentIds: null);

                analysisMap.Add(analyzer, analysisResult);
            }

            var telemetryMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

            var telemetryCount = reader.ReadInt32();

            for (var i = 0; i < telemetryCount; i++)
            {
                var analyzer      = analyzerMap[reader.ReadString()];
                var telemetryInfo = ReadTelemetry(reader, cancellationToken);

                telemetryMap.Add(analyzer, telemetryInfo);
            }

            return(DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable()));
        }
        public async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeAsync(CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
        {
            if (analyzerDriver.Analyzers.Length == 0)
            {
                // quick bail out
                return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
            }

            var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

            // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
            var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

            // get compiler result builder map
            var builderMap = analysisResult.ToResultBuilderMap(project, version, analyzerDriver.Compilation, analyzerDriver.Analyzers, cancellationToken);

            return(DiagnosticAnalysisResultMap.Create(builderMap.ToImmutableDictionary(kv => kv.Key, kv => new DiagnosticAnalysisResult(kv.Value)), analysisResult.AnalyzerTelemetryInfo));
        }
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            bool reportSuppressedDiagnostics,
            bool logAnalyzerExecutionTime,
            CancellationToken cancellationToken)
        {
            var compilation = await _project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // TODO: can we support analyzerExceptionFilter in remote host?
            //       right now, host doesn't support watson, we might try to use new NonFatal watson API?
            var analyzerOptions = new CompilationWithAnalyzersOptions(
                options: _project.AnalyzerOptions,
                onAnalyzerException: OnAnalyzerException,
                analyzerExceptionFilter: null,
                concurrentAnalysis: true,
                logAnalyzerExecutionTime: logAnalyzerExecutionTime,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var analyzerDriver = compilation.WithAnalyzers(analyzers, analyzerOptions);

            // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
            var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

            // REVIEW: the design of current analyzer engine is that, information/states in CompilationWithAnalyzer (more specifically AnalyzerManager singleton)
            //         will live forever until analyzer references (analyzers), which is given to CompilationWithAnalyzer, go away.
            //         that is not suitable for OOP since OOP will create new workspace
            //         for each analysis but share all resources including analyzer references.
            //         until, we address this issue, OOP will clear state every time analysis is done.
            //
            //         * NOTE * this only works for now since we don't run analysis on multiple threads.
            //
            //         best way to fix this is doing this - https://github.com/dotnet/roslyn/issues/2830
            //         host should control lifetime of all information related to analyzer reference explicitly
            CompilationWithAnalyzers.ClearAnalyzerState(analyzers);

            var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken);

            return(DiagnosticAnalysisResultMap.Create(
                       builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                       analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
                       _exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray())));
        }
            private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync(
                RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken)
            {
                var solution        = project.Solution;
                var snapshotService = solution.Workspace.Services.GetService <IRemotableDataService>();

                using (var pooledObject = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject())
                {
                    var analyzerMap = pooledObject.Object;

                    analyzerMap.AppendAnalyzerMap(analyzerDriver.Analyzers.Where(a => !a.IsInProcessOnly() && (forcedAnalysis || !a.IsOpenFileOnly(solution.Workspace))));
                    if (analyzerMap.Count == 0)
                    {
                        return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
                    }

                    var optionAsset = GetOptionsAsset(solution, project.Language, cancellationToken);

                    var argument = new DiagnosticArguments(
                        forcedAnalysis, analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics, analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime,
                        project.Id, optionAsset.Checksum, analyzerMap.Keys.ToArray());

                    using (var session = await client.TryCreateCodeAnalysisSessionAsync(solution, cancellationToken).ConfigureAwait(false))
                    {
                        if (session == null)
                        {
                            // session is not available
                            return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
                        }

                        session.AddAdditionalAssets(optionAsset);

                        var result = await session.InvokeAsync(
                            nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync),
                            new object[] { argument },
                            (s, c) => GetCompilerAnalysisResultAsync(s, analyzerMap, project, c), cancellationToken).ConfigureAwait(false);

                        ReportAnalyzerExceptions(project, result.Exceptions);

                        return(result);
                    }
                }
            }
        public static (int diagnostics, int telemetry, int exceptions) Serialize(
            ObjectWriter writer, DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
        {
            var diagnosticCount      = 0;
            var diagnosticSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisResult = result.AnalysisResult;

            writer.WriteInt32(analysisResult.Count);
            foreach (var kv in analysisResult)
            {
                writer.WriteString(kv.Key);

                diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.SyntaxLocals, cancellationToken);
                diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.SemanticLocals, cancellationToken);
                diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.NonLocals, cancellationToken);

                diagnosticSerializer.WriteTo(writer, kv.Value.Others, cancellationToken);
                diagnosticCount += kv.Value.Others.Length;
            }

            var telemetryInfo = result.TelemetryInfo;

            writer.WriteInt32(telemetryInfo.Count);
            foreach (var kv in telemetryInfo)
            {
                writer.WriteString(kv.Key);
                Serialize(writer, kv.Value, cancellationToken);
            }

            var exceptions = result.Exceptions;

            writer.WriteInt32(exceptions.Count);
            foreach (var kv in exceptions)
            {
                writer.WriteString(kv.Key);
                diagnosticSerializer.WriteTo(writer, kv.Value, cancellationToken);
            }

            // report how many data has been sent
            return(diagnosticCount, telemetryInfo.Count, exceptions.Count);
        }
            private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync(
                RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
            {
                var solution        = project.Solution;
                var snapshotService = solution.Workspace.Services.GetService <ISolutionSynchronizationService>();

                // TODO: this should be moved out
                var analyzerMap = CreateAnalyzerMap(analyzerDriver.Analyzers);

                if (analyzerMap.Count == 0)
                {
                    return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
                }

                var optionAsset   = GetOptionsAsset(solution, project.Language, cancellationToken);
                var hostChecksums = GetHostAnalyzerReferences(snapshotService, project.Language, _analyzerServiceOpt?.GetHostAnalyzerReferences(), cancellationToken);

                var argument = new DiagnosticArguments(
                    analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics,
                    analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime,
                    project.Id, optionAsset.Checksum, hostChecksums, analyzerMap.Keys.ToArray());

                using (var session = await client.TryCreateCodeAnalysisServiceSessionAsync(solution, cancellationToken).ConfigureAwait(false))
                {
                    if (session == null)
                    {
                        // session is not available
                        return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
                    }

                    session.AddAdditionalAssets(optionAsset);

                    var result = await session.InvokeAsync(
                        WellKnownServiceHubServices.CodeAnalysisService_CalculateDiagnosticsAsync,
                        new object[] { argument },
                        (s, c) => GetCompilerAnalysisResultAsync(s, analyzerMap, project, c)).ConfigureAwait(false);

                    ReportAnalyzerExceptions(project, result.Exceptions);

                    return(result);
                }
            }
            public async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeAsync(CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken)
            {
                var workspace = project.Solution.Workspace;
                var service   = workspace.Services.GetService <IRemoteHostClientService>();

                if (service == null)
                {
                    // host doesn't support RemoteHostService such as under unit test
                    return(await AnalyzeInProcAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
                }

                var remoteHostClient = await service.TryGetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);

                if (remoteHostClient == null)
                {
                    // remote host is not running. this can happen if remote host is disabled.
                    return(await AnalyzeInProcAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
                }

                // due to in-process only analyzers, we need to run inproc as well for such analyzers for fix all
                // otherwise, we don't need to run open file only analyzers for closed files even if full solution analysis is on (perf improvement)
                //
                // we have this open file analyzers since some of our built in analyzers such as SimplifyTypeNamesDiagnosticAnalyzer are too
                // slow to run for whole solution when full solution analysis is on. easily taking more than an hour to run whole solution.
                var inProcResultTask = AnalyzeInProcAsync(CreateAnalyzerDriver(analyzerDriver, a => (forcedAnalysis || !a.IsOpenFileOnly(workspace)) && a.IsInProcessOnly()), project, remoteHostClient, cancellationToken);

                // out of proc analysis will use 2 source of analyzers. one is AnalyzerReference from project (nuget). and the other is host analyzers (vsix)
                // that are not part of roslyn solution. these host analyzers must be sync to OOP before hand by the Host.
                var outOfProcResultTask = AnalyzeOutOfProcAsync(remoteHostClient, analyzerDriver, project, forcedAnalysis, cancellationToken);

                // run them concurrently in vs and remote host
                await Task.WhenAll(inProcResultTask, outOfProcResultTask).ConfigureAwait(false);

                // make sure things are not cancelled
                cancellationToken.ThrowIfCancellationRequested();

                // merge 2 results
                return(DiagnosticAnalysisResultMap.Create(
                           inProcResultTask.Result.AnalysisResult.AddRange(outOfProcResultTask.Result.AnalysisResult),
                           inProcResultTask.Result.TelemetryInfo.AddRange(outOfProcResultTask.Result.TelemetryInfo)));
            }
Example #14
0
            public async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeAsync(CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken)
            {
                var workspace = project.Solution.Workspace;

                if (!workspace.Options.GetOption(RemoteFeatureOptions.DiagnosticsEnabled))
                {
                    // diagnostic service running on remote host is disabled. just run things in in proc
                    return(await AnalyzeInProcAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
                }

                var service = project.Solution.Workspace.Services.GetService <IRemoteHostClientService>();

                if (service == null)
                {
                    // host doesn't support RemoteHostService such as under unit test
                    return(await AnalyzeInProcAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
                }

                var remoteHostClient = await service.TryGetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);

                if (remoteHostClient == null)
                {
                    // remote host is not running. this can happen if remote host is disabled.
                    return(await AnalyzeInProcAsync(analyzerDriver, project, cancellationToken).ConfigureAwait(false));
                }

                // due to OpenFileOnly analyzer, we need to run inproc as well for such analyzers
                var inProcResultTask    = AnalyzeInProcAsync(CreateAnalyzerDriver(analyzerDriver, a => a.IsOpenFileOnly(project.Solution.Workspace)), project, cancellationToken);
                var outOfProcResultTask = AnalyzeOutOfProcAsync(remoteHostClient, analyzerDriver, project, forcedAnalysis, cancellationToken);

                // run them concurrently in vs and remote host
                await Task.WhenAll(inProcResultTask, outOfProcResultTask).ConfigureAwait(false);

                // make sure things are not cancelled
                cancellationToken.ThrowIfCancellationRequested();

                // merge 2 results
                return(DiagnosticAnalysisResultMap.Create(
                           inProcResultTask.Result.AnalysisResult.AddRange(outOfProcResultTask.Result.AnalysisResult),
                           inProcResultTask.Result.TelemetryInfo.AddRange(outOfProcResultTask.Result.TelemetryInfo)));
            }
Example #15
0
            private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeInProcAsync(
                CompilationWithAnalyzers compilation, Project project, RemoteHostClient?client, CancellationToken cancellationToken)
            {
                Debug.Assert(compilation.Analyzers.Length != 0);

                var version = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
                var analysisResult = await compilation.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                // if remote host is there, report performance data
                var asyncToken = _asyncOperationListener.BeginAsyncOperation(nameof(AnalyzeInProcAsync));
                var _          = FireAndForgetReportAnalyzerPerformanceAsync(project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken);

                // get compiler result builder map
                var builderMap = analysisResult.ToResultBuilderMap(project, version, compilation.Compilation, compilation.Analyzers, cancellationToken);

                return(DiagnosticAnalysisResultMap.Create(
                           builderMap.ToImmutableDictionary(kv => kv.Key, kv => DiagnosticAnalysisResult.CreateFromBuilder(kv.Value)),
                           analysisResult.AnalyzerTelemetryInfo));
            }
Example #16
0
        public async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > GetDiagnosticsAsync(
            IEnumerable <AnalyzerReference> hostAnalyzers,
            OptionSet options,
            IEnumerable <string> analyzerIds,
            bool reportSuppressedDiagnostics,
            bool logAnalyzerExecutionTime,
            CancellationToken cancellationToken)
        {
            var analyzerMap = CreateAnalyzerMap(hostAnalyzers, _project);
            var analyzers   = GetAnalyzers(analyzerMap, analyzerIds);

            if (analyzers.Length == 0)
            {
                return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <string, DiagnosticAnalysisResultBuilder> .Empty, ImmutableDictionary <string, AnalyzerTelemetryInfo> .Empty));
            }

            var cacheService = _project.Solution.Workspace.Services.GetService <IProjectCacheService>();

            using var cache = cacheService.EnableCaching(_project.Id);
            return(await AnalyzeAsync(analyzerMap, analyzers, options, reportSuppressedDiagnostics, logAnalyzerExecutionTime, cancellationToken).ConfigureAwait(false));
        }
        private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync(
            RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
        {
            var solution = project.Solution;

            var snapshotService = solution.Workspace.Services.GetService <ISolutionChecksumService>();

            // TODO: incremental build of solution snapshot should be its own service
            await UpdateLastSolutionSnapshotAsync(snapshotService, solution).ConfigureAwait(false);

            // TODO: this should be moved out
            var hostChecksums = GetHostAnalyzerReferences(snapshotService, _analyzerService.GetHostAnalyzerReferences(), cancellationToken);
            var analyzerMap   = CreateAnalyzerMap(analyzerDriver.Analyzers.Where(a => !a.MustRunInProcess()));

            if (analyzerMap.Count == 0)
            {
                return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
            }

            // TODO: send telemetry on session
            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(solution, cancellationToken).ConfigureAwait(false))
            {
                var argument = new DiagnosticArguments(
                    analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics,
                    analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime,
                    project.Id, hostChecksums, analyzerMap.Keys.ToArray());

                var result = await session.InvokeAsync(
                    WellKnownServiceHubServices.CodeAnalysisService_CalculateDiagnosticsAsync,
                    new object[] { argument },
                    (s, c) => GetCompilerAnalysisResultAsync(s, analyzerMap, project, c)).ConfigureAwait(false);

                ReportAnalyzerExceptions(project, result.Exceptions);

                return(result);
            }
        }
Example #18
0
        private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeInProcAsync(
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            CompilationWithAnalyzers compilationWithAnalyzers,
            RemoteHostClient?client,
            bool logPerformanceInfo,
            bool getTelemetryInfo,
            CancellationToken cancellationToken)
        {
            var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

            var(analysisResult, additionalPragmaSuppressionDiagnostics) = await compilationWithAnalyzers.GetAnalysisResultAsync(
                documentAnalysisScope, project, AnalyzerInfoCache, cancellationToken).ConfigureAwait(false);

            if (logPerformanceInfo)
            {
                // if remote host is there, report performance data
                var asyncToken = _asyncOperationListener.BeginAsyncOperation(nameof(AnalyzeInProcAsync));
                var _          = FireAndForgetReportAnalyzerPerformanceAsync(documentAnalysisScope, project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken);
            }

            var analyzers            = documentAnalysisScope?.Analyzers ?? compilationWithAnalyzers.Analyzers;
            var skippedAnalyzersInfo = project.GetSkippedAnalyzersInfo(AnalyzerInfoCache);

            // get compiler result builder map
            var builderMap = await analysisResult.ToResultBuilderMapAsync(
                additionalPragmaSuppressionDiagnostics, documentAnalysisScope, project, version,
                compilationWithAnalyzers.Compilation, analyzers, skippedAnalyzersInfo,
                compilationWithAnalyzers.AnalysisOptions.ReportSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);

            var result    = builderMap.ToImmutableDictionary(kv => kv.Key, kv => DiagnosticAnalysisResult.CreateFromBuilder(kv.Value));
            var telemetry = getTelemetryInfo
                ? analysisResult.AnalyzerTelemetryInfo
                : ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty;

            return(DiagnosticAnalysisResultMap.Create(result, telemetry));
        }
        public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
        {
            var diagnosticSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisResult = result.AnalysisResult;

            writer.WriteInt32(analysisResult.Count);
            foreach (var kv in analysisResult)
            {
                writer.WriteString(kv.Key);

                Serialize(writer, diagnosticSerializer, kv.Value.SyntaxLocals, cancellationToken);
                Serialize(writer, diagnosticSerializer, kv.Value.SemanticLocals, cancellationToken);
                Serialize(writer, diagnosticSerializer, kv.Value.NonLocals, cancellationToken);

                diagnosticSerializer.WriteTo(writer, kv.Value.Others, cancellationToken);
            }

            var telemetryInfo = result.TelemetryInfo;

            writer.WriteInt32(telemetryInfo.Count);
            foreach (var kv in telemetryInfo)
            {
                writer.WriteString(kv.Key);
                Serialize(writer, kv.Value, cancellationToken);
            }

            var exceptions = result.Exceptions;

            writer.WriteInt32(exceptions.Count);
            foreach (var kv in exceptions)
            {
                writer.WriteString(kv.Key);
                diagnosticSerializer.WriteTo(writer, kv.Value, cancellationToken);
            }
        }
Example #20
0
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            CompilationWithAnalyzers compilationWithAnalyzers,
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerToIdMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            SkippedHostAnalyzersInfo skippedAnalyzersInfo,
            bool reportSuppressedDiagnostics,
            bool logPerformanceInfo,
            bool getTelemetryInfo,
            CancellationToken cancellationToken)
        {
            var documentAnalysisScope = _document != null
                ? new DocumentAnalysisScope(_document, _span, analyzers, _analysisKind !.Value)
                : null;

            var(analysisResult, additionalPragmaSuppressionDiagnostics) = await compilationWithAnalyzers.GetAnalysisResultAsync(
                documentAnalysisScope, _project, _analyzerInfoCache, cancellationToken).ConfigureAwait(false);

            // Record performance if tracker is available
            if (logPerformanceInfo && _performanceTracker != null)
            {
                // +1 to include project itself
                var unitCount = documentAnalysisScope != null ? 1 : _project.DocumentIds.Count + 1;
                _performanceTracker.AddSnapshot(analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(_analyzerInfoCache), unitCount);
            }

            var builderMap = await analysisResult.ToResultBuilderMapAsync(
                additionalPragmaSuppressionDiagnostics, documentAnalysisScope,
                _project, VersionStamp.Default, compilationWithAnalyzers.Compilation,
                analyzers, skippedAnalyzersInfo, reportSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);

            var result    = builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerToIdMap, kv.Key), kv => kv.Value);
            var telemetry = getTelemetryInfo
                ? GetTelemetryInfo(analysisResult, analyzers, analyzerToIdMap)
                : ImmutableDictionary <string, AnalyzerTelemetryInfo> .Empty;

            return(DiagnosticAnalysisResultMap.Create(result, telemetry));
            private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeInProcAsync(
                CompilationWithAnalyzers analyzerDriver, Project project, RemoteHostClient client, CancellationToken cancellationToken)
            {
                if (analyzerDriver == null ||
                    analyzerDriver.Analyzers.Length == 0)
                {
                    // quick bail out
                    return(DiagnosticAnalysisResultMap.Create(ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty, ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty));
                }

                var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API.
                var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                // if remote host is there, report performance data
                var asyncToken = _owner?.Listener.BeginAsyncOperation(nameof(AnalyzeInProcAsync));
                var _          = FireAndForgetReportAnalyzerPerformanceAsync(project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken);

                // get compiler result builder map
                var builderMap = analysisResult.ToResultBuilderMap(project, version, analyzerDriver.Compilation, analyzerDriver.Analyzers, cancellationToken);

                return(DiagnosticAnalysisResultMap.Create(builderMap.ToImmutableDictionary(kv => kv.Key, kv => DiagnosticAnalysisResult.CreateFromBuilder(kv.Value)), analysisResult.AnalyzerTelemetryInfo));
            }
        public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
        {
            var diagnosticSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisResult = result.AnalysisResult;

            writer.WriteInt32(analysisResult.Count);
            foreach (var kv in analysisResult)
            {
                writer.WriteString(kv.Key);

                Serialize(writer, diagnosticSerializer, kv.Value.SyntaxLocals, cancellationToken);
                Serialize(writer, diagnosticSerializer, kv.Value.SemanticLocals, cancellationToken);
                Serialize(writer, diagnosticSerializer, kv.Value.NonLocals, cancellationToken);

                diagnosticSerializer.WriteTo(writer, kv.Value.Others, cancellationToken);
            }

            var telemetryInfo = result.TelemetryInfo;

            writer.WriteInt32(telemetryInfo.Count);
            foreach (var kv in telemetryInfo)
            {
                writer.WriteString(kv.Key);
                Serialize(writer, kv.Value, cancellationToken);
            }

            var exceptions = result.Exceptions;

            writer.WriteInt32(exceptions.Count);
            foreach (var kv in exceptions)
            {
                writer.WriteString(kv.Key);
                diagnosticSerializer.WriteTo(writer, kv.Value, cancellationToken);
            }
        }
Example #23
0
        public static (int diagnostics, int telemetry, int exceptions) WriteDiagnosticAnalysisResults(
            ObjectWriter writer, DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
        {
            var diagnosticCount      = 0;
            var diagnosticSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            writer.WriteInt32(result.AnalysisResult.Count);
            foreach (var(analyzerId, analyzerResults) in result.AnalysisResult)
            {
                writer.WriteString(analyzerId);

                diagnosticCount += WriteDiagnosticDataMap(writer, diagnosticSerializer, analyzerResults.SyntaxLocals, cancellationToken);
                diagnosticCount += WriteDiagnosticDataMap(writer, diagnosticSerializer, analyzerResults.SemanticLocals, cancellationToken);
                diagnosticCount += WriteDiagnosticDataMap(writer, diagnosticSerializer, analyzerResults.NonLocals, cancellationToken);

                diagnosticSerializer.WriteDiagnosticData(writer, analyzerResults.Others, cancellationToken);
                diagnosticCount += analyzerResults.Others.Length;
            }

            writer.WriteInt32(result.TelemetryInfo.Count);
            foreach (var(analyzerId, analyzerTelemetry) in result.TelemetryInfo)
            {
                writer.WriteString(analyzerId);
                WriteTelemetry(writer, analyzerTelemetry, cancellationToken);
            }

            writer.WriteInt32(result.Exceptions.Count);
            foreach (var(analyzerId, analyzerExceptions) in result.Exceptions)
            {
                writer.WriteString(analyzerId);
                diagnosticSerializer.WriteDiagnosticData(writer, analyzerExceptions, cancellationToken);
            }

            // report how many data has been sent
            return(diagnosticCount, result.TelemetryInfo.Count, result.Exceptions.Count);
        }
 private static string GetResultLogInfo(DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result)
 {
     // for now, simple logging
     return $"Analyzer: {result.AnalysisResult.Count}, Telemetry: {result.TelemetryInfo.Count}, Exceptions: {result.Exceptions.Count}";
 }
 private void UpdateAnalyzerTelemetryData(
     DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult> analysisResults, Project project, CancellationToken cancellationToken)
 {
     foreach (var kv in analysisResults.TelemetryInfo)
     {
         DiagnosticAnalyzerLogger.UpdateAnalyzerTypeCount(kv.Key, kv.Value, project, _owner.DiagnosticLogAggregator);
     }
 }
Example #26
0
        public static DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> ReadDiagnosticAnalysisResults(
            ObjectReader reader,
            IDictionary <string, DiagnosticAnalyzer> analyzerMap,
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            VersionStamp version,
            CancellationToken cancellationToken)
        {
            var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

            var analysisMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();
            var documentIds = documentAnalysisScope != null?ImmutableHashSet.Create(documentAnalysisScope.TextDocument.Id) : null;

            var analysisCount = reader.ReadInt32();

            for (var i = 0; i < analysisCount; i++)
            {
                var analyzer = analyzerMap[reader.ReadString()];

                DiagnosticAnalysisResult analysisResult;
                if (documentAnalysisScope != null)
                {
                    ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > syntaxLocalMap, semanticLocalMap;
                    if (documentAnalysisScope.Kind == AnalysisKind.Syntax)
                    {
                        syntaxLocalMap   = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                        semanticLocalMap = ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty;
                    }
                    else
                    {
                        Debug.Assert(documentAnalysisScope.Kind == AnalysisKind.Semantic);
                        semanticLocalMap = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                        syntaxLocalMap   = ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty;
                    }

                    analysisResult = DiagnosticAnalysisResult.Create(
                        project,
                        version,
                        syntaxLocalMap,
                        semanticLocalMap,
                        nonLocalMap: ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                        others: ImmutableArray <DiagnosticData> .Empty,
                        documentIds);
                }
                else
                {
                    var syntaxLocalMap   = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                    var semanticLocalMap = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);
                    var nonLocalMap      = ReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken);

                    var others = diagnosticDataSerializer.ReadDiagnosticData(reader, project, document: null, cancellationToken);

                    analysisResult = DiagnosticAnalysisResult.Create(
                        project,
                        version,
                        syntaxLocalMap,
                        semanticLocalMap,
                        nonLocalMap,
                        others.NullToEmpty(),
                        documentIds: null);
                }

                analysisMap.Add(analyzer, analysisResult);
            }

            var telemetryMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

            var telemetryCount = reader.ReadInt32();

            for (var i = 0; i < telemetryCount; i++)
            {
                var analyzer      = analyzerMap[reader.ReadString()];
                var telemetryInfo = ReadTelemetry(reader, cancellationToken);

                telemetryMap.Add(analyzer, telemetryInfo);
            }

            return(DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable()));
        }
Example #27
0
 private static string GetResultLogInfo(DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> result)
 {
     // for now, simple logging
     return($"Analyzer: {result.AnalysisResult.Count}, Telemetry: {result.TelemetryInfo.Count}, Exceptions: {result.Exceptions.Count}");
 }
        public static bool TryReadDiagnosticAnalysisResults(
            ObjectReader reader,
            IDictionary <string, DiagnosticAnalyzer> analyzerMap,
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            VersionStamp version,
            CancellationToken cancellationToken,
            [NotNullWhen(returnValue: true)] out DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult>?result)
        {
            result = null;

            try
            {
                var diagnosticDataSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);

                var analysisMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();
                var documentIds = documentAnalysisScope != null?ImmutableHashSet.Create(documentAnalysisScope.TextDocument.Id) : null;

                var analysisCount = reader.ReadInt32();
                for (var i = 0; i < analysisCount; i++)
                {
                    var analyzer = analyzerMap[reader.ReadString()];

                    DiagnosticAnalysisResult analysisResult;
                    if (documentAnalysisScope != null)
                    {
                        ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> >?syntaxLocalMap, semanticLocalMap;
                        if (documentAnalysisScope.Kind == AnalysisKind.Syntax)
                        {
                            if (!TryReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken, out syntaxLocalMap))
                            {
                                return(false);
                            }

                            semanticLocalMap = ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty;
                        }
                        else
                        {
                            Debug.Assert(documentAnalysisScope.Kind == AnalysisKind.Semantic);
                            if (!TryReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken, out semanticLocalMap))
                            {
                                return(false);
                            }

                            syntaxLocalMap = ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty;
                        }

                        analysisResult = DiagnosticAnalysisResult.Create(
                            project,
                            version,
                            syntaxLocalMap,
                            semanticLocalMap,
                            nonLocalMap: ImmutableDictionary <DocumentId, ImmutableArray <DiagnosticData> > .Empty,
                            others: ImmutableArray <DiagnosticData> .Empty,
                            documentIds);
                    }
                    else
                    {
                        if (!TryReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken, out var syntaxLocalMap) ||
                            !TryReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken, out var semanticLocalMap) ||
                            !TryReadDiagnosticDataMap(reader, diagnosticDataSerializer, project, cancellationToken, out var nonLocalMap) ||
                            !diagnosticDataSerializer.TryReadDiagnosticData(reader, project, document: null, cancellationToken, out var others))
                        {
                            return(false);
                        }

                        analysisResult = DiagnosticAnalysisResult.Create(
                            project,
                            version,
                            syntaxLocalMap,
                            semanticLocalMap,
                            nonLocalMap,
                            others.NullToEmpty(),
                            documentIds: null);
                    }

                    analysisMap.Add(analyzer, analysisResult);
                }

                var telemetryMap = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalyzerTelemetryInfo>();

                var telemetryCount = reader.ReadInt32();
                for (var i = 0; i < telemetryCount; i++)
                {
                    var analyzer      = analyzerMap[reader.ReadString()];
                    var telemetryInfo = ReadTelemetry(reader, cancellationToken);

                    telemetryMap.Add(analyzer, telemetryInfo);
                }

                result = DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable());
                return(true);
            }
            catch (Exception ex) when(FatalError.ReportWithoutCrashUnlessCanceled(ex))
            {
                return(false);
            }
        }