Exemplo n.º 1
0
        private ImmutableArray <Diagnostic> GetDiagnostics(string filePath, string csharpSource)
        {
            SyntaxTree tree = CSharpSyntaxTree.ParseText(csharpSource, path: filePath);

            CSharpCompilation compilation = CSharpCompilation.Create("target")
                                            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
                                            .AddSyntaxTrees(tree);

            ImmutableArray <Diagnostic> parseDiagnostics = compilation.GetParseDiagnostics();

            Assembly stylecopAnalyzersAssembly            = Assembly.LoadFile(GetPathToFile(@"StyleCop.Analyzers.dll"));
            ImmutableArray <DiagnosticAnalyzer> analyzers = stylecopAnalyzersAssembly.GetTypes()
                                                            .Where(t => t.IsAbstract == false && typeof(DiagnosticAnalyzer).IsAssignableFrom(t))
                                                            .Select(t => Activator.CreateInstance(t) as DiagnosticAnalyzer)
                                                            .ToImmutableArray();

            CompilationWithAnalyzersOptions options = new CompilationWithAnalyzersOptions(
                new AnalyzerOptions(default(ImmutableArray <AdditionalText>)), OnAnalyzerException, false, false);

            CompilationWithAnalyzers compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, options);

            Task <ImmutableArray <Diagnostic> > analyzerDiagnosticsTask = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();

            analyzerDiagnosticsTask.Wait();
            ImmutableArray <Diagnostic> analyzerDiagnostics = analyzerDiagnosticsTask.Result;

            return(parseDiagnostics.Concat(analyzerDiagnostics).ToImmutableArray());
        }
Exemplo n.º 2
0
            static async Task <CompilationWithAnalyzers> CreateCompilationWithAnalyzerAsync(
                Project project,
                ImmutableArray <DiagnosticAnalyzer> analyzers,
                CancellationToken cancellationToken)
            {
                // Always run analyzers concurrently in OOP
                const bool concurrentAnalysis = 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(concurrentAnalysis));

                // Run analyzers concurrently, with performance logging and reporting suppressed diagnostics.
                // This allows all client requests with or without performance data and/or suppressed diagnostics to be satisfied.
                // 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),
                    onAnalyzerException: null,
                    analyzerExceptionFilter: null,
                    concurrentAnalysis: concurrentAnalysis,
                    logAnalyzerExecutionTime: true,
                    reportSuppressedDiagnostics: true);

                return(compilation.WithAnalyzers(analyzers, analyzerOptions));
            }
Exemplo n.º 3
0
        private static void ExecuteAnalyzers(
            PreviewWorkspace previewWorkspace,
            ImmutableArray <DiagnosticAnalyzer> analyzers
            )
        {
            var analyzerOptions = new AnalyzerOptions(
                additionalFiles: ImmutableArray <AdditionalText> .Empty
                );
            var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(
                analyzerOptions,
                previewWorkspace.CurrentSolution
                );
            var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                workspaceAnalyzerOptions,
                onAnalyzerException: null,
                concurrentAnalysis: false,
                logAnalyzerExecutionTime: false
                );
            var project     = previewWorkspace.CurrentSolution.Projects.Single();
            var compilation = project.GetRequiredCompilationAsync(CancellationToken.None).Result;
            var compilationWithAnalyzers = new CompilationWithAnalyzers(
                compilation,
                analyzers,
                compilationWithAnalyzersOptions
                );
            var result =
                compilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None).Result;

            Assert.Equal(1, result.CompilationDiagnostics.Count);
        }
        internal CompilationWithAnalyzers GetCompilationWithAnalyzers(Project project, Compilation compilation, bool concurrentAnalysis, bool reportSuppressedDiagnostics)
        {
            Contract.ThrowIfFalse(project.SupportsCompilation);
            Contract.ThrowIfNull(compilation);

            var analysisOptions = new CompilationWithAnalyzersOptions(
                new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
                GetOnAnalyzerException(project.Id),
                concurrentAnalysis,
                logAnalyzerExecutionTime: true,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var analyzers         = _stateManager.GetAnalyzers(project);
            var filteredAnalyzers = analyzers
                                    .Where(a => !CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(a, compilation.Options, analysisOptions.OnAnalyzerException))
                                    .Distinct()
                                    .ToImmutableArray();

            if (filteredAnalyzers.IsEmpty)
            {
                return(null);
            }

            return(new CompilationWithAnalyzers(compilation, filteredAnalyzers, analysisOptions));
        }
Exemplo n.º 5
0
        public static ImmutableArray <Diagnostic> GetAnalyzerDiagnostics <TCompilation>(
            this TCompilation c,
            DiagnosticAnalyzer[] analyzers,
            TestValidationMode validationMode,
            AnalyzerOptions options = null)
            where TCompilation : Compilation
        {
            var compilationWithAnalyzerOptions = new CompilationWithAnalyzersOptions(options, OnAnalyzerException, concurrentAnalysis: c.Options.ConcurrentBuild, logAnalyzerExecutionTime: false);
            var compilationWithAnalyzers       = c.WithAnalyzers(analyzers.ToImmutableArray(), compilationWithAnalyzerOptions);
            var diagnostics = c.GetDiagnostics();

            if (validationMode != TestValidationMode.AllowCompileErrors)
            {
                CompilationUtils.ValidateNoCompileErrors(diagnostics);
            }

            var diagnosticDescriptors = analyzers.SelectMany(analyzer => analyzer.SupportedDiagnostics);
            var analyzerDiagnosticIds = diagnosticDescriptors.Select(diagnosticDescriptor => diagnosticDescriptor.Id);
            var allDiagnosticIds      = new HashSet <string>(analyzerDiagnosticIds, StringComparer.Ordinal)
            {
                "AD0001"    // Failures caught by the Analyzer Driver.
            };
            var allDiagnostics    = compilationWithAnalyzers.GetAllDiagnosticsAsync().Result;
            var resultDiagnostics = allDiagnostics.Where(diagnostic => allDiagnosticIds.Contains(diagnostic.Id));

            return(resultDiagnostics.ToImmutableArray());
        }
Exemplo n.º 6
0
        internal static async Task <ImmutableArray <Diagnostic> > GetDiagnostics(Project project, List <DiagnosticAnalyzer> providers, CancellationToken token)
        {
            var analyzers = ImmutableArray <DiagnosticAnalyzer> .Empty.AddRange(providers);

            try {
                var compilation = await project.GetCompilationAsync(token).ConfigureAwait(false);

                CompilationWithAnalyzers compilationWithAnalyzer;
                var options = new CompilationWithAnalyzersOptions(
                    null,
                    delegate(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diag) {
                    LoggingService.LogError("Exception in diagnostic analyzer " + diag.Id + ":" + diag.GetMessage(), exception);
                },
                    null,
                    true,
                    false
                    );

                compilationWithAnalyzer = compilation.WithAnalyzers(analyzers, options);
                if (token.IsCancellationRequested)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                return(await compilationWithAnalyzer.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false));
            } catch (Exception) {
                return(ImmutableArray <Diagnostic> .Empty);
            } finally {
                CompilationWithAnalyzers.ClearAnalyzerState(analyzers);
            }
        }
