Пример #1
0
 public InProcOrRemoteHostAnalyzerRunner(
     DiagnosticAnalyzerInfoCache analyzerInfoCache,
     IAsynchronousOperationListener?operationListener = null)
 {
     AnalyzerInfoCache       = analyzerInfoCache;
     _asyncOperationListener = operationListener ?? AsynchronousOperationListenerProvider.NullListener;
 }
Пример #2
0
            static bool ShouldIncludeHostAnalyzer(
                DiagnosticAnalyzer hostAnalyzer,
                ImmutableHashSet <string> idsReportedByProjectAnalyzers,
                DiagnosticAnalyzerInfoCache analyzerInfoCache,
                out ImmutableArray <string> skippedDiagnosticIdsForAnalyzer)
            {
                // Include only those host (VSIX) analyzers that report at least one unique diagnostic ID
                // which is not reported by any project (NuGet) analyzer.
                // See https://github.com/dotnet/roslyn/issues/18818.

                var shouldInclude = false;

                var descriptors = analyzerInfoCache.GetDiagnosticDescriptors(hostAnalyzer);
                var skippedDiagnosticIdsBuilder = ArrayBuilder <string> .GetInstance();

                foreach (var descriptor in descriptors)
                {
                    if (idsReportedByProjectAnalyzers.Contains(descriptor.Id))
                    {
                        skippedDiagnosticIdsBuilder.Add(descriptor.Id);
                    }
                    else
                    {
                        shouldInclude = true;
                    }
                }

                skippedDiagnosticIdsForAnalyzer = skippedDiagnosticIdsBuilder.ToImmutableAndFree();
                return(shouldInclude);
            }
Пример #3
0
        public SkippedHostAnalyzersInfo GetSkippedAnalyzersInfo(
            Project project,
            DiagnosticAnalyzerInfoCache infoCache
            )
        {
            var box = _skippedHostAnalyzers.GetOrCreateValue(project.AnalyzerReferences);

            if (box.Value != null && box.Value.TryGetValue(project.Language, out var info))
            {
                return(info);
            }
            lock (box)
            {
                box.Value ??= ImmutableDictionary <string, SkippedHostAnalyzersInfo> .Empty;

                if (!box.Value.TryGetValue(project.Language, out info))
                {
                    info = SkippedHostAnalyzersInfo.Create(
                        this,
                        project.AnalyzerReferences,
                        project.Language,
                        infoCache
                        );
                    box.Value = box.Value.Add(project.Language, info);
                }

                return(info);
            }
        }
Пример #4
0
 public DefaultDiagnosticAnalyzerService(
     IDiagnosticUpdateSourceRegistrationService registrationService
     )
 {
     _analyzerInfoCache = new DiagnosticAnalyzerInfoCache();
     registrationService.Register(this);
 }
Пример #5
0
            > CreateDiagnosticDescriptorsPerReference(
            DiagnosticAnalyzerInfoCache infoCache,
            ImmutableDictionary <object, ImmutableArray <DiagnosticAnalyzer> > analyzersMap
            )
        {
            var builder = ImmutableDictionary.CreateBuilder <
                object,
                ImmutableArray <DiagnosticDescriptor>
                >();

            foreach (var(referenceId, analyzers) in analyzersMap)
            {
                var descriptors = ImmutableArray.CreateBuilder <DiagnosticDescriptor>();
                foreach (var analyzer in analyzers)
                {
                    // given map should be in good shape. no duplication. no null and etc
                    descriptors.AddRange(infoCache.GetDiagnosticDescriptors(analyzer));
                }

                // there can't be duplication since _hostAnalyzerReferenceMap is already de-duplicated.
                builder.Add(referenceId, descriptors.ToImmutable());
            }

            return(builder.ToImmutable());
        }
 private TestDiagnosticAnalyzerService(
     DiagnosticAnalyzerInfoCache analyzerInfoCache,
     AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
     IDiagnosticUpdateSourceRegistrationService registrationService = null,
     IAsynchronousOperationListener listener = null)
     : base(analyzerInfoCache, hostDiagnosticUpdateSource, registrationService ?? new MockDiagnosticUpdateSourceRegistrationService(), listener)
 {
 }
 public DefaultDiagnosticAnalyzerService(
     IDiagnosticUpdateSourceRegistrationService registrationService,
     IGlobalOptionService globalOptions)
 {
     _analyzerInfoCache = new DiagnosticAnalyzerInfoCache();
     registrationService.Register(this);
     _globalOptions = globalOptions;
 }
