|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Roslyn.VisualStudio.DiagnosticsWindow
{
/// <summary>
/// Interaction logic for TelemetryPanel.xaml
/// </summary>
public partial class TelemetryPanel : UserControl
{
public TelemetryPanel()
{
InitializeComponent();
}
private void OnDump(object sender, RoutedEventArgs e)
{
_ = OnDumpImplAsync();
async Task OnDumpImplAsync()
{
using (Disable(DumpButton))
using (Disable(CopyButton))
{
GenerationProgresBar.IsIndeterminate = true;
var text = await Task.Run(GetTelemetryString).ConfigureAwait(true);
this.Result.Text = text;
GenerationProgresBar.IsIndeterminate = false;
}
}
}
private void OnCopy(object sender, RoutedEventArgs e)
{
Clipboard.SetText(this.Result.Text);
}
private static string GetTelemetryString()
{
var fixAllScopeValues = Enum.GetValues(typeof(FixAllScope));
var sb = new StringBuilder();
var seenType = new HashSet<Type>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var result = ScanAssembly(assembly);
if (result.Length > 0)
{
sb.AppendLine($"Searching: {assembly.FullName}");
sb.AppendLine(result);
}
}
return sb.ToString();
string ScanAssembly(Assembly assembly)
{
var typeDiscovered = new StringBuilder();
try
{
foreach (var module in assembly.GetModules())
{
foreach (var type in module.GetTypes())
{
ScanType(type, typeDiscovered);
}
}
}
catch
{
// ignore
}
return typeDiscovered.ToString();
}
void ScanType(Type type, StringBuilder typeDiscovered)
{
type = type.GetTypeForTelemetry();
if (!seenType.Add(type))
{
return;
}
RecordIfCodeAction(type, typeDiscovered);
foreach (var nestedTypeInfo in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
{
ScanType(nestedTypeInfo, typeDiscovered);
}
}
void RecordIfCodeAction(Type type, StringBuilder typeDiscovered)
{
if (!IsCodeAction(type))
{
return;
}
var telemetryId = type.GetTelemetryId();
typeDiscovered.AppendLine($"Found: {type.FullName}: {telemetryId.ToString()}");
}
bool IsCodeAction(Type type)
{
if (type == null)
{
return false;
}
var codeActionType = typeof(CodeAction);
return codeActionType.IsAssignableFrom(type);
}
}
private static IDisposable Disable(UIElement control)
{
control.IsEnabled = false;
return new RAII(() => control.IsEnabled = true);
}
private sealed class RAII : IDisposable
{
private readonly Action _action;
public RAII(Action disposeAction)
{
_action = disposeAction;
}
public void Dispose()
{
_action?.Invoke();
}
}
}
}
|