Exemplo n.º 7
0
        static async Task <ImmutableArray <Diagnostic> > GetDiagnosticsForDocument(ImmutableArray <DiagnosticAnalyzer> analyzers, Microsoft.CodeAnalysis.Document doc, ImmutableHashSet <string> diagnostics, CancellationToken token)
        {
            var sol     = doc.Project.Solution;
            var options = new CompilationWithAnalyzersOptions(
                new WorkspaceAnalyzerOptions(
                    new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                    sol.Options,
                    sol),
                delegate(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diag) {
                LoggingService.LogError("Exception in diagnostic analyzer " + diag.Id + ":" + diag.GetMessage(), exception);
            },
                true,
                false
                );

            var model = await doc.GetSemanticModelAsync(token).ConfigureAwait(false);

            var compilationWithAnalyzer = model.Compilation.WithAnalyzers(analyzers, options);

            var diagnosticList = new List <Diagnostic> ();

            diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, token).ConfigureAwait(false));
            diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, token).ConfigureAwait(false));

            return(diagnosticList.ToImmutableArray());
        }
Exemplo n.º 8
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())));
        }
Exemplo n.º 9
0
        public async Task RunCodeAnalysisAsync(
            CodeAnalysisResult result,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            Project project,
            ImmutableHashSet <string> formattableDocumentPaths,
            DiagnosticSeverity severity,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            if (compilation is null)
            {
                return;
            }

            // If are not running any analyzers and are not reporting compiler diagnostics, then there is
            // nothing to report.
            if (analyzers.IsEmpty && !_includeComplilerDiagnostics)
            {
                return;
            }

            ImmutableArray <Diagnostic> diagnostics;

            if (analyzers.IsEmpty)
            {
                diagnostics = compilation.GetDiagnostics(cancellationToken);
            }
            else
            {
                var analyzerOptions = new CompilationWithAnalyzersOptions(
                    project.AnalyzerOptions,
                    onAnalyzerException: null,
                    concurrentAnalysis: true,
                    logAnalyzerExecutionTime: false,
                    reportSuppressedDiagnostics: false);
                var analyzerCompilation = compilation.WithAnalyzers(analyzers, analyzerOptions);
                diagnostics = _includeComplilerDiagnostics
                    ? await analyzerCompilation.GetAllDiagnosticsAsync(cancellationToken).ConfigureAwait(false)
                    : await analyzerCompilation.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);
            }

            // filter diagnostics
            foreach (var diagnostic in diagnostics)
            {
                if (!diagnostic.IsSuppressed &&
                    diagnostic.Severity >= severity &&
                    diagnostic.Location.IsInSource &&
                    diagnostic.Location.SourceTree != null &&
                    formattableDocumentPaths.Contains(diagnostic.Location.SourceTree.FilePath))
                {
                    result.AddDiagnostic(project, diagnostic);
                }
            }
        }
