예제 #1
0
        public static ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResultBuilder> ToResultBuilderMap(
            this AnalysisResult analysisResult,
            Project project, VersionStamp version, Compilation compilation, IEnumerable <DiagnosticAnalyzer> analyzers,
            ISkippedAnalyzersInfo skippedAnalyzersInfo,
            CancellationToken cancellationToken)
        {
            var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResultBuilder>();

            ImmutableArray <Diagnostic> diagnostics;

            foreach (var analyzer in analyzers)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (skippedAnalyzersInfo.SkippedAnalyzers.Contains(analyzer))
                {
                    continue;
                }

                var result = new DiagnosticAnalysisResultBuilder(project, version);
                var diagnosticIdsToFilter = skippedAnalyzersInfo.FilteredDiagnosticIdsForAnalyzers.GetValueOrDefault(
                    analyzer,
                    ImmutableArray <string> .Empty);

                foreach (var(tree, diagnosticsByAnalyzerMap) in analysisResult.SyntaxDiagnostics)
                {
                    if (diagnosticsByAnalyzerMap.TryGetValue(analyzer, out diagnostics))
                    {
                        diagnostics = diagnostics.Filter(diagnosticIdsToFilter);
                        Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation).Count());
                        result.AddSyntaxDiagnostics(tree, diagnostics);
                    }
                }

                foreach (var(tree, diagnosticsByAnalyzerMap) in analysisResult.SemanticDiagnostics)
                {
                    if (diagnosticsByAnalyzerMap.TryGetValue(analyzer, out diagnostics))
                    {
                        diagnostics = diagnostics.Filter(diagnosticIdsToFilter);
                        Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation).Count());
                        result.AddSemanticDiagnostics(tree, diagnostics);
                    }
                }

                if (analysisResult.CompilationDiagnostics.TryGetValue(analyzer, out diagnostics))
                {
                    diagnostics = diagnostics.Filter(diagnosticIdsToFilter);
                    Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation).Count());
                    result.AddCompilationDiagnostics(diagnostics);
                }

                builder.Add(analyzer, result);
            }

            return(builder.ToImmutable());
        }
예제 #2
0
 private ProjectAnalyzerStateSets(
     IReadOnlyList <AnalyzerReference> analyzerReferences,
     ImmutableDictionary <object, ImmutableArray <DiagnosticAnalyzer> > mapPerReferences,
     ImmutableDictionary <DiagnosticAnalyzer, StateSet> stateSetMap,
     ISkippedAnalyzersInfo skippedAnalyzersInfo)
 {
     AnalyzerReferences   = analyzerReferences;
     MapPerReferences     = mapPerReferences;
     StateSetMap          = stateSetMap;
     SkippedAnalyzersInfo = skippedAnalyzersInfo;
 }
예제 #3
0
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            ISkippedAnalyzersInfo skippedAnalyzersInfo,
            bool reportSuppressedDiagnostics,
            bool logAnalyzerExecutionTime,
            CancellationToken cancellationToken)
        {
            // flag that controls concurrency
            var useConcurrent = true;

            // get original compilation
            var compilation = await _project.GetRequiredCompilationAsync(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: null,
                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(_analyzerInfoCache), _project.DocumentIds.Count + 1);
            }

            var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, skippedAnalyzersInfo, 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)));
        }