Пример #8
0
 public InProcOrRemoteHostAnalyzerRunner(
     DiagnosticAnalyzerInfoCache analyzerInfoCache,
     Workspace workspace,
     IAsynchronousOperationListener?operationListener = null)
 {
     AnalyzerInfoCache        = analyzerInfoCache;
     _asyncOperationListener  = operationListener ?? AsynchronousOperationListenerProvider.NullListener;
     _documentTrackingService = workspace.Services.GetService <IDocumentTrackingService>();
 }
Пример #9
0
     > GetDiagnosticDescriptorsPerReference(DiagnosticAnalyzerInfoCache infoCache)
 {
     return(ConvertReferenceIdentityToName(
                CreateDiagnosticDescriptorsPerReference(
                    infoCache,
                    _lazyHostDiagnosticAnalyzersPerReferenceMap.Value
                    ),
                _hostAnalyzerReferencesMap
                ));
 }
Пример #10
0
 protected DiagnosticAnalyzerService(
     DiagnosticAnalyzerInfoCache analyzerInfoCache,
     AbstractHostDiagnosticUpdateSource?hostDiagnosticUpdateSource,
     IDiagnosticUpdateSourceRegistrationService registrationService,
     IAsynchronousOperationListener?listener = null)
     : this(registrationService)
 {
     _analyzerInfoCache          = analyzerInfoCache;
     _hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
     Listener = listener ?? AsynchronousOperationListenerProvider.NullListener;
 }
Пример #11
0
 private TestDiagnosticAnalyzerService(
     DiagnosticAnalyzerInfoCache analyzerInfoCache,
     AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
     Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException,
     IDiagnosticUpdateSourceRegistrationService registrationService = null,
     IAsynchronousOperationListener listener = null)
     : base(analyzerInfoCache, hostDiagnosticUpdateSource, registrationService ?? new MockDiagnosticUpdateSourceRegistrationService(), listener)
 {
     _hostAnalyzerReferenceMap = analyzerInfoCache.CreateAnalyzerReferencesMap(project : null);
     _onAnalyzerException      = onAnalyzerException;
 }
Пример #12
0
        public static async Task <(AnalysisResult result, ImmutableArray <Diagnostic> additionalDiagnostics)> GetAnalysisResultAsync(
            this CompilationWithAnalyzers compilationWithAnalyzers,
            Project project,
            DiagnosticAnalyzerInfoCache analyzerInfoCache,
            CancellationToken cancellationToken)
        {
            var result = await compilationWithAnalyzers.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

            var additionalDiagnostics = await compilationWithAnalyzers.GetPragmaSuppressionAnalyzerDiagnosticsAsync(project, analyzerInfoCache, cancellationToken).ConfigureAwait(false);

            return(result, additionalDiagnostics);
        }