Exemplo n.º 10
0
        public static Task <ImmutableArray <Diagnostic> > GetAnalyzerDiagnosticsAsync(
            this Compilation compilation,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            CompilationWithAnalyzersOptions analysisOptions,
            CancellationToken cancellationToken = default)
        {
            var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, analysisOptions);

            return(compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken));
        }
Exemplo n.º 11
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())));
            }
        }
Exemplo n.º 12
0
        public CSharpCompiler()
        {
            whitelist          = new Whitelist();
            parseOptions       = CreateParseOptions();
            compilationOptions = CreateCompilationOptions();
            analyzerOptions    = CreateAnalyzerOptions();
            doubleOptions      = CreateCompilationWithAnalyzersOptions(analyzerOptions);
            var analyzer = new CSharpDiagnosticAnalyser();

            immutableanalyzers = ImmutableArray <DiagnosticAnalyzer> .Empty.Add(analyzer);

            descriptors = new diagnosticdescriptors();
        }
        public void Execute(GeneratorExecutionContext context)
        {
            if (context.SyntaxReceiver is not AggregatedSyntaxCapture asc)
            {
                return;
            }
            // Ensure no analyzer has failed
            using var scope = asc.ServiceProvider.CreateScope();
            var scopeService = scope.ServiceProvider;

            // Setup the service.


            var option = new CompilationWithAnalyzersOptions(null, null, concurrentAnalysis: false,
                                                             logAnalyzerExecutionTime: false,
                                                             reportSuppressedDiagnostics: true,
                                                             analyzerExceptionFilter: null);

            try {
                var analyzers = context.Compilation.WithAnalyzers(scopeService.GetServices <DiagnosticAnalyzer>().ToImmutableArray(), option);

                var hasFailed = false;
                foreach (var result in analyzers.GetAnalyzerDiagnosticsAsync(context.CancellationToken).GetAwaiter().GetResult())
                {
                    context.ReportDiagnostic(result);
                    hasFailed |= result.Severity == DiagnosticSeverity.Error;
                }
                if (hasFailed)
                {
                    return;
                }
                var capturedSyntaxes = scopeService.GetService <PredicateSyntaxCapture>()?.CapturedSyntaxes.ToImmutableArray() ?? default;
                var contextAccessor  = scopeService.GetRequiredService <SourceContextAccessor>();
                {
                    contextAccessor.OnOperationCanceled   = context.CancellationToken;
                    contextAccessor.SourceCompilation     = context.Compilation;
                    contextAccessor.AnalyzerConfigOptions = context.AnalyzerConfigOptions;
                    contextAccessor.AdditionalFiles       = context.AdditionalFiles;
                    contextAccessor.ParseOptions          = context.ParseOptions;
                    contextAccessor.AddSource             = context.AddSource;
                }
                foreach (var generator in scopeService.GetServices <SourcebergGenerator>())
                {
                    generator.CommonContext = contextAccessor;
                    generator.RunGeneration(capturedSyntaxes, context.CancellationToken);
                }
            }
            catch (Exception exception) {
                context.ReportDiagnostic(Diagnostic.Create(UnexpectedExceptionDescriptor, Location.None, exception.GetType(), GeneratorGroupType, exception));
            }
        }
Exemplo n.º 14
0
        public async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > GetDiagnosticsAsync(
            IEnumerable <AnalyzerReference> hostAnalyzers,
            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 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())));
        }
Exemplo n.º 15
0
 public DiagnosticAnalyzerDriver(
     Project project,
     DiagnosticIncrementalAnalyzer owner,
     CancellationToken cancellationToken)
 {
     _project           = project;
     _owner             = owner;
     _cancellationToken = cancellationToken;
     _analysisOptions   = new CompilationWithAnalyzersOptions(
         new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
         owner.GetOnAnalyzerException(project.Id),
         concurrentAnalysis: false,
         logAnalyzerExecutionTime: true);
 }
Exemplo n.º 16
0
 public DiagnosticAnalyzerDriver(
     Project project,
     DiagnosticIncrementalAnalyzer owner,
     CancellationToken cancellationToken)
 {
     _project = project;
     _owner = owner;
     _cancellationToken = cancellationToken;
     _analysisOptions = new CompilationWithAnalyzersOptions(
         new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
         owner.GetOnAnalyzerException(project.Id),
         concurrentAnalysis: false,
         logAnalyzerExecutionTime: true);
 }
Exemplo n.º 17
0
        private async Task <DiagnosticAnalysisResultMap <string, DiagnosticAnalysisResultBuilder> > AnalyzeAsync(
            BidirectionalMap <string, DiagnosticAnalyzer> analyzerMap,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            SkippedHostAnalyzersInfo 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, additionalPragmaSuppressionDiagnostics) = await analyzerDriver.GetAnalysisResultAsync(_project, _analyzerInfoCache, 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(additionalPragmaSuppressionDiagnostics, _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)));
        }
