From 73407668d4100c1aacb34e1685d842de1d5934fd Mon Sep 17 00:00:00 2001 From: Tom Meschter Date: Fri, 6 Mar 2015 15:20:58 -0800 Subject: [PATCH 1/2] Catch exceptions from user code The Solution Explorer calls `DiagnosticAnalyzer.SupportedDiagnostics` to determine the list of items to show. This property is implemented by a 3rd-party (the analyzer author) and could potentially throw. Here we move to using the `DiagnosticAnalyzerService` to obtain this data; it will catch any exceptions and handle reporting them to the user as appropriate. Fixes #898. --- .../DiagnosticItem/DiagnosticItemProvider.cs | 6 +++++- .../DiagnosticItem/DiagnosticItemSource.cs | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs index db20ca3594687..d3c20ee6c1ccc 100644 --- a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs +++ b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.Internal.VisualStudio.PlatformUI; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Utilities; @@ -15,11 +16,14 @@ internal sealed class DiagnosticItemProvider : AttachedCollectionSourceProvider< [Import(typeof(AnalyzersCommandHandler))] private IAnalyzersCommandHandler _commandHandler = null; + [Import] + private IDiagnosticAnalyzerService _diagnosticAnalyzerService = null; + protected override IAttachedCollectionSource CreateCollectionSource(AnalyzerItem item, string relationshipName) { if (relationshipName == KnownRelationships.Contains) { - return new DiagnosticItemSource(item, _commandHandler); + return new DiagnosticItemSource(item, _commandHandler, (DiagnosticAnalyzerService)_diagnosticAnalyzerService); } return null; diff --git a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs index 78d16c6dda2b1..aa1c6cbf16ee9 100644 --- a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs +++ b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Shell; +using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer { @@ -19,16 +20,18 @@ internal partial class DiagnosticItemSource : IAttachedCollectionSource private readonly AnalyzerItem _item; private readonly IAnalyzersCommandHandler _commandHandler; + private readonly DiagnosticAnalyzerService _diagnosticAnalyzerService; private BulkObservableCollection _diagnosticItems; private Workspace _workspace; private ProjectId _projectId; private ReportDiagnostic _generalDiagnosticOption; private ImmutableDictionary _specificDiagnosticOptions; - public DiagnosticItemSource(AnalyzerItem item, IAnalyzersCommandHandler commandHandler) + public DiagnosticItemSource(AnalyzerItem item, IAnalyzersCommandHandler commandHandler, DiagnosticAnalyzerService diagnosticAnalyzerService) { _item = item; _commandHandler = commandHandler; + _diagnosticAnalyzerService = diagnosticAnalyzerService; } public object SourceItem @@ -90,7 +93,7 @@ private IEnumerable GetDiagnosticItems(string language) // one. return _item.AnalyzerReference.GetAnalyzers(language) - .SelectMany(a => a.SupportedDiagnostics) + .SelectMany(a => _diagnosticAnalyzerService.GetDiagnosticDescriptors(a)) .GroupBy(d => d.Id) .OrderBy(g => g.Key, StringComparer.CurrentCulture) .Select(g => From c8c94650605c412a680766a78336b0a37adfdd94 Mon Sep 17 00:00:00 2001 From: Tom Meschter Date: Tue, 10 Mar 2015 09:46:56 -0700 Subject: [PATCH 2/2] Add a method to `IDiagnosticAnalyzerService` Add the `GetDiagnosticDescriptors(DiagnosticAnalyzer)` method to the `IDiagnosticAnalyzerService` interface. --- src/Features/Core/Diagnostics/IDiagnosticAnalyzerService.cs | 6 ++++++ .../DiagnosticItem/DiagnosticItemProvider.cs | 2 +- .../DiagnosticItem/DiagnosticItemSource.cs | 4 ++-- .../Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb | 4 ++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Features/Core/Diagnostics/IDiagnosticAnalyzerService.cs b/src/Features/Core/Diagnostics/IDiagnosticAnalyzerService.cs index 77094a15943bc..47b3550806785 100644 --- a/src/Features/Core/Diagnostics/IDiagnosticAnalyzerService.cs +++ b/src/Features/Core/Diagnostics/IDiagnosticAnalyzerService.cs @@ -70,5 +70,11 @@ internal interface IDiagnosticAnalyzerService /// /// A mapping from analyzer name to the diagnostics produced by that analyzer ImmutableDictionary> GetDiagnosticDescriptors(Project projectOpt); + + /// + /// Gets a list of the diagnostics provided by the given . + /// + /// A list of the diagnostics produced by the given analyzer + ImmutableArray GetDiagnosticDescriptors(DiagnosticAnalyzer analyzer); } } diff --git a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs index d3c20ee6c1ccc..1c3e3c0c570db 100644 --- a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs +++ b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemProvider.cs @@ -23,7 +23,7 @@ protected override IAttachedCollectionSource CreateCollectionSource(AnalyzerItem { if (relationshipName == KnownRelationships.Contains) { - return new DiagnosticItemSource(item, _commandHandler, (DiagnosticAnalyzerService)_diagnosticAnalyzerService); + return new DiagnosticItemSource(item, _commandHandler, _diagnosticAnalyzerService); } return null; diff --git a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs index aa1c6cbf16ee9..928588746ef62 100644 --- a/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs +++ b/src/VisualStudio/Core/SolutionExplorerShim/DiagnosticItem/DiagnosticItemSource.cs @@ -20,14 +20,14 @@ internal partial class DiagnosticItemSource : IAttachedCollectionSource private readonly AnalyzerItem _item; private readonly IAnalyzersCommandHandler _commandHandler; - private readonly DiagnosticAnalyzerService _diagnosticAnalyzerService; + private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService; private BulkObservableCollection _diagnosticItems; private Workspace _workspace; private ProjectId _projectId; private ReportDiagnostic _generalDiagnosticOption; private ImmutableDictionary _specificDiagnosticOptions; - public DiagnosticItemSource(AnalyzerItem item, IAnalyzersCommandHandler commandHandler, DiagnosticAnalyzerService diagnosticAnalyzerService) + public DiagnosticItemSource(AnalyzerItem item, IAnalyzersCommandHandler commandHandler, IDiagnosticAnalyzerService diagnosticAnalyzerService) { _item = item; _commandHandler = commandHandler; diff --git a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb index da810bd1acb85..7288ae767c3e5 100644 --- a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb +++ b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb @@ -185,6 +185,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics Public Function GetProjectDiagnosticsForIdsAsync(solution As Solution, Optional projectId As ProjectId = Nothing, Optional diagnosticIds As ImmutableHashSet(Of String) = Nothing, Optional cancellationToken As CancellationToken = Nothing) As Task(Of ImmutableArray(Of DiagnosticData)) Implements IDiagnosticAnalyzerService.GetProjectDiagnosticsForIdsAsync Return SpecializedTasks.EmptyImmutableArray(Of DiagnosticData)() End Function + + Public Function GetDiagnosticDescriptors(analyzer As DiagnosticAnalyzer) As ImmutableArray(Of DiagnosticDescriptor) Implements IDiagnosticAnalyzerService.GetDiagnosticDescriptors + Return ImmutableArray(Of DiagnosticDescriptor).Empty + End Function End Class End Class End Namespace