diff --git a/src/EditorFeatures/TestUtilities/ServiceTestExportProvider.cs b/src/EditorFeatures/TestUtilities/ServiceTestExportProvider.cs index a02cef76bf0e876597b8fba1080f1f6428a71f9d..6d26ac6ef2f2e184183903a8415e3abd2ee4b8b8 100644 --- a/src/EditorFeatures/TestUtilities/ServiceTestExportProvider.cs +++ b/src/EditorFeatures/TestUtilities/ServiceTestExportProvider.cs @@ -34,8 +34,7 @@ public static Type[] GetLanguageNeutralTypes() typeof(Microsoft.CodeAnalysis.Editor.Implementation.SmartIndent.SmartIndentProvider), typeof(Microsoft.CodeAnalysis.Editor.Implementation.ForegroundNotification.ForegroundNotificationService), typeof(Implementation.InlineRename.InlineRenameService), // Ensure that EditorFeatures.Wpf is included in the composition - typeof(IncrementalCaches.SymbolTreeInfoIncrementalAnalyzerProvider), - typeof(CodeAnalysis.Diagnostics.EngineV2.DiagnosticAnalyzerExecutor) + typeof(IncrementalCaches.SymbolTreeInfoIncrementalAnalyzerProvider) }; return MinimalTestExportProvider.GetLanguageNeutralTypes().Concat(types).Distinct().ToArray(); diff --git a/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs b/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs index 68e757c5d1947b055530404f9112e8d75eee2564..de4d8eca38e1bc4a982e4c8bde92752fa068db9e 100644 --- a/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs +++ b/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs @@ -10,6 +10,9 @@ using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; +using Microsoft.CodeAnalysis.Diagnostics.Log; +using Microsoft.CodeAnalysis.Diagnostics.Telemetry; +using System.Collections.Immutable; namespace Microsoft.CodeAnalysis.Diagnostics { @@ -294,5 +297,15 @@ public static void AppendAnalyzerMap(this Dictionary analyzerMap[analyzer.GetAnalyzerId()] = analyzer; } } + + public static IEnumerable ToAnalyzerPerformanceInfo(this IDictionary analysisResult, IDiagnosticAnalyzerService serviceOpt = null) + { + return Convert(analysisResult.Select(kv => (kv.Key, kv.Value.ExecutionTime)), serviceOpt); + } + + private static IEnumerable Convert(IEnumerable<(DiagnosticAnalyzer analyzer, TimeSpan timeSpan)> analyzerPerf, IDiagnosticAnalyzerService serviceOpt = null) + { + return analyzerPerf.Select(kv => new AnalyzerPerformanceInfo(kv.analyzer.GetAnalyzerId(), DiagnosticAnalyzerLogger.AllowsTelemetry(kv.analyzer, serviceOpt), kv.timeSpan)); + } } } diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs index a446155b3d4478d387567846c6ac97998abcbcf5..4faeb20f9c929ab70d5de691bd3b4c494bb67cbb 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs @@ -82,7 +82,7 @@ public Task CreateAnalyzerDriverAsync(Project project, // Create driver that holds onto compilation and associated analyzers return CreateAnalyzerDriver( - project, compilation, analyzers, logAnalyzerExecutionTime: false, reportSuppressedDiagnostics: includeSuppressedDiagnostics); + project, compilation, analyzers, logAnalyzerExecutionTime: true, reportSuppressedDiagnostics: includeSuppressedDiagnostics); } private CompilationWithAnalyzers CreateAnalyzerDriver( diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs index 2ecff8e2d994622c0e7810b2118fd56d570b7eda..266062d577c4e0c8e8037e1bbf0b04f06221ca6f 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.Executor.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.Diagnostics.Log; using Microsoft.CodeAnalysis.Diagnostics.Telemetry; using Microsoft.CodeAnalysis.ErrorReporting; -using Microsoft.CodeAnalysis.Execution; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Options; using Microsoft.CodeAnalysis.Text; @@ -27,10 +26,12 @@ internal partial class DiagnosticIncrementalAnalyzer private class Executor { private readonly DiagnosticIncrementalAnalyzer _owner; + private readonly InProcOrRemoteHostAnalyzerRunner _diagnosticAnalyzerRunner; public Executor(DiagnosticIncrementalAnalyzer owner) { _owner = owner; + _diagnosticAnalyzerRunner = new InProcOrRemoteHostAnalyzerRunner(_owner.Owner, _owner.HostDiagnosticUpdateSource); } public IEnumerable ConvertToLocalDiagnostics(Document targetDocument, IEnumerable diagnostics, TextSpan? span = null) @@ -578,8 +579,7 @@ private IEnumerable ConvertToLocalDiagnosticsWithoutCompilation( ImmutableDictionary.Empty); } - var executor = project.Solution.Workspace.Services.GetService(); - return await executor.AnalyzeAsync(analyzerDriver, project, forcedAnalysis, cancellationToken).ConfigureAwait(false); + return await _diagnosticAnalyzerRunner.AnalyzeAsync(analyzerDriver, project, forcedAnalysis, cancellationToken).ConfigureAwait(false); } private IEnumerable ConvertToLocalDiagnosticsWithCompilation(Document targetDocument, IEnumerable diagnostics, TextSpan? span = null) diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticAnalyzerExecutor.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner.cs similarity index 81% rename from src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticAnalyzerExecutor.cs rename to src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner.cs index 47b9cd9eaae534e298354f6fd49aa7f6d73b03b5..c98775addb95f7b8d4079ae05291a02c0a29444e 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticAnalyzerExecutor.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner.cs @@ -4,49 +4,36 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; -using System.Composition; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics.Telemetry; +using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Execution; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Remote; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2 { - [ExportWorkspaceServiceFactory(typeof(ICodeAnalysisDiagnosticAnalyzerExecutor)), Shared] - internal class DiagnosticAnalyzerExecutor : IWorkspaceServiceFactory + internal partial class DiagnosticIncrementalAnalyzer { - private readonly AbstractHostDiagnosticUpdateSource _hostDiagnosticUpdateSourceOpt; - - [ImportingConstructor] - public DiagnosticAnalyzerExecutor([Import(AllowDefault = true)]AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) - { - // hostDiagnosticUpdateSource can be null in unit test - _hostDiagnosticUpdateSourceOpt = hostDiagnosticUpdateSource; - } - - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - { - return new AnalyzerExecutor(_hostDiagnosticUpdateSourceOpt); - } - - private class AnalyzerExecutor : ICodeAnalysisDiagnosticAnalyzerExecutor + // internal for testing + internal class InProcOrRemoteHostAnalyzerRunner { + private readonly DiagnosticAnalyzerService _owner; private readonly AbstractHostDiagnosticUpdateSource _hostDiagnosticUpdateSourceOpt; // TODO: this should be removed once we move options down to compiler layer private readonly ConcurrentDictionary> _lastOptionSetPerLanguage; - public AnalyzerExecutor(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) + public InProcOrRemoteHostAnalyzerRunner(DiagnosticAnalyzerService owner, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) { + _owner = owner; _hostDiagnosticUpdateSourceOpt = hostDiagnosticUpdateSource; // currently option is a bit wierd since it is not part of snapshot and @@ -80,7 +67,7 @@ public AnalyzerExecutor(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateS } // due to OpenFileOnly analyzer, we need to run inproc as well for such analyzers - var inProcResultTask = AnalyzeInProcAsync(CreateAnalyzerDriver(analyzerDriver, a => a.IsOpenFileOnly(project.Solution.Workspace)), project, cancellationToken); + var inProcResultTask = AnalyzeInProcAsync(CreateAnalyzerDriver(analyzerDriver, a => a.IsOpenFileOnly(project.Solution.Workspace)), project, remoteHostClient, cancellationToken); var outOfProcResultTask = AnalyzeOutOfProcAsync(remoteHostClient, analyzerDriver, project, forcedAnalysis, cancellationToken); // run them concurrently in vs and remote host @@ -95,8 +82,14 @@ public AnalyzerExecutor(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateS inProcResultTask.Result.TelemetryInfo.AddRange(outOfProcResultTask.Result.TelemetryInfo)); } - private async Task> AnalyzeInProcAsync( + private Task> AnalyzeInProcAsync( CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken) + { + return AnalyzeInProcAsync(analyzerDriver, project, client: null, cancellationToken); + } + + private async Task> AnalyzeInProcAsync( + CompilationWithAnalyzers analyzerDriver, Project project, RemoteHostClient client, CancellationToken cancellationToken) { if (analyzerDriver == null || analyzerDriver.Analyzers.Length == 0) @@ -110,12 +103,41 @@ public AnalyzerExecutor(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateS // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API. var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false); + // if remote host is there, report performance data + var asyncToken = _owner?.Listener.BeginAsyncOperation(nameof(AnalyzeInProcAsync)); + var _ = FireAndForgetReportAnalyzerPerformanceAsync(project, client, analysisResult, cancellationToken).CompletesAsyncOperation(asyncToken); + // get compiler result builder map var builderMap = analysisResult.ToResultBuilderMap(project, version, analyzerDriver.Compilation, analyzerDriver.Analyzers, cancellationToken); return DiagnosticAnalysisResultMap.Create(builderMap.ToImmutableDictionary(kv => kv.Key, kv => new DiagnosticAnalysisResult(kv.Value)), analysisResult.AnalyzerTelemetryInfo); } + private async Task FireAndForgetReportAnalyzerPerformanceAsync(Project project, RemoteHostClient client, AnalysisResult analysisResult, CancellationToken cancellationToken) + { + if (client == null) + { + return; + } + + try + { + await client.TryRunCodeAnalysisRemoteAsync( + nameof(IRemoteDiagnosticAnalyzerService.ReportAnalyzerPerformance), + new object[] + { + analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(_owner), + // +1 for project itself + project.DocumentIds.Count + 1 + }, + cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) when (FatalError.ReportWithoutCrashUnlessCanceled(ex)) + { + // ignore all, this is fire and forget method + } + } + private async Task> AnalyzeOutOfProcAsync( RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken) { @@ -149,7 +171,7 @@ public AnalyzerExecutor(AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateS session.AddAdditionalAssets(optionAsset); var result = await session.InvokeAsync( - WellKnownServiceHubServices.CodeAnalysisService_CalculateDiagnosticsAsync, + nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync), new object[] { argument }, (s, c) => GetCompilerAnalysisResultAsync(s, analyzerMap, project, c), cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs index b6d1fb8dfb932f8d3d5e403ea6a475f3e7c955fe..93eab43d0b052dfc61d07a731d8524733a452509 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs @@ -6,10 +6,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics.Telemetry; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Options; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Roslyn.Utilities; @@ -59,6 +62,9 @@ private async Task AnalyzeDocumentForKindAsync(Document document, AnalysisKind k RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, result.OldItems, result.Items); } + + var asyncToken = Owner.Listener.BeginAsyncOperation(nameof(AnalyzeDocumentForKindAsync)); + var _ = ReportAnalyzerPerformanceAsync(document, analyzerDriverOpt, cancellationToken).CompletesAsyncOperation(asyncToken); } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { @@ -429,5 +435,57 @@ private void RaiseProjectDiagnosticsRemoved(StateSet stateSet, ProjectId project RaiseDiagnosticsRemoved(projectId, nullSolution, stateSet, raiseEvents); } + + private async Task ReportAnalyzerPerformanceAsync(Document document, CompilationWithAnalyzers analyzerDriverOpt, CancellationToken cancellationToken) + { + try + { + if (analyzerDriverOpt == null) + { + return; + } + + var client = await document.Project.Solution.Workspace.TryGetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false); + if (client == null) + { + // no remote support + return; + } + + cancellationToken.ThrowIfCancellationRequested(); + + using (var pooledObject = SharedPools.Default>().GetPooledObject()) + { + var containsData = false; + foreach (var analyzer in analyzerDriverOpt.Analyzers) + { + var telemetryInfo = await analyzerDriverOpt.GetAnalyzerTelemetryInfoAsync(analyzer, cancellationToken).ConfigureAwait(false); + if (!containsData && telemetryInfo.ExecutionTime.Ticks > 0) + { + // this is unfortunate tweak due to how GetAnalyzerTelemetryInfoAsync works when analyzers are asked + // one by one rather than in bulk. + containsData = true; + } + + pooledObject.Object.Add(analyzer, telemetryInfo); + } + + if (!containsData) + { + // looks like there is no new data from driver. skip reporting. + return; + } + + await client.TryRunCodeAnalysisRemoteAsync( + nameof(IRemoteDiagnosticAnalyzerService.ReportAnalyzerPerformance), + new object[] { pooledObject.Object.ToAnalyzerPerformanceInfo(Owner), /* unit count */ 1 }, + cancellationToken).ConfigureAwait(false); + } + } + catch (Exception ex) when (FatalError.ReportWithoutCrashUnlessCanceled(ex)) + { + // this is fire and forget method + } + } } } diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/ICodeAnalysisDiagnosticAnalyzerExecutor.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/ICodeAnalysisDiagnosticAnalyzerExecutor.cs deleted file mode 100644 index 78960f8ebf72d0cf2b5e86f45d61cafdd4288e53..0000000000000000000000000000000000000000 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/ICodeAnalysisDiagnosticAnalyzerExecutor.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Workspaces.Diagnostics; - -namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2 -{ - /// - /// Interface to run DiagnosticAnalyzers. Implementation of this interface should be - /// able to run analyzers that can run in command line (Host agnostic DiagnosticAnalyzers) - /// - /// How and where analyzers run depends on the implementation of this interface - /// - internal interface ICodeAnalysisDiagnosticAnalyzerExecutor : IWorkspaceService - { - Task> AnalyzeAsync(CompilationWithAnalyzers analyzerDriver, Project project, bool forcedAnalysis, CancellationToken cancellationToken); - } -} diff --git a/src/Features/Core/Portable/Diagnostics/IRemoteDiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/IRemoteDiagnosticAnalyzerService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a0984aa3dd5049d5378613db272e6c56cfaecef3 --- /dev/null +++ b/src/Features/Core/Portable/Diagnostics/IRemoteDiagnosticAnalyzerService.cs @@ -0,0 +1,29 @@ +// 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.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.Diagnostics +{ + interface IRemoteDiagnosticAnalyzerService + { + Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, string streamName, CancellationToken cancellationToken); + void ReportAnalyzerPerformance(List snapshot, int unitCount, CancellationToken cancellationToken); + } + + internal struct AnalyzerPerformanceInfo + { + public readonly string AnalyzerId; + public readonly bool BuiltIn; + public readonly TimeSpan TimeSpan; + + public AnalyzerPerformanceInfo(string analyzerid, bool builtIn, TimeSpan timeSpan) + { + AnalyzerId = analyzerid; + BuiltIn = builtIn; + TimeSpan = timeSpan; + } + } +} diff --git a/src/Features/Core/Portable/Diagnostics/Log/DiagnosticAnalyzerLogger.cs b/src/Features/Core/Portable/Diagnostics/Log/DiagnosticAnalyzerLogger.cs index df9a19ca8d908d6cec82fe41e8ad099d7f3a672d..63e47274a7422c0aec27ba6a9bb6416123613afe 100644 --- a/src/Features/Core/Portable/Diagnostics/Log/DiagnosticAnalyzerLogger.cs +++ b/src/Features/Core/Portable/Diagnostics/Log/DiagnosticAnalyzerLogger.cs @@ -52,7 +52,7 @@ public static void LogAnalyzerCrashCount(DiagnosticAnalyzer analyzer, Exception } // TODO: once we create description manager, pass that into here. - bool telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(null, analyzer, projectId); + bool telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(analyzer, null); var tuple = ValueTuple.Create(telemetry, analyzer.GetType(), ex.GetType()); logAggregator.IncreaseCount(tuple); } @@ -137,28 +137,34 @@ public static void LogAnalyzerTypeCountSummary(int correlationId, DiagnosticLogA } } - public static bool AllowsTelemetry(DiagnosticAnalyzerService service, DiagnosticAnalyzer analyzer, ProjectId projectIdOpt) + public static bool AllowsTelemetry(DiagnosticAnalyzer analyzer, IDiagnosticAnalyzerService serviceOpt = null) { if (s_telemetryCache.TryGetValue(analyzer, out var value)) { return value.Value; } - return s_telemetryCache.GetValue(analyzer, a => new StrongBox(CheckTelemetry(service, a))).Value; + return s_telemetryCache.GetValue(analyzer, a => new StrongBox(CheckTelemetry(a, serviceOpt))).Value; } - private static bool CheckTelemetry(DiagnosticAnalyzerService service, DiagnosticAnalyzer analyzer) + private static bool CheckTelemetry(DiagnosticAnalyzer analyzer, IDiagnosticAnalyzerService serviceOpt) { if (analyzer.IsCompilerAnalyzer()) { return true; } + if (analyzer is IBuiltInAnalyzer) + { + // if it is builtin analyzer, telemetry is always allowed + return true; + } + ImmutableArray diagDescriptors; try { // SupportedDiagnostics is potentially user code and can throw an exception. - diagDescriptors = service != null ? service.GetDiagnosticDescriptors(analyzer) : analyzer.SupportedDiagnostics; + diagDescriptors = serviceOpt != null ? serviceOpt.GetDiagnosticDescriptors(analyzer) : analyzer.SupportedDiagnostics; } catch (Exception) { diff --git a/src/Features/Core/Portable/Diagnostics/Log/DiagnosticLogAggregator.cs b/src/Features/Core/Portable/Diagnostics/Log/DiagnosticLogAggregator.cs index 42fc962882ad5d2b70c4f60d7755746f2007be15..097de53cf96ba37c41f41d09f81fb0903bec82ff 100644 --- a/src/Features/Core/Portable/Diagnostics/Log/DiagnosticLogAggregator.cs +++ b/src/Features/Core/Portable/Diagnostics/Log/DiagnosticLogAggregator.cs @@ -41,7 +41,7 @@ public DiagnosticLogAggregator(DiagnosticAnalyzerService owner) public void UpdateAnalyzerTypeCount(DiagnosticAnalyzer analyzer, AnalyzerTelemetryInfo analyzerTelemetryInfo, Project projectOpt) { - var telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(_owner, analyzer, projectOpt?.Id); + var telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(analyzer, _owner); ImmutableInterlocked.AddOrUpdate( ref _analyzerInfoMap, diff --git a/src/VisualStudio/Core/Test.Next/Remote/JsonConverterTests.cs b/src/VisualStudio/Core/Test.Next/Remote/JsonConverterTests.cs index faab8e3a48a13fa00143814d7e05110d6354b765..0d19753f4f26e02002ac4895c883c15c1ee47311 100644 --- a/src/VisualStudio/Core/Test.Next/Remote/JsonConverterTests.cs +++ b/src/VisualStudio/Core/Test.Next/Remote/JsonConverterTests.cs @@ -139,6 +139,14 @@ public void TestPinnedSolutionInfo() }); } + [Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)] + public void TestAnalyzerPerformanceInfo() + { + VerifyJsonSerialization( + new AnalyzerPerformanceInfo("testAnalyzer", builtIn: false, timeSpan: TimeSpan.FromMilliseconds(12345)), + (x, y) => (x.AnalyzerId == y.AnalyzerId && x.BuiltIn == y.BuiltIn && x.TimeSpan == y.TimeSpan) ? 0 : 1); + } + private static void VerifyJsonSerialization(T value, Comparison equality = null) { var serializer = new JsonSerializer(); diff --git a/src/VisualStudio/Core/Test.Next/Services/PerformanceTrackerServiceTests.cs b/src/VisualStudio/Core/Test.Next/Services/PerformanceTrackerServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f470229bf0f84e3fbc6fbf05b0f8aee2dce378d --- /dev/null +++ b/src/VisualStudio/Core/Test.Next/Services/PerformanceTrackerServiceTests.cs @@ -0,0 +1,191 @@ +// 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.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Remote.Diagnostics; +using Xunit; + +namespace Roslyn.VisualStudio.Next.UnitTests.Services +{ + public class PerformanceTrackerServiceTests + { + [Fact] + public void TestTooFewSamples() + { + // minimum sample is 100 + var badAnalyzers = GetBadAnalyzers(@"TestFiles\analyzer_input.csv", to: 80); + + Assert.Empty(badAnalyzers); + } + + [Fact] + public void TestTracking() + { + var badAnalyzers = GetBadAnalyzers(@"TestFiles\analyzer_input.csv", to: 200); + + VerifyBadAnalyzer(badAnalyzers[0], "CSharpRemoveUnnecessaryCastDiagnosticAnalyzer", 101.244432561581, 54.48, 21.8163001442628); + VerifyBadAnalyzer(badAnalyzers[1], "CSharpInlineDeclarationDiagnosticAnalyzer", 49.9389715502954, 26.6686092715232, 9.2987133054884); + VerifyBadAnalyzer(badAnalyzers[2], "VisualBasicRemoveUnnecessaryCastDiagnosticAnalyzer", 42.0967360557792, 23.277619047619, 7.25464266261805); + } + + [Fact] + public void TestTrackingMaxSample() + { + var badAnalyzers = GetBadAnalyzers(@"TestFiles\analyzer_input.csv", to: 300); + + VerifyBadAnalyzer(badAnalyzers[0], "CSharpRemoveUnnecessaryCastDiagnosticAnalyzer", 85.6039521236341, 58.4542358078603, 18.4245217226717); + VerifyBadAnalyzer(badAnalyzers[1], "VisualBasic.UseAutoProperty.UseAutoPropertyAnalyzer", 45.0918385052674, 29.0622535211268, 9.13728667060397); + VerifyBadAnalyzer(badAnalyzers[2], "CSharpInlineDeclarationDiagnosticAnalyzer", 42.2014208750466, 28.7935371179039, 7.99261581900397); + } + + [Fact] + public void TestTrackingRolling() + { + // data starting to rolling at 300 data points + var badAnalyzers = GetBadAnalyzers(@"TestFiles\analyzer_input.csv", to: 400); + + VerifyBadAnalyzer(badAnalyzers[0], "CSharpRemoveUnnecessaryCastDiagnosticAnalyzer", 76.2748443491852, 51.1698695652174, 17.3819563479479); + VerifyBadAnalyzer(badAnalyzers[1], "VisualBasic.UseAutoProperty.UseAutoPropertyAnalyzer", 43.5700167914005, 29.2597857142857, 9.21213873850298); + VerifyBadAnalyzer(badAnalyzers[2], "InlineDeclaration.CSharpInlineDeclarationDiagnosticAnalyzer", 36.4336594793033, 23.9764782608696, 7.43956680199015); + } + + [Fact] + public void TestBadAnalyzerInfoPII() + { + var badAnalyzer1 = new ExpensiveAnalyzerInfo(true, "test", 0.1, 0.1, 0.1); + Assert.True(badAnalyzer1.PIISafeAnalyzerId == badAnalyzer1.AnalyzerId); + Assert.True(badAnalyzer1.PIISafeAnalyzerId == "test"); + + var badAnalyzer2 = new ExpensiveAnalyzerInfo(false, "test", 0.1, 0.1, 0.1); + Assert.True(badAnalyzer2.PIISafeAnalyzerId == badAnalyzer2.AnalyzerIdHash); + Assert.True(badAnalyzer2.PIISafeAnalyzerId == "test".GetHashCode().ToString()); + } + + private void VerifyBadAnalyzer(ExpensiveAnalyzerInfo analyzer, string analyzerId, double lof, double mean, double stddev) + { + Assert.True(analyzer.PIISafeAnalyzerId.IndexOf(analyzerId, StringComparison.OrdinalIgnoreCase) >= 0); + Assert.Equal(analyzer.LocalOutlierFactor, lof, precision: 4); + Assert.Equal(analyzer.Average, mean, precision: 4); + Assert.Equal(analyzer.AdjustedStandardDeviation, stddev, precision: 4); + } + + private List GetBadAnalyzers(string testFileName, int to) + { + var testFile = ReadTestFile(testFileName); + + var (matrix, dataCount) = CreateMatrix(testFile); + + to = Math.Min(to, dataCount); + + var service = new PerformanceTrackerService(minLOFValue: 0, averageThreshold: 0, stddevThreshold: 0); + + for (var i = 0; i < to; i++) + { + service.AddSnapshot(CreateSnapshots(matrix, i), unitCount: 100); + } + + var badAnalyzerInfo = new List(); + service.GenerateReport(badAnalyzerInfo); + + return badAnalyzerInfo; + } + + private IEnumerable CreateSnapshots(Dictionary matrix, int index) + { + foreach (var kv in matrix) + { + var timeSpan = kv.Value[index]; + if (double.IsNaN(timeSpan)) + { + continue; + } + + yield return new AnalyzerPerformanceInfo(kv.Key, true, TimeSpan.FromMilliseconds(timeSpan)); + } + } + + private (Dictionary matrix, int dataCount) CreateMatrix(string testFile) + { + var matrix = new Dictionary(); + + var lines = testFile.Split('\n'); + var expectedDataCount = GetExpectedDataCount(lines[0]); + + for (var i = 1; i < lines.Length; i++) + { + if (lines[i].Trim().Length == 0) + { + continue; + } + + var data = SkipAnalyzerId(lines[i]).Split(','); + Assert.Equal(data.Length, expectedDataCount); + + var analyzerId = GetAnalyzerId(lines[i]); + + var timeSpans = new double[expectedDataCount]; + for (var j = 0; j < data.Length; j++) + { + double result; + if (!double.TryParse(data[j], out result)) + { + // no data for this analyzer for this particular run + result = double.NaN; + } + + timeSpans[j] = result; + } + + matrix[analyzerId] = timeSpans; + } + + return (matrix, expectedDataCount); + } + + private string GetAnalyzerId(string line) + { + return line.Substring(1, line.LastIndexOf('"') - 1); + } + + private int GetExpectedDataCount(string header) + { + var data = header.Split(','); + return data.Length - 1; + } + + private string SkipAnalyzerId(string line) + { + return line.Substring(line.LastIndexOf('"') + 2); + } + + private string ReadTestFile(string name) + { + var assembly = typeof(PerformanceTrackerServiceTests).Assembly; + var resourceName = GetResourceName(assembly, name); + + using (var stream = assembly.GetManifestResourceStream(resourceName)) + { + if (stream == null) + { + throw new InvalidOperationException($"Resource '{resourceName}' not found in {assembly.FullName}."); + } + + using (var reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + } + + private static string GetResourceName(Assembly assembly, string name) + { + var convert = name.Replace(@"\", "."); + + return assembly.GetManifestResourceNames().Where(n => n.EndsWith(convert, StringComparison.OrdinalIgnoreCase)).First(); + } + } +} diff --git a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs index d420ce384988ee04b1d6cfb613d3b3769646f36d..7dc0d4d103d5999b0086586f8811fb2871c58e52 100644 --- a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs @@ -156,7 +156,7 @@ void Method() // run analysis var project = workspace.CurrentSolution.Projects.First(); - var executor = (ICodeAnalysisDiagnosticAnalyzerExecutor)new DiagnosticAnalyzerExecutor(new MyUpdateSource(workspace)).CreateService(workspace.Services); + var executor = new DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner(owner: null, hostDiagnosticUpdateSource: new MyUpdateSource(workspace)); var analyzerDriver = (await project.GetCompilationAsync()).WithAnalyzers( analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(), new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Options, project.Solution)); @@ -202,7 +202,7 @@ void Method() // run analysis var project = workspace.CurrentSolution.Projects.First().AddAnalyzerReference(analyzerReference); - var executor = (ICodeAnalysisDiagnosticAnalyzerExecutor)new DiagnosticAnalyzerExecutor(new MyUpdateSource(workspace)).CreateService(workspace.Services); + var executor = new DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner(owner: null, hostDiagnosticUpdateSource: new MyUpdateSource(workspace)); var analyzerDriver = (await project.GetCompilationAsync()).WithAnalyzers( analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(), new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution.Options, project.Solution)); @@ -219,7 +219,7 @@ void Method() private static async Task AnalyzeAsync(TestWorkspace workspace, ProjectId projectId, Type analyzerType, CancellationToken cancellationToken = default(CancellationToken)) { - var executor = (ICodeAnalysisDiagnosticAnalyzerExecutor)new DiagnosticAnalyzerExecutor(new MyUpdateSource(workspace)).CreateService(workspace.Services); + var executor = new DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner(owner: null, hostDiagnosticUpdateSource: new MyUpdateSource(workspace)); var analyzerReference = new AnalyzerFileReference(analyzerType.Assembly.Location, new TestAnalyzerAssemblyLoader()); var project = workspace.CurrentSolution.GetProject(projectId).AddAnalyzerReference(analyzerReference); diff --git a/src/VisualStudio/Core/Test.Next/TestFiles/analyzer_input.csv b/src/VisualStudio/Core/Test.Next/TestFiles/analyzer_input.csv new file mode 100644 index 0000000000000000000000000000000000000000..4cf5b114ea6f7ec4117f274d639a9006f950ed8f --- /dev/null +++ b/src/VisualStudio/Core/Test.Next/TestFiles/analyzer_input.csv @@ -0,0 +1,54 @@ +Analyzer,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,163,164,165,166,167,173,174,175,176,177,178,179,180,181,182,183,184,185,191,192,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400 +"Microsoft.ApiDesignGuidelines.Analyzers.CancellationTokenParametersMustComeLastAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,7.0,3.0,0.0,0.0,0.0,3.0,,0.0,22.0,53.0,26.0,115.0,2.0,24.0,62.0,20.0,48.0,,7.0,,,0.0,6.0,0.0,0.0,0.0,0.0,,119.0,,5.0,,44.0,,0.0,4.0,0.0,,2.0,,0.0,0.0,1.0,7.0,66.0,196.0,20.0,8.0,80.0,46.0,52.0,0.0,8.0,0.0,0.0,0.0,2.0,10.0,0.0,256.0,0.0,1.0,2.0,9.0,0.0,0.0,0.0,3.0,3.0,,,,,,,,0.0,0.0,16.0,1.0,3.0,7.0,0.0,1.0,,0.0,0.0,,0.0,0.0,20.0,,,,,,,,,,,,,,,0.0,0.0,2.0,0.0,3.0,0.0,0.0,1.0,0.0,2.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,12.0,0.0,124.0,9.0,2.0,,86.0,1.0,,25.0,0.0,74.0,0.0,,,8.0,,,0.0,,3.0,,1.0,69.0,32.0,80.0,,59.0,,,,9.0,0.0,469.0,0.0,0.0,0.0,,,3.0,,1.0,,,86.0,,0.0,40.0,62.0,0.0,33.0,2.0,24.0,3.0,92.0,0.0,7.0,4.0,21.0,5.0,13.0,0.0,8.0,3.0,89.0,30.0,39.0,25.0,125.0,98.0,1.0,14.0,6.0,1.0,0.0,0.0,0.0,85.0,3.0,10.0,0.0,,3.0,4.0,2.0,0.0,2.0,40.0,,,,0.0,,,,,,,,,,,,8.0,3.0,25.0,4.0,46.0,0.0,48.0,0.0,29.0,128.0,0.0,0.0,1.0,0.0,0.0,19.0,154.0,0.0,,,2.0,,,,,,,83.0,,,0.0,,,,,,,,,,,,,,,,,,,1.0,,,,,,,, +"Microsoft.ApiDesignGuidelines.Analyzers.DoNotDirectlyAwaitATaskAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,3.0,0.0,0.0,,,,,,,,,,,,,,0.0,,,,,,,,0.0,,0.0,,0.0,,0.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,,,,,0.0,0.0,0.0,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,0.0,,,,,,,0.0,,,,,,,,0.0,,,,,,,,,,,,,0.0,0.0,,0.0,0.0,,,,,,,,,,,0.0,0.0,,0.0,0.0,,,0.0,0.0,,,,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,,,0.0,,,,0.0,0.0,0.0,0.0,,0.0,,0.0,,,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"Microsoft.ApiDesignGuidelines.Analyzers.EquatableAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,10.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,1.0,0.0,1.0,33.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,9.0,,0.0,,0.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,1.0,3.0,2.0,0.0,0.0,4.0,1.0,0.0,0.0,28.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,1.0,0.0,0.0,,0.0,0.0,,0.0,0.0,1.0,0.0,,,0.0,,,0.0,,1.0,,0.0,0.0,1.0,0.0,,0.0,,,,1.0,0.0,1.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,4.0,0.0,4.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0,1.0,4.0,0.0,2.0,0.0,6.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,24.0,,,,,,,,,,,,0.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,27.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.ApiDesignGuidelines.Analyzers.OperatorsShouldHaveSymmetricalOverloadsAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,4.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,3.0,,0.0,,29.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,,,,2.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.ApiDesignGuidelines.Analyzers.PropertiesShouldNotBeWriteOnlyAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,15.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,11.0,,,0.0,2.0,0.0,0.0,0.0,0.0,,10.0,,0.0,,0.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,9.0,0.0,0.0,0.0,0.0,12.0,20.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,0.0,3.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,14.0,4.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,1.0,,,,9.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,0.0,0.0,10.0,0.0,0.0,0.0,45.0,0.0,0.0,7.0,0.0,0.0,0.0,0.0,0.0,0.0,70.0,0.0,11.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,14.0,1.0,0.0,0.0,,0.0,3.0,2.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,,,4.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.CodeAnalysis.CSharp.Analyzers.CSharpImmutableObjectMethodAnalyzer,Microsoft.CodeAnalysis.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,2.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,,,,,,12.0,,,0.0,13.0,4.0,,0.0,0.0,,74.0,,,,1.0,,2.0,0.0,0.0,,0.0,,,0.0,1.0,70.0,,67.0,24.0,58.0,59.0,11.0,,,,3.0,0.0,,1.0,0.0,,12.0,0.0,,11.0,,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,2.0,0.0,8.0,0.0,0.0,0.0,0.0,42.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,7.0,0.0,,,0.0,,,0.0,,0.0,,,,,,0.0,,0.0,,0.0,,0.0,,,,,,,60.0,0.0,,0.0,0.0,0.0,,,,,0.0,,,,,0.0,1.0,,0.0,32.0,1.0,23.0,0.0,42.0,,42.0,43.0,,0.0,,0.0,0.0,,11.0,,66.0,8.0,110.0,2.0,,333.0,4.0,0.0,0.0,,1.0,5.0,2.0,0.0,0.0,,3.0,1.0,1.0,0.0,0.0,1.0,,,,,,,,,,,,,,,,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.CodeAnalysis.CSharp.Diagnostics.AddBraces.CSharpAddBracesDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",281.0,52.0,0.0,,286.0,0.0,3.0,1.0,1.0,0.0,0.0,0.0,25.0,0.0,0.0,0.0,73.0,49.0,,,,,,,20.0,2.0,10.0,,0.0,1.0,0.0,,0.0,0.0,74.0,27.0,,,8.0,1.0,2.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,2.0,,2.0,0.0,1.0,42.0,2.0,,,,0.0,0.0,,0.0,0.0,,3.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,,0.0,1.0,0.0,,0.0,0.0,0.0,33.0,19.0,,,0.0,5.0,0.0,0.0,0.0,0.0,,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,30.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,,,1.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,11.0,27.0,,832.0,,164.0,0.0,113.0,37.0,0.0,1.0,0.0,1.0,,0.0,3.0,,446.0,78.0,0.0,0.0,0.0,,0.0,,3.0,0.0,10.0,,1.0,,,0.0,,0.0,4.0,,,358.0,89.0,0.0,53.0,1.0,0.0,0.0,,1.0,,,,46.0,0.0,0.0,2.0,0.0,,0.0,0.0,0.0,43.0,,,625.0,1.0,74.0,165.0,,0.0,0.0,0.0,,0.0,8.0,0.0,0.0,0.0,3.0,,0.0,0.0,,0.0,,0.0,0.0,,2.0,,37.0,0.0,1.0,44.0,,1.0,2.0,0.0,0.0,,0.0,2.0,0.0,0.0,0.0,25.0,1.0,0.0,0.0,0.0,0.0,0.0,4.0,,590.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,23.0,1.0,272.0,26.0,0.0,1.0,21.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,47.0,0.0,,51.0,68.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,1.0,0.0,,0.0,1.0,0.0,47.0,0.0,0.0,0.0,0.0,,25.0,,1.0,0.0,16.0,,0.0,1.0,0.0 +"Microsoft.CodeAnalysis.CSharp.Diagnostics.CSharpUnboundIdentifiersDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",11.0,52.0,0.0,,34.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,3.0,,,,,,,4.0,0.0,1.0,,0.0,1.0,0.0,,0.0,0.0,3.0,2.0,,,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,2.0,0.0,1.0,2.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,2.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,19.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,3.0,0.0,,4.0,,25.0,0.0,1.0,3.0,0.0,0.0,0.0,0.0,,0.0,0.0,,4.0,1.0,0.0,0.0,0.0,,0.0,,0.0,0.0,1.0,,0.0,,,0.0,,0.0,1.0,,,3.0,4.0,0.0,1.0,1.0,0.0,0.0,,1.0,,,,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,107.0,0.0,4.0,1.0,,0.0,0.0,0.0,,0.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,30.0,,0.0,,2.0,0.0,1.0,0.0,,1.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,94.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,1.0,3.0,1.0,0.0,1.0,3.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,30.0,0.0,0.0,36.0,0.0,,1.0,2.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.Diagnostics.RemoveUnnecessaryCast.CSharpRemoveUnnecessaryCastDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",681.0,140706.0,0.0,,11888.0,87.0,320.0,9.0,367.0,7.0,13.0,4.0,7.0,28.0,0.0,57.0,7264.0,2631.0,,,,,,,513.0,18.0,691.0,,2.0,144.0,52.0,,1.0,0.0,116.0,38.0,,,439.0,17.0,78.0,5.0,0.0,0.0,0.0,0.0,,,0.0,31.0,101.0,,111.0,1.0,78.0,463.0,66.0,,,,0.0,0.0,,15.0,34.0,,205.0,0.0,,59.0,,0.0,0.0,0.0,1.0,2.0,19.0,23.0,,7.0,111.0,7.0,,0.0,7.0,269.0,72.0,114.0,,,85.0,16.0,0.0,2.0,0.0,1.0,,0.0,2775.0,900.0,0.0,0.0,0.0,0.0,18.0,6.0,,,,,0.0,0.0,0.0,0.0,107.0,3.0,0.0,0.0,0.0,0.0,2.0,8.0,0.0,5.0,0.0,0.0,0.0,6.0,0.0,8.0,0.0,0.0,3.0,0.0,1.0,0.0,24.0,,,18.0,,7.0,4.0,4.0,0.0,,3.0,1.0,0.0,0.0,0.0,173.0,322.0,,12223.0,,148948.0,0.0,155591.0,131.0,0.0,111.0,0.0,41.0,,0.0,577.0,,13569.0,149424.0,0.0,5.0,5.0,,4.0,,27.0,3.0,1187.0,,10.0,,,25.0,,0.0,625.0,,,12459.0,469.0,4.0,154214.0,209.0,0.0,3.0,,310.0,,,,967.0,4.0,3.0,21.0,4.0,,4.0,6.0,0.0,417.0,,,11013.0,41.0,493.0,153061.0,,0.0,0.0,4.0,,0.0,110.0,47.0,3.0,0.0,317.0,,0.0,17.0,,0.0,,0.0,0.0,,121.0,,412.0,0.0,74.0,125.0,,260.0,98.0,0.0,8.0,,2.0,64.0,4.0,45.0,0.0,160069.0,46.0,3.0,15.0,0.0,1.0,6.0,300.0,,14423.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1832.0,992.0,10450.0,152650.0,86.0,179.0,6510.0,,,1.0,,0.0,3.0,,0.0,0.0,6.0,17.0,4.0,,,0.0,,0.0,174.0,0.0,0.0,442.0,0.0,,697.0,2532.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,21.0,37.0,,9.0,19.0,0.0,359.0,0.0,33.0,5.0,3.0,,9.0,,2.0,0.0,1.0,,40.0,21.0,0.0 +"Microsoft.CodeAnalysis.CSharp.InlineDeclaration.CSharpInlineDeclarationDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",32480.0,12870.0,2.0,,59782.0,411.0,335.0,161.0,588.0,121.0,71.0,59.0,279.0,66.0,0.0,173.0,1831.0,969.0,,,,,,,476.0,23.0,96.0,,4.0,44.0,18.0,,24.0,0.0,513.0,140.0,,,288.0,4.0,287.0,50.0,124.0,0.0,29.0,29.0,,,63.0,2.0,158.0,,1334.0,109.0,72.0,250.0,14.0,,,,1.0,0.0,,1.0,127.0,,12.0,0.0,,77.0,,0.0,0.0,0.0,6.0,5.0,346.0,640.0,,71.0,264.0,24.0,,0.0,229.0,6668.0,430.0,508.0,,,11.0,63.0,1.0,0.0,92.0,7.0,,5.0,949.0,2010.0,0.0,0.0,0.0,0.0,10.0,127.0,,,,,0.0,0.0,0.0,9.0,84.0,0.0,38.0,0.0,0.0,0.0,0.0,2.0,0.0,73.0,0.0,0.0,0.0,92.0,0.0,107.0,40.0,0.0,42.0,0.0,5.0,0.0,9.0,,,428.0,,20.0,64.0,48.0,0.0,,22.0,5.0,0.0,0.0,74.0,396.0,514.0,,71588.0,,14201.0,2.0,12114.0,410.0,50.0,374.0,8.0,409.0,,8.0,424.0,,66528.0,15468.0,3.0,97.0,41.0,,40.0,,138.0,135.0,168.0,,338.0,,,198.0,,1.0,435.0,,,74871.0,359.0,33.0,13777.0,629.0,27.0,106.0,,618.0,,,,281.0,30.0,60.0,246.0,56.0,,86.0,186.0,1.0,562.0,,,69029.0,232.0,463.0,14138.0,,2.0,0.0,17.0,,0.0,236.0,60.0,165.0,8.0,47.0,,42.0,73.0,,97.0,,0.0,85.0,,40.0,,171.0,104.0,523.0,6.0,,69.0,176.0,0.0,136.0,,0.0,131.0,4.0,222.0,0.0,14611.0,59.0,6.0,1.0,0.0,37.0,2.0,451.0,,67037.0,,2.0,0.0,0.0,0.0,0.0,0.0,0.0,1032.0,1473.0,69111.0,12423.0,181.0,588.0,1269.0,,,26.0,,1.0,92.0,,0.0,0.0,106.0,70.0,83.0,,,0.0,,0.0,34.0,0.0,0.0,197.0,0.0,,124.0,901.0,,,0.0,0.0,0.0,5.0,19.0,,39.0,341.0,11.0,,21.0,63.0,0.0,327.0,0.0,124.0,20.0,21.0,,214.0,,31.0,0.0,5.0,,618.0,77.0,2.0 +"Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess.InvokeDelegateWithConditionalAccessAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",128.0,111.0,0.0,,225.0,0.0,18.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,34.0,1.0,153.0,,0.0,0.0,0.0,,0.0,0.0,10.0,5.0,,,36.0,1.0,47.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,1.0,,0.0,0.0,0.0,8.0,2.0,,,,0.0,0.0,,0.0,0.0,,2.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,22.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,19.0,,,1.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,9.0,2.0,,145.0,,74.0,0.0,51.0,9.0,0.0,1.0,0.0,35.0,,0.0,2.0,,192.0,127.0,0.0,0.0,0.0,,0.0,,1.0,0.0,55.0,,0.0,,,0.0,,0.0,2.0,,,208.0,62.0,0.0,54.0,0.0,0.0,0.0,,0.0,,,,8.0,0.0,0.0,1.0,0.0,,0.0,0.0,0.0,64.0,,,308.0,0.0,78.0,79.0,,0.0,0.0,0.0,,0.0,5.0,0.0,0.0,0.0,35.0,,0.0,0.0,,0.0,,0.0,0.0,,2.0,,36.0,0.0,0.0,1.0,,0.0,1.0,0.0,0.0,,0.0,1.0,0.0,0.0,0.0,53.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,,174.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,263.0,74.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,1.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,42.0,0.0,,11.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,1.0,0.0,,0.0,0.0,0.0,30.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.QualifyMemberAccess.CSharpQualifyMemberAccessDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",628.0,195.0,0.0,,649.0,1.0,62.0,25.0,55.0,1.0,0.0,0.0,2.0,0.0,0.0,5.0,243.0,301.0,,,,,,,140.0,23.0,21.0,,0.0,63.0,7.0,,0.0,0.0,243.0,94.0,,,39.0,25.0,66.0,0.0,0.0,0.0,0.0,0.0,,,1.0,1.0,156.0,,119.0,11.0,20.0,77.0,10.0,,,,0.0,0.0,,2.0,0.0,,24.0,0.0,,1.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,,1.0,2.0,0.0,,0.0,0.0,1.0,3.0,0.0,,,0.0,4.0,0.0,0.0,0.0,0.0,,0.0,74.0,331.0,0.0,0.0,0.0,0.0,0.0,71.0,,,,,0.0,0.0,0.0,0.0,3.0,0.0,37.0,0.0,0.0,0.0,0.0,2.0,0.0,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,1.0,89.0,4.0,,766.0,,150.0,0.0,170.0,106.0,0.0,25.0,0.0,27.0,,0.0,27.0,,703.0,234.0,0.0,0.0,0.0,,0.0,,67.0,1.0,155.0,,1.0,,,1.0,,0.0,25.0,,,886.0,203.0,0.0,355.0,2.0,0.0,32.0,,2.0,,,,82.0,52.0,0.0,70.0,34.0,,50.0,1.0,0.0,47.0,,,521.0,1.0,170.0,324.0,,0.0,0.0,2.0,,0.0,57.0,0.0,0.0,0.0,41.0,,0.0,1.0,,1.0,,0.0,0.0,,105.0,,83.0,10.0,94.0,1.0,,3.0,61.0,25.0,0.0,,0.0,6.0,3.0,5.0,0.0,153.0,3.0,0.0,1.0,0.0,0.0,1.0,29.0,,768.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,121.0,13.0,610.0,166.0,59.0,44.0,71.0,,,0.0,,0.0,23.0,,0.0,0.0,29.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,226.0,0.0,,27.0,149.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,2.0,0.0,,0.0,4.0,0.0,29.0,0.0,0.0,0.0,31.0,,1.0,,0.0,0.0,0.0,,45.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseCoalesceExpression.CSharpUseCoalesceExpressionDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",51.0,7.0,0.0,,33.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,26.0,0.0,,,,,,,2.0,0.0,1.0,,0.0,0.0,0.0,,0.0,0.0,165.0,0.0,,,85.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,2.0,0.0,,48.0,,3.0,0.0,3.0,2.0,0.0,0.0,0.0,0.0,,0.0,0.0,,131.0,2.0,0.0,0.0,0.0,,0.0,,0.0,0.0,1.0,,0.0,,,0.0,,0.0,0.0,,,81.0,2.0,0.0,35.0,0.0,0.0,0.0,,0.0,,,,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,69.0,0.0,2.0,2.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,35.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,45.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,27.0,0.0,77.0,2.0,0.0,0.0,0.0,,,31.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,2.0,0.0,,1.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseCoalesceExpression.CSharpUseCoalesceExpressionForNullableDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",28.0,23.0,0.0,,7.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,3.0,3.0,18.0,,0.0,0.0,0.0,,0.0,0.0,28.0,1.0,,,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,1.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,3.0,0.0,,83.0,,2.0,0.0,2.0,2.0,0.0,0.0,0.0,0.0,,0.0,0.0,,36.0,2.0,0.0,0.0,0.0,,0.0,,0.0,0.0,37.0,,0.0,,,0.0,,0.0,0.0,,,8.0,3.0,0.0,2.0,0.0,0.0,0.0,,0.0,,,,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,38.0,0.0,3.0,2.0,,0.0,0.0,0.0,,0.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,1.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,7.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,31.0,2.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,3.0,0.0,,1.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer.CSharpUseCollectionInitializerDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",2.0,732.0,0.0,,364.0,35.0,26.0,45.0,20.0,4.0,2.0,19.0,71.0,3.0,0.0,6.0,26.0,58.0,,,,,,,513.0,49.0,127.0,,0.0,18.0,10.0,,4.0,23.0,320.0,178.0,,,88.0,6.0,36.0,3.0,2.0,0.0,0.0,0.0,,,50.0,2.0,59.0,,483.0,1.0,25.0,517.0,36.0,,,,1.0,0.0,,1.0,0.0,,58.0,0.0,,6.0,,0.0,0.0,0.0,26.0,2.0,3.0,37.0,,0.0,38.0,0.0,,0.0,2.0,5.0,32.0,6.0,,,0.0,4.0,1.0,0.0,1.0,3.0,,0.0,44.0,62.0,0.0,0.0,0.0,0.0,0.0,6.0,,,,,0.0,0.0,0.0,0.0,5.0,1.0,2.0,0.0,0.0,1.0,0.0,28.0,0.0,2.0,0.0,0.0,0.0,3.0,0.0,2.0,6.0,0.0,4.0,0.0,1.0,0.0,0.0,,,4.0,,0.0,2.0,2.0,0.0,,3.0,8.0,0.0,0.0,4.0,2150.0,233.0,,315.0,,1690.0,0.0,1101.0,214.0,6.0,6.0,0.0,25.0,,0.0,254.0,,301.0,806.0,0.0,3.0,3.0,,2.0,,36.0,54.0,203.0,,15.0,,,4.0,,1.0,58.0,,,375.0,357.0,2.0,779.0,23.0,0.0,6.0,,20.0,,,,373.0,3.0,2.0,70.0,3.0,,30.0,42.0,1.0,71.0,,,274.0,19.0,1016.0,786.0,,0.0,1.0,8.0,,52.0,2700.0,3.0,6.0,1.0,26.0,,1.0,6.0,,2.0,,0.0,0.0,,115.0,,3215.0,2.0,140.0,6.0,,31.0,55.0,1.0,0.0,,0.0,60.0,7.0,6.0,0.0,658.0,34.0,4.0,2.0,0.0,3.0,4.0,97.0,,446.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,83.0,27.0,340.0,1450.0,6.0,26.0,25.0,,,4.0,,1.0,6.0,,0.0,0.0,4.0,3.0,25.0,,,0.0,,0.0,0.0,0.0,0.0,3460.0,0.0,,151.0,181.0,,,0.0,0.0,0.0,1.0,1.0,,1.0,8.0,0.0,,5.0,183.0,0.0,745.0,0.0,3.0,2.0,2.0,,45.0,,0.0,0.0,0.0,,3.0,8.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseDefaultLiteral.CSharpUseDefaultLiteralDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",26.0,16.0,0.0,,3.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,1.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,3.0,,1.0,0.0,1.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,36.0,55.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,,0.0,0.0,,,92.0,2.0,0.0,1.0,0.0,0.0,0.0,,0.0,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,39.0,0.0,3.0,1.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,28.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,3.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,52.0,45.0,1591.0,191.0,0.0,68.0,187.0,,,0.0,,0.0,4.0,,0.0,0.0,4.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,243.0,0.0,,115.0,29.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,7.0,6.0,,0.0,0.0,0.0,8.0,0.0,1.0,0.0,0.0,,1.0,,0.0,0.0,0.0,,1.0,1.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseExpressionBody.UseExpressionBodyDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",1467.0,5767.0,1.0,,4787.0,5.0,462.0,5.0,15.0,4.0,1.0,1.0,104.0,52.0,0.0,28.0,185.0,213.0,,,,,,,4423.0,64.0,222.0,,0.0,127.0,6.0,,27.0,2.0,1053.0,3824.0,,,684.0,5.0,374.0,1.0,2.0,0.0,0.0,0.0,,,42.0,4.0,93.0,,1557.0,155.0,109.0,2287.0,1247.0,,,,0.0,0.0,,159.0,1.0,,77.0,0.0,,13.0,,0.0,0.0,0.0,0.0,1.0,5.0,3.0,,23.0,123.0,1.0,,0.0,2.0,22.0,86.0,5.0,,,48.0,38.0,0.0,0.0,2.0,0.0,,0.0,253.0,871.0,0.0,0.0,0.0,0.0,0.0,4.0,,,,,0.0,0.0,0.0,0.0,17.0,0.0,7.0,0.0,0.0,1.0,0.0,89.0,0.0,31.0,0.0,1.0,0.0,3.0,0.0,30.0,5.0,0.0,22.0,0.0,0.0,0.0,1.0,,,5.0,,1.0,1.0,0.0,0.0,,2.0,0.0,0.0,0.0,1.0,4971.0,160.0,,2457.0,,1072.0,1.0,1412.0,1781.0,0.0,41.0,0.0,73.0,,0.0,138.0,,3848.0,740.0,1.0,1.0,0.0,,1.0,,232.0,14.0,244.0,,8.0,,,3.0,,0.0,188.0,,,8414.0,530.0,1.0,2413.0,16.0,1.0,2.0,,68.0,,,,246.0,54.0,0.0,110.0,11.0,,1.0,29.0,0.0,129.0,,,3416.0,48.0,861.0,3662.0,,1.0,2.0,8.0,,4.0,5038.0,1.0,116.0,0.0,341.0,,0.0,50.0,,4.0,,0.0,11.0,,630.0,,5788.0,9.0,2504.0,9.0,,28.0,51.0,40.0,44.0,,0.0,29.0,9.0,7.0,0.0,12252.0,51.0,84.0,302.0,26.0,1.0,6.0,640.0,,8751.0,,18.0,0.0,0.0,0.0,0.0,0.0,0.0,1865.0,5231.0,40612.0,10337.0,35.0,637.0,3600.0,,,184.0,,0.0,2.0,,0.0,0.0,3.0,2.0,1.0,,,0.0,,0.0,1.0,0.0,0.0,6852.0,0.0,,105.0,158.0,,,0.0,0.0,0.0,1.0,3.0,,1.0,453.0,0.0,,4.0,191.0,0.0,131.0,0.0,2.0,1.0,2.0,,68.0,,10.0,0.0,0.0,,3.0,3.0,1.0 +"Microsoft.CodeAnalysis.CSharp.UseNullPropagation.CSharpUseNullPropagationDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",8.0,68.0,0.0,,75.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,41.0,0.0,1.0,,0.0,0.0,0.0,,0.0,0.0,21.0,1.0,,,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,1.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,23.0,0.0,0.0,0.0,0.0,1.0,0.0,,141.0,,2.0,0.0,1.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,108.0,1.0,0.0,0.0,0.0,,0.0,,0.0,0.0,1.0,,0.0,,,0.0,,0.0,0.0,,,39.0,2.0,0.0,2.0,0.0,0.0,0.0,,0.0,,,,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,40.0,,,72.0,0.0,2.0,1.0,,0.0,0.0,0.0,,0.0,1.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,1.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,46.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,67.0,1.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,2.0,0.0,,1.0,17.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseObjectInitializer.CSharpUseObjectInitializerDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",537.0,85.0,0.0,,272.0,1.0,40.0,3.0,68.0,4.0,1.0,26.0,9.0,2.0,0.0,57.0,248.0,15.0,,,,,,,82.0,5.0,11.0,,0.0,48.0,1.0,,6.0,1.0,46.0,60.0,,,11.0,3.0,3.0,2.0,1.0,0.0,0.0,0.0,,,1.0,0.0,161.0,,62.0,0.0,75.0,28.0,32.0,,,,0.0,0.0,,0.0,0.0,,7.0,0.0,,4.0,,0.0,0.0,0.0,0.0,0.0,2.0,1.0,,1.0,176.0,0.0,,0.0,0.0,15.0,6.0,23.0,,,0.0,2.0,13.0,0.0,0.0,0.0,,0.0,188.0,40.0,0.0,0.0,0.0,0.0,0.0,5.0,,,,,0.0,0.0,0.0,0.0,3.0,0.0,69.0,0.0,0.0,1.0,0.0,3.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,6.0,1.0,0.0,8.0,0.0,0.0,0.0,0.0,,,2.0,,0.0,1.0,0.0,0.0,,1.0,0.0,0.0,0.0,1.0,42.0,87.0,,441.0,,74.0,0.0,70.0,70.0,0.0,3.0,0.0,3.0,,0.0,35.0,,173.0,153.0,0.0,2.0,0.0,,1.0,,5.0,65.0,10.0,,3.0,,,4.0,,122.0,8.0,,,302.0,84.0,1.0,73.0,58.0,0.0,8.0,,36.0,,,,57.0,2.0,0.0,7.0,1.0,,1.0,3.0,57.0,8.0,,,189.0,5.0,71.0,154.0,,0.0,2.0,4.0,,1.0,71.0,6.0,0.0,0.0,7.0,,0.0,6.0,,1.0,,0.0,0.0,,8.0,,84.0,7.0,110.0,3.0,,173.0,19.0,0.0,0.0,,0.0,18.0,2.0,55.0,0.0,68.0,28.0,1.0,1.0,0.0,0.0,0.0,42.0,,294.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,79.0,17.0,270.0,97.0,36.0,94.0,116.0,,,6.0,,38.0,8.0,,0.0,0.0,4.0,1.0,1.0,,,0.0,,0.0,0.0,0.0,0.0,70.0,0.0,,51.0,16.0,,,0.0,0.0,0.0,25.0,0.0,,0.0,3.0,0.0,,5.0,2.0,0.0,748.0,0.0,1.0,0.0,0.0,,2.0,,0.0,0.0,0.0,,2.0,1.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UsePatternMatching.CSharpAsAndNullCheckDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",242.0,146.0,0.0,,316.0,0.0,5.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,346.0,6.0,,,,,,,73.0,20.0,117.0,,0.0,1.0,0.0,,0.0,0.0,38.0,33.0,,,40.0,9.0,6.0,0.0,2.0,0.0,0.0,0.0,,,1.0,0.0,2.0,,6.0,0.0,0.0,34.0,54.0,,,,0.0,0.0,,0.0,0.0,,18.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,33.0,1.0,,0.0,1.0,0.0,,0.0,0.0,0.0,2.0,0.0,,,0.0,60.0,0.0,0.0,0.0,0.0,,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,,,1.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,1.0,23.0,27.0,,775.0,,157.0,0.0,111.0,51.0,0.0,27.0,0.0,5.0,,0.0,5.0,,463.0,162.0,0.0,0.0,0.0,,0.0,,42.0,0.0,229.0,,0.0,,,0.0,,0.0,5.0,,,479.0,89.0,0.0,154.0,0.0,0.0,0.0,,0.0,,,,254.0,0.0,0.0,2.0,0.0,,0.0,0.0,0.0,45.0,,,425.0,1.0,66.0,85.0,,0.0,0.0,0.0,,0.0,48.0,0.0,0.0,0.0,63.0,,0.0,0.0,,4.0,,0.0,0.0,,8.0,,73.0,0.0,6.0,67.0,,0.0,2.0,0.0,0.0,,0.0,2.0,0.0,0.0,0.0,122.0,2.0,0.0,1.0,0.0,0.0,0.0,49.0,,533.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,311.0,158.0,0.0,0.0,29.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,153.0,0.0,,248.0,6.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,6.0,0.0,,0.0,15.0,0.0,42.0,0.0,0.0,0.0,0.0,,0.0,,2.0,0.0,0.0,,0.0,1.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UsePatternMatching.CSharpIsAndCastCheckDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",4.0,15.0,0.0,,3.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,2.0,0.0,2.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,24.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,1.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,1.0,0.0,0.0,0.0,0.0,,0.0,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,6.0,,1.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,3.0,1.0,0.0,0.0,0.0,,0.0,,0.0,0.0,2.0,,0.0,,,0.0,,0.0,0.0,,,3.0,1.0,0.0,1.0,0.0,0.0,0.0,,0.0,,,,2.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,28.0,0.0,1.0,1.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,3.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,3.0,1.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,30.0,0.0,,2.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,1.0,0.0,0.0,,0.0,1.0,0.0 +"Microsoft.CodeAnalysis.CSharp.UseThrowExpression.CSharpUseThrowExpressionDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",1549.0,701.0,0.0,,847.0,27.0,118.0,33.0,7.0,4.0,2.0,2.0,6.0,3.0,0.0,7.0,137.0,44.0,,,,,,,770.0,62.0,46.0,,20.0,11.0,0.0,,3.0,2.0,151.0,70.0,,,35.0,0.0,64.0,5.0,3.0,0.0,1.0,0.0,,,1.0,1.0,28.0,,1.0,0.0,2.0,164.0,109.0,,,,0.0,0.0,,1.0,0.0,,406.0,0.0,,1.0,,0.0,0.0,0.0,2.0,0.0,5.0,12.0,,56.0,10.0,2.0,,0.0,4.0,48.0,72.0,2.0,,,1.0,6.0,0.0,0.0,0.0,0.0,,0.0,9.0,5.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,99.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,28.0,0.0,2.0,,,5.0,,1.0,2.0,2.0,0.0,,2.0,1.0,0.0,0.0,1.0,170.0,107.0,,916.0,,854.0,0.0,791.0,193.0,2.0,64.0,2.0,26.0,,1.0,163.0,,780.0,874.0,0.0,3.0,4.0,,2.0,,227.0,7.0,84.0,,18.0,,,4.0,,0.0,132.0,,,802.0,531.0,2.0,982.0,8.0,0.0,7.0,,9.0,,,,88.0,2.0,2.0,123.0,2.0,,2.0,4.0,0.0,220.0,,,963.0,52.0,587.0,897.0,,0.0,2.0,3.0,,2.0,77.0,0.0,0.0,0.0,484.0,,0.0,1.0,,4.0,,0.0,0.0,,136.0,,129.0,0.0,1.0,1.0,,2.0,28.0,0.0,0.0,,0.0,57.0,3.0,7.0,0.0,790.0,142.0,0.0,1.0,0.0,3.0,1.0,128.0,,953.0,,0.0,1.0,0.0,0.0,1.0,0.0,0.0,9.0,5.0,1136.0,742.0,7.0,7.0,109.0,,,1.0,,0.0,6.0,,0.0,0.0,27.0,2.0,2.0,,,0.0,,0.0,1.0,0.0,0.0,424.0,0.0,,113.0,33.0,,,0.0,0.0,0.0,1.0,1.0,,1.0,44.0,0.0,,0.0,6.0,0.0,65.0,0.0,2.0,2.0,2.0,,15.0,,1.0,0.0,27.0,,66.0,4.0,0.0 +"Microsoft.CodeAnalysis.Diagnostics.CSharp.CSharpCompilerDiagnosticAnalyzer,Microsoft.CodeAnalysis.CSharp,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",18209.0,1446.0,2.0,,2085.0,7.0,69.0,15.0,49.0,9.0,6.0,4.0,4.0,6.0,0.0,3.0,54.0,42.0,,,,,,,1285.0,57.0,148.0,,1.0,23.0,3.0,,4.0,4.0,862.0,841.0,,,450.0,49.0,25.0,3.0,8.0,0.0,4.0,2.0,,,4.0,5.0,100.0,,359.0,60.0,56.0,702.0,90.0,,,,1.0,0.0,,9.0,2.0,,162.0,17.0,,30.0,,0.0,0.0,0.0,25.0,5.0,45.0,17.0,,9.0,31.0,4.0,,0.0,2.0,13.0,54.0,6.0,,,4.0,13.0,1.0,0.0,6.0,2.0,,0.0,79.0,55.0,0.0,0.0,0.0,0.0,0.0,6.0,,,,,0.0,0.0,0.0,1.0,48.0,1.0,42.0,0.0,0.0,3.0,1.0,14.0,0.0,23.0,0.0,2.0,0.0,4.0,0.0,3.0,19.0,0.0,2.0,0.0,1.0,0.0,3.0,,,45.0,,18.0,4.0,3.0,0.0,,23.0,1.0,0.0,0.0,4.0,896.0,66.0,,1789.0,,1650.0,2.0,1599.0,1174.0,4.0,41.0,5.0,49.0,,4.0,62.0,,1946.0,1556.0,2.0,7.0,3.0,,5.0,,77.0,6.0,173.0,,10.0,,,10.0,,1.0,57.0,,,1726.0,1500.0,5.0,1560.0,50.0,2.0,4.0,,31.0,,,,182.0,7.0,4.0,59.0,5.0,,6.0,49.0,3.0,114.0,,,1737.0,10.0,1482.0,1573.0,,2.0,33.0,10.0,,4.0,952.0,2.0,63.0,2.0,81.0,,1.0,43.0,,8.0,,0.0,32.0,,90.0,,635.0,18.0,409.0,63.0,,46.0,79.0,4.0,1.0,,1.0,80.0,10.0,5.0,0.0,1725.0,17.0,5.0,9.0,0.0,37.0,5.0,70.0,,1748.0,,28.0,65.0,0.0,0.0,0.0,1.0,0.0,83.0,65.0,1559.0,1445.0,5.0,57.0,69.0,,,4.0,,1.0,4.0,,0.0,0.0,16.0,4.0,4.0,,,0.0,,0.0,30.0,0.0,0.0,1473.0,0.0,,181.0,86.0,,,1.0,0.0,0.0,1.0,3.0,,32.0,23.0,0.0,,19.0,14.0,0.0,41.0,0.0,7.0,4.0,3.0,,10.0,,3.0,0.0,1.0,,3.0,5.0,2.0 +"Microsoft.CodeAnalysis.Diagnostics.VisualBasic.VisualBasicCompilerDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,51762.0,,,,,,,,,,,,,,,19.0,7.0,152.0,165.0,76.0,89.0,,,,413.0,,,,20.0,,,,,1420.0,135.0,,,,,,,,,40.0,3.0,,,,993.0,,,,,,173.0,6.0,186.0,,,0.0,,,2.0,,,9.0,,893.0,,,,,,,,51.0,,,,32.0,,,,,,47.0,25.0,,,,,,,2.0,,,,,,,,,,37.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,6.0,0.0,,45.0,,,,,0.0,,,,,,,,51669.0,,1551.0,,,,,,,,,1875.0,,,54464.0,,,,,,133.0,,103.0,,,,11.0,,459.0,176.0,,276.0,,,53219.0,10.0,,,,,,,,11.0,,125.0,476.0,163.0,,,,,,234.0,,,,,53417.0,35.0,,,,,137.0,,,,1120.0,,,,,,,6.0,,,183.0,,589.0,,,134.0,,187.0,,,,,10.0,,,,,31.0,,,,,,,,,,,,,,54364.0,,2.0,,,,,,,,,,,,,,,6.0,127.0,,119.0,,,135.0,,,,,,105.0,33.0,,0.0,,,,,,,0.0,,,383.0,0.0,,,,,,7.0,,,,2.0,,,,,,,,,0.0,,23.0,,,,49946.0,,, +"Microsoft.CodeAnalysis.Editor.CSharp.UseAutoProperty.UseAutoPropertyAnalyzer,Microsoft.CodeAnalysis.CSharp.EditorFeatures,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",1004.0,311.0,23.0,,613.0,2.0,76.0,1.0,6.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,232.0,602.0,,,,,,,363.0,6.0,398.0,,0.0,19.0,50.0,,52.0,0.0,172.0,51.0,,,24.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,33.0,,74.0,21.0,58.0,121.0,10.0,,,,0.0,0.0,,2.0,0.0,,4.0,0.0,,13.0,,0.0,0.0,0.0,0.0,0.0,1.0,0.0,,0.0,21.0,0.0,,0.0,0.0,138.0,3.0,153.0,,,0.0,20.0,0.0,0.0,0.0,0.0,,0.0,231.0,305.0,0.0,0.0,0.0,0.0,0.0,37.0,,,,,0.0,0.0,0.0,0.0,2.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,40.0,0.0,0.0,0.0,0.0,16.0,0.0,0.0,,,1.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,119.0,6.0,,1001.0,,267.0,2.0,208.0,54.0,0.0,40.0,0.0,3.0,,0.0,71.0,,892.0,306.0,2.0,0.0,28.0,,38.0,,41.0,0.0,97.0,,53.0,,,73.0,,0.0,7.0,,,2028.0,136.0,0.0,188.0,89.0,27.0,0.0,,25.0,,,,99.0,0.0,0.0,55.0,0.0,,0.0,50.0,0.0,228.0,,,976.0,1.0,281.0,270.0,,2.0,0.0,0.0,,0.0,104.0,0.0,32.0,0.0,48.0,,0.0,2.0,,0.0,,0.0,0.0,,43.0,,143.0,2.0,137.0,174.0,,5.0,6.0,0.0,0.0,,0.0,26.0,0.0,2.0,0.0,176.0,2.0,0.0,2.0,0.0,0.0,0.0,76.0,,1048.0,,2.0,0.0,0.0,0.0,0.0,0.0,0.0,167.0,97.0,854.0,131.0,25.0,6.0,136.0,,,1.0,,0.0,1.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,122.0,0.0,,101.0,238.0,,,0.0,0.0,0.0,0.0,0.0,,29.0,2.0,0.0,,0.0,2.0,0.0,146.0,0.0,0.0,0.0,0.0,,24.0,,0.0,0.0,0.0,,1.0,0.0,2.0 +"Microsoft.CodeAnalysis.Editor.VisualBasic.UseAutoProperty.UseAutoPropertyAnalyzer,Microsoft.CodeAnalysis.VisualBasic.EditorFeatures,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,12685.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,,,,35.0,,,,0.0,,,,,0.0,6.0,,,,,,,,,0.0,0.0,,,,0.0,,,,,,47.0,2.0,10.0,,,0.0,,,0.0,,,23.0,,9.0,,,,,,,,14.0,,,,0.0,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,,,0.0,,,,,,,,13561.0,,0.0,,,,,,,,,0.0,,,12758.0,,,,,,0.0,,0.0,,,,0.0,,36.0,0.0,,0.0,,,15289.0,0.0,,,,,,,,0.0,,0.0,38.0,0.0,,,,,,0.0,,,,,12805.0,57.0,,,,,0.0,,,,0.0,,,,,,,2.0,,,3.0,,10.0,,,6.0,,11.0,,,,,25.0,,,,,0.0,,,,,,,,,,,,,,12819.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,0.0,,,,,,0.0,0.0,,0.0,,,,,,,0.0,,,38.0,0.0,,,,,,0.0,,,,0.0,,,,,,,,,0.0,,0.0,,,,11983.0,,, +"Microsoft.CodeAnalysis.PopulateSwitch.PopulateSwitchDiagnosticAnalyzer,Microsoft.CodeAnalysis.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",15.0,42.0,0.0,414.0,374.0,0.0,4.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,10.0,86.0,0.0,0.0,15.0,15.0,3.0,1.0,4.0,0.0,25.0,204.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,2.0,1882.0,2.0,67.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,38.0,2.0,22.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,27.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,52.0,23.0,37.0,28.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,52.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,18.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,25.0,447.0,570.0,270.0,15.0,0.0,53.0,3.0,0.0,0.0,0.0,0.0,72.0,0.0,0.0,2288.0,3767.0,152.0,0.0,0.0,0.0,3.0,0.0,3.0,0.0,0.0,29.0,0.0,0.0,280.0,3.0,0.0,42.0,0.0,0.0,878.0,0.0,858.0,3.0,0.0,36.0,0.0,0.0,0.0,0.0,0.0,860.0,292.0,110.0,393.0,0.0,0.0,0.0,0.0,3.0,0.0,0.0,0.0,0.0,1706.0,0.0,1679.0,0.0,30.0,33.0,9.0,0.0,0.0,0.0,1.0,0.0,5.0,0.0,0.0,0.0,84.0,0.0,0.0,0.0,435.0,0.0,0.0,0.0,0.0,3.0,5.0,1.0,12.0,0.0,30.0,13.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,57.0,0.0,0.0,0.0,0.0,0.0,0.0,9.0,839.0,1609.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,9.0,1215.0,137.0,0.0,0.0,76.0,0.0,6.0,0.0,9.0,0.0,0.0,6.0,0.0,0.0,1.0,0.0,0.0,34.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,10.0,0.0,0.0,159.0,101.0,275.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,7.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1339.0,0.0,0.0,0.0 +"Microsoft.CodeAnalysis.UseExplicitTupleName.UseExplicitTupleNameDiagnosticAnalyzer,Microsoft.CodeAnalysis.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",207.0,453.0,22.0,1075.0,748.0,2.0,8.0,2.0,7.0,1.0,0.0,0.0,1.0,1.0,0.0,7.0,276.0,171.0,2.0,7.0,73.0,267.0,52.0,230.0,39.0,5.0,19.0,183.0,0.0,6.0,7.0,8.0,0.0,0.0,73.0,79.0,128.0,228.0,21.0,2.0,2.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,6.0,87.0,74.0,6.0,7.0,31.0,28.0,26.0,1.0,47.0,0.0,0.0,0.0,1.0,0.0,0.0,42.0,0.0,2.0,3.0,53.0,0.0,0.0,0.0,0.0,0.0,3.0,1.0,4.0,20.0,78.0,2.0,4.0,0.0,1.0,118.0,5.0,43.0,8.0,2.0,1.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,269.0,60.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0,8.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,7.0,0.0,9.0,4.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,30.0,8.0,1022.0,365.0,352.0,211.0,1.0,102.0,30.0,40.0,2.0,0.0,23.0,181.0,0.0,8.0,636.0,752.0,275.0,1.0,0.0,0.0,103.0,0.0,111.0,85.0,1.0,61.0,3.0,2.0,30.0,191.0,1.0,114.0,0.0,11.0,640.0,21.0,436.0,68.0,0.0,165.0,28.0,1.0,1.0,2.0,51.0,67.0,59.0,48.0,94.0,0.0,0.0,5.0,0.0,221.0,0.0,1.0,0.0,8.0,692.0,45.0,622.0,3.0,93.0,155.0,63.0,1.0,0.0,1.0,31.0,0.0,20.0,0.0,7.0,1.0,9.0,1.0,0.0,4.0,70.0,1.0,98.0,0.0,0.0,5.0,5.0,42.0,82.0,8.0,60.0,2.0,1.0,8.0,6.0,0.0,0.0,0.0,0.0,7.0,1.0,7.0,0.0,74.0,3.0,0.0,1.0,0.0,0.0,1.0,9.0,455.0,714.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,157.0,81.0,2437.0,130.0,19.0,7.0,82.0,7.0,137.0,32.0,70.0,0.0,1.0,265.0,0.0,0.0,34.0,0.0,0.0,39.0,2.0,0.0,0.0,0.0,1.0,0.0,0.0,251.0,0.0,0.0,72.0,309.0,844.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,0.0,1.0,2.0,0.0,8.0,0.0,0.0,17.0,0.0,0.0,2.0,43.0,2.0,0.0,1.0,19879.0,1.0,1.0,1.0 +"Microsoft.CodeAnalysis.VisualBasic.Diagnostics.RemoveUnnecessaryCast.VisualBasicRemoveUnnecessaryCastDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,5117.0,,,,,,,,,,,,,,,234.0,49.0,5188.0,3095.0,3684.0,661.0,,,,2095.0,,,,9.0,,,,,1041.0,94.0,,,,,,,,,0.0,0.0,,,,127.0,,,,,,800.0,6.0,250.0,,,0.0,,,0.0,,,7.0,,751.0,,,,,,,,92.0,,,,10.0,,,,,,375.0,38.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,18.0,0.0,,30.0,,,,,0.0,,,,,,,,5580.0,,1421.0,,,,,,,,,1417.0,,,4633.0,,,,,,1115.0,,4437.0,,,,193.0,,1643.0,6604.0,,2602.0,,,4728.0,121.0,,,,,,,,154.0,,5478.0,2480.0,8453.0,,,,,,3373.0,,,,,4521.0,18.0,,,,,772.0,,,,127.0,,,,,,,7.0,,,776.0,,745.0,,,73.0,,144.0,,,,,7.0,,,,,0.0,,,,,,,,,,,,,,4672.0,,0.0,,,,,,,,,,,,,,,44.0,5649.0,,685.0,,,2965.0,,,,,,4316.0,152.0,,0.0,,,,,,,0.0,,,1616.0,0.0,,,,,,4.0,,,,0.0,,,,,,,,,0.0,,21.0,,,,4247.0,,, +"Microsoft.CodeAnalysis.VisualBasic.Diagnostics.VisualBasicUnboundIdentifiersDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,7.0,,,,,,,,,,,,,,,0.0,0.0,2.0,3.0,2.0,0.0,,,,1.0,,,,0.0,,,,,1.0,0.0,,,,,,,,,0.0,0.0,,,,1.0,,,,,,1.0,0.0,25.0,,,0.0,,,0.0,,,0.0,,1.0,,,,,,,,0.0,,,,0.0,,,,,,1.0,0.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,,,0.0,,,,,,,,5.0,,1.0,,,,,,,,,15.0,,,5.0,,,,,,0.0,,4.0,,,,0.0,,2.0,2.0,,37.0,,,5.0,0.0,,,,,,,,0.0,,30.0,3.0,3.0,,,,,,2.0,,,,,5.0,0.0,,,,,2.0,,,,1.0,,,,,,,0.0,,,0.0,,2.0,,,0.0,,25.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,5.0,,0.0,,,,,,,,,,,,,,,0.0,2.0,,0.0,,,2.0,,,,,,2.0,0.0,,0.0,,,,,,,0.0,,,2.0,0.0,,,,,,0.0,,,,0.0,,,,,,,,,0.0,,0.0,,,,51.0,,, +"Microsoft.CodeAnalysis.VisualBasic.UseCoalesceExpression.VisualBasicUseCoalesceExpressionDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,115.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,,,,2.0,,,,0.0,,,,,2.0,57.0,,,,,,,,,0.0,0.0,,,,0.0,,,,,,0.0,0.0,0.0,,,0.0,,,0.0,,,0.0,,0.0,,,,,,,,0.0,,,,0.0,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,,,0.0,,,,,,,,84.0,,4.0,,,,,,,,,3.0,,,64.0,,,,,,0.0,,0.0,,,,0.0,,2.0,0.0,,0.0,,,15.0,0.0,,,,,,,,0.0,,0.0,2.0,0.0,,,,,,0.0,,,,,12.0,0.0,,,,,0.0,,,,0.0,,,,,,,0.0,,,1.0,,0.0,,,0.0,,0.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,26.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,0.0,,,,,,0.0,30.0,,0.0,,,,,,,0.0,,,1189.0,0.0,,,,,,0.0,,,,0.0,,,,,,,,,0.0,,0.0,,,,12.0,,, +"Microsoft.CodeAnalysis.VisualBasic.UseCoalesceExpression.VisualBasicUseCoalesceExpressionForNullableDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,131.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,,,,1.0,,,,0.0,,,,,1.0,0.0,,,,,,,,,0.0,0.0,,,,0.0,,,,,,0.0,0.0,0.0,,,0.0,,,0.0,,,0.0,,0.0,,,,,,,,0.0,,,,0.0,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,,,0.0,,,,,,,,116.0,,1.0,,,,,,,,,1.0,,,10.0,,,,,,0.0,,0.0,,,,0.0,,1.0,0.0,,0.0,,,9.0,0.0,,,,,,,,0.0,,0.0,1.0,0.0,,,,,,0.0,,,,,34.0,0.0,,,,,0.0,,,,0.0,,,,,,,0.0,,,0.0,,0.0,,,0.0,,0.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,47.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,0.0,,,,,,0.0,0.0,,0.0,,,,,,,0.0,,,1.0,0.0,,,,,,0.0,,,,0.0,,,,,,,,,0.0,,0.0,,,,10.0,,, +"Microsoft.CodeAnalysis.VisualBasic.UseCollectionInitializer.VisualBasicUseCollectionInitializerDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,1598.0,,,,,,,,,,,,,,,485.0,54.0,870.0,674.0,458.0,311.0,,,,250.0,,,,44.0,,,,,404.0,77.0,,,,,,,,,1.0,1.0,,,,3132.0,,,,,,111.0,4.0,278.0,,,1.0,,,1.0,,,34.0,,569.0,,,,,,,,234.0,,,,2.0,,,,,,216.0,10.0,,,,,,,1.0,,,,,,,,,,4.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,49.0,0.0,,3.0,,,,,1.0,,,,,,,,1413.0,,844.0,,,,,,,,,1378.0,,,1406.0,,,,,,325.0,,7149.0,,,,32.0,,162.0,1354.0,,464.0,,,1836.0,153.0,,,,,,,,42.0,,400.0,1434.0,1152.0,,,,,,1206.0,,,,,1236.0,140.0,,,,,407.0,,,,545.0,,,,,,,4.0,,,89.0,,566.0,,,48.0,,538.0,,,,,13.0,,,,,2.0,,,,,,,,,,,,,,2007.0,,32.0,,,,,,,,,,,,,,,57.0,873.0,,235.0,,,512.0,,,,,,316.0,287.0,,0.0,,,,,,,0.0,,,279.0,0.0,,,,,,3.0,,,,32.0,,,,,,,,,0.0,,30.0,,,,1096.0,,, +"Microsoft.CodeAnalysis.VisualBasic.UseNullPropagation.VisualBasicUseNullPropagationDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,454.0,,,,,,,,,,,,,,,24.0,0.0,417.0,0.0,0.0,0.0,,,,28.0,,,,0.0,,,,,0.0,0.0,,,,,,,,,0.0,0.0,,,,0.0,,,,,,1.0,0.0,0.0,,,0.0,,,0.0,,,0.0,,0.0,,,,,,,,0.0,,,,0.0,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,,,0.0,,,,,,,,150.0,,0.0,,,,,,,,,1.0,,,110.0,,,,,,0.0,,0.0,,,,2.0,,53.0,26.0,,433.0,,,738.0,0.0,,,,,,,,2.0,,0.0,3.0,2.0,,,,,,0.0,,,,,16.0,0.0,,,,,0.0,,,,0.0,,,,,,,0.0,,,220.0,,0.0,,,0.0,,0.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,77.0,,0.0,,,,,,,,,,,,,,,0.0,2.0,,0.0,,,0.0,,,,,,0.0,1.0,,0.0,,,,,,,0.0,,,33.0,0.0,,,,,,0.0,,,,0.0,,,,,,,,,0.0,,0.0,,,,20.0,,, +"Microsoft.CodeAnalysis.VisualBasic.UseObjectInitializer.VisualBasicUseObjectInitializerDiagnosticAnalyzer,Microsoft.CodeAnalysis.VisualBasic.Features,Version=42.42.42.42,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,747.0,,,,,,,,,,,,,,,2.0,37.0,21.0,90.0,26.0,43.0,,,,66.0,,,,0.0,,,,,137.0,4.0,,,,,,,,,0.0,0.0,,,,18.0,,,,,,138.0,1.0,11.0,,,0.0,,,0.0,,,75.0,,91.0,,,,,,,,9.0,,,,0.0,,,,,,149.0,4.0,,,,,,,0.0,,,,,,,,,,3.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.0,0.0,,0.0,,,,,0.0,,,,,,,,828.0,,117.0,,,,,,,,,128.0,,,602.0,,,,,,56.0,,167.0,,,,55.0,,120.0,24.0,,88.0,,,767.0,23.0,,,,,,,,2.0,,60.0,58.0,101.0,,,,,,157.0,,,,,997.0,61.0,,,,,15.0,,,,17.0,,,,,,,1.0,,,5.0,,19.0,,,5.0,,11.0,,,,,3.0,,,,,0.0,,,,,,,,,,,,,,560.0,,0.0,,,,,,,,,,,,,,,45.0,23.0,,3602.0,,,40.0,,,,,,26.0,2.0,,0.0,,,,,,,0.0,,,82.0,0.0,,,,,,0.0,,,,3.0,,,,,,,,,0.0,,2.0,,,,11812.0,,, +"Microsoft.Composition.Analyzers.DoNotMixAttributesFromDifferentVersionsOfMEFAnalyzer,Microsoft.NetCore.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,1.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,59.0,,,0.0,35.0,0.0,0.0,0.0,0.0,,6.0,,28.0,,1.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,2.0,1.0,1.0,1.0,1.0,4.0,20.0,1.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,25.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,1.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,,,,36.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,2.0,0.0,6.0,0.0,1.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,0.0,1.0,1.0,1.0,4.0,0.0,1.0,1.0,0.0,2.0,2.0,0.0,0.0,0.0,0.0,3.0,2.0,0.0,0.0,,0.0,0.0,1.0,0.0,1.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.Composition.Analyzers.PartsExportedWithMEFv2MustBeMarkedAsSharedAnalyzer,Microsoft.NetCore.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,1.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,19.0,0.0,,35.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,5.0,,1.0,,0.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,2.0,3.0,0.0,0.0,3.0,1.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,,,,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,32.0,0.0,4.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,36.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,3.0,1.0,3.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,18.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.QualityGuidelines.Analyzers.SealMethodsThatSatisfyPrivateInterfacesAnalyzer,Microsoft.CodeQuality.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,11.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,,0.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,73.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,,,,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,100.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,44.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.QualityGuidelines.CSharp.Analyzers.CSharpRethrowToPreserveStackDetailsAnalyzer,Microsoft.CodeQuality.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,2.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,,,,,,0.0,,,0.0,0.0,0.0,,0.0,0.0,,0.0,,,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,0.0,0.0,,,0.0,,,0.0,,0.0,,,,,,0.0,,0.0,,0.0,,0.0,,,,,,,0.0,0.0,,0.0,0.0,0.0,,,,,0.0,,,,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Microsoft.QualityGuidelines.VisualBasic.Analyzers.BasicRethrowToPreserveStackDetailsAnalyzer,Microsoft.CodeQuality.VisualBasic.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,,,,,,,,,,1.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,,,,,,0.0,,,,,,,,,,0.0,,,,0.0,,,,,,2.0,0.0,0.0,,,0.0,,,0.0,,,0.0,,0.0,,,,,,,,,,,,,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,,0.0,,,,0.0,,,0.0,,0.0,,,,0.0,,,,,,,,0.0,,0.0,,0.0,,,,,,0.0,,,,,,0.0,,,,,0.0,,,,0.0,,,,,,,0.0,,,1.0,,32.0,,,0.0,,0.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,0.0,0.0,,0.0,,,0.0,,,,,,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"Microsoft.VisualStudio.Azure.Fabric.DiagnosticAnalyzers.ServiceAssemblyNameMismatchAnalyzer,Microsoft.VisualStudio.Azure.Fabric.DiagnosticAnalyzers,Version=1.6.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a",43.0,5.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Microsoft.VisualStudio.Azure.Fabric.DiagnosticAnalyzers.ServiceNameMismatchSessionAnalyzer,Microsoft.VisualStudio.Azure.Fabric.DiagnosticAnalyzers,Version=1.6.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a",32.0,26.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,14.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,30.0,0.0,0.0,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,1.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,,0.0,0.0,0.0 +"Roslyn.Diagnostics.Analyzers.DeclarePublicAPIAnalyzer,Roslyn.Diagnostics.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,106.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,154.0,,,0.0,0.0,0.0,0.0,0.0,0.0,,34.0,,1.0,,1.0,,0.0,1.0,0.0,,0.0,,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,1.0,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,4.0,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,,,,6.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,,,0.0,,29.0,2.0,0.0,0.0,71.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0,0.0,0.0,40.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"Roslyn.Diagnostics.CSharp.Analyzers.CSharpCodeActionCreateAnalyzer,Roslyn.Diagnostics.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,2.0,0.0,0.0,,,,,,,,,,,,,,352.0,,,,,,,,39.0,,2163.0,,,,315.0,,64.0,47.0,0.0,,35.0,,,146.0,74.0,,,,,,2602.0,569.0,,,,,0.0,,85.0,0.0,,825.0,39.0,,,,0.0,5.0,6.0,19.0,17.0,,,,,,,,0.0,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,0.0,85.0,9.0,165.0,1.0,33.0,0.0,0.0,0.0,0.0,1.0,,0.0,0.0,,0.0,,,,,,,,,,,,,,,,,130.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,505.0,,,,,,,0.0,,,,,,,,0.0,,,,,,,,,,,,,426.0,0.0,,0.0,0.0,,,,,,,,,,,49.0,198.0,,18.0,1853.0,,,10.0,1002.0,,,,,55.0,,24.0,73.0,,534.0,,1999.0,,,591.0,,,,14.0,0.0,,13.0,,176.0,,0.0,,,67.0,136.0,8.0,18.0,190.0,,,,,,,,,,,,,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"Roslyn.Diagnostics.CSharp.Analyzers.CSharpSpecializedEnumerableCreationAnalyzer,Roslyn.Diagnostics.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,16.0,47.0,1.0,0.0,0.0,0.0,,0.0,0.0,30.0,57.0,,,,,,,,0.0,,,0.0,0.0,0.0,,0.0,0.0,,0.0,,,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,,0.0,13.0,0.0,0.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,42.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,0.0,0.0,,,2.0,,,0.0,,0.0,,,,,,0.0,,2.0,,0.0,,1.0,,,,,,,0.0,0.0,,0.0,1.0,0.0,,,,,3.0,,,,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,0.0,1.0,66.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,,,,,,53.0,,,0.0,,,,,,,,,,,,,,,,,,,3.0,,,,,,,, +"Roslyn.Diagnostics.VisualBasic.Analyzers.BasicCodeActionCreateAnalyzer,Roslyn.Diagnostics.VisualBasic.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,47.0,,,,,,,,,,23.0,,,,,,,,,,151.0,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,114.0,,,,,64.0,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,2.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"Roslyn.Diagnostics.VisualBasic.Analyzers.BasicSpecializedEnumerableCreationAnalyzer,Roslyn.Diagnostics.VisualBasic.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,,,,,,,,,,8.0,0.0,5.0,39.0,28.0,3.0,,,,,,,,0.0,,,,,,0.0,,,,,,,,,,0.0,,,,0.0,,,,,,0.0,0.0,0.0,,,0.0,,,0.0,,,0.0,,0.0,,,,,,,,,,,,,,,,,,215.0,40.0,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3.0,,5.0,,,,1.0,,,58.0,,320.0,,,,1.0,,,,,,,,1.0,,35.0,,6.0,,,,,,110.0,,,,,,0.0,,,,,4.0,,,,0.0,,,,,,,0.0,,,0.0,,0.0,,,0.0,,0.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,0.0,51.0,,73.0,,,56.0,,,,,,35.0,2.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"System.Runtime.Analyzers.AttributeStringLiteralsShouldParseCorrectlyAnalyzer,Microsoft.NetCore.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,15.0,13.0,2.0,1.0,1.0,3.0,,0.0,6.0,816.0,170.0,9.0,5.0,136.0,129.0,40.0,116.0,,12.0,,,0.0,74.0,8.0,7.0,2.0,44.0,,23.0,,9.0,,5.0,,1.0,1.0,0.0,,0.0,,0.0,0.0,2.0,11.0,323.0,335.0,124.0,16.0,45.0,22.0,13.0,2.0,99.0,1.0,0.0,0.0,3.0,0.0,0.0,140.0,0.0,3.0,17.0,109.0,0.0,0.0,0.0,1.0,1.0,,,,,,,,0.0,1.0,9.0,56.0,6.0,7.0,3.0,3.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,39.0,7.0,0.0,9.0,0.0,0.0,1.0,0.0,3.0,0.0,1.0,0.0,16.0,0.0,1.0,0.0,1.0,1.0,0.0,16.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,35.0,2.0,133.0,11.0,2.0,,6.0,5.0,,55.0,2.0,112.0,1.0,,,42.0,,,1.0,,14.0,,33.0,37.0,14.0,69.0,,57.0,,,,78.0,1.0,118.0,1.0,2.0,1.0,,,5.0,,33.0,,,85.0,,2.0,4.0,267.0,1.0,54.0,1.0,94.0,0.0,13.0,1.0,1.0,18.0,13.0,1.0,134.0,0.0,1.0,12.0,24.0,83.0,24.0,9.0,239.0,9.0,3.0,78.0,18.0,1.0,0.0,0.0,12.0,13.0,4.0,6.0,0.0,,38.0,1.0,3.0,0.0,1.0,2.0,,,,0.0,,,,,,,,,,,,5.0,14.0,94.0,5.0,115.0,2.0,105.0,0.0,2.0,109.0,0.0,0.0,2.0,1.0,1.0,73.0,25.0,0.0,,,2.0,,,,,,,101.0,,,0.0,,,,,,,,,,,,,,,,,,,5.0,,,,,,,, +"System.Runtime.InteropServices.CSharp.Analyzers.CSharpAlwaysConsumeTheValueReturnedByMethodsMarkedWithPreserveSigAttributeAnalyzer,Microsoft.NetCore.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,35.0,60.0,1.0,0.0,0.0,2.0,,0.0,35.0,164.0,407.0,,,,,,,,3.0,,,0.0,51.0,29.0,,1.0,0.0,,29.0,,,,3.0,,0.0,1.0,0.0,,0.0,,,1.0,0.0,56.0,,221.0,35.0,20.0,44.0,59.0,,,,0.0,0.0,,0.0,0.0,,3.0,0.0,,5.0,,0.0,0.0,0.0,1.0,0.0,,,,,,,,0.0,1.0,110.0,9.0,43.0,,,79.0,,0.0,0.0,,25.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,4.0,0.0,11.0,0.0,0.0,0.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,35.0,0.0,,,,,,,,,,,,,,,,,1.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,38.0,46.0,,,3.0,,,1.0,,0.0,,,,,,0.0,,20.0,,2.0,,19.0,,,,,,,3.0,0.0,,0.0,1.0,0.0,,,,,3.0,,,,,0.0,2.0,,0.0,69.0,1.0,51.0,0.0,72.0,,1.0,39.0,,1.0,,0.0,0.0,,29.0,,40.0,12.0,140.0,7.0,,55.0,31.0,12.0,0.0,,0.0,32.0,2.0,49.0,0.0,,39.0,1.0,0.0,0.0,2.0,0.0,,,,,,,,,,,,,,,,14.0,107.0,207.0,,,1.0,,0.0,2.0,,0.0,0.0,1.0,0.0,0.0,,,0.0,,,14.0,,,,,,,370.0,,,0.0,,,,,,,,,,,,,,,,,,,3.0,,,,,,,, +"System.Runtime.InteropServices.VisualBasic.Analyzers.BasicAlwaysConsumeTheValueReturnedByMethodsMarkedWithPreserveSigAttributeAnalyzer,Microsoft.NetCore.VisualBasic.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,,,,,,,,,,384.0,580.0,6976.0,15743.0,6600.0,5695.0,,,,,,,,314.0,,,,,,62.0,,,,,,,,,,0.0,,,,2042.0,,,,,,387.0,12.0,2130.0,,,0.0,,,0.0,,,10.0,,2023.0,,,,,,,,,,,,,,,,,,370.0,176.0,,,,,,,6.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3734.0,,8480.0,,,,456.0,,,9310.0,,20826.0,,,,1498.0,,,,,,,,91.0,,9753.0,,9572.0,,,,,,19572.0,,,,,,1160.0,,,,,4641.0,,,,1391.0,,,,,,,11.0,,,525.0,,2261.0,,,210.0,,1405.0,,,,,101.0,,,,,0.0,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,769.0,7117.0,,4249.0,,,16154.0,,,,,,7166.0,159.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +"System.Threading.Tasks.Analyzers.DoNotCreateTasksWithoutPassingATaskSchedulerAnalyzer,Microsoft.NetCore.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,7.0,86.0,0.0,0.0,0.0,19.0,,0.0,4.0,176.0,555.0,2.0,3.0,126.0,407.0,50.0,141.0,,2.0,,,0.0,71.0,5.0,2.0,0.0,0.0,,10.0,,2.0,,55.0,,0.0,0.0,0.0,,0.0,,0.0,0.0,0.0,3.0,128.0,279.0,55.0,6.0,11.0,5.0,56.0,0.0,436.0,0.0,0.0,1.0,0.0,0.0,0.0,12.0,0.0,0.0,29.0,67.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,138.0,22.0,6.0,49.0,19.0,1.0,,0.0,0.0,,0.0,0.0,0.0,,,,,,,,,,,,,,,0.0,0.0,2.0,0.0,4.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,,,,,,,,,,,,,,,,,28.0,,,,,,,,,,,,,,,,,,,,,,,77.0,0.0,173.0,2.0,2.0,,56.0,1.0,,140.0,55.0,471.0,0.0,,,4.0,,,0.0,,36.0,,1.0,1.0,7.0,205.0,,338.0,,,,2.0,0.0,237.0,0.0,0.0,0.0,,,2.0,,27.0,,,209.0,,0.0,1.0,60.0,0.0,11.0,0.0,113.0,0.0,3.0,0.0,0.0,5.0,29.0,0.0,134.0,0.0,0.0,2.0,67.0,79.0,37.0,4.0,134.0,3.0,0.0,6.0,69.0,0.0,0.0,0.0,0.0,3.0,1.0,5.0,0.0,,2.0,0.0,0.0,0.0,0.0,0.0,,,,0.0,,,,,,,,,,,,5.0,30.0,243.0,3.0,166.0,0.0,15.0,0.0,1.0,419.0,0.0,0.0,29.0,0.0,0.0,168.0,1.0,0.0,,,34.0,,,,,,,214.0,,,0.0,,,,,,,,,,,,,,,,,,,1.0,,,,,,,, +"XmlDocumentationComments.CSharp.Analyzers.CSharpAvoidUsingCrefTagsWithAPrefixAnalyzer,Microsoft.CodeQuality.CSharp.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,1.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,,,,,,,0.0,,,0.0,0.0,0.0,,0.0,0.0,,0.0,,,,0.0,,0.0,0.0,0.0,,0.0,,,0.0,0.0,0.0,,0.0,0.0,0.0,2.0,0.0,,,,0.0,0.0,,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,0.0,,,,,,,,0.0,0.0,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,,0.0,,,,,,,,,,,,,,,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,0.0,,0.0,0.0,,,0.0,,,0.0,,0.0,,,,,,0.0,,0.0,,0.0,,0.0,,,,,,,0.0,0.0,,0.0,0.0,0.0,,,,,0.0,,,,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,,0.0,,0.0,0.0,,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,0.0,0.0,0.0,,,0.0,,0.0,0.0,,0.0,0.0,0.0,0.0,0.0,,,0.0,,,0.0,,,,,,,0.0,,,0.0,,,,,,,,,,,,,,,,,,,0.0,,,,,,,, +"XmlDocumentationComments.VisualBasic.Analyzers.BasicAvoidUsingCrefTagsWithAPrefixAnalyzer,Microsoft.CodeQuality.VisualBasic.Analyzers,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35",,,,,,,,,,,,,,,,,,,1.0,0.0,76.0,299.0,41.0,71.0,,,,,,,,0.0,,,,,,0.0,,,,,,,,,,0.0,,,,0.0,,,,,,0.0,0.0,29.0,,,0.0,,,0.0,,,0.0,,1.0,,,,,,,,,,,,,,,,,,0.0,0.0,,,,,,,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2.0,,169.0,,,,0.0,,,100.0,,78.0,,,,0.0,,,,,,,,0.0,,90.0,,147.0,,,,,,167.0,,,,,,0.0,,,,,92.0,,,,0.0,,,,,,,0.0,,,0.0,,1.0,,,0.0,,3.0,,,,,0.0,,,,,0.0,,,,,,,,,,,,,,,,0.0,,,,,,,,,,,,,,,0.0,102.0,,2.0,,,60.0,,,,,,3.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/src/VisualStudio/Core/Test.Next/VisualStudioTest.Next.csproj b/src/VisualStudio/Core/Test.Next/VisualStudioTest.Next.csproj index a963126adc96ad7b0f2fc25501b67230e248dc60..b70300e84d39189f8f422fb67fd35bbec49a561b 100644 --- a/src/VisualStudio/Core/Test.Next/VisualStudioTest.Next.csproj +++ b/src/VisualStudio/Core/Test.Next/VisualStudioTest.Next.csproj @@ -94,4 +94,7 @@ - + + + + \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/Log/FunctionId.cs b/src/Workspaces/Core/Portable/Log/FunctionId.cs index 8fe8c7d0267ef65fcb6f2537a36bf08b1498a3af..aef7bc78527d4e2761db5570a9cf8f28a11366ba 100644 --- a/src/Workspaces/Core/Portable/Log/FunctionId.cs +++ b/src/Workspaces/Core/Portable/Log/FunctionId.cs @@ -403,7 +403,10 @@ internal enum FunctionId MetadataOnlyImage_EmitFailure, LiveTableDataSource_OnDiagnosticsUpdated, Experiment_KeybindingsReset, - + Diagnostics_GeneratePerformaceReport, + Diagnostics_BadAnalyzer, + CodeAnalysisService_ReportAnalyzerPerformance, + PerformanceTrackerService_AddSnapshot, AbstractProject_SetIntelliSenseBuild, AbstractProject_Created, AbstractProject_PushedToWorkspace, diff --git a/src/Workspaces/Core/Portable/Remote/RemoteHostClientExtensions.cs b/src/Workspaces/Core/Portable/Remote/RemoteHostClientExtensions.cs index d545895d9604bea62bc1b7de97568a41c2bd421e..0bd5c9310fbf0c1c1a37c9a8788fec3429e3ebac 100644 --- a/src/Workspaces/Core/Portable/Remote/RemoteHostClientExtensions.cs +++ b/src/Workspaces/Core/Portable/Remote/RemoteHostClientExtensions.cs @@ -225,6 +225,14 @@ public static bool IsOutOfProcessEnabled(this Workspace workspace, Option this RemoteHostClient client, Solution solution, string targetName, object[] arguments, CancellationToken cancellationToken) => TryRunRemoteAsync(client, WellKnownServiceHubServices.CodeAnalysisService, solution, targetName, arguments, cancellationToken); + public static Task TryRunCodeAnalysisRemoteAsync( + this RemoteHostClient client, string targetName, object argument, CancellationToken cancellationToken) + => TryRunRemoteAsync(client, WellKnownServiceHubServices.CodeAnalysisService, targetName, new object[] { argument }, cancellationToken); + + public static Task TryRunCodeAnalysisRemoteAsync( + this RemoteHostClient client, string targetName, object[] arguments, CancellationToken cancellationToken) + => TryRunRemoteAsync(client, WellKnownServiceHubServices.CodeAnalysisService, targetName, arguments, cancellationToken); + /// /// Synchronize given solution as primary workspace solution in remote host /// diff --git a/src/Workspaces/Core/Portable/Remote/WellKnownServiceHubServices.cs b/src/Workspaces/Core/Portable/Remote/WellKnownServiceHubServices.cs index 9a21a9118acf6f1689d136147daecf8f418e096e..00357808a2cebb8dadda33010dc73ab61a57e2ae 100644 --- a/src/Workspaces/Core/Portable/Remote/WellKnownServiceHubServices.cs +++ b/src/Workspaces/Core/Portable/Remote/WellKnownServiceHubServices.cs @@ -25,7 +25,5 @@ public static void Set64bit(bool x64) public const string ServiceHubServiceBase_Initialize = "Initialize"; public const string AssetService_RequestAssetAsync = "RequestAssetAsync"; - - public const string CodeAnalysisService_CalculateDiagnosticsAsync = "CalculateDiagnosticsAsync"; } } diff --git a/src/Workspaces/Remote/Core/Diagnostics/DiagnosticComputer.cs b/src/Workspaces/Remote/Core/Diagnostics/DiagnosticComputer.cs index fdb8cada81046de8ed7b54abf1a411df8c04612f..f7432d59b4fe8deb66d4154d575f9280aff89d5e 100644 --- a/src/Workspaces/Remote/Core/Diagnostics/DiagnosticComputer.cs +++ b/src/Workspaces/Remote/Core/Diagnostics/DiagnosticComputer.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Diagnostics.Telemetry; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Roslyn.Utilities; @@ -19,11 +20,15 @@ internal class DiagnosticComputer { private readonly Project _project; private readonly Dictionary> _exceptions; + private readonly IPerformanceTrackerService _performanceTracker; public DiagnosticComputer(Project project) { _project = project; _exceptions = new Dictionary>(); + + // we only track performance from primary branch. all forked branch we don't care such as preview. + _performanceTracker = project.IsFromPrimaryBranch() ? project.Solution.Workspace.Services.GetService() : null; } public async Task> GetDiagnosticsAsync( @@ -87,6 +92,13 @@ public DiagnosticComputer(Project project) // PERF: Run all analyzers at once using the new GetAnalysisResultAsync API. var analysisResult = await analyzerDriver.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false); + // record performance if tracker is available + if (_performanceTracker != null) + { + // +1 to include project itself + _performanceTracker.AddSnapshot(analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(), _project.DocumentIds.Count + 1); + } + var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken); return DiagnosticAnalysisResultMap.Create( diff --git a/src/Workspaces/Remote/Core/Diagnostics/IPerformanceTrackerService.cs b/src/Workspaces/Remote/Core/Diagnostics/IPerformanceTrackerService.cs new file mode 100644 index 0000000000000000000000000000000000000000..fd872c4950c1b446e612e1c05fa0d7a0b862a1df --- /dev/null +++ b/src/Workspaces/Remote/Core/Diagnostics/IPerformanceTrackerService.cs @@ -0,0 +1,39 @@ +// 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.Generic; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.CodeAnalysis.Remote.Diagnostics +{ + internal interface IPerformanceTrackerService : IWorkspaceService + { + void AddSnapshot(IEnumerable snapshot, int unitCount); + void GenerateReport(List badAnalyzers); + + event EventHandler SnapshotAdded; + } + + internal struct ExpensiveAnalyzerInfo + { + public readonly bool BuiltIn; + public readonly string AnalyzerId; + public readonly string AnalyzerIdHash; + public readonly double LocalOutlierFactor; + public readonly double Average; + public readonly double AdjustedStandardDeviation; + + public ExpensiveAnalyzerInfo(bool builtIn, string analyzerId, double lof_value, double average, double stddev) : this() + { + BuiltIn = builtIn; + AnalyzerId = analyzerId; + AnalyzerIdHash = analyzerId.GetHashCode().ToString(); + LocalOutlierFactor = lof_value; + Average = average; + AdjustedStandardDeviation = stddev; + } + + public string PIISafeAnalyzerId => BuiltIn ? AnalyzerId : AnalyzerIdHash; + } +} diff --git a/src/Workspaces/Remote/Core/Diagnostics/PerformanceQueue.cs b/src/Workspaces/Remote/Core/Diagnostics/PerformanceQueue.cs new file mode 100644 index 0000000000000000000000000000000000000000..4fbc2607bbcc289e78f2f5c2c98b5467b6ae6653 --- /dev/null +++ b/src/Workspaces/Remote/Core/Diagnostics/PerformanceQueue.cs @@ -0,0 +1,227 @@ +// 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.Generic; +using System.Linq; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Remote.Diagnostics +{ + /// + /// This queue hold onto raw performance data. this type itself is not thread safe. the one who uses this type + /// should take care of that. + /// + /// + internal class PerformanceQueue + { + // we need at least 100 samples for result to be stable + private const int MinSampleSize = 100; + + private readonly int _maxSampleSize; + private readonly LinkedList _snapshots; + + public PerformanceQueue(int maxSampleSize) + { + Contract.ThrowIfFalse(maxSampleSize > MinSampleSize); + + _maxSampleSize = maxSampleSize; + _snapshots = new LinkedList(); + } + + public int Count => _snapshots.Count; + + public void Add(IEnumerable<(string analyzerId, TimeSpan timeSpan)> rawData, int unitCount) + { + if (_snapshots.Count < _maxSampleSize) + { + _snapshots.AddLast(new Snapshot(rawData, unitCount)); + } + else + { + // remove the first one + var first = _snapshots.First; + _snapshots.RemoveFirst(); + + // update data to new data and put it back + first.Value.Update(rawData, unitCount); + _snapshots.AddLast(first); + } + } + + public void GetPerformanceData(Dictionary aggregatedPerformanceDataPerAnalyzer) + { + if (_snapshots.Count < MinSampleSize) + { + // we don't have enough data to report this + return; + } + + using (var pooledMap = SharedPools.Default>().GetPooledObject()) + using (var pooledSet = SharedPools.Default>().GetPooledObject()) + using (var pooledList = SharedPools.Default>().GetPooledObject()) + { + var reverseMap = pooledMap.Object; + AnalyzerNumberAssigner.Instance.GetReverseMap(reverseMap); + + var analyzerSet = pooledSet.Object; + + // get all analyzers + foreach (var snapshot in _snapshots) + { + snapshot.AppendAnalyzers(analyzerSet); + } + + var list = pooledList.Object; + + // calculate aggregated data per analyzer + foreach (var assignedAnalyzerNumber in analyzerSet) + { + foreach (var snapshot in _snapshots) + { + var timeSpan = snapshot.GetTimeSpanInMillisecond(assignedAnalyzerNumber); + if (timeSpan == null) + { + // not all snapshot contains all analyzers + continue; + } + + list.Add(timeSpan.Value); + } + + // data is only stable once we have more than certain set + // of samples + if (list.Count < MinSampleSize) + { + continue; + } + + // set performance data + aggregatedPerformanceDataPerAnalyzer[reverseMap[assignedAnalyzerNumber]] = GetAverageAndAdjustedStandardDeviation(list); + + list.Clear(); + } + } + } + + private (double average, double stddev) GetAverageAndAdjustedStandardDeviation(List data) + { + var average = data.Average(); + var stddev = Math.Sqrt(data.Select(ms => Math.Pow(ms - average, 2)).Average()); + var squareLength = Math.Sqrt(data.Count); + + return (average, stddev / squareLength); + } + + private class Snapshot + { + /// + /// Raw performance data. + /// Keyed by analyzer unique number got from AnalyzerNumberAssigner. + /// Value is delta (TimeSpan - minSpan) among span in this snapshot + /// + private readonly Dictionary _performanceMap; + + public Snapshot(IEnumerable<(string analyzerId, TimeSpan timeSpan)> snapshot, int unitCount) : + this(Convert(snapshot), unitCount) + { + } + + public Snapshot(IEnumerable<(int assignedAnalyzerNumber, TimeSpan timeSpan)> rawData, int unitCount) + { + _performanceMap = new Dictionary(); + + Reset(_performanceMap, rawData, unitCount); + } + + public void Update(IEnumerable<(string analyzerId, TimeSpan timeSpan)> rawData, int unitCount) + { + Reset(_performanceMap, Convert(rawData), unitCount); + } + + public void AppendAnalyzers(HashSet analyzerSet) + { + analyzerSet.UnionWith(_performanceMap.Keys); + } + + public double? GetTimeSpanInMillisecond(int assignedAnalyzerNumber) + { + if (!_performanceMap.TryGetValue(assignedAnalyzerNumber, out var value)) + { + return null; + } + + return value; + } + + private void Reset( + Dictionary map, IEnumerable<(int assignedAnalyzerNumber, TimeSpan timeSpan)> rawData, int fileCount) + { + // get smallest timespan in the snapshot + var minSpan = rawData.Select(kv => kv.timeSpan).Min(); + + // for now, we just clear the map, if reusing dictionary blindly became an issue due to + // dictionary grew too big, then we need to do a bit more work to determine such case + // and re-create new dictionary + map.Clear(); + + // map is normalized to current timespan - min timspan of the snapshot + foreach (var (assignedAnalyzerNumber, timeSpan) in rawData) + { + map[assignedAnalyzerNumber] = (timeSpan.TotalMilliseconds - minSpan.TotalMilliseconds) / fileCount; + } + } + + private static IEnumerable<(int assignedAnalyzerNumber, TimeSpan timeSpan)> Convert(IEnumerable<(string analyzerId, TimeSpan timeSpan)> rawData) + { + return rawData.Select(kv => (AnalyzerNumberAssigner.Instance.GetUniqueNumber(kv.analyzerId), kv.timeSpan)); + } + } + + /// + /// Assign unique number to diagnostic analyzers + /// + private class AnalyzerNumberAssigner + { + public static readonly AnalyzerNumberAssigner Instance = new AnalyzerNumberAssigner(); + + private int _currentId; + + // use simple approach for now. we don't expect it to grow too much. so entry added + // won't be removed until process goes away + private readonly Dictionary _idMap; + + private AnalyzerNumberAssigner() + { + _currentId = 0; + _idMap = new Dictionary(); + } + + public int GetUniqueNumber(DiagnosticAnalyzer analyzer) + { + return GetUniqueNumber(analyzer.GetAnalyzerId()); + } + + public int GetUniqueNumber(string analyzerName) + { + if (!_idMap.TryGetValue(analyzerName, out var id)) + { + id = _currentId++; + _idMap.Add(analyzerName, id); + } + + return id; + } + + public void GetReverseMap(Dictionary reverseMap) + { + reverseMap.Clear(); + + foreach (var kv in _idMap) + { + reverseMap.Add(kv.Value, kv.Key); + } + } + } + } +} diff --git a/src/Workspaces/Remote/Core/Diagnostics/PerformanceTrackerService.cs b/src/Workspaces/Remote/Core/Diagnostics/PerformanceTrackerService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a35588637252e7bd9d50a32b6bfe44f9fe83125d --- /dev/null +++ b/src/Workspaces/Remote/Core/Diagnostics/PerformanceTrackerService.cs @@ -0,0 +1,447 @@ +// 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.Concurrent; +using System.Collections.Generic; +using System.Composition; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Internal.Log; + +namespace Microsoft.CodeAnalysis.Remote.Diagnostics +{ + /// + /// Track diagnostic performance + /// + [ExportWorkspaceService(typeof(IPerformanceTrackerService), WorkspaceKind.Host), Shared] + internal class PerformanceTrackerService : IPerformanceTrackerService + { + private static readonly Func, int, string> s_snapshotLogger = SnapshotLogger; + + private const double DefaultMinLOFValue = 20; + private const double DefaultAverageThreshold = 100; + private const double DefaultStddevThreshold = 100; + + private const int SampleSize = 300; + private const double K_Value_Ratio = 2D / 3D; + + private readonly double _minLOFValue; + private readonly double _averageThreshold; + private readonly double _stddevThreshold; + + private readonly object _gate; + private readonly PerformanceQueue _queue; + private readonly ConcurrentDictionary _builtInMap = new ConcurrentDictionary(concurrencyLevel: 2, capacity: 10); + + public event EventHandler SnapshotAdded; + + public PerformanceTrackerService() : + this(DefaultMinLOFValue, DefaultAverageThreshold, DefaultStddevThreshold) + { + } + + // internal for testing + internal PerformanceTrackerService(double minLOFValue, double averageThreshold, double stddevThreshold) + { + _minLOFValue = minLOFValue; + _averageThreshold = averageThreshold; + _stddevThreshold = stddevThreshold; + + _gate = new object(); + _queue = new PerformanceQueue(SampleSize); + } + + public void AddSnapshot(IEnumerable snapshot, int unitCount) + { + Logger.Log(FunctionId.PerformanceTrackerService_AddSnapshot, s_snapshotLogger, snapshot, unitCount); + + RecordBuiltInAnalyzers(snapshot); + + lock (_gate) + { + _queue.Add(snapshot.Select(entry => (entry.AnalyzerId, entry.TimeSpan)), unitCount); + } + + OnSnapshotAdded(); + } + + public void GenerateReport(List badAnalyzers) + { + using (var pooledRaw = SharedPools.Default>().GetPooledObject()) + { + var rawPerformanceData = pooledRaw.Object; + + lock (_gate) + { + // first get raw aggregated peformance data from the queue + _queue.GetPerformanceData(rawPerformanceData); + } + + // make sure there are some data + if (rawPerformanceData.Count == 0) + { + return; + } + + using (var generator = new ReportGenerator(this, _minLOFValue, _averageThreshold, _stddevThreshold, badAnalyzers)) + { + generator.Report(rawPerformanceData); + } + } + } + + private void RecordBuiltInAnalyzers(IEnumerable snapshot) + { + foreach (var entry in snapshot) + { + _builtInMap[entry.AnalyzerId] = entry.BuiltIn; + } + } + + private bool AllowTelemetry(string analyzerId) + { + if (_builtInMap.TryGetValue(analyzerId, out var builtIn)) + { + return builtIn; + } + + return false; + } + + private void OnSnapshotAdded() + { + SnapshotAdded?.Invoke(this, EventArgs.Empty); + } + + private static string SnapshotLogger(IEnumerable snapshots, int unitCount) + { + using (var pooledObject = SharedPools.Default().GetPooledObject()) + { + var sb = pooledObject.Object; + + sb.Append(unitCount); + + foreach (var snapshot in snapshots) + { + sb.Append("|"); + sb.Append(snapshot.AnalyzerId); + sb.Append(":"); + sb.Append(snapshot.BuiltIn); + sb.Append(":"); + sb.Append(snapshot.TimeSpan.TotalMilliseconds); + } + + sb.Append("*"); + + return sb.ToString(); + } + } + + private sealed class ReportGenerator : IDisposable, IComparer + { + private readonly double _minLOFValue; + private readonly double _averageThreshold; + private readonly double _stddevThreshold; + + private readonly PerformanceTrackerService _owner; + private readonly List _badAnalyzers; + private readonly PooledObject> _pooledObjects; + + public ReportGenerator( + PerformanceTrackerService owner, + double minLOFValue, + double averageThreshold, + double stddevThreshold, + List badAnalyzers) + { + _pooledObjects = SharedPools.Default>().GetPooledObject(); + + _owner = owner; + + _minLOFValue = minLOFValue; + _averageThreshold = averageThreshold; + _stddevThreshold = stddevThreshold; + + _badAnalyzers = badAnalyzers; + } + + public void Report(Dictionary rawPerformanceData) + { + // this is implementation of local outlier factor (LOF) + // see the wiki (https://en.wikipedia.org/wiki/Local_outlier_factor) for more information + + // convert string (analyzerId) to index + var analyzerIdIndex = GetAnalyzerIdIndex(rawPerformanceData.Keys); + + // now calculate normalized value per analyzer + var normalizedMap = GetNormalizedPerformanceMap(analyzerIdIndex, rawPerformanceData); + + // get k value + var k_value = (int)(rawPerformanceData.Count * K_Value_Ratio); + + // calculate distances + + // calculate all distance first + var allDistances = GetAllDistances(normalizedMap); + + // find k distance from all distances + var kDistances = GetKDistances(allDistances, k_value); + + // find k nearest neighbors + var kNeighborIndices = GetKNeighborIndices(allDistances, kDistances); + + var analyzerCount = kNeighborIndices.Count; + for (var index = 0; index < analyzerCount; index++) + { + var analyzerId = analyzerIdIndex[index]; + + // if result performance is lower than our threshold, don't need to calcuate + // LOF value for the analyzer + var rawData = rawPerformanceData[analyzerId]; + if (rawData.average <= _averageThreshold && rawData.stddev <= _stddevThreshold) + { + continue; + } + + // possible bad analyzer, calcuate LOF + var lof_value = TryGetLocalOutlierFactor(allDistances, kNeighborIndices, kDistances, index); + if (!lof_value.HasValue) + { + // this analyzer doesn't have lof value + continue; + } + + if (lof_value <= _minLOFValue) + { + // this doesn't stand out from other analyzers + continue; + } + + // report found possible bad analyzers + _badAnalyzers.Add(new ExpensiveAnalyzerInfo(_owner.AllowTelemetry(analyzerId), analyzerId, lof_value.Value, rawData.average, rawData.stddev)); + } + + _badAnalyzers.Sort(this); + } + + private double? TryGetLocalOutlierFactor( + List> allDistances, List> kNeighborIndices, List kDistances, int analyzerIndex) + { + var rowKNeighborsIndices = kNeighborIndices[analyzerIndex]; + if (rowKNeighborsIndices.Count == 0) + { + // nothing to calculate if there is no neighbor to compare + return null; + } + + var lrda = TryGetLocalReachabilityDensity(allDistances, kNeighborIndices, kDistances, analyzerIndex); + if (!lrda.HasValue) + { + // can't calculate reachability for the analyzer. can't calculate lof for this analyzer + return null; + } + + var lrdb = 0D; + foreach (var neighborIndex in rowKNeighborsIndices) + { + var reachability = TryGetLocalReachabilityDensity(allDistances, kNeighborIndices, kDistances, neighborIndex); + if (!reachability.HasValue) + { + // this neighbor analyzer doesn't have its own neighbor. skip it + continue; + } + + lrdb += reachability.Value; + } + + return (lrdb / rowKNeighborsIndices.Count) / lrda; + } + + private double GetReachabilityDistance( + List> allDistances, List kDistances, int analyzerIndex1, int analyzerIndex2) + { + return Math.Max(allDistances[analyzerIndex1][analyzerIndex2], kDistances[analyzerIndex2]); + } + + private double? TryGetLocalReachabilityDensity( + List> allDistances, List> kNeighborIndices, List kDistances, int analyzerIndex) + { + var rowKNeighborsIndices = kNeighborIndices[analyzerIndex]; + if (rowKNeighborsIndices.Count == 0) + { + // no neighbor to get reachability + return null; + } + + var distanceSum = 0.0; + foreach (var neighborIndex in rowKNeighborsIndices) + { + distanceSum += GetReachabilityDistance(allDistances, kDistances, analyzerIndex, neighborIndex); + } + + return 1 / distanceSum / rowKNeighborsIndices.Count; + } + + private List> GetKNeighborIndices(List> allDistances, List kDistances) + { + var analyzerCount = kDistances.Count; + var kNeighborIndices = GetPooledListAndSetCapacity>(analyzerCount); + + for (var rowIndex = 0; rowIndex < analyzerCount; rowIndex++) + { + var rowKNeighborIndices = GetPooledList(); + + var rowDistances = allDistances[rowIndex]; + var kDistance = kDistances[rowIndex]; + + for (var colIndex = 0; colIndex < analyzerCount; colIndex++) + { + var value = rowDistances[colIndex]; + + // get neighbors closer than k distance + if (value > 0 && value <= kDistance) + { + rowKNeighborIndices.Add(colIndex); + } + } + + kNeighborIndices[rowIndex] = rowKNeighborIndices; + } + + return kNeighborIndices; + } + + private List GetKDistances(List> allDistances, int kValue) + { + var analyzerCount = allDistances.Count; + var kDistances = GetPooledListAndSetCapacity(analyzerCount); + var sortedRowDistance = GetPooledList(); + + for (var index = 0; index < analyzerCount; index++) + { + sortedRowDistance.Clear(); + sortedRowDistance.AddRange(allDistances[index]); + + sortedRowDistance.Sort(); + + kDistances[index] = sortedRowDistance[kValue]; + } + + return kDistances; + } + + private List> GetAllDistances(List<(double normaliedAverage, double normalizedStddev)> normalizedMap) + { + var analyzerCount = normalizedMap.Count; + var allDistances = GetPooledListAndSetCapacity>(analyzerCount); + + for (var rowIndex = 0; rowIndex < analyzerCount; rowIndex++) + { + var rowDistances = GetPooledListAndSetCapacity(analyzerCount); + var rowAnalyzer = normalizedMap[rowIndex]; + + for (var colIndex = 0; colIndex < analyzerCount; colIndex++) + { + var colAnalyzer = normalizedMap[colIndex]; + var distance = Math.Sqrt(Math.Pow(colAnalyzer.normaliedAverage - rowAnalyzer.normaliedAverage, 2) + + Math.Pow(colAnalyzer.normalizedStddev - rowAnalyzer.normalizedStddev, 2)); + + rowDistances[colIndex] = distance; + } + + allDistances[rowIndex] = rowDistances; + } + + return allDistances; + } + + private List<(double normaliedAverage, double normalizedStddev)> GetNormalizedPerformanceMap( + List analyzerIdIndex, Dictionary rawPerformanceData) + { + var averageMin = rawPerformanceData.Values.Select(kv => kv.average).Min(); + var averageMax = rawPerformanceData.Values.Select(kv => kv.average).Max(); + var averageDelta = averageMax - averageMin; + + var stddevMin = rawPerformanceData.Values.Select(kv => kv.stddev).Min(); + var stddevMax = rawPerformanceData.Values.Select(kv => kv.stddev).Max(); + var stddevDelta = stddevMax - stddevMin; + + // make sure delta is not 0 + averageDelta = averageDelta == 0 ? 1 : averageDelta; + stddevDelta = stddevDelta == 0 ? 1 : stddevDelta; + + // calculate normalized average and stddev and convert analyzerId string to index + var analyzerCount = analyzerIdIndex.Count; + var normalizedMap = GetPooledListAndSetCapacity<(double normalizedAverage, double normalizedStddev)>(analyzerCount); + + for (var index = 0; index < analyzerCount; index++) + { + var value = rawPerformanceData[analyzerIdIndex[index]]; + var normalizedAverage = (value.average - averageMin) / averageDelta; + var normalizedStddev = (value.stddev - stddevMin) / stddevDelta; + + normalizedMap[index] = (normalizedAverage, normalizedStddev); + } + + return normalizedMap; + } + + private List GetAnalyzerIdIndex(IEnumerable analyzerIds) + { + var analyzerIdIndex = GetPooledList(); + analyzerIdIndex.AddRange(analyzerIds); + + return analyzerIdIndex; + } + + public void Dispose() + { + foreach (var disposable in _pooledObjects.Object) + { + disposable.Dispose(); + } + + _pooledObjects.Dispose(); + } + + private List GetPooledList() + { + var pooledObject = SharedPools.Default>().GetPooledObject(); + _pooledObjects.Object.Add(pooledObject); + + return pooledObject.Object; + } + + private List GetPooledListAndSetCapacity(int capacity) + { + var pooledObject = SharedPools.Default>().GetPooledObject(); + _pooledObjects.Object.Add(pooledObject); + + for (var i = 0; i < capacity; i++) + { + pooledObject.Object.Add(default(T)); + } + + return pooledObject.Object; + } + + public int Compare(ExpensiveAnalyzerInfo x, ExpensiveAnalyzerInfo y) + { + if (x.LocalOutlierFactor == y.LocalOutlierFactor) + { + return 0; + } + + // want reversed order + if (x.LocalOutlierFactor - y.LocalOutlierFactor > 0) + { + return -1; + } + + return 1; + } + } + } +} diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs index e3f03144f2a5ea9d22ae3d946f126ba111e43ef5..4c2e6b3fae9f936be679676d6483ff211861ebc5 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs @@ -1,5 +1,6 @@ // 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.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; @@ -15,12 +16,12 @@ namespace Microsoft.CodeAnalysis.Remote { // root level service for all Roslyn services - internal partial class CodeAnalysisService + internal partial class CodeAnalysisService : IRemoteDiagnosticAnalyzerService { /// - /// This is top level entry point for diagnostic calculation from client (VS). - /// - /// This will be called by ServiceHub/JsonRpc framework + /// Calculate dignostics. this works differently than other ones such as todo comments or designer attribute scanner + /// since in proc and out of proc runs quite differently due to concurrency and due to possible amount of data + /// that needs to pass through between processes /// public Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, string streamName, CancellationToken cancellationToken) { @@ -53,6 +54,25 @@ public Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, string stre }, cancellationToken); } + public void ReportAnalyzerPerformance(List snapshot, int unitCount, CancellationToken cancellationToken) + { + RunService(token => + { + using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_ReportAnalyzerPerformance, token)) + { + token.ThrowIfCancellationRequested(); + + var service = SolutionService.PrimaryWorkspace.Services.GetService(); + if (service == null) + { + return; + } + + service.AddSnapshot(snapshot, unitCount); + } + }, cancellationToken); + } + private async Task SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap result, CancellationToken cancellationToken) { using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_SerializeDiagnosticResultAsync, GetResultLogInfo, result, cancellationToken)) diff --git a/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.PerformanceReporter.cs b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.PerformanceReporter.cs new file mode 100644 index 0000000000000000000000000000000000000000..d29994c134f3939997ea41bb0242b494bf5a1d37 --- /dev/null +++ b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.PerformanceReporter.cs @@ -0,0 +1,109 @@ +// 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.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Remote.Diagnostics; +using Microsoft.CodeAnalysis.Shared.TestHooks; +using Microsoft.CodeAnalysis.SolutionCrawler; +using RoslynLogger = Microsoft.CodeAnalysis.Internal.Log.Logger; + +namespace Microsoft.CodeAnalysis.Remote +{ + internal partial class RemoteHostService : ServiceHubServiceBase, IRemoteHostService + { + /// + /// Track when last time report has sent and send new report if there is update after given internal + /// + private class PerformanceReporter : GlobalOperationAwareIdleProcessor + { + private readonly SemaphoreSlim _event; + private readonly HashSet _reported; + + private readonly IPerformanceTrackerService _diagnosticAnalyzerPerformanceTracker; + private readonly TraceSource _logger; + + public PerformanceReporter(TraceSource logger, IPerformanceTrackerService diagnosticAnalyzerPerformanceTracker, TimeSpan reportingInterval, CancellationToken shutdownToken) : base( + AsynchronousOperationListenerProvider.NullListener, + SolutionService.PrimaryWorkspace.Services.GetService(), + (int)reportingInterval.TotalMilliseconds, shutdownToken) + { + _event = new SemaphoreSlim(initialCount: 0); + _reported = new HashSet(); + + _logger = logger; + _diagnosticAnalyzerPerformanceTracker = diagnosticAnalyzerPerformanceTracker; + _diagnosticAnalyzerPerformanceTracker.SnapshotAdded += OnSnapshotAdded; + Start(); + } + + protected override void PauseOnGlobalOperation() + { + // we won't cancel report already running. we will just prevent + // new one from starting. + } + + protected override async Task ExecuteAsync() + { + // wait for global operation such as build + await GlobalOperationTask.ConfigureAwait(false); + + using (var pooledObject = SharedPools.Default>().GetPooledObject()) + using (RoslynLogger.LogBlock(FunctionId.Diagnostics_GeneratePerformaceReport, CancellationToken)) + { + _diagnosticAnalyzerPerformanceTracker.GenerateReport(pooledObject.Object); + + foreach (var badAnalyzerInfo in pooledObject.Object) + { + var newAnalyzer = _reported.Add(badAnalyzerInfo.AnalyzerId); + var internalUser = WatsonReporter.IsUserMicrosoftInternal; + + // we only report same analyzer once unless it is internal user + if (internalUser || newAnalyzer) + { + // this will report telemetry under VS. this will let us see how accurate our performance tracking is + RoslynLogger.Log(FunctionId.Diagnostics_BadAnalyzer, KeyValueLogMessage.Create(m => + { + // since it is telemetry, we hash analyzer name if it is not builtin analyzer + m[nameof(badAnalyzerInfo.AnalyzerId)] = internalUser ? badAnalyzerInfo.AnalyzerId : badAnalyzerInfo.PIISafeAnalyzerId; + m[nameof(badAnalyzerInfo.LocalOutlierFactor)] = badAnalyzerInfo.LocalOutlierFactor; + m[nameof(badAnalyzerInfo.Average)] = badAnalyzerInfo.Average; + m[nameof(badAnalyzerInfo.AdjustedStandardDeviation)] = badAnalyzerInfo.AdjustedStandardDeviation; + })); + } + + // for logging, we only log once. we log here so that we can ask users to provide this log to us + // when we want to find out VS performance issue that could be caused by analyzer + if (newAnalyzer) + { + _logger.TraceEvent(TraceEventType.Error, 0, $"[{badAnalyzerInfo.AnalyzerId} ({badAnalyzerInfo.AnalyzerIdHash})] LOF: {badAnalyzerInfo.LocalOutlierFactor}, Avg: {badAnalyzerInfo.Average}, Stddev: {badAnalyzerInfo.AdjustedStandardDeviation}"); + } + } + } + } + + protected override Task WaitAsync(CancellationToken cancellationToken) + { + return _event.WaitAsync(cancellationToken); + } + + private void OnSnapshotAdded(object sender, EventArgs e) + { + // this acts like Monitor.Pulse. (wake up event if it is currently waiting + // if not, ignore. this can have race, but that's fine for this usage case) + // not using Monitor.Pulse since that doesn't support WaitAsync + if (_event.CurrentCount > 0) + { + return; + } + + _event.Release(); + } + } + } +} diff --git a/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs index 78fe65e1da40d651f7c92d97207e45b7279e3e6e..69130e99533a193553954cda3f24af2a5006c18b 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Remote.Diagnostics; using Microsoft.CodeAnalysis.Remote.Services; using Microsoft.CodeAnalysis.Remote.Storage; using Microsoft.CodeAnalysis.Storage; @@ -29,13 +30,16 @@ namespace Microsoft.CodeAnalysis.Remote /// /// basically, this is used to manage lifetime of the service hub. /// - internal class RemoteHostService : ServiceHubServiceBase, IRemoteHostService + internal partial class RemoteHostService : ServiceHubServiceBase, IRemoteHostService { + private readonly static TimeSpan s_reportInterval = TimeSpan.FromMinutes(2); + // it is saved here more on debugging purpose. private static Func s_logChecker = _ => false; private string _host; private int _primaryInstance; + private PerformanceReporter _performanceReporter; static RemoteHostService() { @@ -195,7 +199,7 @@ private void SetSessionInfo(Dictionary m) m["InstanceId"] = _primaryInstance; } - private static void SetGlobalContext(int uiCultureLCID, int cultureLCID, string serializedSession) + private void SetGlobalContext(int uiCultureLCID, int cultureLCID, string serializedSession) { // set global telemetry session var session = GetTelemetrySession(serializedSession); @@ -214,6 +218,13 @@ private static void SetGlobalContext(int uiCultureLCID, int cultureLCID, string // set both handler as NFW FatalError.Handler = WatsonReporter.Report; FatalError.NonFatalHandler = WatsonReporter.Report; + + // start performance reporter + var diagnosticAnalyzerPerformanceTracker = SolutionService.PrimaryWorkspace.Services.GetService(); + if (diagnosticAnalyzerPerformanceTracker != null) + { + _performanceReporter = new PerformanceReporter(Logger, diagnosticAnalyzerPerformanceTracker, s_reportInterval, ShutdownCancellationToken); + } } private static void EnsureCulture(int uiCultureLCID, int cultureLCID) diff --git a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.RoslynOnly.cs b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.RoslynOnly.cs index 4d3204ca26e01e1d5815b3bcac126f8d6a4b352b..b29e449ecb325ee8714b5413f8eff9f9ac029580 100644 --- a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.RoslynOnly.cs +++ b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.RoslynOnly.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.DesignerAttributes; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.DocumentHighlighting; using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.SymbolSearch; @@ -34,6 +35,8 @@ internal partial class AggregateJsonConverter : JsonConverter Add(builder, new ReferenceAssemblyWithTypeResultJsonConverter()); Add(builder, new AddImportFixDataJsonConverter()); + + Add(builder, new AnalyzerPerformanceInfoConverter()); } private class TodoCommentDescriptorJsonConverter : BaseJsonConverter @@ -73,7 +76,7 @@ protected override TodoComment ReadValue(JsonReader reader, JsonSerializer seria Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject); // all integer is long - var descriptor = ReadProperty(serializer, reader); + var descriptor = ReadProperty(reader, serializer); var message = ReadProperty(reader); var position = ReadProperty(reader); @@ -168,7 +171,7 @@ protected override HighlightSpan ReadValue(JsonReader reader, JsonSerializer ser { Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject); - var textSpan = ReadProperty(serializer, reader); + var textSpan = ReadProperty(reader, serializer); var kind = (HighlightSpanKind)ReadProperty(reader); Contract.ThrowIfFalse(reader.Read()); @@ -201,7 +204,7 @@ protected override PackageWithTypeResult ReadValue(JsonReader reader, JsonSerial var typeName = ReadProperty(reader); var version = ReadProperty(reader); var rank = (int)ReadProperty(reader); - var containingNamespaceNames = ReadProperty>(serializer, reader); + var containingNamespaceNames = ReadProperty>(reader, serializer); Contract.ThrowIfFalse(reader.Read()); Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject); @@ -273,7 +276,7 @@ protected override ReferenceAssemblyWithTypeResult ReadValue(JsonReader reader, var assemblyName = ReadProperty(reader); var typeName = ReadProperty(reader); - var containingNamespaceNames = ReadProperty>(serializer, reader); + var containingNamespaceNames = ReadProperty>(reader, serializer); Contract.ThrowIfFalse(reader.Read()); Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject); @@ -334,14 +337,14 @@ protected override AddImportFixData ReadValue(JsonReader reader, JsonSerializer Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject); var kind = (AddImportFixKind)ReadProperty(reader); - var textChanges = ReadProperty>(serializer, reader).ToImmutableArrayOrEmpty(); + var textChanges = ReadProperty>(reader, serializer).ToImmutableArrayOrEmpty(); var title = ReadProperty(reader); - var tags = ReadProperty>(serializer, reader).ToImmutableArrayOrEmpty(); + var tags = ReadProperty>(reader, serializer).ToImmutableArrayOrEmpty(); var priority = (CodeActionPriority)ReadProperty(reader); - var projectReferenceToAdd = ReadProperty(serializer, reader); + var projectReferenceToAdd = ReadProperty(reader, serializer); - var portableExecutableReferenceProjectId = ReadProperty(serializer, reader); + var portableExecutableReferenceProjectId = ReadProperty(reader, serializer); var portableExecutableReferenceFilePathToAdd = ReadProperty(reader); var assemblyReferenceAssemblyName = ReadProperty(reader); @@ -418,5 +421,38 @@ protected override void WriteValue(JsonWriter writer, AddImportFixData source, J writer.WriteEndObject(); } } + + private class AnalyzerPerformanceInfoConverter : BaseJsonConverter + { + protected override AnalyzerPerformanceInfo ReadValue(JsonReader reader, JsonSerializer serializer) + { + Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject); + + var analyzerid = ReadProperty(reader); + var builtIn = ReadProperty(reader); + var timeSpan = ReadProperty(reader, serializer); + + Contract.ThrowIfFalse(reader.Read()); + Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject); + + return new AnalyzerPerformanceInfo(analyzerid, builtIn, timeSpan); + } + + protected override void WriteValue(JsonWriter writer, AnalyzerPerformanceInfo info, JsonSerializer serializer) + { + writer.WriteStartObject(); + + writer.WritePropertyName(nameof(AnalyzerPerformanceInfo.AnalyzerId)); + writer.WriteValue(info.AnalyzerId); + + writer.WritePropertyName(nameof(AnalyzerPerformanceInfo.BuiltIn)); + writer.WriteValue(info.BuiltIn); + + writer.WritePropertyName(nameof(AnalyzerPerformanceInfo.TimeSpan)); + serializer.Serialize(writer, info.TimeSpan); + + writer.WriteEndObject(); + } + } } } diff --git a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.SolutionIdConverters.cs b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.SolutionIdConverters.cs index e5fea048378bae7e42ff500384f88105f47c82db..ea029041d05af994a8048a6f7d0530043941b2cb 100644 --- a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.SolutionIdConverters.cs +++ b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.SolutionIdConverters.cs @@ -87,7 +87,7 @@ protected override DocumentId ReadValue(JsonReader reader, JsonSerializer serial Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject); - var projectId = ReadProperty(serializer, reader); + var projectId = ReadProperty(reader, serializer); var (id, debugName) = ReadIdAndName(reader); diff --git a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.cs b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.cs index 7b9acbcf92be7d4f1096c43b7352da0b9455afa8..a97d85c2827f996997e064cf261892bcb6aaa43e 100644 --- a/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.cs +++ b/src/Workspaces/Remote/ServiceHub/Shared/RoslynJsonConverter.cs @@ -72,7 +72,7 @@ public sealed override void WriteJson(JsonWriter writer, object value, JsonSeria protected abstract T ReadValue(JsonReader reader, JsonSerializer serializer); protected abstract void WriteValue(JsonWriter writer, T value, JsonSerializer serializer); - protected static U ReadProperty(JsonSerializer serializer, JsonReader reader) + protected static U ReadProperty(JsonReader reader, JsonSerializer serializer) { // read property Contract.ThrowIfFalse(reader.Read()); @@ -189,7 +189,7 @@ protected override PinnedSolutionInfo ReadValue(JsonReader reader, JsonSerialize // all integer is long var scopeId = ReadProperty(reader); var fromPrimaryBranch = ReadProperty(reader); - var checksum = ReadProperty(serializer, reader); + var checksum = ReadProperty(reader, serializer); Contract.ThrowIfFalse(reader.Read()); Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject); diff --git a/src/Workspaces/Remote/ServiceHub/Telemetry/WatsonReporter.cs b/src/Workspaces/Remote/ServiceHub/Telemetry/WatsonReporter.cs index b5016b975790402ed30ac653ad307820e37795ba..2b058c937ca3bdec3dcd716157c4b527e3c4ebb3 100644 --- a/src/Workspaces/Remote/ServiceHub/Telemetry/WatsonReporter.cs +++ b/src/Workspaces/Remote/ServiceHub/Telemetry/WatsonReporter.cs @@ -30,6 +30,11 @@ public static void SetTelemetrySession(TelemetrySession session) /// public static TelemetrySession SessionOpt => s_sessionOpt; + /// + /// Check whether current user is microsoft internal or not + /// + public static bool IsUserMicrosoftInternal => SessionOpt?.IsUserMicrosoftInternal ?? false; + /// /// Report Non-Fatal Watson ///