未验证 提交 61381850 编写于 作者: T Tomáš Matoušek 提交者: GitHub

Display compiler generated members in raw view. (#32769)

* Display compiler generated members in raw view.

* Fix dumping of PDBs in DumpAssemblyData
上级 fb970c97
// 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 System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Roslyn.Test.Utilities;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using BindingFlags = System.Reflection.BindingFlags;
......@@ -816,6 +817,131 @@ class C
}
}
[Fact]
public void AsyncStateMachine()
{
var source = @"
using System;
using System.Threading.Tasks;
class C
{
static void Main() => Async(1).Wait();
static async Task Async(int parameter)
{
int i = 42;
await Task.FromResult(1);
Console.WriteLine(i + parameter);
}
}
";
var assembly = GetAssembly(source);
var assemblies = ReflectionUtilities.GetMscorlibAndSystemCore(typeof(Task).Assembly, assembly);
using (ReflectionUtilities.LoadAssemblies(assemblies))
{
var runtime = new DkmClrRuntimeInstance(assemblies);
var stateMachineType = assembly.GetType("C").GetNestedTypes(BindingFlags.NonPublic).Single();
var value = CreateDkmClrValue(
value: stateMachineType.Instantiate(),
type: runtime.GetType((TypeImpl)stateMachineType));
// Raw view
var evalResult = FormatResult("sm", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ShowValueRaw));
Verify(evalResult,
EvalResult("sm", "{C.<Async>d__1}", "C.<Async>d__1", "sm, raw", DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
Verify(children,
EvalResult("<>1__state", "0", "int", null, DkmEvaluationResultFlags.None),
EvalResult("<>t__builder", "{System.Runtime.CompilerServices.AsyncTaskMethodBuilder}", "System.Runtime.CompilerServices.AsyncTaskMethodBuilder", null, DkmEvaluationResultFlags.Expandable),
EvalResult("<>u__1", "{System.Runtime.CompilerServices.TaskAwaiter<int>}", "System.Runtime.CompilerServices.TaskAwaiter<int>", null, DkmEvaluationResultFlags.Expandable),
EvalResult("<i>5__2", "0", "int", null, DkmEvaluationResultFlags.None),
EvalResult("parameter", "0", "int", "sm.parameter", DkmEvaluationResultFlags.None));
// Regular view
evalResult = FormatResult("sm", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.None));
Verify(evalResult,
EvalResult("sm", "{C.<Async>d__1}", "C.<Async>d__1", "sm", DkmEvaluationResultFlags.Expandable));
children = GetChildren(evalResult);
Verify(children,
EvalResult("parameter", "0", "int", "sm.parameter", DkmEvaluationResultFlags.None));
}
}
[Fact]
public void IteratorStateMachine()
{
var source = @"
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
class C
{
static void Main() => Iter(1).ToArray();
static IEnumerable<int> Iter(int parameter)
{
int i = 42;
yield return 1;
Console.WriteLine(i + parameter);
}
}
";
var assembly = GetAssembly(source);
var assemblies = ReflectionUtilities.GetMscorlibAndSystemCore(typeof(Task).Assembly, assembly);
using (ReflectionUtilities.LoadAssemblies(assemblies))
{
var runtime = new DkmClrRuntimeInstance(assemblies);
var stateMachineType = assembly.GetType("C").GetNestedTypes(BindingFlags.NonPublic).Single();
var value = CreateDkmClrValue(
value: stateMachineType.Instantiate(1),
type: runtime.GetType((TypeImpl)stateMachineType));
// Raw view
var evalResult = FormatResult("sm", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ShowValueRaw));
Verify(evalResult,
EvalResult("sm", "{C.<Iter>d__1}", "C.<Iter>d__1", "sm, raw", DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
Verify(children,
EvalResult("<>1__state", "1", "int", null, DkmEvaluationResultFlags.None),
EvalResult("<>2__current", "0", "int", null, DkmEvaluationResultFlags.None),
EvalResult("<>3__parameter", "0", "int", null, DkmEvaluationResultFlags.None),
EvalResult("<>l__initialThreadId", UnspecifiedValue, "int", null, DkmEvaluationResultFlags.None),
EvalResult("<i>5__2", "0", "int", null, DkmEvaluationResultFlags.None),
EvalResult("System.Collections.Generic.IEnumerator<int>.Current", "0", "int", "((System.Collections.Generic.IEnumerator<int>)sm).Current", DkmEvaluationResultFlags.ReadOnly),
EvalResult("System.Collections.IEnumerator.Current", "0", "object {int}", "((System.Collections.IEnumerator)sm).Current", DkmEvaluationResultFlags.ReadOnly),
EvalResult("parameter", "0", "int", "sm.parameter", DkmEvaluationResultFlags.None),
EvalResult("Results View", "Expanding the Results View will enumerate the IEnumerable", "", "sm, raw, results", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
// Regular view
evalResult = FormatResult("sm", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.None));
Verify(evalResult,
EvalResult("sm", "{C.<Iter>d__1}", "C.<Iter>d__1", "sm", DkmEvaluationResultFlags.Expandable));
children = GetChildren(evalResult);
Verify(children,
EvalResult("System.Collections.Generic.IEnumerator<int>.Current", "0", "int", "((System.Collections.Generic.IEnumerator<int>)sm).Current", DkmEvaluationResultFlags.ReadOnly),
EvalResult("System.Collections.IEnumerator.Current", "0", "object {int}", "((System.Collections.IEnumerator)sm).Current", DkmEvaluationResultFlags.ReadOnly),
EvalResult("parameter", "0", "int", "sm.parameter", DkmEvaluationResultFlags.None),
EvalResult("Results View", "Expanding the Results View will enumerate the IEnumerable", "", "sm, results", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
}
}
[WorkItem(1006160, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1006160")]
[Fact]
public void MultipleImplementations_DifferentImplementors()
......
......@@ -58,25 +58,21 @@ internal sealed class MemberExpansion : Expansion
var expansions = ArrayBuilder<Expansion>.GetInstance();
// Expand members. TODO: Ideally, this would be done lazily (https://github.com/dotnet/roslyn/issues/32800)
// From the members, collect the fields and properties,
// separated into static and instance members.
var staticMembers = ArrayBuilder<MemberAndDeclarationInfo>.GetInstance();
var instanceMembers = ArrayBuilder<MemberAndDeclarationInfo>.GetInstance();
var appDomain = value.Type.AppDomain;
// Expand members. (Ideally, this should be done lazily.)
var allMembers = ArrayBuilder<MemberAndDeclarationInfo>.GetInstance();
var includeInherited = (flags & ExpansionFlags.IncludeBaseMembers) == ExpansionFlags.IncludeBaseMembers;
var hideNonPublic = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.HideNonPublicMembers) == DkmEvaluationFlags.HideNonPublicMembers;
runtimeType.AppendTypeMembers(allMembers, predicate, declaredTypeAndInfo.Type, appDomain, includeInherited, hideNonPublic, isProxyType);
var includeCompilerGenerated = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.ShowValueRaw) == DkmEvaluationFlags.ShowValueRaw;
runtimeType.AppendTypeMembers(allMembers, predicate, declaredTypeAndInfo.Type, appDomain, includeInherited, hideNonPublic, isProxyType, includeCompilerGenerated);
foreach (var member in allMembers)
{
var name = member.Name;
if (name.IsCompilerGenerated())
{
continue;
}
if (member.IsStatic)
{
staticMembers.Add(member);
......
......@@ -30,7 +30,8 @@ internal static class TypeHelpers
DkmClrAppDomain appDomain,
bool includeInherited,
bool hideNonPublic,
bool isProxyType)
bool isProxyType,
bool includeCompilerGenerated)
{
Debug.Assert(!type.IsInterface);
......@@ -65,9 +66,15 @@ internal static class TypeHelpers
foreach (var member in type.GetMembers(MemberBindingFlags))
{
var memberName = member.Name;
if (!includeCompilerGenerated && memberName.IsCompilerGenerated())
{
continue;
}
// The native EE shows proxy members regardless of accessibility if they have a
// DebuggerBrowsable attribute of any value. Match that behaviour here.
if (!isProxyType || browsableState == null || !browsableState.ContainsKey(member.Name))
if (!isProxyType || browsableState == null || !browsableState.ContainsKey(memberName))
{
if (!predicate(member))
{
......@@ -75,7 +82,6 @@ internal static class TypeHelpers
}
}
var memberName = member.Name;
// This represents information about the immediately preceding (more derived)
// declaration with the same name as the current member.
var previousDeclaration = DeclarationInfo.None;
......
......@@ -67,7 +67,7 @@ public override string Name
{
get
{
throw new NotImplementedException();
return Event.Name;
}
}
......
......@@ -270,6 +270,7 @@ internal DkmEvaluationResult[] GetItems(DkmEvaluationResultEnumContext enumConte
private const DkmEvaluationResultCategory UnspecifiedCategory = (DkmEvaluationResultCategory)(-1);
private const DkmEvaluationResultAccessType UnspecifiedAccessType = (DkmEvaluationResultAccessType)(-1);
public const string UnspecifiedValue = "<<unspecified value>>";
internal static DkmEvaluationResult EvalResult(
string name,
......@@ -482,7 +483,13 @@ internal static void Verify(DkmEvaluationResult actual, DkmEvaluationResult expe
if (expectedSuccess != null)
{
var actualSuccess = (DkmSuccessEvaluationResult)actual;
Assert.Equal(expectedSuccess.Value, actualSuccess.Value);
Assert.NotEqual(UnspecifiedValue, actualSuccess.Value);
if (expectedSuccess.Value != UnspecifiedValue)
{
Assert.Equal(expectedSuccess.Value, actualSuccess.Value);
}
Assert.Equal(expectedSuccess.Type, actualSuccess.Type);
Assert.Equal(expectedSuccess.Flags, actualSuccess.Flags);
if (expectedSuccess.Category != UnspecifiedCategory)
......@@ -493,6 +500,7 @@ internal static void Verify(DkmEvaluationResult actual, DkmEvaluationResult expe
{
Assert.Equal(expectedSuccess.Access, actualSuccess.Access);
}
Assert.Equal(expectedSuccess.EditableValue, actualSuccess.EditableValue);
Assert.True(
(expectedSuccess.CustomUIVisualizers == actualSuccess.CustomUIVisualizers) ||
......
......@@ -250,7 +250,7 @@ public static string DumpAssemblyData(IEnumerable<ModuleData> modules, out strin
{
dumpDirectory = null;
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
foreach (var module in modules)
{
// Limit the number of dumps to 10. After 10 we're likely in a bad state and are
......@@ -289,23 +289,34 @@ public static string DumpAssemblyData(IEnumerable<ModuleData> modules, out strin
}
string pePath = Path.Combine(dumpDirectory, fileName + module.Kind.GetDefaultExtension());
string pdbPath = (module.Pdb != null) ? pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb") : null;
try
{
module.Image.WriteToFile(pePath);
if (pdbPath != null)
}
catch (IOException e)
{
pePath = $"<unable to write file: '{pePath}' -- {e.Message}>";
}
string pdbPath;
if (!module.Pdb.IsDefaultOrEmpty)
{
pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb");
try
{
module.Pdb.WriteToFile(pdbPath);
}
}
catch (IOException)
{
pePath = "<unable to write file>";
if (pdbPath != null)
catch (IOException e)
{
pdbPath = "<unable to write file>";
pdbPath = $"<unable to write file: '{pdbPath}' -- {e.Message}>";
}
}
else
{
pdbPath = null;
}
sb.Append("PE(" + module.Kind + "): ");
sb.AppendLine(pePath);
if (pdbPath != null)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册