Exemplo n.º 18
0
        private static async Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(
            Project project,
            ImmutableArray <DiagnosticAnalyzer> diagnosticAnalyzers,
            CancellationToken cancellationToken)
        {
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            RoslynDebug.AssertNotNull(compilation);

            var analyzerOptions = new CompilationWithAnalyzersOptions(
                project.AnalyzerOptions,
                onAnalyzerException: null,
                concurrentAnalysis: true,
                logAnalyzerExecutionTime: false,
                reportSuppressedDiagnostics: false);
            var analyzerCompilation = compilation.WithAnalyzers(diagnosticAnalyzers, analyzerOptions);

            return(await analyzerCompilation.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false));
        }
        public static async Task <IEnumerable <Diagnostic> > GetAnalyzerDiagnostics(this Compilation compilation, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken = default)
        {
            var exceptions = new List <Exception>();

            var analysisOptions = new CompilationWithAnalyzersOptions(
                new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                (exception, _, __) => exceptions.Add(exception),
                concurrentAnalysis: false,
                logAnalyzerExecutionTime: false);

            var diagnostics = await compilation
                              .WithAnalyzers(ImmutableArray.Create(analyzer), analysisOptions)
                              .GetAnalyzerDiagnosticsAsync(cancellationToken);

            if (exceptions.Any())
            {
                throw new AggregateException(exceptions);
            }

            return(diagnostics
                   .OrderBy(diagnostic => diagnostic.Location.SourceSpan)
                   .ThenBy(diagnostic => diagnostic.Id));
        }
Exemplo n.º 20
0
        public async Task <IEnumerable <ISymbol> > GetSymbolsAsync(
            Project project,
            RenameScope scope,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                options: default(AnalyzerOptions),
                onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                concurrentAnalysis: true,
                logAnalyzerExecutionTime: false,
                reportSuppressedDiagnostics: false);

            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            ImmutableArray <SymbolKind> symbolKinds = scope switch
            {
                RenameScope.Type => ImmutableArray.Create(SymbolKind.NamedType),
                RenameScope.Member => ImmutableArray.Create(SymbolKind.Field, SymbolKind.Event, SymbolKind.Method, SymbolKind.Property),
                RenameScope.Local => ImmutableArray.Create(SymbolKind.Field, SymbolKind.Event, SymbolKind.Method, SymbolKind.Property),
                _ => throw new InvalidOperationException(),
            };

            var analyzer = new Analyzer(
                symbolKinds,
                IncludeGeneratedCode);

            var compilationWithAnalyzers = new CompilationWithAnalyzers(
                compilation,
                ImmutableArray.Create((DiagnosticAnalyzer)analyzer),
                compilationWithAnalyzersOptions);

            ImmutableArray <Diagnostic> _ = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

            return(analyzer.Symbols);
        }
        internal CompilationWithAnalyzers GetCompilationWithAnalyzers(Project project, Compilation compilation, bool concurrentAnalysis, bool reportSuppressedDiagnostics)
        {
            Contract.ThrowIfFalse(project.SupportsCompilation);
            Contract.ThrowIfNull(compilation);

            Func <Exception, bool> analyzerExceptionFilter = ex =>
            {
                if (project.Solution.Workspace.Options.GetOption(InternalDiagnosticsOptions.CrashOnAnalyzerException))
                {
                    // if option is on, crash the host to get crash dump.
                    FatalError.ReportUnlessCanceled(ex);
                }

                return(true);
            };

            var analysisOptions = new CompilationWithAnalyzersOptions(
                new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
                GetOnAnalyzerException(project.Id),
                analyzerExceptionFilter,
                concurrentAnalysis,
                logAnalyzerExecutionTime: true,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var analyzers         = _stateManager.GetAnalyzers(project);
            var filteredAnalyzers = analyzers
                                    .Where(a => !CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(a, compilation.Options, analysisOptions.OnAnalyzerException))
                                    .Distinct()
                                    .ToImmutableArray();

            if (filteredAnalyzers.IsEmpty)
            {
                return(null);
            }

            return(new CompilationWithAnalyzers(compilation, filteredAnalyzers, analysisOptions));
        }
Exemplo n.º 22
0
        private ImmutableArray <Diagnostic> GetDiagnostics(Document document)
        {
            var analyzers   = ImmutableArray.Create(CreateAnalyzer());
            var compilation = document.Project.GetCompilationAsync(CancellationToken.None).Result;

            List <Exception> exceptions = new List <Exception>();

            var options = new CompilationWithAnalyzersOptions(
                options: new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                onAnalyzerException: (exception, analyzer, arg3) => exceptions.Add(exception),
                concurrentAnalysis: true,
                logAnalyzerExecutionTime: false);
            var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, options);

            var discarded = compilation.GetDiagnostics(CancellationToken.None);

            var tree = document.GetSyntaxTreeAsync(CancellationToken.None).Result;

            var builder = ImmutableArray.CreateBuilder <Diagnostic>();

            foreach (var diagnostic in compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result)
            {
                var location = diagnostic.Location;
                if (location.IsInSource && location.SourceTree == tree)
                {
                    builder.Add(diagnostic);
                }
            }

            if (exceptions.Count != 0)
            {
                Assert.Fail($"Unhandled exception occurred during analysis: \r\n{string.Join("\r\n", exceptions)}");
            }

            return(builder.ToImmutable());
        }