Пример #13
0
        private static async Task <ImmutableArray <Diagnostic> > GetPragmaSuppressionAnalyzerDiagnosticsAsync(
            this CompilationWithAnalyzers compilationWithAnalyzers,
            Project project,
            DiagnosticAnalyzerInfoCache analyzerInfoCache,
            CancellationToken cancellationToken)
        {
            var suppressionAnalyzer = compilationWithAnalyzers.Analyzers.OfType <IPragmaSuppressionsAnalyzer>().FirstOrDefault();

            if (suppressionAnalyzer == null)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            if (compilationWithAnalyzers.AnalysisOptions.ConcurrentAnalysis)
            {
                var bag = new ConcurrentBag <Diagnostic>();
                using var _ = ArrayBuilder <Task> .GetInstance(project.DocumentIds.Count, out var tasks);

                foreach (var document in project.Documents)
                {
                    tasks.Add(AnalyzeDocumentAsync(suppressionAnalyzer, document, bag.Add));
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);

                return(bag.ToImmutableArray());
            }
            else
            {
                using var _ = ArrayBuilder <Diagnostic> .GetInstance(out var diagnosticsBuilder);

                foreach (var document in project.Documents)
                {
                    await AnalyzeDocumentAsync(suppressionAnalyzer, document, diagnosticsBuilder.Add).ConfigureAwait(false);
                }

                return(diagnosticsBuilder.ToImmutable());
            }

            // Local functions.
            async Task AnalyzeDocumentAsync(IPragmaSuppressionsAnalyzer suppressionAnalyzer, Document document, Action <Diagnostic> reportDiagnostic)
            {
                var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                using var _ = ArrayBuilder <Diagnostic> .GetInstance(out var diagnostics);

                await suppressionAnalyzer.AnalyzeAsync(semanticModel, span : null, compilationWithAnalyzers,
                                                       analyzerInfoCache.GetDiagnosticDescriptors, IsCompilationEndAnalyzer, reportDiagnostic, cancellationToken).ConfigureAwait(false);
            }

            bool IsCompilationEndAnalyzer(DiagnosticAnalyzer analyzer)
            => analyzerInfoCache.IsCompilationEndAnalyzer(analyzer, compilationWithAnalyzers.AnalysisOptions.Options !, compilationWithAnalyzers.Compilation) ?? true;
        }
            private static IEnumerable <DiagnosticAnalyzer> GetAnalyzers(DiagnosticAnalyzerInfoCache analyzerInfoCache, Project project)
            {
                // C# or VB document that supports compiler
                var compilerAnalyzer = analyzerInfoCache.GetCompilerDiagnosticAnalyzer(project.Language);

                if (compilerAnalyzer != null)
                {
                    return(SpecializedCollections.SingletonEnumerable(compilerAnalyzer));
                }

                // document that doesn't support compiler diagnostics such as FSharp or TypeScript
                return(analyzerInfoCache.CreateDiagnosticAnalyzersPerReference(project).Values.SelectMany(v => v));
            }
