未验证 提交 531243f5 编写于 作者: I Ivan Basov 提交者: GitHub

Debugger shows property as field (#35433)

上级 cb056d86
......@@ -629,6 +629,40 @@ class C
EvalResult("F", "1", "object {int}", "(new C()).s1.F"));
}
[Fact]
public void NullableProperty()
{
var source =
@"
class R
{
public int? A { get; set; }
public int? B { get; set; }
}
class C
{
R r = new R();
public C()
{
r.A = 1;
r.B = null;
}
}";
var assembly = GetAssembly(source);
var type = assembly.GetType("C");
var value = CreateDkmClrValue(Activator.CreateInstance(type));
var rootExpr = "new C()";
var evalResult = FormatResult(rootExpr, value);
Verify(evalResult,
EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
Verify(children,
EvalResult("r", "{R}", "R", "(new C()).r", flags: DkmEvaluationResultFlags.Expandable));
Verify(GetChildren(children[0]),
EvalResult("A", "1", "int?", "(new C()).r.A", category: DkmEvaluationResultCategory.Property),
EvalResult("B", "null", "int?", "(new C()).r.B", category: DkmEvaluationResultCategory.Property));
}
[Fact]
public void Pointers()
{
......
......@@ -459,6 +459,8 @@ private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workL
// which typically appears to be set to the default value ("Other").
var category = (result.Category != DkmEvaluationResultCategory.Other) ? result.Category : value.Category;
var nullableMemberInfo = value.GetDataItem<NullableMemberInfo>();
// Valid value
return DkmSuccessEvaluationResult.Create(
InspectionContext: inspectionContext,
......@@ -469,10 +471,10 @@ private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workL
Value: display,
EditableValue: result.EditableValue,
Type: typeName,
Category: category,
Access: value.Access,
StorageType: value.StorageType,
TypeModifierFlags: value.TypeModifierFlags,
Category: nullableMemberInfo?.Category ?? category,
Access: nullableMemberInfo?.Access ?? value.Access,
StorageType: nullableMemberInfo?.StorageType ?? value.StorageType,
TypeModifierFlags: nullableMemberInfo?.TypeModifierFlags ?? value.TypeModifierFlags,
Address: value.Address,
CustomUIVisualizers: customUIVisualizers,
ExternalModules: null,
......@@ -557,6 +559,16 @@ private void CreateEvaluationResultAndContinue(EvalResult result, WorkList workL
}
else
{
// nullableValue is taken from an internal field.
// It may have different category, access, etc comparing the original member.
// For example, the orignal member can be a property not a field.
// Save original member values to restore them later.
if (value != nullableValue)
{
var nullableMemberInfo = new NullableMemberInfo(value.Category, value.Access, value.StorageType, value.TypeModifierFlags);
nullableValue.SetDataItem(DkmDataCreationDisposition.CreateAlways, nullableMemberInfo);
}
value = nullableValue;
Debug.Assert(lmrNullableTypeArg.Equals(value.Type.GetLmrType())); // If this is not the case, add a test for includeRuntimeTypeIfNecessary.
// CONSIDER: The DynamicAttribute for the type argument should just be Skip(1) of the original flag array.
......@@ -1058,5 +1070,21 @@ private void Execute()
_state = State.Executed;
}
}
private class NullableMemberInfo : DkmDataItem
{
public readonly DkmEvaluationResultCategory Category;
public readonly DkmEvaluationResultAccessType Access;
public readonly DkmEvaluationResultStorageType StorageType;
public readonly DkmEvaluationResultTypeModifierFlags TypeModifierFlags;
public NullableMemberInfo(DkmEvaluationResultCategory category, DkmEvaluationResultAccessType access, DkmEvaluationResultStorageType storageType, DkmEvaluationResultTypeModifierFlags typeModifierFlags)
{
Category = category;
Access = access;
StorageType = storageType;
TypeModifierFlags = typeModifierFlags;
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册