Exemplo n.º 23
0
        public async Task <ImmutableArray <SpellingFixResult> > FixProjectAsync(
            Project project,
            CancellationToken cancellationToken = default)
        {
            project = CurrentSolution.GetProject(project.Id);

            ISpellingService service = MefWorkspaceServices.Default.GetService <ISpellingService>(project.Language);

            if (service == null)
            {
                return(ImmutableArray <SpellingFixResult> .Empty);
            }

            ImmutableArray <Diagnostic> previousDiagnostics         = ImmutableArray <Diagnostic> .Empty;
            ImmutableArray <Diagnostic> previousPreviousDiagnostics = ImmutableArray <Diagnostic> .Empty;

            ImmutableArray <SpellingFixResult> .Builder results = ImmutableArray.CreateBuilder <SpellingFixResult>();

            bool nonSymbolsFixed = (Options.ScopeFilter & (SpellingScopeFilter.NonSymbol)) == 0;

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                    options: default(AnalyzerOptions),
                    onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                    concurrentAnalysis: true,
                    logAnalyzerExecutionTime: false,
                    reportSuppressedDiagnostics: false);

                Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                DiagnosticAnalyzer analyzer = service.CreateAnalyzer(SpellingData, Options);

                var compilationWithAnalyzers = new CompilationWithAnalyzers(
                    compilation,
                    ImmutableArray.Create(analyzer),
                    compilationWithAnalyzersOptions);

                ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

#if DEBUG
                foreach (IGrouping <Diagnostic, Diagnostic> grouping in diagnostics
                         .GroupBy(f => f, DiagnosticDeepEqualityComparer.Instance))
                {
                    using (IEnumerator <Diagnostic> en = grouping.GetEnumerator())
                    {
                        if (en.MoveNext() &&
                            en.MoveNext())
                        {
                            Debug.Fail(DiagnosticFormatter.FormatDiagnostic(en.Current));
                        }
                    }
                }
