提交 84c62ce8 编写于 作者: C Charles Stoner

Include "Raw View" for tuples in EE

上级 bda4d971
......@@ -217,7 +217,7 @@ class C
}
[Fact]
public void LongTuple()
public void LongTuple_NoNames()
{
var source =
@"class C
......@@ -247,25 +247,55 @@ public void LongTuple()
"o._17",
DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[0], inspectionContext);
Assert.Equal(18, children.Length);
var child = children[children.Length - 1];
Verify(child,
EvalResult(
"Rest",
"(0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011)",
"(short, short, short, short, short, short, short, short, short, short)",
"o._17.Rest",
DkmEvaluationResultFlags.Expandable));
children = GetChildren(child, inspectionContext);
Assert.Equal(11, children.Length);
child = children[children.Length - 1];
Verify(child,
Verify(children,
EvalResult("Item1", "0x0001", "short", "o._17.Item1"),
EvalResult("Item2", "0x0002", "short", "o._17.Item2"),
EvalResult("Item3", "0x0003", "short", "o._17.Item3"),
EvalResult("Item4", "0x0004", "short", "o._17.Item4"),
EvalResult("Item5", "0x0005", "short", "o._17.Item5"),
EvalResult("Item6", "0x0006", "short", "o._17.Item6"),
EvalResult("Item7", "0x0007", "short", "o._17.Item7"),
EvalResult("Item8", "0x0008", "short", "o._17.Rest.Item1"),
EvalResult("Item9", "0x0009", "short", "o._17.Rest.Item2"),
EvalResult("Item10", "0x000a", "short", "o._17.Rest.Item3"),
EvalResult("Item11", "0x000b", "short", "o._17.Rest.Item4"),
EvalResult("Item12", "0x000c", "short", "o._17.Rest.Item5"),
EvalResult("Item13", "0x000d", "short", "o._17.Rest.Item6"),
EvalResult("Item14", "0x000e", "short", "o._17.Rest.Item7"),
EvalResult("Item15", "0x000f", "short", "o._17.Rest.Rest.Item1"),
EvalResult("Item16", "0x0010", "short", "o._17.Rest.Rest.Item2"),
EvalResult("Item17", "0x0011", "short", "o._17.Rest.Rest.Item3"),
EvalResult(
"Rest",
"(0x000f, 0x0010, 0x0011)",
"(short, short, short)",
"o._17.Rest.Rest",
DkmEvaluationResultFlags.Expandable));
"Raw View",
"(0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011)",
"(short, short, short, short, short, short, short, short, short, short, short, short, short, short, short, short, short)",
"o._17, raw",
DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
children = GetChildren(children[children.Length - 1], inspectionContext);
Verify(children,
EvalResult("Item1", "0x0001", "short", "o._17.Item1"),
EvalResult("Item2", "0x0002", "short", "o._17.Item2"),
EvalResult("Item3", "0x0003", "short", "o._17.Item3"),
EvalResult("Item4", "0x0004", "short", "o._17.Item4"),
EvalResult("Item5", "0x0005", "short", "o._17.Item5"),
EvalResult("Item6", "0x0006", "short", "o._17.Item6"),
EvalResult("Item7", "0x0007", "short", "o._17.Item7"),
EvalResult("Rest", "(0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011)", "(short, short, short, short, short, short, short, short, short, short)", "o._17.Rest, raw", DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[children.Length - 1], inspectionContext);
Verify(children,
EvalResult("Item1", "0x0008", "short", "o._17.Rest.Item1"),
EvalResult("Item2", "0x0009", "short", "o._17.Rest.Item2"),
EvalResult("Item3", "0x000a", "short", "o._17.Rest.Item3"),
EvalResult("Item4", "0x000b", "short", "o._17.Rest.Item4"),
EvalResult("Item5", "0x000c", "short", "o._17.Rest.Item5"),
EvalResult("Item6", "0x000d", "short", "o._17.Rest.Item6"),
EvalResult("Item7", "0x000e", "short", "o._17.Rest.Item7"),
EvalResult("Rest", "(0x000f, 0x0010, 0x0011)", "(short, short, short)", "o._17.Rest.Rest, raw", DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[children.Length - 1], inspectionContext);
Verify(children,
EvalResult("Item1", "0x000f", "short", "o._17.Rest.Rest.Item1"),
EvalResult("Item2", "0x0010", "short", "o._17.Rest.Rest.Item2"),
EvalResult("Item3", "0x0011", "short", "o._17.Rest.Rest.Item3"));
}
}
......@@ -349,21 +379,19 @@ class C
var moreChildren = GetChildren(children[0]);
Verify(moreChildren,
EvalResult("A", "1", "int", "o.F.Item1"),
EvalResult("Item1", "1", "int", "o.F.Item1"));
EvalResult("Raw View", "{(int, int)}", "(int A, int B)", "o.F, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
moreChildren = GetChildren(children[1]);
Verify(moreChildren);
moreChildren = GetChildren(children[2]);
Verify(moreChildren,
EvalResult("Item1", "1", "int", "o.H.Item1"),
EvalResult("B", "2", "int", "o.H.Item2"),
EvalResult("Item2", "2", "int", "o.H.Item2"),
EvalResult("Item3", "3", "int", "o.H.Item3"),
EvalResult("D", "4", "int", "o.H.Item4"),
EvalResult("Item4", "4", "int", "o.H.Item4"),
EvalResult("Item5", "5", "int", "o.H.Item5"),
EvalResult("F", "6", "int", "o.H.Item6"),
EvalResult("Item6", "6", "int", "o.H.Item6"),
EvalResult("Item7", "7", "int", "o.H.Item7"));
EvalResult("Item7", "7", "int", "o.H.Item7"),
EvalResult("Raw View", "{(int, int, int, int, int, int, int, int, int)}", "(int, int B, int, int D, int, int F, int, int H, int)", "o.H, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
}
}
......@@ -677,15 +705,13 @@ class C
moreChildren = GetChildren(moreChildren[0]);
Verify(moreChildren,
EvalResult("X", "null", "dynamic {object}", "o.G.F.Item1"),
EvalResult("Item1", "null", "dynamic {object}", "o.G.F.Item1"),
EvalResult("Y", "(null, {B<(object, object)>.S})", "(object E, B<(object F, dynamic G)>.S H) {(object, B<(object, object)>.S)}", "o.G.F.Item2", DkmEvaluationResultFlags.Expandable),
EvalResult("Item2", "(null, {B<(object, object)>.S})", "(object E, B<(object F, dynamic G)>.S H) {(object, B<(object, object)>.S)}", "o.G.F.Item2", DkmEvaluationResultFlags.Expandable));
moreChildren = GetChildren(moreChildren[3]);
EvalResult("Raw View", "(null, (null, {B<(object, object)>.S}))", "(dynamic X, (object E, B<(object F, dynamic G)>.S H) Y) {(object, (object, B<(object, object)>.S))}", "o.G.F, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
moreChildren = GetChildren(moreChildren[1]);
Verify(moreChildren,
EvalResult("E", "null", "object", "o.G.F.Item2.Item1"),
EvalResult("Item1", "null", "object", "o.G.F.Item2.Item1"),
EvalResult("H", "{B<(object, object)>.S}", "B<(object F, dynamic G)>.S {B<(object, object)>.S}", "o.G.F.Item2.Item2"),
EvalResult("Item2", "{B<(object, object)>.S}", "B<(object F, dynamic G)>.S {B<(object, object)>.S}", "o.G.F.Item2.Item2"));
EvalResult("Raw View", "(null, {B<(object, object)>.S})", "(object E, B<(object F, dynamic G)>.S H) {(object, B<(object, object)>.S)}", "o.G.F.Item2, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
}
}
......@@ -821,14 +847,17 @@ public void InvalidElementName()
children = GetChildren(children[0]);
Verify(children,
EvalResult("Item2", "null", "object", "o.F.Item1"),
EvalResult("Item1", "null", "object", "o.F.Item1"),
EvalResult("struct { }", "null", "object", "o.F.Item2"),
EvalResult("Raw View", "(null, null)", "(object Item2, object struct { })", "o.F, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
children = GetChildren(children[children.Length - 1]);
Verify(children,
EvalResult("Item1", "null", "object", "o.F.Item1"),
EvalResult("Item2", "null", "object", "o.F.Item2"));
}
}
[Fact]
public void LongTuple_Expansion()
public void LongTuple_ElementNames()
{
// Define in IL to include tuple element names
// for the Rest elements.
......@@ -862,50 +891,96 @@ public void LongTuple_Expansion()
children = GetChildren(children[0]);
Verify(children,
EvalResult("One", "0", "int", "o.F.Item1"),
EvalResult("Item1", "0", "int", "o.F.Item1"),
EvalResult("Two", "0", "int", "o.F.Item2"),
EvalResult("Item2", "0", "int", "o.F.Item2"),
EvalResult("Item3", "0", "int", "o.F.Item3"),
EvalResult("Item4", "0", "int", "o.F.Item4"),
EvalResult("Five", "0", "int", "o.F.Item5"),
EvalResult("Item5", "0", "int", "o.F.Item5"),
EvalResult("Six", "0", "int", "o.F.Item6"),
EvalResult("Item6", "0", "int", "o.F.Item6"),
EvalResult("Item7", "0", "int", "o.F.Item7"),
EvalResult("Item8", "0", "int", "o.F.Rest.Item1"),
EvalResult("Nine", "0", "int", "o.F.Rest.Item2"),
EvalResult("Item9", "0", "int", "o.F.Rest.Item2"),
EvalResult("Ten", "0", "int", "o.F.Rest.Item3"),
EvalResult("Item10", "0", "int", "o.F.Rest.Item3"),
EvalResult("Item11", "0", "int", "o.F.Rest.Item4"),
EvalResult("Item12", "0", "int", "o.F.Rest.Item5"),
EvalResult("Thirteen", "0", "int", "o.F.Rest.Item6"),
EvalResult("Item13", "0", "int", "o.F.Rest.Item6"),
EvalResult("Fourteen", "0", "int", "o.F.Rest.Item7"),
EvalResult("Item14", "0", "int", "o.F.Rest.Item7"),
EvalResult("Item15", "0", "int", "o.F.Rest.Rest.Item1"),
EvalResult("Rest", "(0, 0, 0, 0, 0, 0, 0, 0)", "(int, int Seventeen, int Eighteen, int, int, int TwentyOne, int TwentyTwo, int)", "o.F.Rest", DkmEvaluationResultFlags.Expandable));
EvalResult(
"Raw View",
"(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)", "(int One, int Two, int, int, int Five, int Six, int, int, int Nine, int Ten, int, int, int Thirteen, int Fourteen, int)",
"o.F, raw",
DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
children = GetChildren(children[children.Length - 1]);
Verify(children,
EvalResult("Item1", "0", "int", "o.F.Item1"),
EvalResult("Item2", "0", "int", "o.F.Item2"),
EvalResult("Item3", "0", "int", "o.F.Item3"),
EvalResult("Item4", "0", "int", "o.F.Item4"),
EvalResult("Item5", "0", "int", "o.F.Item5"),
EvalResult("Item6", "0", "int", "o.F.Item6"),
EvalResult("Item7", "0", "int", "o.F.Item7"),
EvalResult("Rest", "(0, 0, 0, 0, 0, 0, 0, 0)", "(int, int Seventeen, int Eighteen, int, int, int TwentyOne, int TwentyTwo, int)", "o.F.Rest, raw", DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[children.Length - 1]);
Verify(children,
EvalResult("Item1", "0", "int", "o.F.Rest.Item1"),
EvalResult("Seventeen", "0", "int", "o.F.Rest.Item2"),
EvalResult("Item2", "0", "int", "o.F.Rest.Item2"),
EvalResult("Eighteen", "0", "int", "o.F.Rest.Item3"),
EvalResult("Item3", "0", "int", "o.F.Rest.Item3"),
EvalResult("Item4", "0", "int", "o.F.Rest.Item4"),
EvalResult("Item5", "0", "int", "o.F.Rest.Item5"),
EvalResult("TwentyOne", "0", "int", "o.F.Rest.Item6"),
EvalResult("Item6", "0", "int", "o.F.Rest.Item6"),
EvalResult("TwentyTwo", "0", "int", "o.F.Rest.Item7"),
EvalResult("Item7", "0", "int", "o.F.Rest.Item7"),
EvalResult("Item8", "0", "int", "o.F.Rest.Rest.Item1"),
EvalResult("Rest", "{System.ValueTuple<int>}", "System.ValueTuple<int>", "o.F.Rest.Rest", DkmEvaluationResultFlags.Expandable));
EvalResult("Rest", "{System.ValueTuple<int>}", "System.ValueTuple<int>", "o.F.Rest.Rest, raw", DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[children.Length - 1]);
Verify(children,
EvalResult("Item1", "0", "int", "o.F.Rest.Rest.Item1"));
}
}
[Fact]
public void RawView()
{
var source =
@"class C
{
(int A, int, (int C, int D) E, int, int, int H, int, int J) T = (1, 2, (3, 4), 5, 6, 7, 8, 9);
}";
var assembly0 = GenerateTupleAssembly();
var reference0 = AssemblyMetadata.CreateFromImage(assembly0).GetReference();
var compilation1 = CSharpTestBaseBase.CreateCompilationWithMscorlib(source, references: new[] { reference0 });
var assembly1 = compilation1.EmitToArray();
var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(ReflectionUtilities.Load(assembly0), ReflectionUtilities.Load(assembly1)));
using (runtime.Load())
{
var inspectionContext = CreateDkmInspectionContext(DkmEvaluationFlags.ShowValueRaw);
var type = runtime.GetType("C");
var value = type.Instantiate();
var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o, raw", DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult, inspectionContext);
Verify(children,
EvalResult(
"T",
"(1, 2, (3, 4), 5, 6, 7, 8, 9)",
"(int A, int, (int C, int D) E, int, int, int H, int, int J)",
"o.T, raw",
DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[0], inspectionContext);
Verify(children,
EvalResult("Item1", "1", "int", "o.T.Item1, raw"),
EvalResult("Item2", "2", "int", "o.T.Item2, raw"),
EvalResult("Item3", "(3, 4)", "(int C, int D)", "o.T.Item3, raw", DkmEvaluationResultFlags.Expandable),
EvalResult("Item4", "5", "int", "o.T.Item4, raw"),
EvalResult("Item5", "6", "int", "o.T.Item5, raw"),
EvalResult("Item6", "7", "int", "o.T.Item6, raw"),
EvalResult("Item7", "8", "int", "o.T.Item7, raw"),
EvalResult("Rest", "{System.ValueTuple<int>}", "System.ValueTuple<int>", "o.T.Rest, raw", DkmEvaluationResultFlags.Expandable));
children = GetChildren(children[7], inspectionContext);
Verify(children,
EvalResult("Item1", "9", "int", "o.T.Rest.Item1, raw"));
}
}
[Fact]
public void Keywords()
{
......@@ -1075,10 +1150,10 @@ public void Exception()
children = GetChildren(children[0]);
Verify(children,
EvalResult("A", "1", "object {int}", "o.F.Item1"),
EvalResult("Item1", "1", "object {int}", "o.F.Item1"),
EvalResult("Item2", "'o.F.Item2' threw an exception of type 'System.InvalidOperationException'", "int {System.InvalidOperationException}", "o.F.Item2", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ExceptionThrown),
EvalResult("Item3", "3", "int", "o.F.Item3"));
children = GetChildren(children[2]);
EvalResult("Item3", "3", "int", "o.F.Item3"),
EvalResult("Raw View", "(1, {System.InvalidOperationException: Unable to evaluate}, 3)", "(object A, int, int)", "o.F, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
children = GetChildren(children[1]);
Assert.True(children.Length > 0);
Assert.Null(children[0].FullName); // FullName null for members of thrown Exception.
}
......@@ -1119,6 +1194,10 @@ class E : System.Exception
Verify(children,
EvalResult("Item1", "1", "int", null),
EvalResult("B", "2", "int", null),
EvalResult("Raw View", "(1, 2)", "(int, int B)", null, DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly));
children = GetChildren(children[children.Length - 1]);
Verify(children,
EvalResult("Item1", "1", "int", null),
EvalResult("Item2", "2", "int", null));
}
}
......
......@@ -14,24 +14,32 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal sealed class TupleExpansion : Expansion
{
internal static TupleExpansion CreateExpansion(DkmClrValue value, TypeAndCustomInfo declaredTypeAndInfo, int cardinality)
internal static TupleExpansion CreateExpansion(
DkmInspectionContext inspectionContext,
TypeAndCustomInfo declaredTypeAndInfo,
DkmClrValue value,
int cardinality)
{
if (value.IsNull)
{
// No expansion.
return null;
}
return new TupleExpansion(new TypeAndCustomInfo(value.Type, declaredTypeAndInfo.Info), cardinality);
bool useRawView = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.ShowValueRaw) != 0;
return new TupleExpansion(new TypeAndCustomInfo(value.Type, declaredTypeAndInfo.Info), cardinality, useRawView);
}
private readonly TypeAndCustomInfo _typeAndInfo;
private readonly int _cardinality;
private ReadOnlyCollection<Field> _lazyFields;
private readonly bool _useRawView;
private Fields _lazyFields;
private TupleExpansion(TypeAndCustomInfo typeAndInfo, int cardinality)
private TupleExpansion(TypeAndCustomInfo typeAndInfo, int cardinality, bool useRawView)
{
_typeAndInfo = typeAndInfo;
_cardinality = cardinality;
_useRawView = useRawView;
}
internal override void GetRows(
......@@ -46,19 +54,30 @@ private TupleExpansion(TypeAndCustomInfo typeAndInfo, int cardinality)
ref int index)
{
var fields = GetFields();
var defaultView = fields.DefaultView;
int startIndex2;
int count2;
GetIntersection(startIndex, count, index, fields.Count, out startIndex2, out count2);
GetIntersection(startIndex, count, index, defaultView.Count, out startIndex2, out count2);
int offset = startIndex2 - index;
for (int i = 0; i < count2; i++)
{
var row = GetMemberRow(resultProvider, inspectionContext, value, fields[i + offset], parent);
var row = GetMemberRow(resultProvider, inspectionContext, value, defaultView[i + offset], parent, _cardinality);
rows.Add(row);
}
index += fields.Count;
index += defaultView.Count;
if (fields.IncludeRawView)
{
if (InRange(startIndex, count, index))
{
rows.Add(this.CreateRawViewRow(resultProvider, inspectionContext, parent, value));
}
index++;
}
}
private static EvalResult GetMemberRow(
......@@ -66,7 +85,8 @@ private TupleExpansion(TypeAndCustomInfo typeAndInfo, int cardinality)
DkmInspectionContext inspectionContext,
DkmClrValue value,
Field field,
EvalResultDataItem parent)
EvalResultDataItem parent,
int cardinality)
{
var fullNameProvider = resultProvider.FullNameProvider;
var parentFullName = parent.ChildFullNamePrefix;
......@@ -94,19 +114,56 @@ private TupleExpansion(TypeAndCustomInfo typeAndInfo, int cardinality)
field,
parentFullName,
out fullName);
var name = field.Name;
var typeDeclaringMemberAndInfo = default(TypeAndCustomInfo);
var declaredTypeAndInfo = field.FieldTypeAndInfo;
var flags = fieldValue.EvalFlags;
var formatSpecifiers = Formatter.NoFormatSpecifiers;
if (field.IsRest)
{
var displayValue = fieldValue.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers);
var displayType = ResultProvider.GetTypeName(
inspectionContext,
fieldValue,
declaredTypeAndInfo.ClrType,
declaredTypeAndInfo.Info,
isPointerDereference: false);
var expansion = new TupleExpansion(declaredTypeAndInfo, cardinality - (TypeHelpers.TupleFieldRestPosition - 1), useRawView: true);
return new EvalResult(
ExpansionKind.Explicit,
name,
typeDeclaringMemberAndInfo,
declaredTypeAndInfo,
useDebuggerDisplay: false,
value: fieldValue,
displayValue: displayValue,
expansion: expansion,
childShouldParenthesize: false,
fullName: fullName,
childFullNamePrefixOpt: flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName,
formatSpecifiers: Formatter.AddFormatSpecifier(formatSpecifiers, "raw"),
category: DkmEvaluationResultCategory.Other,
flags: flags,
editableValue: null,
inspectionContext: inspectionContext,
displayName: name,
displayType: displayType);
}
return resultProvider.CreateDataItem(
inspectionContext,
field.Name,
typeDeclaringMemberAndInfo: default(TypeAndCustomInfo),
declaredTypeAndInfo: field.FieldTypeAndInfo,
name,
typeDeclaringMemberAndInfo: typeDeclaringMemberAndInfo,
declaredTypeAndInfo: declaredTypeAndInfo,
value: fieldValue,
useDebuggerDisplay: false,
expansionFlags: ExpansionFlags.All,
childShouldParenthesize: false,
fullName: fullName,
formatSpecifiers: Formatter.NoFormatSpecifiers,
formatSpecifiers: formatSpecifiers,
category: DkmEvaluationResultCategory.Other,
flags: fieldValue.EvalFlags,
flags: flags,
evalFlags: DkmEvaluationFlags.None);
}
......@@ -150,13 +207,15 @@ private sealed class Field
internal readonly FieldInfo FieldInfo; // type field
internal readonly string Name;
internal readonly Field Parent; // parent Rest field, if any
internal readonly bool IsRest;
internal Field(
TypeAndCustomInfo declaringTypeAndInfo,
TypeAndCustomInfo fieldTypeAndInfo,
FieldInfo fieldInfo,
string name,
Field parent)
Field parent,
bool isRest)
{
Debug.Assert(declaringTypeAndInfo.ClrType != null);
Debug.Assert(fieldTypeAndInfo.ClrType != null);
......@@ -171,30 +230,43 @@ private sealed class Field
FieldInfo = fieldInfo;
Name = name;
Parent = parent;
IsRest = isRest;
}
}
private sealed class Fields
{
internal readonly ReadOnlyCollection<Field> DefaultView;
internal readonly bool IncludeRawView;
internal Fields(ReadOnlyCollection<Field> defaultView, bool includeRawView)
{
DefaultView = defaultView;
IncludeRawView = includeRawView;
}
}
private ReadOnlyCollection<Field> GetFields()
private Fields GetFields()
{
if (_lazyFields == null)
{
_lazyFields = GetFields(_typeAndInfo, _cardinality);
_lazyFields = GetFields(_typeAndInfo, _cardinality, _useRawView);
}
return _lazyFields;
}
private static ReadOnlyCollection<Field> GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality)
private static Fields GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality, bool useRawView)
{
Debug.Assert(declaringTypeAndInfo.Type.GetTupleCardinalityIfAny() == cardinality);
var appDomain = declaringTypeAndInfo.ClrType.AppDomain;
var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaringTypeAndInfo);
var tupleElementNames = customTypeInfoMap.TupleElementNames;
var builder = ArrayBuilder<Field>.GetInstance();
Field parent = null;
int offset = 0;
bool includeRawView = false;
while (true)
{
......@@ -211,17 +283,24 @@ private static ReadOnlyCollection<Field> GetFields(TypeAndCustomInfo declaringTy
}
var fieldTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, field, customTypeInfoMap);
var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index);
if (name != null)
if (!useRawView)
{
builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent));
var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index);
if (name != null)
{
includeRawView = true;
builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent, isRest: false));
continue;
}
}
builder.Add(new Field(
declaringTypeAndInfo,
fieldTypeAndInfo,
field,
(offset == 0) ? fieldName : TypeHelpers.GetTupleFieldName(offset + index),
parent));
parent,
isRest: false));
}
cardinality -= n;
......@@ -238,23 +317,21 @@ private static ReadOnlyCollection<Field> GetFields(TypeAndCustomInfo declaringTy
}
var restTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, rest, customTypeInfoMap);
parent = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent);
declaringTypeAndInfo = restTypeAndInfo;
offset += TypeHelpers.TupleFieldRestPosition - 1;
}
var restField = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent, isRest: true);
// If there were any nested ValueTuples,
// add the Rest field of the outermost.
if (parent != null)
{
while (parent.Parent != null)
if (useRawView)
{
parent = parent.Parent;
builder.Add(restField);
break;
}
builder.Add(parent);
includeRawView = true;
parent = restField;
declaringTypeAndInfo = restTypeAndInfo;
offset += TypeHelpers.TupleFieldRestPosition - 1;
}
return builder.ToImmutableAndFree();
return new Fields(builder.ToImmutableAndFree(), includeRawView);
}
private static TypeAndCustomInfo GetTupleFieldTypeAndInfo(
......@@ -268,5 +345,41 @@ private static ReadOnlyCollection<Field> GetFields(TypeAndCustomInfo declaringTy
var fieldTypeInfo = customTypeInfoMap.SubstituteCustomTypeInfo(fieldDef.FieldType, null);
return new TypeAndCustomInfo(fieldType, fieldTypeInfo);
}
private EvalResult CreateRawViewRow(
ResultProvider resultProvider,
DkmInspectionContext inspectionContext,
EvalResultDataItem parent,
DkmClrValue value)
{
var displayName = Resources.RawView;
var displayValue = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers);
var displayType = ResultProvider.GetTypeName(
inspectionContext,
value,
_typeAndInfo.ClrType,
_typeAndInfo.Info,
isPointerDereference: false);
var expansion = new TupleExpansion(_typeAndInfo, _cardinality, useRawView: true);
return new EvalResult(
ExpansionKind.Explicit,
displayName,
default(TypeAndCustomInfo),
_typeAndInfo,
useDebuggerDisplay: false,
value: value,
displayValue: displayValue,
expansion: expansion,
childShouldParenthesize: parent.ChildShouldParenthesize,
fullName: parent.FullNameWithoutFormatSpecifiers,
childFullNamePrefixOpt: parent.ChildFullNamePrefix,
formatSpecifiers: Formatter.AddFormatSpecifier(parent.FormatSpecifiers, "raw"),
category: DkmEvaluationResultCategory.Data,
flags: DkmEvaluationResultFlags.ReadOnly,
editableValue: null,
inspectionContext: inspectionContext,
displayName: displayName,
displayType: displayType);
}
}
}
......@@ -66,6 +66,7 @@ protected override void OnClose()
internal enum ExpansionKind
{
Default,
Explicit, // All interesting fields set explicitly including DisplayName, DisplayValue, DisplayType.
DynamicView,
Error,
NativeView,
......@@ -85,7 +86,9 @@ internal sealed class EvalResult
public readonly TypeAndCustomInfo DeclaredTypeAndInfo;
public readonly bool UseDebuggerDisplay;
public readonly DkmClrValue Value;
public readonly string DisplayName;
public readonly string DisplayValue; // overrides the "Value" text displayed for certain kinds of DataItems (errors, invalid pointer dereferences, etc)...not to be confused with DebuggerDisplayAttribute Value...
public readonly string DisplayType;
public readonly Expansion Expansion;
public readonly bool ChildShouldParenthesize;
public readonly string FullNameWithoutFormatSpecifiers;
......@@ -149,7 +152,9 @@ public EvalResult(string name, string errorMessage, DkmInspectionContext inspect
DkmEvaluationResultCategory category,
DkmEvaluationResultFlags flags,
string editableValue,
DkmInspectionContext inspectionContext)
DkmInspectionContext inspectionContext,
string displayName = null,
string displayType = null)
{
Debug.Assert(name != null);
Debug.Assert(formatSpecifiers != null);
......@@ -171,6 +176,8 @@ public EvalResult(string name, string errorMessage, DkmInspectionContext inspect
this.Flags = flags | GetFlags(value, inspectionContext) | ((expansion == null) ? DkmEvaluationResultFlags.None : DkmEvaluationResultFlags.Expandable);
this.Expansion = expansion;
this.InspectionContext = inspectionContext;
this.DisplayName = displayName;
this.DisplayType = displayType;
}
internal EvalResultDataItem ToDataItem()
......
......@@ -240,6 +240,25 @@ private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workL
{
switch (result.Kind)
{
case ExpansionKind.Explicit:
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
stackFrame,
Name: result.DisplayName,
FullName: result.FullName,
Flags: result.Flags,
Value: result.DisplayValue,
EditableValue: result.EditableValue,
Type: result.DisplayType,
Category: DkmEvaluationResultCategory.Data,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: result.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: result.ToDataItem()));
break;
case ExpansionKind.Error:
completionRoutine(DkmFailedEvaluationResult.Create(
inspectionContext,
......@@ -465,14 +484,19 @@ private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workL
/// The qualified name (i.e. including containing types and namespaces) of a named, pointer,
/// or array type followed by the qualified name of the actual runtime type, if provided.
/// </returns>
private static string GetTypeName(DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, ExpansionKind kind)
internal static string GetTypeName(
DkmInspectionContext inspectionContext,
DkmClrValue value,
DkmClrType declaredType,
DkmClrCustomTypeInfo declaredTypeInfo,
bool isPointerDereference)
{
var declaredLmrType = declaredType.GetLmrType();
var runtimeType = value.Type;
var declaredTypeName = inspectionContext.GetTypeName(declaredType, declaredTypeInfo, Formatter.NoFormatSpecifiers);
// Include the runtime type if distinct.
if (!declaredLmrType.IsPointer &&
(kind != ExpansionKind.PointerDereference) &&
!isPointerDereference &&
(!declaredLmrType.IsNullable() || value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown)))
{
// Generate the declared type name without tuple element names.
......@@ -831,7 +855,7 @@ private static string GetTypeName(DkmInspectionContext inspectionContext, DkmClr
display = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers);
}
var typeName = displayType ?? GetTypeName(inspectionContext, value, declaredType, declaredTypeInfo, result.Kind);
var typeName = displayType ?? GetTypeName(inspectionContext, value, declaredType, declaredTypeInfo, result.Kind == ExpansionKind.PointerDereference);
return CreateEvaluationResult(inspectionContext, value, name, typeName, display, result);
}
......@@ -951,7 +975,7 @@ private static string GetTypeName(DkmInspectionContext inspectionContext, DkmClr
int cardinality;
if (runtimeType.IsTupleCompatible(out cardinality))
{
return TupleExpansion.CreateExpansion(value, declaredTypeAndInfo, cardinality);
return TupleExpansion.CreateExpansion(inspectionContext, declaredTypeAndInfo, value, cardinality);
}
return MemberExpansion.CreateExpansion(inspectionContext, declaredTypeAndInfo, value, flags, TypeHelpers.IsVisibleMember, this);
......
......@@ -16,7 +16,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
Inherits VisualBasicResultProviderTestBase
<Fact>
Public Sub LongTuple()
Public Sub LongTuple_NoNames()
Const source =
"Class C
Private _17 As (Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short) =
......@@ -32,7 +32,7 @@ End Class"
Dim value = type.Instantiate()
Dim result = FormatResult("o", value)
Verify(result,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable))
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable))
Dim children = GetChildren(result)
Verify(children,
EvalResult(
......@@ -42,25 +42,55 @@ End Class"
"o._17",
DkmEvaluationResultFlags.Expandable))
children = GetChildren(children(0))
Assert.Equal(18, children.Length)
Dim child = children(children.Length - 1)
Verify(child,
EvalResult(
"Rest",
"(8, 9, 10, 11, 12, 13, 14, 15, 16, 17)",
"(Short, Short, Short, Short, Short, Short, Short, Short, Short, Short)",
"o._17.Rest",
DkmEvaluationResultFlags.Expandable))
children = GetChildren(child)
Assert.Equal(11, children.Length)
child = children(children.Length - 1)
Verify(child,
Verify(children,
EvalResult("Item1", "1", "Short", "o._17.Item1"),
EvalResult("Item2", "2", "Short", "o._17.Item2"),
EvalResult("Item3", "3", "Short", "o._17.Item3"),
EvalResult("Item4", "4", "Short", "o._17.Item4"),
EvalResult("Item5", "5", "Short", "o._17.Item5"),
EvalResult("Item6", "6", "Short", "o._17.Item6"),
EvalResult("Item7", "7", "Short", "o._17.Item7"),
EvalResult("Item8", "8", "Short", "o._17.Rest.Item1"),
EvalResult("Item9", "9", "Short", "o._17.Rest.Item2"),
EvalResult("Item10", "10", "Short", "o._17.Rest.Item3"),
EvalResult("Item11", "11", "Short", "o._17.Rest.Item4"),
EvalResult("Item12", "12", "Short", "o._17.Rest.Item5"),
EvalResult("Item13", "13", "Short", "o._17.Rest.Item6"),
EvalResult("Item14", "14", "Short", "o._17.Rest.Item7"),
EvalResult("Item15", "15", "Short", "o._17.Rest.Rest.Item1"),
EvalResult("Item16", "16", "Short", "o._17.Rest.Rest.Item2"),
EvalResult("Item17", "17", "Short", "o._17.Rest.Rest.Item3"),
EvalResult(
"Rest",
"(15, 16, 17)",
"(Short, Short, Short)",
"o._17.Rest.Rest",
DkmEvaluationResultFlags.Expandable))
"Raw View",
"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)",
"(Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short)",
"o._17, raw",
DkmEvaluationResultFlags.Expandable Or DkmEvaluationResultFlags.ReadOnly))
children = GetChildren(children(children.Length - 1))
Verify(children,
EvalResult("Item1", "1", "Short", "o._17.Item1"),
EvalResult("Item2", "2", "Short", "o._17.Item2"),
EvalResult("Item3", "3", "Short", "o._17.Item3"),
EvalResult("Item4", "4", "Short", "o._17.Item4"),
EvalResult("Item5", "5", "Short", "o._17.Item5"),
EvalResult("Item6", "6", "Short", "o._17.Item6"),
EvalResult("Item7", "7", "Short", "o._17.Item7"),
EvalResult("Rest", "(8, 9, 10, 11, 12, 13, 14, 15, 16, 17)", "(Short, Short, Short, Short, Short, Short, Short, Short, Short, Short)", "o._17.Rest, raw", DkmEvaluationResultFlags.Expandable))
children = GetChildren(children(children.Length - 1))
Verify(children,
EvalResult("Item1", "8", "Short", "o._17.Rest.Item1"),
EvalResult("Item2", "9", "Short", "o._17.Rest.Item2"),
EvalResult("Item3", "10", "Short", "o._17.Rest.Item3"),
EvalResult("Item4", "11", "Short", "o._17.Rest.Item4"),
EvalResult("Item5", "12", "Short", "o._17.Rest.Item5"),
EvalResult("Item6", "13", "Short", "o._17.Rest.Item6"),
EvalResult("Item7", "14", "Short", "o._17.Rest.Item7"),
EvalResult("Rest", "(15, 16, 17)", "(Short, Short, Short)", "o._17.Rest.Rest, raw", DkmEvaluationResultFlags.Expandable))
children = GetChildren(children(children.Length - 1))
Verify(children,
EvalResult("Item1", "15", "Short", "o._17.Rest.Rest.Item1"),
EvalResult("Item2", "16", "Short", "o._17.Rest.Rest.Item2"),
EvalResult("Item3", "17", "Short", "o._17.Rest.Rest.Item3"))
End Using
End Sub
......@@ -136,15 +166,13 @@ class C
moreChildren = GetChildren(moreChildren(0))
Verify(moreChildren,
EvalResult("X", "Nothing", "Object", "o.G.F.Item1"),
EvalResult("Item1", "Nothing", "Object", "o.G.F.Item1"),
EvalResult("Y", "(Nothing, {B(Of (Object, Object)).S})", "(E As Object, H As B(Of (F As Object, G As Object)).S)", "o.G.F.Item2", DkmEvaluationResultFlags.Expandable),
EvalResult("Item2", "(Nothing, {B(Of (Object, Object)).S})", "(E As Object, H As B(Of (F As Object, G As Object)).S)", "o.G.F.Item2", DkmEvaluationResultFlags.Expandable))
moreChildren = GetChildren(moreChildren(3))
EvalResult("Raw View", "(Nothing, (Nothing, {B(Of (Object, Object)).S}))", "(X As Object, Y As (E As Object, H As B(Of (F As Object, G As Object)).S))", "o.G.F, raw", DkmEvaluationResultFlags.Expandable Or DkmEvaluationResultFlags.ReadOnly))
moreChildren = GetChildren(moreChildren(1))
Verify(moreChildren,
EvalResult("E", "Nothing", "Object", "o.G.F.Item2.Item1"),
EvalResult("Item1", "Nothing", "Object", "o.G.F.Item2.Item1"),
EvalResult("H", "{B(Of (Object, Object)).S}", "B(Of (F As Object, G As Object)).S", "o.G.F.Item2.Item2"),
EvalResult("Item2", "{B(Of (Object, Object)).S}", "B(Of (F As Object, G As Object)).S", "o.G.F.Item2.Item2"))
EvalResult("Raw View", "(Nothing, {B(Of (Object, Object)).S})", "(E As Object, H As B(Of (F As Object, G As Object)).S)", "o.G.F.Item2, raw", DkmEvaluationResultFlags.Expandable Or DkmEvaluationResultFlags.ReadOnly))
End Using
End Sub
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册