提交 67969bc0 编写于 作者: M Manish Vasani

Merge pull request #1341 from mavasani/Issue249

Fixes #249 : Fix IDE diagnostics test framework to use DiagnosticAnalyzerService to compute diagnostics rather than DiagnosticAnalyzerDriver.

This change serves multiple purposes:
1) Makes our test framework consistent with the IDE scenario in fetching diagnostics. We have missed out on multiple regressions where the core IDE DiagnosticAnalyzerDriver does the right thing and hence the tests pass, but the DiagnosticService in IDE does additional filtering and certain diagnostics are not reported in VS. This change should avoid such bugs.
2) Enable testing for diagnostics V2 engine work that JohnHamby is doing to merge IDE and compiler analyzer drivers. For this engine, there is no IDE driver and hence existing IDE diagnostics tests can't be run. This change should enable running IDE diagnostic tests on V2 engine.
3) Move a whole bunch of test only code in DiagnosticAnalyzerService_Test.cs into the test layer.
......@@ -1222,9 +1222,17 @@ private static Compilation CreateCompilation(string source, string language, Dia
}
}
protected static DiagnosticDescription Diagnostic(string id, string squiggledText)
protected virtual bool ConsiderArgumentsForComparingDiagnostics
{
var arguments = squiggledText != null ? new[] { squiggledText } : null;
get
{
return true;
}
}
protected DiagnosticDescription Diagnostic(string id, string squiggledText)
{
var arguments = (this.ConsiderArgumentsForComparingDiagnostics && squiggledText != null) ? new[] { squiggledText } : null;
return new DiagnosticDescription(id, false, squiggledText, arguments, null, null, false);
}
}
......
......@@ -148,7 +148,7 @@ public void AnalyzerOptionsArePassedToAllAnalyzers()
private void AccessSupportedDiagnostics(DiagnosticAnalyzer analyzer)
{
var diagnosticService = new DiagnosticAnalyzerService(LanguageNames.CSharp, analyzer);
var diagnosticService = new TestDiagnosticAnalyzerService(LanguageNames.CSharp, analyzer);
diagnosticService.GetDiagnosticDescriptors(projectOpt: null);
}
......
......@@ -23,7 +23,7 @@ public class CodeFixServiceTests
[Fact]
public void TestGetFirstDiagnosticWithFixAsync()
{
var diagnosticService = new DiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
var diagnosticService = new TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
var fixers = CreateFixers();
var fixService = new CodeFixService(
......
......@@ -4,27 +4,22 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.EngineV1;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics
{
public static class DiagnosticProviderTestUtilities
{
private static IEnumerable<Diagnostic> GetDiagnostics(DiagnosticAnalyzer analyzerOpt, Document document, TextSpan span, Project project, bool getDocumentDiagnostics, bool getProjectDiagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException, bool logAnalyzerExceptionAsDiagnostics)
private static IEnumerable<Diagnostic> GetDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Document document, TextSpan span, Project project, bool getDocumentDiagnostics, bool getProjectDiagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException, bool logAnalyzerExceptionAsDiagnostics)
{
var documentDiagnostics = SpecializedCollections.EmptyEnumerable<Diagnostic>();
var projectDiagnostics = SpecializedCollections.EmptyEnumerable<Diagnostic>();
// If no user diagnostic analyzer, then test compiler diagnostics.
var analyzer = analyzerOpt ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(project.Language);
var workspaceAnalyzer = workspaceAnalyzerOpt ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(project.Language);
// If the test is not configured with a custom onAnalyzerException handler AND has not requested exceptions to be handled and logged as diagnostics, then FailFast on exceptions.
if (onAnalyzerException == null && !logAnalyzerExceptionAsDiagnostics)
......@@ -33,114 +28,68 @@ private static IEnumerable<Diagnostic> GetDiagnostics(DiagnosticAnalyzer analyze
}
var exceptionDiagnosticsSource = new TestHostDiagnosticUpdateSource(project.Solution.Workspace);
var analyzerService = new TestDiagnosticAnalyzerService(project.Language, workspaceAnalyzer, exceptionDiagnosticsSource, onAnalyzerException);
var incrementalAnalyzer = analyzerService.CreateIncrementalAnalyzer(project.Solution.Workspace);
if (getDocumentDiagnostics)
{
var tree = document.GetSyntaxTreeAsync().Result;
var root = document.GetSyntaxRootAsync().Result;
var semanticModel = document.GetSemanticModelAsync().Result;
var builder = new List<Diagnostic>();
var nodeInBodyAnalyzerService = document.Project.Language == LanguageNames.CSharp ?
(ISyntaxNodeAnalyzerService)new CSharpSyntaxNodeAnalyzerService() :
new VisualBasicSyntaxNodeAnalyzerService();
// Lets replicate the IDE diagnostic incremental analyzer behavior to determine span to test:
// (a) If the span is contained within a method level member and analyzer supports semantic in span: analyze in member span.
// (b) Otherwise, analyze entire syntax tree span.
var spanToTest = root.FullSpan;
var driver = new DiagnosticAnalyzerDriver(document, spanToTest, root,
syntaxNodeAnalyzerService: nodeInBodyAnalyzerService,
hostDiagnosticUpdateSource: exceptionDiagnosticsSource,
overriddenOnAnalyzerException: onAnalyzerException);
var diagnosticAnalyzerCategory = analyzer.GetDiagnosticAnalyzerCategory(driver);
bool supportsSemanticInSpan = (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0;
if (supportsSemanticInSpan)
{
var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
if (syntaxFacts != null)
{
var member = syntaxFacts.GetContainingMemberDeclaration(root, span.Start);
if (member != null && syntaxFacts.IsMethodLevelMember(member) && member.FullSpan.Contains(span))
{
spanToTest = member.FullSpan;
}
}
}
if ((diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SyntaxAnalysis) != 0)
{
builder.AddRange(driver.GetSyntaxDiagnosticsAsync(analyzer).Result);
}
if (supportsSemanticInSpan || (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticDocumentAnalysis) != 0)
{
builder.AddRange(driver.GetSemanticDiagnosticsAsync(analyzer).Result);
}
documentDiagnostics = builder.Where(d => d.Location == Location.None ||
(d.Location.SourceTree == tree && d.Location.SourceSpan.IntersectsWith(span)));
var root = tree.GetRoot();
var dxs = analyzerService.GetDiagnosticsAsync(project.Solution, project.Id, document.Id).WaitAndGetResult(CancellationToken.None);
documentDiagnostics = dxs.Where(d => d.HasTextSpan && d.TextSpan.IntersectsWith(span)).Select(d => d.ToDiagnostic(tree));
}
if (getProjectDiagnostics)
{
var nodeInBodyAnalyzerService = project.Language == LanguageNames.CSharp ?
(ISyntaxNodeAnalyzerService)new CSharpSyntaxNodeAnalyzerService() :
new VisualBasicSyntaxNodeAnalyzerService();
var driver = new DiagnosticAnalyzerDriver(project, nodeInBodyAnalyzerService, exceptionDiagnosticsSource, overriddenOnAnalyzerException: onAnalyzerException);
if (analyzer.SupportsProjectDiagnosticAnalysis(driver))
{
projectDiagnostics = driver.GetProjectDiagnosticsAsync(analyzer, null).Result;
}
var dxs = analyzerService.GetDiagnosticsAsync(project.Solution, project.Id).WaitAndGetResult(CancellationToken.None);
projectDiagnostics = dxs.Where(d => !d.HasTextSpan).Select(d => d.ToDiagnostic(tree: null));
}
var exceptionDiagnostics = exceptionDiagnosticsSource.TestOnly_GetReportedDiagnostics(analyzer).Select(d => d.ToDiagnostic(tree: null));
var exceptionDiagnostics = exceptionDiagnosticsSource.TestOnly_GetReportedDiagnostics(workspaceAnalyzer).Select(d => d.ToDiagnostic(tree: null));
return documentDiagnostics.Concat(projectDiagnostics).Concat(exceptionDiagnostics);
}
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer providerOpt, Document document, TextSpan span, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Document document, TextSpan span, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
{
return GetDiagnostics(providerOpt, document, span, document.Project, getDocumentDiagnostics: true, getProjectDiagnostics: true, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
return GetDiagnostics(workspaceAnalyzerOpt, document, span, document.Project, getDocumentDiagnostics: true, getProjectDiagnostics: true, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
}
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer providerOpt, Project project, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Project project, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
{
var diagnostics = new List<Diagnostic>();
foreach (var document in project.Documents)
{
var span = document.GetSyntaxRootAsync().Result.FullSpan;
var documentDiagnostics = GetDocumentDiagnostics(providerOpt, document, span, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
var documentDiagnostics = GetDocumentDiagnostics(workspaceAnalyzerOpt, document, span, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
diagnostics.AddRange(documentDiagnostics);
}
var projectDiagnostics = GetProjectDiagnostics(providerOpt, project, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
var projectDiagnostics = GetProjectDiagnostics(workspaceAnalyzerOpt, project, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
diagnostics.AddRange(projectDiagnostics);
return diagnostics;
}
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer providerOpt, Solution solution, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
public static IEnumerable<Diagnostic> GetAllDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Solution solution, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
{
var diagnostics = new List<Diagnostic>();
foreach (var project in solution.Projects)
{
var projectDiagnostics = GetAllDiagnostics(providerOpt, project, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
var projectDiagnostics = GetAllDiagnostics(workspaceAnalyzerOpt, project, onAnalyzerException, logAnalyzerExceptionAsDiagnostics);
diagnostics.AddRange(projectDiagnostics);
}
return diagnostics;
}
public static IEnumerable<Diagnostic> GetDocumentDiagnostics(DiagnosticAnalyzer providerOpt, Document document, TextSpan span, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
public static IEnumerable<Diagnostic> GetDocumentDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Document document, TextSpan span, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
{
return GetDiagnostics(providerOpt, document, span, document.Project, getDocumentDiagnostics: true, getProjectDiagnostics: false, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
return GetDiagnostics(workspaceAnalyzerOpt, document, span, document.Project, getDocumentDiagnostics: true, getProjectDiagnostics: false, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
}
public static IEnumerable<Diagnostic> GetProjectDiagnostics(DiagnosticAnalyzer providerOpt, Project project, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
public static IEnumerable<Diagnostic> GetProjectDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Project project, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
{
return GetDiagnostics(providerOpt, null, default(TextSpan), project, getDocumentDiagnostics: false, getProjectDiagnostics: true, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
return GetDiagnostics(workspaceAnalyzerOpt, null, default(TextSpan), project, getDocumentDiagnostics: false, getProjectDiagnostics: true, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics);
}
}
}
......@@ -73,7 +73,7 @@ private static void GetTagSource(TestWorkspace workspace, DiagnosticServiceWaite
{
analyzer = new Analyzer();
var analyzerMap = new Dictionary<string, ImmutableArray<DiagnosticAnalyzer>>() { { LanguageNames.CSharp, ImmutableArray.Create<DiagnosticAnalyzer>(analyzer) } };
analyzerService = new DiagnosticAnalyzerService(analyzerMap.ToImmutableDictionary());
analyzerService = new TestDiagnosticAnalyzerService(analyzerMap.ToImmutableDictionary());
var diagnosticListeners = SpecializedCollections.SingletonEnumerable(new Lazy<IAsynchronousOperationListener, FeatureMetadata>(
() => diagnosticWaiter, new FeatureMetadata(new Dictionary<string, object>() { { "FeatureName", FeatureAttribute.DiagnosticService } })));
......
......@@ -45,5 +45,15 @@ private static TestWorkspace CreateWorkspaceFromFile(string source, string langu
OutputKind.DynamicallyLinkedLibrary, rootNamespace: rootNamespace));
}
}
protected override bool ConsiderArgumentsForComparingDiagnostics
{
get
{
// Round tripping diagnostics from DiagnosticData causes the Arguments info stored within compiler DiagnosticWithInfo to be lost, so don't compare Arguments in IDE.
// NOTE: We will still compare squiggled text for the diagnostics, which is also a sufficient test.
return false;
}
}
}
}
// 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;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics.Log;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics
{
// put anything test related here
internal partial class DiagnosticAnalyzerService
internal sealed class TestDiagnosticAnalyzerService : DiagnosticAnalyzerService
{
// Internal for testing purposes.
internal DiagnosticAnalyzerService(string language, DiagnosticAnalyzer analyzer, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
: this(language, ImmutableArray.Create(analyzer), hostDiagnosticUpdateSource)
private readonly Action<Exception, DiagnosticAnalyzer, Diagnostic> _onAnalyzerException;
internal TestDiagnosticAnalyzerService(string language, DiagnosticAnalyzer analyzer, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: this(language, ImmutableArray.Create(analyzer), hostDiagnosticUpdateSource, onAnalyzerException)
{
}
// Internal for testing purposes.
internal DiagnosticAnalyzerService(string language, ImmutableArray<DiagnosticAnalyzer> analyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
internal TestDiagnosticAnalyzerService(string language, ImmutableArray<DiagnosticAnalyzer> analyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: this(ImmutableDictionary.CreateRange(
SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(language, analyzers))), hostDiagnosticUpdateSource)
SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(language, analyzers))), hostDiagnosticUpdateSource, onAnalyzerException)
{
}
internal TestDiagnosticAnalyzerService(ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzersMap, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: base(ImmutableArray.Create<AnalyzerReference>(new TestAnalyzerReferenceByLanguage(analyzersMap)), hostDiagnosticUpdateSource)
{
_onAnalyzerException = onAnalyzerException;
}
internal TestDiagnosticAnalyzerService(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: base(workspaceAnalyzerAssemblies: SpecializedCollections.EmptyEnumerable<string>(), hostDiagnosticUpdateSource: hostDiagnosticUpdateSource)
{
_onAnalyzerException = onAnalyzerException;
}
internal TestDiagnosticAnalyzerService(ImmutableArray<AnalyzerReference> workspaceAnalyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null)
: base(workspaceAnalyzers, hostDiagnosticUpdateSource)
{
_onAnalyzerException = onAnalyzerException;
}
// Internal for testing purposes.
internal DiagnosticAnalyzerService(ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzersMap, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
: this(ImmutableArray.Create<AnalyzerReference>(new TestAnalyzerReferenceByLanguage(analyzersMap)), hostDiagnosticUpdateSource)
internal override Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException(Project project, DiagnosticLogAggregator diagnosticLogAggregator)
{
return _onAnalyzerException ?? base.GetOnAnalyzerException(project, diagnosticLogAggregator);
}
// Internal for testing purposes.
internal DiagnosticAnalyzerService(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null)
: this(workspaceAnalyzerAssemblies: SpecializedCollections.EmptyEnumerable<string>(), hostDiagnosticUpdateSource: hostDiagnosticUpdateSource)
internal override Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException_NoTelemetryLogging(Project project)
{
return _onAnalyzerException ?? base.GetOnAnalyzerException_NoTelemetryLogging(project);
}
private class TestAnalyzerReferenceByLanguage : AnalyzerReference
......
......@@ -234,6 +234,7 @@
<Compile Include="Diagnostics\AbstractSuppressionDiagnosticTest.cs" />
<Compile Include="Diagnostics\AbstractDiagnosticProviderBasedUserDiagnosticTest.cs" />
<Compile Include="Diagnostics\AbstractUserDiagnosticTest.cs" />
<Compile Include="Diagnostics\TestDiagnosticAnalyzerService.cs" />
<Compile Include="Diagnostics\DiagnosticDataTests.cs" />
<Compile Include="Diagnostics\DiagnosticProviderTestUtilities.cs" />
<Compile Include="Diagnostics\DiagnosticServiceTests.cs" />
......
......@@ -36,11 +36,11 @@ protected static IEnumerable<ITagSpan<IErrorTag>> GetErrorSpans(TestWorkspace wo
if (analyzerMap == null || analyzerMap.Count == 0)
{
var compilerAnalyzersMap = DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap();
analyzerService = new DiagnosticAnalyzerService(compilerAnalyzersMap);
analyzerService = new TestDiagnosticAnalyzerService(compilerAnalyzersMap);
}
else
{
analyzerService = new DiagnosticAnalyzerService(analyzerMap);
analyzerService = new TestDiagnosticAnalyzerService(analyzerMap);
}
var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(analyzerService), diagnosticListeners);
......
......@@ -32,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
Dim workspaceDiagnosticAnalyzer = New WorkspaceDiagnosticAnalyzer()
Dim workspaceCodeFixProvider = New WorkspaceCodeFixProvider()
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
Dim analyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
Dim codefixService = New CodeFixService(
diagnosticService,
......@@ -94,7 +94,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
Dim workspaceDiagnosticAnalyzer = New WorkspaceDiagnosticAnalyzer()
Dim workspaceCodeFixProvider = New WorkspaceCodeFixProvider()
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.VisualBasic, workspaceDiagnosticAnalyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.VisualBasic, workspaceDiagnosticAnalyzer)
Dim analyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
Dim codefixService = New CodeFixService(
......
......@@ -291,7 +291,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim notificationServie = New TestForegroundNotificationService()
Dim compilerAnalyzersMap = DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap()
Dim analyzerService = New DiagnosticAnalyzerService(compilerAnalyzersMap)
Dim analyzerService = New TestDiagnosticAnalyzerService(compilerAnalyzersMap)
' CollectErrors generates interleaved background and foreground tasks.
Dim service = DirectCast(workspace.Services.GetService(Of ISolutionCrawlerRegistrationService)(), SolutionCrawlerRegistrationService)
......
......@@ -11,6 +11,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics
Imports Roslyn.Utilities
Imports Xunit.Sdk
......@@ -35,7 +36,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim projectDiagnosticAnalyzer1 = New ProjectDiagnosticAnalyzer(1)
Dim projectDiagnosticAnalyzer2 = New ProjectDiagnosticAnalyzer2(2)
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
' Verify available diagnostic descriptors/analyzers
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -144,7 +145,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim project = workspace.CurrentSolution.Projects(0)
Dim workspaceDiagnosticAnalyzer = New WorkspaceDiagnosticAnalyzer()
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
' Add project analyzer reference with no analyzers.
Dim projectAnalyzersEmpty = ImmutableArray(Of DiagnosticAnalyzer).Empty
......@@ -177,7 +178,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim project = workspace.CurrentSolution.Projects(0)
Dim workspaceDiagnosticAnalyzer = New WorkspaceDiagnosticAnalyzer()
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.CSharp, workspaceDiagnosticAnalyzer)
' Verify available diagnostic descriptors/analyzers
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -246,7 +247,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
bravo = bravo.WithAnalyzerReferences(SpecializedCollections.SingletonCollection(New AnalyzerImageReference(ImmutableArray(Of DiagnosticAnalyzer).Empty.Add(projectDiagnosticAnalyzer2))))
solution = bravo.Solution
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim analyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
Dim workspaceDescriptors = diagnosticService.GetDiagnosticDescriptors(projectOpt:=Nothing)
......@@ -281,7 +282,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim analyzersMap = New Dictionary(Of String, ImmutableArray(Of DiagnosticAnalyzer))
analyzersMap.Add(LanguageNames.CSharp, ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer1))
analyzersMap.Add(LanguageNames.VisualBasic, ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer2))
Dim diagnosticService2 = New DiagnosticAnalyzerService(analyzersMap.ToImmutableDictionary())
Dim diagnosticService2 = New TestDiagnosticAnalyzerService(analyzersMap.ToImmutableDictionary())
Dim descriptors = diagnosticService2.GetDiagnosticDescriptors(projectOpt:=Nothing)
Assert.Equal(1, descriptors.Count)
......@@ -327,7 +328,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
project = project.AddAnalyzerReference(analyzerReference1)
Dim analyzerReference2 = New AnalyzerFileReference(Assembly.GetExecutingAssembly().Location)
Dim diagnosticService = New DiagnosticAnalyzerService(ImmutableArray.Create(Of AnalyzerReference)(analyzerReference2))
Dim diagnosticService = New TestDiagnosticAnalyzerService(ImmutableArray.Create(Of AnalyzerReference)(analyzerReference2))
Dim analyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -384,7 +385,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -419,7 +420,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
project = project.AddAnalyzerReference(analyzerReference)
Dim exceptionDiagnosticsSource = New TestHostDiagnosticUpdateSource(workspace)
Dim diagnosticService = New DiagnosticAnalyzerService(hostDiagnosticUpdateSource:=exceptionDiagnosticsSource)
Dim diagnosticService = New TestDiagnosticAnalyzerService(hostDiagnosticUpdateSource:=exceptionDiagnosticsSource)
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -456,7 +457,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -489,7 +490,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
' Ensure no duplicate diagnostics.
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -565,7 +566,7 @@ class AnonymousFunctions
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
' Ensure no duplicate diagnostics.
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -604,7 +605,7 @@ class AnonymousFunctions
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
......@@ -662,17 +663,7 @@ class AnonymousFunctions
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
Dim incrementalAnalyzer = DirectCast(DirectCast(diagnosticService.CreateIncrementalAnalyzer(workspace), DiagnosticAnalyzerService.IncrementalAnalyzerDelegatee).Analyzer, DiagnosticIncrementalAnalyzer)
' Verify that for an analyzer which has a registered compilation start action such that the start action registered an end action,
' we go and force complete all document diagnostics for entire project and then invoke and report end action diagnostics.
Dim driver = New DiagnosticAnalyzerDriver(project, project.LanguageServices.GetService(Of ISyntaxNodeAnalyzerService)(), Nothing)
Dim projectDiagnostics = driver.GetProjectDiagnosticsAsync(analyzer, AddressOf incrementalAnalyzer.ForceAnalyzeAllDocuments).WaitAndGetResult(CancellationToken.None)
Dim projectDiagnostics = DiagnosticProviderTestUtilities.GetProjectDiagnostics(workspaceAnalyzerOpt:=Nothing, project:=project)
Assert.Equal(1, projectDiagnostics.Count())
Dim diagnostic = projectDiagnostics.Single()
Assert.Equal(StatefulCompilationAnalyzer.Descriptor.Id, diagnostic.Id)
......@@ -700,7 +691,7 @@ class AnonymousFunctions
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -738,7 +729,7 @@ public class B
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -779,7 +770,7 @@ public class B
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -820,7 +811,7 @@ public class B
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -870,7 +861,7 @@ End Class
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -931,7 +922,7 @@ public class B
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project)
Assert.Equal(1, descriptorsMap.Count)
......@@ -1000,7 +991,7 @@ public class B
Dim additionalDoc = project.AddAdditionalDocument("AdditionalDoc", additionalDocText)
project = additionalDoc.Project
Dim diagnosticService = New DiagnosticAnalyzerService()
Dim diagnosticService = New TestDiagnosticAnalyzerService()
Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)
TestCompilationAnalyzerWithAnalyzerOptionsCore(project, additionalDocText, diagnosticService)
......
......@@ -78,7 +78,7 @@ End Class
End Sub
Private Sub AccessSupportedDiagnostics(analyzer As DiagnosticAnalyzer)
Dim diagnosticService = New DiagnosticAnalyzerService(LanguageNames.VisualBasic, analyzer)
Dim diagnosticService = New TestDiagnosticAnalyzerService(LanguageNames.VisualBasic, analyzer)
diagnosticService.GetDiagnosticDescriptors(projectOpt:=Nothing)
End Sub
......
......@@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
......@@ -13,10 +14,13 @@ namespace Microsoft.CodeAnalysis.Diagnostics
{
internal abstract class BaseDiagnosticIncrementalAnalyzer : IIncrementalAnalyzer
{
protected BaseDiagnosticIncrementalAnalyzer(Workspace workspace, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
protected BaseDiagnosticIncrementalAnalyzer(DiagnosticAnalyzerService owner, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{
this.Owner = owner;
this.Workspace = workspace;
this.HostAnalyzerManager = hostAnalyzerManager;
this.HostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
this.DiagnosticLogAggregator = new DiagnosticLogAggregator(owner);
}
#region IIncrementalAnalyzer
......@@ -162,8 +166,16 @@ protected BaseDiagnosticIncrementalAnalyzer(Workspace workspace, AbstractHostDia
public abstract Task<IEnumerable<DiagnosticData>> GetDiagnosticsForSpanAsync(Document document, TextSpan range, CancellationToken cancellationToken);
#endregion
protected Workspace Workspace { get; }
protected AbstractHostDiagnosticUpdateSource HostDiagnosticUpdateSource { get; }
internal DiagnosticAnalyzerService Owner { get; }
internal Workspace Workspace { get; }
internal AbstractHostDiagnosticUpdateSource HostDiagnosticUpdateSource { get; }
internal HostAnalyzerManager HostAnalyzerManager { get; }
internal DiagnosticLogAggregator DiagnosticLogAggregator { get; private set; }
protected void ResetDiagnosticLogAggregator()
{
DiagnosticLogAggregator = new DiagnosticLogAggregator(Owner);
}
public virtual bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
{
......@@ -173,5 +185,17 @@ public virtual bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedE
public virtual void LogAnalyzerCountSummary()
{
}
// internal for testing purposes.
internal Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException(Project project)
{
return Owner?.GetOnAnalyzerException(project, DiagnosticLogAggregator);
}
// internal for testing purposes.
internal Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException_NoTelemetryLogging(Project project)
{
return Owner?.GetOnAnalyzerException_NoTelemetryLogging(project);
}
}
}
......@@ -6,6 +6,7 @@
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics.Log;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
......@@ -36,14 +37,15 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticAnalyzerService
public IAsynchronousOperationListener Listener => _listener;
private DiagnosticAnalyzerService(IEnumerable<string> workspaceAnalyzerAssemblies, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : this()
// protected for testing purposes.
protected DiagnosticAnalyzerService(IEnumerable<string> workspaceAnalyzerAssemblies, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : this()
{
_hostAnalyzerManager = new HostAnalyzerManager(workspaceAnalyzerAssemblies, hostDiagnosticUpdateSource);
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
}
// internal for testing purposes.
internal DiagnosticAnalyzerService(ImmutableArray<AnalyzerReference> workspaceAnalyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null) : this()
// protected for testing purposes.
protected DiagnosticAnalyzerService(ImmutableArray<AnalyzerReference> workspaceAnalyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource = null) : this()
{
_hostAnalyzerManager = new HostAnalyzerManager(workspaceAnalyzers, hostDiagnosticUpdateSource);
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
......@@ -166,5 +168,24 @@ public Task<ImmutableArray<DiagnosticData>> GetSpecificDiagnosticsAsync(Solution
return SpecializedTasks.EmptyImmutableArray<DiagnosticData>();
}
// virtual for testing purposes.
internal virtual Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException(Project project, DiagnosticLogAggregator diagnosticLogAggregator)
{
return (ex, analyzer, diagnostic) =>
{
// Log telemetry, if analyzer supports telemetry.
DiagnosticAnalyzerLogger.LogAnalyzerCrashCount(analyzer, ex, diagnosticLogAggregator);
AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, analyzer, diagnostic, _hostDiagnosticUpdateSource, project);
};
}
// virtual for testing purposes.
internal virtual Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException_NoTelemetryLogging(Project project)
{
return (ex, analyzer, diagnostic) =>
AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, analyzer, diagnostic, _hostDiagnosticUpdateSource, project);
}
}
}
......@@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics.Log;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Options;
......@@ -60,9 +61,6 @@ private void OnDocumentActiveContextChanged(object sender, DocumentEventArgs e)
// internal for testing
internal class IncrementalAnalyzerDelegatee : BaseDiagnosticIncrementalAnalyzer
{
private readonly HostAnalyzerManager _hostAnalyzerManager;
private readonly DiagnosticAnalyzerService _owner;
// v1 diagnostic engine
private readonly EngineV1.DiagnosticIncrementalAnalyzer _engineV1;
......@@ -70,16 +68,13 @@ internal class IncrementalAnalyzerDelegatee : BaseDiagnosticIncrementalAnalyzer
private readonly EngineV2.DiagnosticIncrementalAnalyzer _engineV2;
public IncrementalAnalyzerDelegatee(DiagnosticAnalyzerService owner, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
: base(workspace, hostDiagnosticUpdateSource)
: base(owner, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource)
{
_hostAnalyzerManager = hostAnalyzerManager;
_owner = owner;
var v1CorrelationId = LogAggregator.GetNextId();
_engineV1 = new EngineV1.DiagnosticIncrementalAnalyzer(_owner, v1CorrelationId, workspace, _hostAnalyzerManager, hostDiagnosticUpdateSource);
_engineV1 = new EngineV1.DiagnosticIncrementalAnalyzer(owner, v1CorrelationId, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource);
var v2CorrelationId = LogAggregator.GetNextId();
_engineV2 = new EngineV2.DiagnosticIncrementalAnalyzer(_owner, v2CorrelationId, workspace, _hostAnalyzerManager, hostDiagnosticUpdateSource);
_engineV2 = new EngineV2.DiagnosticIncrementalAnalyzer(owner, v2CorrelationId, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource);
}
#region IIncrementalAnalyzer
......
......@@ -8,8 +8,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics.Log;
using Microsoft.CodeAnalysis.GeneratedCodeRecognition;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -26,7 +24,7 @@ internal class DiagnosticAnalyzerDriver
// for the entire file.
private readonly TextSpan? _span;
private readonly Project _project;
private readonly AbstractHostDiagnosticUpdateSource _hostDiagnosticUpdateSource;
private readonly BaseDiagnosticIncrementalAnalyzer _owner;
private readonly CancellationToken _cancellationToken;
private readonly ISyntaxNodeAnalyzerService _syntaxNodeAnalyzerService;
private readonly IGeneratedCodeRecognitionService _generatedCodeService;
......@@ -35,67 +33,39 @@ internal class DiagnosticAnalyzerDriver
private readonly Action<Exception, DiagnosticAnalyzer, Diagnostic> _onAnalyzerException;
private readonly Action<Exception, DiagnosticAnalyzer, Diagnostic> _onAnalyzerException_NoTelemetryLogging;
private LogAggregator _logAggregator;
private ImmutableArray<DeclarationInfo> _lazyDeclarationInfos;
private ImmutableArray<ISymbol> _lazySymbols;
private ImmutableArray<SyntaxNode> _lazyAllSyntaxNodesToAnalyze;
private AnalyzerOptions _analyzerOptions = null;
public DiagnosticAnalyzerDriver(Document document, TextSpan? span, SyntaxNode root, LogAggregator logAggregator, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, CancellationToken cancellationToken)
: this(document, span, root, document.Project.LanguageServices.GetService<ISyntaxNodeAnalyzerService>(), hostDiagnosticUpdateSource, overriddenOnAnalyzerException: null, cancellationToken: cancellationToken)
{
_logAggregator = logAggregator;
}
public DiagnosticAnalyzerDriver(Project project, LogAggregator logAggregator, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource, CancellationToken cancellationToken)
: this(project, project.LanguageServices.GetService<ISyntaxNodeAnalyzerService>(), hostDiagnosticUpdateSource, overriddenOnAnalyzerException: null, cancellationToken: cancellationToken)
{
_logAggregator = logAggregator;
}
// internal for testing purposes
internal DiagnosticAnalyzerDriver(
Document document,
TextSpan? span,
public DiagnosticAnalyzerDriver(
Document document,
TextSpan? span,
SyntaxNode root,
ISyntaxNodeAnalyzerService syntaxNodeAnalyzerService,
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
Action<Exception, DiagnosticAnalyzer, Diagnostic> overriddenOnAnalyzerException = null,
CancellationToken cancellationToken = default(CancellationToken))
BaseDiagnosticIncrementalAnalyzer owner,
CancellationToken cancellationToken)
: this (document.Project, owner, cancellationToken)
{
_document = document;
_span = span;
_root = root;
_project = document.Project;
_syntaxNodeAnalyzerService = syntaxNodeAnalyzerService;
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
_cancellationToken = cancellationToken;
_generatedCodeService = document.Project.Solution.Workspace.Services.GetService<IGeneratedCodeRecognitionService>();
_analyzerDriverService = document.Project.LanguageServices.GetService<IAnalyzerDriverService>();
_analyzerOptions = new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, _project.Solution.Workspace);
_onAnalyzerException = overriddenOnAnalyzerException ?? Default_OnAnalyzerException;
_onAnalyzerException_NoTelemetryLogging = overriddenOnAnalyzerException ?? Default_OnAnalyzerException_NoTelemetryLogging;
}
// internal for testing purposes
internal DiagnosticAnalyzerDriver(
public DiagnosticAnalyzerDriver(
Project project,
ISyntaxNodeAnalyzerService syntaxNodeAnalyzerService,
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
Action<Exception, DiagnosticAnalyzer, Diagnostic> overriddenOnAnalyzerException = null,
CancellationToken cancellationToken = default(CancellationToken))
BaseDiagnosticIncrementalAnalyzer owner,
CancellationToken cancellationToken)
{
_project = project;
_owner = owner;
_syntaxNodeAnalyzerService = project.LanguageServices.GetService<ISyntaxNodeAnalyzerService>();
_cancellationToken = cancellationToken;
_syntaxNodeAnalyzerService = syntaxNodeAnalyzerService;
_generatedCodeService = project.Solution.Workspace.Services.GetService<IGeneratedCodeRecognitionService>();
_analyzerDriverService = project.LanguageServices.GetService<IAnalyzerDriverService>();
_hostDiagnosticUpdateSource = hostDiagnosticUpdateSource;
_analyzerOptions = new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, _project.Solution.Workspace);
_onAnalyzerException = overriddenOnAnalyzerException ?? Default_OnAnalyzerException;
_onAnalyzerException_NoTelemetryLogging = overriddenOnAnalyzerException ?? Default_OnAnalyzerException_NoTelemetryLogging;
_analyzerOptions = new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Workspace);
_onAnalyzerException = owner.GetOnAnalyzerException(project);
_onAnalyzerException_NoTelemetryLogging = owner.GetOnAnalyzerException_NoTelemetryLogging(project);
}
public Document Document
......@@ -339,14 +309,14 @@ public bool IsAnalyzerSuppressed(DiagnosticAnalyzer analyzer)
return false;
}
var analyzerExecutor = AnalyzerHelper.GetAnalyzerExecutorForSupportedDiagnostics(analyzer, _hostDiagnosticUpdateSource, _onAnalyzerException_NoTelemetryLogging, _cancellationToken);
var analyzerExecutor = AnalyzerHelper.GetAnalyzerExecutorForSupportedDiagnostics(analyzer, _owner.HostDiagnosticUpdateSource, _onAnalyzerException_NoTelemetryLogging, _cancellationToken);
return AnalyzerManager.Instance.IsDiagnosticAnalyzerSuppressed(analyzer, options, AnalyzerHelper.IsCompilerAnalyzer, analyzerExecutor);
}
private async Task<AnalyzerActions> GetAnalyzerActionsAsync(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
{
var analyzerActions = await AnalyzerManager.Instance.GetAnalyzerActionsAsync(analyzer, analyzerExecutor).ConfigureAwait(false);
DiagnosticAnalyzerLogger.UpdateAnalyzerTypeCount(analyzer, analyzerActions, (DiagnosticLogAggregator)_logAggregator);
DiagnosticAnalyzerLogger.UpdateAnalyzerTypeCount(analyzer, analyzerActions, _owner.DiagnosticLogAggregator);
return analyzerActions;
}
......@@ -489,18 +459,5 @@ private async Task GetCompilationDiagnosticsAsync(DiagnosticAnalyzer analyzer, L
diagnostics.AddRange(filteredDiagnostics);
}
}
private void Default_OnAnalyzerException_NoTelemetryLogging(Exception e, DiagnosticAnalyzer analyzer, Diagnostic diagnostic)
{
AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(e, analyzer, diagnostic, _hostDiagnosticUpdateSource, _project);
}
private void Default_OnAnalyzerException(Exception e, DiagnosticAnalyzer analyzer, Diagnostic diagnostic)
{
// Log telemetry, if analyzer supports telemetry.
DiagnosticAnalyzerLogger.LogAnalyzerCrashCount(analyzer, e, _logAggregator);
Default_OnAnalyzerException_NoTelemetryLogging(e, analyzer, diagnostic);
}
}
}
......@@ -210,7 +210,7 @@ private static ImmutableArray<DiagnosticData> GetExistingItems(AnalysisData exis
private void ValidateMemberDiagnostics(DiagnosticAnalyzer analyzer, Document document, SyntaxNode root, ImmutableArray<DiagnosticData> diagnostics)
{
#if RANGE
var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, CancellationToken.None);
var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, CancellationToken.None);
var expected = GetSemanticDiagnosticsAsync(documentBasedDriver, analyzer).WaitAndGetResult(documentBasedDriver.CancellationToken) ?? SpecializedCollections.EmptyEnumerable<DiagnosticData>();
Contract.Requires(diagnostics.SetEquals(expected));
#endif
......
......@@ -24,23 +24,19 @@ namespace Microsoft.CodeAnalysis.Diagnostics.EngineV1
internal partial class DiagnosticIncrementalAnalyzer : BaseDiagnosticIncrementalAnalyzer
{
private readonly int _correlationId;
private readonly DiagnosticAnalyzerService _owner;
private readonly MemberRangeMap _memberRangeMap;
private readonly AnalyzerExecutor _executor;
private readonly StateManager _stateManger;
private readonly SimpleTaskQueue _eventQueue;
private DiagnosticLogAggregator _diagnosticLogAggregator;
public DiagnosticIncrementalAnalyzer(
DiagnosticAnalyzerService owner,
int correlationId,
Workspace workspace,
HostAnalyzerManager analyzerManager,
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
: base(workspace, hostDiagnosticUpdateSource)
: base(owner, workspace, analyzerManager, hostDiagnosticUpdateSource)
{
_owner = owner;
_correlationId = correlationId;
_memberRangeMap = new MemberRangeMap();
_executor = new AnalyzerExecutor(this);
......@@ -48,8 +44,6 @@ internal partial class DiagnosticIncrementalAnalyzer : BaseDiagnosticIncremental
_stateManger = new StateManager(analyzerManager);
_stateManger.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged;
_diagnosticLogAggregator = new DiagnosticLogAggregator(_owner);
}
private void OnProjectAnalyzerReferenceChanged(object sender, ProjectAnalyzerReferenceChangedEventArgs e)
......@@ -61,7 +55,7 @@ private void OnProjectAnalyzerReferenceChanged(object sender, ProjectAnalyzerRef
}
// guarantee order of the events.
var asyncToken = _owner.Listener.BeginAsyncOperation(nameof(OnProjectAnalyzerReferenceChanged));
var asyncToken = Owner.Listener.BeginAsyncOperation(nameof(OnProjectAnalyzerReferenceChanged));
_eventQueue.ScheduleTask(() => ClearProjectStatesAsync(e.Project, e.Removed, CancellationToken.None), CancellationToken.None).CompletesAsyncOperation(asyncToken);
}
......@@ -129,7 +123,7 @@ private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet<string
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;
var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, this, cancellationToken);
var openedDocument = document.IsOpen();
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
......@@ -205,8 +199,8 @@ private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var memberId = syntaxFacts.GetMethodLevelMemberId(root, member);
var spanBasedDriver = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
var spanBasedDriver = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, this, cancellationToken);
var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, cancellationToken);
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
{
......@@ -251,7 +245,7 @@ private async Task AnalyzeDocumentAsync(Document document, VersionArgument versi
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;
var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, this, cancellationToken);
bool openedDocument = document.IsOpen();
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
......@@ -305,7 +299,7 @@ private async Task AnalyzeProjectAsync(Project project, ImmutableHashSet<string>
var projectTextVersion = await project.GetLatestDocumentVersionAsync(cancellationToken).ConfigureAwait(false);
var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
var analyzerDriver = new DiagnosticAnalyzerDriver(project, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
var analyzerDriver = new DiagnosticAnalyzerDriver(project, this, cancellationToken);
var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);
foreach (var stateSet in _stateManger.GetOrUpdateStateSets(project))
......@@ -439,14 +433,14 @@ private bool ShouldRunAnalyzerForClosedFile(bool openedDocument, DiagnosticAnaly
return true;
}
return _owner.GetDiagnosticDescriptors(analyzer).Any(d => d.DefaultSeverity != DiagnosticSeverity.Hidden);
return Owner.GetDiagnosticDescriptors(analyzer).Any(d => d.DefaultSeverity != DiagnosticSeverity.Hidden);
}
private bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer,
StateType stateTypeId, ImmutableHashSet<string> diagnosticIds)
{
bool discarded;
return ShouldRunAnalyzerForStateType(driver, analyzer, stateTypeId, out discarded, diagnosticIds, _owner.GetDiagnosticDescriptors);
return ShouldRunAnalyzerForStateType(driver, analyzer, stateTypeId, out discarded, diagnosticIds, Owner.GetDiagnosticDescriptors);
}
private static bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId,
......@@ -479,17 +473,17 @@ private bool ShouldRunAnalyzerForClosedFile(bool openedDocument, DiagnosticAnaly
// internal for testing purposes only.
internal void ForceAnalyzeAllDocuments(Project project, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
{
var diagnosticIds = _owner.GetDiagnosticDescriptors(analyzer).Select(d => d.Id).ToImmutableHashSet();
var diagnosticIds = Owner.GetDiagnosticDescriptors(analyzer).Select(d => d.Id).ToImmutableHashSet();
ReanalyzeAllDocumentsAsync(project, diagnosticIds, cancellationToken).Wait(cancellationToken);
}
public override void LogAnalyzerCountSummary()
{
DiagnosticAnalyzerLogger.LogAnalyzerCrashCountSummary(_correlationId, _diagnosticLogAggregator);
DiagnosticAnalyzerLogger.LogAnalyzerTypeCountSummary(_correlationId, _diagnosticLogAggregator);
DiagnosticAnalyzerLogger.LogAnalyzerCrashCountSummary(_correlationId, DiagnosticLogAggregator);
DiagnosticAnalyzerLogger.LogAnalyzerTypeCountSummary(_correlationId, DiagnosticLogAggregator);
// reset the log aggregator
_diagnosticLogAggregator = new DiagnosticLogAggregator(_owner);
ResetDiagnosticLogAggregator();
}
private static bool CheckSyntaxVersions(Document document, AnalysisData existingData, VersionArgument versions)
......@@ -596,13 +590,13 @@ private static ImmutableArray<DiagnosticData> GetDiagnosticData(ILookup<Document
private void RaiseDiagnosticsUpdated(
StateType type, object key, DiagnosticAnalyzer analyzer, SolutionArgument solution, ImmutableArray<DiagnosticData> diagnostics)
{
if (_owner == null)
if (Owner == null)
{
return;
}
var id = new ArgumentKey(analyzer, type, key);
_owner.RaiseDiagnosticsUpdated(this,
Owner.RaiseDiagnosticsUpdated(this,
new DiagnosticsUpdatedArgs(id, Workspace, solution.Solution, solution.ProjectId, solution.DocumentId, diagnostics));
}
......
......@@ -360,14 +360,14 @@ protected async Task<DiagnosticAnalyzerDriver> GetDiagnosticAnalyzerDriverAsync(
{
Contract.Requires(stateType != StateType.Project);
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
return new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this.DiagnosticLogAggregator, this.Owner.HostDiagnosticUpdateSource, cancellationToken);
return new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this.Owner, cancellationToken);
}
var project = documentOrProject as Project;
if (project != null)
{
Contract.Requires(stateType == StateType.Project);
return new DiagnosticAnalyzerDriver(project, this.DiagnosticLogAggregator, this.Owner.HostDiagnosticUpdateSource, cancellationToken);
return new DiagnosticAnalyzerDriver(project, this.Owner, cancellationToken);
}
return Contract.FailWithReturn<DiagnosticAnalyzerDriver>("Can't reach here");
......@@ -444,7 +444,7 @@ protected Project GetProject(object documentOrProject)
private DiagnosticLogAggregator DiagnosticLogAggregator
{
get { return this.Owner._diagnosticLogAggregator; }
get { return this.Owner.DiagnosticLogAggregator; }
}
}
......
......@@ -47,9 +47,9 @@ private class LatestDiagnosticsForSpanGetter
// Share the diagnostic analyzer driver across all analyzers.
var fullSpan = root?.FullSpan;
_spanBasedDriver = new DiagnosticAnalyzerDriver(_document, _range, root, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
_documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
_projectDriver = new DiagnosticAnalyzerDriver(_document.Project, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
_spanBasedDriver = new DiagnosticAnalyzerDriver(_document, _range, root, _owner, _cancellationToken);
_documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner, _cancellationToken);
_projectDriver = new DiagnosticAnalyzerDriver(_document.Project, _owner, _cancellationToken);
}
public List<DiagnosticData> Diagnostics { get; }
......
......@@ -14,15 +14,11 @@ namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2
internal class DiagnosticIncrementalAnalyzer : BaseDiagnosticIncrementalAnalyzer
{
private readonly int _correlationId;
private readonly DiagnosticAnalyzerService _owner;
private readonly HostAnalyzerManager _hostAnalyzerManager;
public DiagnosticIncrementalAnalyzer(DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
: base(workspace, hostDiagnosticUpdateSource)
: base(owner, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource)
{
_correlationId = correlationId;
_owner = owner;
_hostAnalyzerManager = hostAnalyzerManager;
}
#region IIncrementalAnalyzer
......@@ -60,13 +56,13 @@ public override Task NewSolutionSnapshotAsync(Solution solution, CancellationTok
public override void RemoveDocument(DocumentId documentId)
{
_owner.RaiseDiagnosticsUpdated(
Owner.RaiseDiagnosticsUpdated(
this, new DiagnosticsUpdatedArgs(ValueTuple.Create(this, documentId), Workspace, null, null, null, ImmutableArray<DiagnosticData>.Empty));
}
public override void RemoveProject(ProjectId projectId)
{
_owner.RaiseDiagnosticsUpdated(
Owner.RaiseDiagnosticsUpdated(
this, new DiagnosticsUpdatedArgs(ValueTuple.Create(this, projectId), Workspace, null, null, null, ImmutableArray<DiagnosticData>.Empty));
}
#endregion
......@@ -154,7 +150,7 @@ private async Task<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsAsync(Pr
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var analyzers = _hostAnalyzerManager.CreateDiagnosticAnalyzers(project);
var analyzers = HostAnalyzerManager.CreateDiagnosticAnalyzers(project);
var compilationWithAnalyzer = compilation.WithAnalyzers(analyzers, project.AnalyzerOptions, cancellationToken);
......@@ -196,13 +192,13 @@ private void RaiseEvents(Project project, ImmutableArray<DiagnosticData> diagnos
{
if (kv.Key == null)
{
_owner.RaiseDiagnosticsUpdated(
Owner.RaiseDiagnosticsUpdated(
this, new DiagnosticsUpdatedArgs(
ValueTuple.Create(this, project.Id), workspace, solution, project.Id, null, kv.ToImmutableArrayOrEmpty()));
continue;
}
_owner.RaiseDiagnosticsUpdated(
Owner.RaiseDiagnosticsUpdated(
this, new DiagnosticsUpdatedArgs(
ValueTuple.Create(this, kv.Key), workspace, solution, project.Id, kv.Key, kv.ToImmutableArrayOrEmpty()));
}
......
......@@ -205,7 +205,6 @@
<Compile Include="Diagnostics\EngineV1\DiagnosticIncrementalAnalyzer.StateType.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerService_IncrementalAnalyzer.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerService_UpdateSource.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerService_Test.cs" />
<Compile Include="Diagnostics\IAnalyzerDriverService.cs" />
<Compile Include="Diagnostics\IBuiltInAnalyzer.cs" />
<Compile Include="Diagnostics\IDiagnosticAnalyzerService.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册