#endif
                int length = diagnostics.Length;

                if (length == 0)
                {
                    break;
                }

                if (length == previousDiagnostics.Length &&
                    !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    break;
                }

                if (length == previousPreviousDiagnostics.Length &&
                    !diagnostics.Except(previousPreviousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    LogHelpers.WriteInfiniteLoopSummary(diagnostics, previousDiagnostics, project, FormatProvider);
                    break;
                }

                var spellingDiagnostics = new List <SpellingDiagnostic>();

                foreach (Diagnostic diagnostic in diagnostics)
                {
                    Debug.Assert(diagnostic.Id == CommonDiagnosticIdentifiers.PossibleMisspellingOrTypo, diagnostic.Id);

                    if (diagnostic.Id != CommonDiagnosticIdentifiers.PossibleMisspellingOrTypo)
                    {
                        if (diagnostic.IsAnalyzerExceptionDiagnostic())
                        {
                            LogHelpers.WriteDiagnostic(diagnostic, baseDirectoryPath: Path.GetDirectoryName(project.FilePath), formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Detailed);
                        }

                        continue;
                    }

                    SpellingDiagnostic spellingDiagnostic = service.CreateSpellingDiagnostic(diagnostic);

                    spellingDiagnostics.Add(spellingDiagnostic);
                }

                if (!nonSymbolsFixed)
                {
                    List <SpellingFixResult> commentResults = await FixCommentsAsync(project, spellingDiagnostics, cancellationToken).ConfigureAwait(false);

                    results.AddRange(commentResults);
                    nonSymbolsFixed = true;
                }

                if ((Options.ScopeFilter & SpellingScopeFilter.Symbol) == 0)
                {
                    break;
                }

                (List <SpellingFixResult> symbolResults, bool allIgnored) = await FixSymbolsAsync(
                    project,
                    spellingDiagnostics,
                    service.SyntaxFacts,
                    cancellationToken)
                                                                            .ConfigureAwait(false);

                results.AddRange(symbolResults);

                if (allIgnored)
                {
                    break;
                }

                if (Options.DryRun)
                {
                    break;
                }

                project = CurrentSolution.GetProject(project.Id);

                previousPreviousDiagnostics = previousDiagnostics;
                previousDiagnostics         = diagnostics;
            }

            return(results.ToImmutableArray());
        }
        internal CompilationWithAnalyzers GetCompilationWithAnalyzers(Project project, Compilation compilation, bool concurrentAnalysis, bool reportSuppressedDiagnostics)
        {
            Contract.ThrowIfFalse(project.SupportsCompilation);
            Contract.ThrowIfNull(compilation);

            var analysisOptions = new CompilationWithAnalyzersOptions(
                new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
                GetOnAnalyzerException(project.Id),
                concurrentAnalysis,
                logAnalyzerExecutionTime: true,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var analyzers = _stateManager.GetAnalyzers(project);
            var filteredAnalyzers = analyzers
                .Where(a => !CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(a, compilation.Options, analysisOptions.OnAnalyzerException))
                .Distinct()
                .ToImmutableArray();
            if (filteredAnalyzers.IsEmpty)
            {
                return null;
            }

            return new CompilationWithAnalyzers(compilation, filteredAnalyzers, analysisOptions);
        }
Exemplo n.º 25
0
        protected async Task <Diagnostic[]> GetSortedDiagnosticsFromDocumentsAsync(AnalyzerVerificationContext context, DiagnosticAnalyzer analyzer, Document[] documents, params DiagnosticResult[] expected)
        {
            var projects = new HashSet <Project>();

            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List <Diagnostic>();

            foreach (var project in projects)
            {
                var analyzers = ImmutableArray.Create(analyzer)
                                .AddRange(GetRelatedAnalyzers(analyzer));

                var compilation = await project.GetCompilationAsync();

                Assert.NotNull(compilation);

                var optionsProvider = new AnalyzerOptionsProvider(context.Options);
                var options         = new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty, optionsProvider);
                var analyzerOptions = new CompilationWithAnalyzersOptions(options, null, true, true, true);

                var compilationOptions        = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, reportSuppressedDiagnostics: true);
                var specificDiagnosticOptions = compilationOptions.SpecificDiagnosticOptions;

                // Force all tested diagnostics to be enabled
                foreach (var descriptor in analyzer.SupportedDiagnostics)
                {
                    specificDiagnosticOptions = specificDiagnosticOptions.SetItem(descriptor.Id, ReportDiagnostic.Info);
                }

                var compilationWithAnalyzers = compilation
                                               .WithOptions(compilationOptions.WithSpecificDiagnosticOptions(specificDiagnosticOptions))
                                               .WithAnalyzers(analyzers, analyzerOptions);

                var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync();

                var errors = allDiagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).ToList();
                foreach (var error in errors)
                {
                    Assert.True(false, $"Line {error.Location.GetLineSpan().StartLinePosition.Line}: {error.GetMessage()}");
                }

                var diags = allDiagnostics
                            .Except(errors)
                            .Where(d => d.Location.IsInSource);             //only keep diagnostics related to a source location

                foreach (var diag in diags)
                {
                    // We should not hit this anymore, but keep in case we change the previous filter
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        foreach (var document in documents)
                        {
                            var tree = await document.GetSyntaxTreeAsync();

                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(FilterDiagnostics(diagnostics, context.Filters));

            diagnostics.Clear();
            return(results);
        }
Exemplo n.º 26
0
        public async Task RunCodeAnalysisAsync(
            CodeAnalysisResult result,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            Project project,
            ImmutableHashSet <string> formattableDocumentPaths,
            DiagnosticSeverity severity,
            bool includeCompilerDiagnostics,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            // If are not running any analyzers and are not reporting compiler diagnostics, then there is
            // nothing to report.
            if (analyzers.IsEmpty && includeCompilerDiagnostics)
            {
                return;
            }

            // For projects targeting NetStandard, the Runtime references are resolved from the project.assets.json.
            // This file is generated during a `dotnet restore`.
            if (!AllReferencedProjectsLoaded(project))
            {
                logger.LogWarning(Resources.Required_references_did_not_load_for_0_or_referenced_project_Run_dotnet_restore_prior_to_formatting, project.Name);
                return;
            }

            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            if (compilation is null)
            {
                return;
            }

            ImmutableArray <Diagnostic> diagnostics;

            if (analyzers.IsEmpty)
            {
                diagnostics = compilation.GetDiagnostics(cancellationToken);
            }
            else
            {
                logger.LogDebug(Resources.Running_0_analyzers_on_1, analyzers.Length, project.Name);

                var analyzerOptions = new CompilationWithAnalyzersOptions(
                    project.AnalyzerOptions,
                    onAnalyzerException: null,
                    concurrentAnalysis: true,
                    logAnalyzerExecutionTime: false,
                    reportSuppressedDiagnostics: false);
                var analyzerCompilation = compilation.WithAnalyzers(analyzers, analyzerOptions);
                diagnostics = includeCompilerDiagnostics
                    ? await analyzerCompilation.GetAllDiagnosticsAsync(cancellationToken).ConfigureAwait(false)
                    : await analyzerCompilation.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);
            }

            // filter diagnostics
            foreach (var diagnostic in diagnostics)
            {
                if (!diagnostic.IsSuppressed &&
                    diagnostic.Severity >= severity &&
                    diagnostic.Location.IsInSource &&
                    diagnostic.Location.SourceTree != null &&
                    formattableDocumentPaths.Contains(diagnostic.Location.SourceTree.FilePath))
                {
                    result.AddDiagnostic(project, diagnostic);
                }
            }

            return;
        internal CompilationWithAnalyzers GetCompilationWithAnalyzers(
            Project project,
            IEnumerable<DiagnosticAnalyzer> analyzers,
            Compilation compilation,
            bool concurrentAnalysis,
            bool reportSuppressedDiagnostics)
        {
            Contract.ThrowIfFalse(project.SupportsCompilation);
            Contract.ThrowIfNull(compilation);

            Func<Exception, bool> analyzerExceptionFilter = ex =>
            {
                if (project.Solution.Workspace.Options.GetOption(InternalDiagnosticsOptions.CrashOnAnalyzerException))
                {
                    // if option is on, crash the host to get crash dump.
                    FatalError.ReportUnlessCanceled(ex);
                }

                return true;
            };

            var analysisOptions = new CompilationWithAnalyzersOptions(
                new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace),
                GetOnAnalyzerException(project.Id),
                analyzerExceptionFilter: analyzerExceptionFilter,
                concurrentAnalysis: concurrentAnalysis,
                logAnalyzerExecutionTime: true,
                reportSuppressedDiagnostics: reportSuppressedDiagnostics);

            var filteredAnalyzers = analyzers
                .Where(a => !CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(a, compilation.Options, analysisOptions.OnAnalyzerException))
                .Distinct()
                .ToImmutableArray();
            if (filteredAnalyzers.IsEmpty)
            {
                return null;
            }

            return new CompilationWithAnalyzers(compilation, filteredAnalyzers, analysisOptions);
        }
        protected async Task <Diagnostic[]> GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer analyzer, Document[] documents, bool allowCompilationErrors)
        {
            if (documents == null)
            {
                throw new ArgumentNullException(nameof(documents));
            }

            var projects = new HashSet <Project>();

            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics        = new List <Diagnostic>();
            var analyzerExceptions = new List <Exception>();

            foreach (var project in projects)
            {
                var options = new CompilationWithAnalyzersOptions(
                    new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                    (exception, diagnosticAnalyzer, diagnostic) => analyzerExceptions.Add(exception),
                    false,
                    true);
                var compilationWithAnalyzers = (await project.GetCompilationAsync())
                                               .WithAnalyzers(ImmutableArray.Create(analyzer), options);

                if (!allowCompilationErrors)
                {
                    AssertThatCompilationSucceeded(compilationWithAnalyzers);
                }

                var diags = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();

                if (analyzerExceptions.Any())
                {
                    if (analyzerExceptions.Count == 1)
                    {
                        ExceptionDispatchInfo.Capture(analyzerExceptions[0]).Throw();
                    }
                    else
                    {
                        throw new AggregateException("Multiple exceptions thrown during analysis", analyzerExceptions);
                    }
                }

                foreach (var diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree     = await document.GetSyntaxTreeAsync();

                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDiagnostics(diagnostics);

            diagnostics.Clear();
            return(results);
        }
Exemplo n.º 29
0
        private async Task <ProjectAnalysisResult> AnalyzeProjectCoreAsync(Project project, ImmutableArray <DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken = default)
        {
            LogHelpers.WriteUsedAnalyzers(analyzers, null, Options, ConsoleColors.DarkGray, Verbosity.Diagnostic);

            cancellationToken.ThrowIfCancellationRequested();

            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            ImmutableArray <Diagnostic> compilerDiagnostics = (Options.IgnoreCompilerDiagnostics)
                ? ImmutableArray <Diagnostic> .Empty
                : compilation.GetDiagnostics(cancellationToken);

            compilerDiagnostics = FilterDiagnostics(compilerDiagnostics, project, cancellationToken).ToImmutableArray();

            ImmutableArray <Diagnostic> diagnostics = ImmutableArray <Diagnostic> .Empty;

            ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> telemetry = ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty;

            if (analyzers.Any())
            {
                var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                    options: project.AnalyzerOptions,
                    onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                    concurrentAnalysis: Options.ConcurrentAnalysis,
                    logAnalyzerExecutionTime: Options.LogAnalyzerExecutionTime,
                    reportSuppressedDiagnostics: Options.ReportSuppressedDiagnostics);

                var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, compilationWithAnalyzersOptions);

                if (Options.LogAnalyzerExecutionTime)
                {
                    AnalysisResult analysisResult = await compilationWithAnalyzers.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                    diagnostics = analysisResult.GetAllDiagnostics();
                    telemetry   = analysisResult.AnalyzerTelemetryInfo;
                }
                else
                {
                    diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);
                }
            }

            string projectDirectoryPath = Path.GetDirectoryName(project.FilePath);

            LogHelpers.WriteDiagnostics(FilterDiagnostics(diagnostics.Where(f => f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray(), baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Detailed);
#if DEBUG
            if (ConsoleOut.Verbosity >= Verbosity.Detailed &&
                diagnostics.Any(f => f.IsAnalyzerExceptionDiagnostic()))
            {
                Console.Write("Stop (Y/N)? ");

                if (char.ToUpperInvariant((char)Console.Read()) == 'Y')
                {
                    throw new OperationCanceledException();
                }
            }
#endif
            diagnostics = FilterDiagnostics(diagnostics.Where(f => !f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray();

            LogHelpers.WriteDiagnostics(compilerDiagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Normal);

            LogHelpers.WriteDiagnostics(diagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Normal);

            return(ProjectAnalysisResult.Create(project, compilerDiagnostics, diagnostics, telemetry));
        }
Exemplo n.º 30
0
        public static async Task <IEnumerable <Result> > Check(AnalysisDocument analysisDocument, CancellationToken cancellationToken)
        {
            var input = analysisDocument.DocumentContext;

            if (!AnalysisOptions.EnableFancyFeatures || input.Project == null || !input.IsCompileableInProject || input.AnalysisDocument == null)
            {
                return(Enumerable.Empty <Result> ());
            }
            if (SkipContext(input))
            {
                return(Enumerable.Empty <Result> ());
            }
            try {
                var model = await analysisDocument.DocumentContext.AnalysisDocument.GetSemanticModelAsync(cancellationToken);

                if (model == null)
                {
                    return(Enumerable.Empty <Result> ());
                }
                var compilation = model.Compilation;
                var language    = CodeRefactoringService.MimeTypeToLanguage(analysisDocument.Editor.MimeType);

                var providers    = new List <DiagnosticAnalyzer> ();
                var alreadyAdded = new HashSet <Type>();
                if (diagnostics == null)
                {
                    diagnostics = await CodeRefactoringService.GetCodeDiagnosticsAsync(analysisDocument.DocumentContext, language, cancellationToken);
                }
                var diagnosticTable = new Dictionary <string, CodeDiagnosticDescriptor> ();
                foreach (var diagnostic in diagnostics)
                {
                    if (alreadyAdded.Contains(diagnostic.DiagnosticAnalyzerType))
                    {
                        continue;
                    }
                    if (!diagnostic.IsEnabled)
                    {
                        continue;
                    }
                    alreadyAdded.Add(diagnostic.DiagnosticAnalyzerType);
                    var provider = diagnostic.GetProvider();
                    if (provider == null)
                    {
                        continue;
                    }
                    foreach (var diag in provider.SupportedDiagnostics)
                    {
                        diagnosticTable [diag.Id] = diagnostic;
                    }
                    providers.Add(provider);
                }

                if (providers.Count == 0 || cancellationToken.IsCancellationRequested)
                {
                    return(Enumerable.Empty <Result> ());
                }
                                #if DEBUG
                Debug.Listeners.Add(consoleTraceListener);
                                #endif

                CompilationWithAnalyzers compilationWithAnalyzer;
                var analyzers = ImmutableArray <DiagnosticAnalyzer> .Empty.AddRange(providers);

                var diagnosticList = new List <Diagnostic> ();
                try {
                    var sol     = analysisDocument.DocumentContext.AnalysisDocument.Project.Solution;
                    var options = new CompilationWithAnalyzersOptions(
                        new WorkspaceAnalyzerOptions(
                            new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                            sol.Options,
                            sol),
                        delegate(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diag) {
                        LoggingService.LogError("Exception in diagnostic analyzer " + diag.Id + ":" + diag.GetMessage(), exception);
                    },
                        false,
                        false
                        );

                    compilationWithAnalyzer = compilation.WithAnalyzers(analyzers, options);
                    if (input.ParsedDocument == null || cancellationToken.IsCancellationRequested)
                    {
                        return(Enumerable.Empty <Result> ());
                    }

                    diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, cancellationToken).ConfigureAwait(false));
                    diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSyntaxDiagnosticsAsync(model.SyntaxTree, cancellationToken).ConfigureAwait(false));
                } catch (OperationCanceledException) {
                } catch (AggregateException ae) {
                    ae.Flatten().Handle(ix => ix is OperationCanceledException);
                } catch (Exception ex) {
                    LoggingService.LogError("Error creating analyzer compilation", ex);
                    return(Enumerable.Empty <Result> ());
                } finally {
                                        #if DEBUG
                    Debug.Listeners.Remove(consoleTraceListener);
                                        #endif
                    CompilationWithAnalyzers.ClearAnalyzerState(analyzers);
                }

                return(diagnosticList
                       .Where(d => !d.Id.StartsWith("CS", StringComparison.Ordinal))
                       .Where(d => diagnosticTable[d.Id].GetIsEnabled(d.Descriptor))
                       .Select(diagnostic => {
                    var res = new DiagnosticResult(diagnostic);
                    // var line = analysisDocument.Editor.GetLineByOffset (res.Region.Start);
                    // Console.WriteLine (diagnostic.Id + "/" + res.Region +"/" + analysisDocument.Editor.GetTextAt (line));
                    return res;
                }));
            } catch (OperationCanceledException) {
                return(Enumerable.Empty <Result> ());
            }  catch (AggregateException ae) {
                ae.Flatten().Handle(ix => ix is OperationCanceledException);
                return(Enumerable.Empty <Result> ());
            } catch (Exception e) {
                LoggingService.LogError("Error while running diagnostics.", e);
                return(Enumerable.Empty <Result> ());
            }
        }