Пример #1
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
            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);

            // 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())));
        }
Пример #2
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);

                // 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())));
            }
        }