Пример #15
0
        private static SkippedHostAnalyzersInfo Create(
            IEnumerable <DiagnosticAnalyzer> projectAnalyzers,
            IEnumerable <DiagnosticAnalyzer> hostAnalyzers,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            ComputeSkippedHostAnalyzers(projectAnalyzers, hostAnalyzers, analyzerInfoCache,
                                        out var fullySkippedHostAnalyzers, out var filteredDiagnosticIdsForAnalyzers);
            if (fullySkippedHostAnalyzers.IsEmpty && filteredDiagnosticIdsForAnalyzers.IsEmpty)
            {
                return(Default);
            }

            return(new SkippedHostAnalyzersInfo(fullySkippedHostAnalyzers, filteredDiagnosticIdsForAnalyzers));
Пример #16
0
            static ImmutableHashSet <string> GetIdsReportedByProjectAnalyzers(
                IEnumerable <DiagnosticAnalyzer> projectAnalyzers,
                DiagnosticAnalyzerInfoCache analyzerInfoCache)
            {
                var builder = ImmutableHashSet.CreateBuilder <string>();

                foreach (var analyzer in projectAnalyzers)
                {
                    var descriptors = analyzerInfoCache.GetDiagnosticDescriptors(analyzer);
                    builder.AddRange(descriptors.Select(d => d.Id));
                }

                return(builder.ToImmutable());
            }
Пример #17
0
            static bool ShouldIncludeHostAnalyzer(
                DiagnosticAnalyzer hostAnalyzer,
                HashSet <string> projectAnalyzerDiagnosticIds,
                HashSet <string> projectSuppressedDiagnosticIds,
                DiagnosticAnalyzerInfoCache analyzerInfoCache,
                out ImmutableArray <string> skippedDiagnosticIdsForAnalyzer)
            {
                // Include only those host (VSIX) analyzers that report at least one unique diagnostic ID
                // which is not reported by any project (NuGet) analyzer.
                // See https://github.com/dotnet/roslyn/issues/18818.

                var shouldInclude = false;

                var descriptors = analyzerInfoCache.GetDiagnosticDescriptors(hostAnalyzer);
                var skippedDiagnosticIdsBuilder = ArrayBuilder <string> .GetInstance();

                foreach (var descriptor in descriptors)
                {
                    if (projectAnalyzerDiagnosticIds.Contains(descriptor.Id))
                    {
                        skippedDiagnosticIdsBuilder.Add(descriptor.Id);
                    }
                    else
                    {
                        shouldInclude = true;
                    }
                }

                if (hostAnalyzer is DiagnosticSuppressor suppressor)
                {
                    skippedDiagnosticIdsForAnalyzer = ImmutableArray <string> .Empty;

                    // Only execute host suppressor if it does not suppress any diagnostic ID reported by project analyzer
                    // and does not share any suppression ID with a project suppressor.
                    foreach (var descriptor in suppressor.SupportedSuppressions)
                    {
                        if (projectAnalyzerDiagnosticIds.Contains(descriptor.SuppressedDiagnosticId) ||
                            projectSuppressedDiagnosticIds.Contains(descriptor.SuppressedDiagnosticId))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }

                skippedDiagnosticIdsForAnalyzer = skippedDiagnosticIdsBuilder.ToImmutableAndFree();
                return(shouldInclude);
            }
Пример #18
0
        public DiagnosticAnalyzerService(
            IDiagnosticUpdateSourceRegistrationService registrationService,
            IAsynchronousOperationListenerProvider listenerProvider)
        {
            AnalyzerInfoCache = new DiagnosticAnalyzerInfoCache();
            Listener          = listenerProvider.GetListener(FeatureAttribute.DiagnosticService);

            _map = new ConditionalWeakTable <Workspace, DiagnosticIncrementalAnalyzer>();
            _createIncrementalAnalyzer = CreateIncrementalAnalyzerCallback;
            _eventMap = new EventMap();

            _eventQueue = new TaskQueue(Listener, TaskScheduler.Default);

            registrationService.Register(this);
        }
Пример #19
0
        public DocumentAnalysisExecutor(
            DocumentAnalysisScope analysisScope,
            CompilationWithAnalyzers?compilationWithAnalyzers,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            AnalysisScope             = analysisScope;
            _compilationWithAnalyzers = compilationWithAnalyzers;
            _analyzerInfoCache        = analyzerInfoCache;

            var compilationBasedAnalyzers = compilationWithAnalyzers?.Analyzers.ToImmutableHashSet();

            _compilationBasedAnalyzersInAnalysisScope = compilationBasedAnalyzers != null
                ? analysisScope.Analyzers.WhereAsArray(compilationBasedAnalyzers.Contains)
                : ImmutableArray <DiagnosticAnalyzer> .Empty;
        }
Пример #20
0
            > GetDiagnosticDescriptorsPerReference(
            DiagnosticAnalyzerInfoCache infoCache,
            Project project
            )
        {
            var descriptorPerReference = CreateDiagnosticDescriptorsPerReference(
                infoCache,
                CreateDiagnosticAnalyzersPerReference(project)
                );
            var map = _hostAnalyzerReferencesMap.AddRange(
                CreateProjectAnalyzerReferencesMap(project.AnalyzerReferences)
                );

            return(ConvertReferenceIdentityToName(descriptorPerReference, map));
        }
Пример #21
0
        public static SkippedHostAnalyzersInfo Create(
            Project project,
            HostDiagnosticAnalyzers hostAnalyzers,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            var projectAnalyzers = hostAnalyzers.CreateProjectDiagnosticAnalyzersPerReference(project).SelectMany(v => v.Value);

            if (projectAnalyzers.IsEmpty())
            {
                return(Default);
            }

            var hostAnalyzersPerReference = hostAnalyzers.GetOrCreateHostDiagnosticAnalyzersPerReference(project.Language).SelectMany(v => v.Value);

            return(Create(projectAnalyzers, hostAnalyzersPerReference, analyzerInfoCache));
        }
Пример #22
0
        public static SkippedHostAnalyzersInfo Create(
            Project project,
            IEnumerable <AnalyzerReference> hostAnalyzerReferences,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            var projectAnalyzers = project.AnalyzerReferences.SelectMany(p => p.GetAnalyzers(project.Language));

            if (projectAnalyzers.IsEmpty())
            {
                return(Default);
            }

            var hostAnalyzers = hostAnalyzerReferences.SelectMany(p => p.GetAnalyzers(project.Language));

            return(Create(projectAnalyzers, hostAnalyzers, analyzerInfoCache));
        }
Пример #23
0
        protected DiagnosticAnalyzerService(
            IDiagnosticUpdateSourceRegistrationService registrationService,
            IAsynchronousOperationListener?listener)
        {
            AnalyzerInfoCache = new DiagnosticAnalyzerInfoCache();
            Listener          = listener ?? AsynchronousOperationListenerProvider.NullListener;

            _map = new ConditionalWeakTable <Workspace, DiagnosticIncrementalAnalyzer>();
            _createIncrementalAnalyzer = CreateIncrementalAnalyzerCallback;
            _eventMap = new EventMap();

            // use diagnostic event task scheduler so that we never flood async events queue with million of events.
            // queue itself can handle huge number of events but we are seeing OOM due to captured data in pending events.
            _eventQueue = new TaskQueue(Listener, s_eventScheduler);

            registrationService.Register(this);
        }
Пример #24
0
            static void ComputeSkippedHostAnalyzers(
                IEnumerable <DiagnosticAnalyzer> projectAnalyzers,
                IEnumerable <DiagnosticAnalyzer> hostAnalyzers,
                DiagnosticAnalyzerInfoCache analyzerInfoCache,
                out ImmutableHashSet <DiagnosticAnalyzer> fullySkippedHostAnalyzers,
                out ImmutableDictionary <DiagnosticAnalyzer, ImmutableArray <string> > filteredDiagnosticIdsForAnalyzers)
            {
                var idsReportedByProjectAnalyzers        = GetIdsReportedByProjectAnalyzers(projectAnalyzers, analyzerInfoCache);
                var fullySkippedHostAnalyzersBuilder     = ImmutableHashSet.CreateBuilder <DiagnosticAnalyzer>();
                var partiallySkippedHostAnalyzersBuilder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, ImmutableArray <string> >();

                using var _ = PooledHashSet <DiagnosticAnalyzer> .GetInstance(out var projectAnalyzersSet);

                projectAnalyzersSet.AddRange(projectAnalyzers);

                foreach (var hostAnalyzer in hostAnalyzers)
                {
                    if (projectAnalyzersSet.Contains(hostAnalyzer))
                    {
                        // Duplicate project and host analyzer.
                        // Do not mark this as a skipped host analyzer as that will also cause the project analyzer to be skipped.
                        // We already perform the required host analyzer reference de-duping in the executor.
                        continue;
                    }

                    if (!ShouldIncludeHostAnalyzer(hostAnalyzer, idsReportedByProjectAnalyzers, analyzerInfoCache, out var skippedIdsForAnalyzer))
                    {
                        fullySkippedHostAnalyzersBuilder.Add(hostAnalyzer);
                    }
                    else if (skippedIdsForAnalyzer.Length > 0)
                    {
                        partiallySkippedHostAnalyzersBuilder.Add(hostAnalyzer, skippedIdsForAnalyzer);
                    }
                }

                fullySkippedHostAnalyzers         = fullySkippedHostAnalyzersBuilder.ToImmutable();
                filteredDiagnosticIdsForAnalyzers = partiallySkippedHostAnalyzersBuilder.ToImmutable();
            }
Пример #25
0
        public static SkippedHostAnalyzersInfo Create(
            HostDiagnosticAnalyzers hostAnalyzers,
            IReadOnlyList <AnalyzerReference> projectAnalyzerReferences,
            string language,
            DiagnosticAnalyzerInfoCache analyzerInfoCache)
        {
            using var _1 = PooledHashSet <object> .GetInstance(out var projectAnalyzerIds);

            using var _2 = PooledHashSet <string> .GetInstance(out var projectAnalyzerDiagnosticIds);

            using var _3 = PooledHashSet <string> .GetInstance(out var projectSuppressedDiagnosticIds);

            foreach (var(analyzerId, analyzers) in hostAnalyzers.CreateProjectDiagnosticAnalyzersPerReference(projectAnalyzerReferences, language))
            {
                projectAnalyzerIds.Add(analyzerId);

                foreach (var analyzer in analyzers)
                {
                    foreach (var descriptor in analyzerInfoCache.GetDiagnosticDescriptors(analyzer))
                    {
                        projectAnalyzerDiagnosticIds.Add(descriptor.Id);
                    }

                    if (analyzer is DiagnosticSuppressor suppressor)
                    {
                        foreach (var descriptor in suppressor.SupportedSuppressions)
                        {
                            projectSuppressedDiagnosticIds.Add(descriptor.SuppressedDiagnosticId);
                        }
                    }
                }
            }

            if (projectAnalyzerIds.Count == 0)
            {
                return(Empty);
            }

            var fullySkippedHostAnalyzersBuilder     = ImmutableHashSet.CreateBuilder <DiagnosticAnalyzer>();
            var partiallySkippedHostAnalyzersBuilder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, ImmutableArray <string> >();

            foreach (var(hostAnalyzerId, analyzers) in hostAnalyzers.GetOrCreateHostDiagnosticAnalyzersPerReference(language))
            {
                foreach (var hostAnalyzer in analyzers)
                {
                    if (projectAnalyzerIds.Contains(hostAnalyzerId))
                    {
                        // Duplicate project and host analyzer.
                        // Do not mark this as a skipped host analyzer as that will also cause the project analyzer to be skipped.
                        // We already perform the required host analyzer reference de-duping in the executor.
                        continue;
                    }

                    if (!ShouldIncludeHostAnalyzer(hostAnalyzer, projectAnalyzerDiagnosticIds, projectSuppressedDiagnosticIds, analyzerInfoCache, out var skippedIdsForAnalyzer))
                    {
                        fullySkippedHostAnalyzersBuilder.Add(hostAnalyzer);
                    }
                    else if (skippedIdsForAnalyzer.Length > 0)
                    {
                        partiallySkippedHostAnalyzersBuilder.Add(hostAnalyzer, skippedIdsForAnalyzer);
                    }
                }
            }

            var fullySkippedHostAnalyzers         = fullySkippedHostAnalyzersBuilder.ToImmutable();
            var filteredDiagnosticIdsForAnalyzers = partiallySkippedHostAnalyzersBuilder.ToImmutable();

            if (fullySkippedHostAnalyzers.IsEmpty && filteredDiagnosticIdsForAnalyzers.IsEmpty)
            {
                return(Empty);
            }

            return(new SkippedHostAnalyzersInfo(fullySkippedHostAnalyzers, filteredDiagnosticIdsForAnalyzers));
Пример #26
0
        public ImmutableDictionary <string, ImmutableArray <DiagnosticDescriptor> > GetDiagnosticDescriptorsPerReference(DiagnosticAnalyzerInfoCache infoCache, Project project)
        {
            var descriptorPerReference = CreateDiagnosticDescriptorsPerReference(infoCache, CreateDiagnosticAnalyzersPerReference(project));
            var map = _hostAnalyzerReferencesMap.Value.AddRange(CreateProjectAnalyzerReferencesMap(project));

            return(ConvertReferenceIdentityToName(descriptorPerReference, map));
        }
Пример #27
0
 public ImmutableDictionary <string, ImmutableArray <DiagnosticDescriptor> > GetDiagnosticDescriptorsPerReference(DiagnosticAnalyzerInfoCache infoCache)
 {
     return(ConvertReferenceIdentityToName(
                CreateDiagnosticDescriptorsPerReference(infoCache, _lazyHostDiagnosticAnalyzersPerReferenceMap.Value),
                _hostAnalyzerReferencesMap.Value));
 }