提交 87c1a611 编写于 作者: C Charles Stoner

Merge pull request #1957 from cston/1028624

EE: "Static members", etc. should not inherit Access, StorageType, TypeModifierFlags from parent item
......@@ -6,10 +6,12 @@
using Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.ComponentInterfaces;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Symbols;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -2124,52 +2126,68 @@ class D : C
}
/// <summary>
/// Do not copy state from parent for base or derived items.
/// Do not copy state from parent.
/// </summary>
[WorkItem(1028624)]
[Fact(Skip = "1028624")]
[Fact]
public void DoNotCopyParentState()
{
var source =
@"class E : System.Exception
var sourceA =
@"public class A
{
}
public class A
{
}
class B : A
public static object F = 1;
internal object G = 2;
}";
var sourceB =
@"class B
{
protected class C : B
{
private B F = new B();
protected A G = new B();
internal virtual B P { get { return new B(); } }
protected object Q { get { throw new E(); } }
}
private A _1 = new A();
protected A _2 = new A();
internal A _3 = new A();
public A _4 = new A();
}";
var assembly = GetAssembly(source);
var type = assembly.GetType("B+C");
var value = CreateDkmClrValue(
Activator.CreateInstance(type),
alias: "1",
evalFlags: DkmEvaluationResultFlags.UnflushedSideEffects | DkmEvaluationResultFlags.HasObjectId | DkmEvaluationResultFlags.CanHaveObjectId);
var evalResult = FormatResult("o", value, new DkmClrType((TypeImpl)type.BaseType));
Verify(evalResult,
EvalResult("o", "{B.C} {$1}", "B {B.C}", "o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.UnflushedSideEffects | DkmEvaluationResultFlags.HasObjectId | DkmEvaluationResultFlags.CanHaveObjectId));
var children = GetChildren(evalResult);
Verify(children,
EvalResult("[B.C]", "{B.C} {$1}", "B.C", "(B.C)o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.HasObjectId, DkmEvaluationResultCategory.Data),
EvalResult("base", "{B.C} {$1}", "A {B.C}", "(A)o", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.HasObjectId, DkmEvaluationResultCategory.Data));
children = GetChildren(children[0]);
Verify(children,
EvalResult("base", "{B.C} {$1}", "B {B.C}", "(B)o", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.HasObjectId, DkmEvaluationResultCategory.Data),
EvalResult("F", "{B}", "B", "((B.C)o).F", DkmEvaluationResultFlags.Expandable),
EvalResult("G", "{B}", "A {B}", "((B.C)o).G", DkmEvaluationResultFlags.Expandable),
EvalResult("P", "{B}", "B", "((B.C)o).P", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly),
EvalResult("Q", "'((B.C)o).Q' threw an exception of type 'E'", "object {E}", "((B.C)o).Q", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown));
// Also need to check Access, StorageType, and TypeModifierFlags fields.
// ...
var compilationA = CSharpTestBase.CreateCompilationWithMscorlib(sourceA, options: TestOptions.ReleaseDll);
var bytesA = compilationA.EmitToArray();
var referenceA = MetadataReference.CreateFromImage(bytesA);
var compilationB = CSharpTestBase.CreateCompilationWithMscorlib(sourceB, options: TestOptions.DebugDll, references: new MetadataReference[] { referenceA });
var bytesB = compilationB.EmitToArray();
var assemblyA = ReflectionUtilities.Load(bytesA);
var assemblyB = ReflectionUtilities.Load(bytesB);
DkmClrRuntimeInstance runtime = null;
GetModuleDelegate getModule = (r, a) => (a == assemblyB) ? new DkmClrModuleInstance(r, a, new DkmModule(a.GetName().Name + ".dll")) : null;
runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(assemblyA, assemblyB), getModule: getModule);
using (runtime.Load())
{
var type = runtime.GetType("B");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
// Format with "Just my code".
var inspectionContext = CreateDkmInspectionContext(DkmEvaluationFlags.HideNonPublicMembers, runtimeInstance: runtime);
var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
var children = GetChildren(evalResult, inspectionContext: inspectionContext);
Verify(children,
EvalResult("_1", "{A}", "A", "o._1", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Private),
EvalResult("_2", "{A}", "A", "o._2", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Protected),
EvalResult("_3", "{A}", "A", "o._3", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Internal),
EvalResult("_4", "{A}", "A", "o._4", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Public));
var moreChildren = GetChildren(children[0], inspectionContext: inspectionContext);
Verify(moreChildren,
EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
EvalResult("Non-Public members", null, "", "o._1, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
moreChildren = GetChildren(children[1], inspectionContext: inspectionContext);
Verify(moreChildren,
EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
EvalResult("Non-Public members", null, "", "o._2, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
moreChildren = GetChildren(children[2], inspectionContext: inspectionContext);
Verify(moreChildren,
EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
EvalResult("Non-Public members", null, "", "o._3, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
moreChildren = GetChildren(children[3], inspectionContext: inspectionContext);
Verify(moreChildren,
EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
EvalResult("Non-Public members", null, "", "o._4, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
}
}
[WorkItem(1130978)]
......
......@@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests
public class NativeViewTests : CSharpResultProviderTestBase
{
[Fact]
public void NativeView1()
public void NativeView()
{
TestNativeView(true);
}
......@@ -25,8 +25,7 @@ public void NativeViewManagedOnly()
private void TestNativeView(bool enableNativeDebugging)
{
var source =
@"using System.Collections;
class C
@"class C
{
}";
using (new EnsureEnglishUICulture())
......@@ -41,7 +40,7 @@ class C
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: runtime.GetType((TypeImpl)type),
isComObject: true);
nativeComPointer: 0xfe);
var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -50,7 +49,7 @@ class C
{
DkmLanguage language = new DkmLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
Verify(children,
EvalIntermediateResult("Native View", "{C++}(IUnknown*)0x00000001", "(IUnknown*)0x00000001", language));
EvalIntermediateResult("Native View", "{C++}(IUnknown*)0x000000FE", "(IUnknown*)0x000000FE", language));
}
else
{
......
......@@ -1460,8 +1460,7 @@ internal IEnumerable Q
"\"Exception of type 'E' was thrown.\"",
"string",
null,
DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly,
DkmEvaluationResultCategory.Other));
DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly));
}
}
......@@ -1615,7 +1614,7 @@ class C
"S",
DkmEvaluationResultFlags.RawString,
DkmEvaluationResultCategory.Other,
"\"\""));
editableValue: "\"\""));
// array (unchanged)
evalResult = FormatPropertyValue(runtime, value, "T");
......
......@@ -110,7 +110,7 @@ internal sealed class MemberExpansion : Expansion
if (value.NativeComPointer != 0)
{
expansions.Add(new NativeViewExpansion());
expansions.Add(NativeViewExpansion.Instance);
}
if (nonPublicInstanceExpansion != null)
......
......@@ -9,6 +9,12 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal sealed class NativeViewExpansion : Expansion
{
internal static readonly NativeViewExpansion Instance = new NativeViewExpansion();
private NativeViewExpansion()
{
}
internal override void GetRows(
ResultProvider resultProvider,
ArrayBuilder<EvalResultDataItem> rows,
......
......@@ -58,7 +58,7 @@ private EvalResultDataItem GetRow(ResultProvider resultProvider, DkmInspectionCo
var typeArgument = _typeArguments[index];
var formatSpecifiers = Formatter.NoFormatSpecifiers;
return new EvalResultDataItem(
ExpansionKind.TypeVariables,
ExpansionKind.TypeVariable,
typeParameter.Name,
typeDeclaringMember: null,
declaredType: typeArgument,
......
......@@ -19,7 +19,7 @@ internal enum ExpansionKind
RawView,
ResultsView,
StaticMembers,
TypeVariables
TypeVariable
}
/// <summary>
......
......@@ -133,36 +133,120 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
DataItem: null));
break;
case ExpansionKind.NativeView:
{
var value = dataItem.Value;
var name = Resources.NativeView;
var fullName = dataItem.FullName;
var display = dataItem.Name;
DkmEvaluationResult evalResult;
if (value.IsError())
{
evalResult = DkmFailedEvaluationResult.Create(
inspectionContext,
stackFrame,
Name: name,
FullName: fullName,
ErrorMessage: display,
Flags: dataItem.Flags,
Type: null,
DataItem: dataItem);
}
else
{
// For Native View, create a DkmIntermediateEvaluationResult.
// This will allow the C++ EE to take over expansion.
var process = inspectionContext.RuntimeInstance.Process;
var cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
evalResult = DkmIntermediateEvaluationResult.Create(
inspectionContext,
stackFrame,
Name: name,
FullName: fullName,
Expression: display,
IntermediateLanguage: cpp,
TargetRuntime: process.GetNativeRuntimeInstance(),
DataItem: dataItem);
}
completionRoutine(evalResult);
}
break;
case ExpansionKind.NonPublicMembers:
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
stackFrame,
Name: Resources.NonPublicMembers,
FullName: dataItem.FullName,
Flags: dataItem.Flags,
Value: null,
EditableValue: null,
Type: string.Empty,
Category: DkmEvaluationResultCategory.Data,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: dataItem.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: dataItem));
break;
case ExpansionKind.StaticMembers:
completionRoutine(CreateEvaluationResult(
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
dataItem.Value,
dataItem.Name,
typeName: string.Empty,
display: null,
dataItem: dataItem));
stackFrame,
Name: Formatter.StaticMembersString,
FullName: dataItem.FullName,
Flags: dataItem.Flags,
Value: null,
EditableValue: null,
Type: string.Empty,
Category: DkmEvaluationResultCategory.Class,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: dataItem.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: dataItem));
break;
case ExpansionKind.RawView:
completionRoutine(CreateEvaluationResult(
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
dataItem.Value,
Resources.RawView,
typeName: string.Empty,
display: null,
dataItem: dataItem));
stackFrame,
Name: Resources.RawView,
FullName: dataItem.FullName,
Flags: dataItem.Flags,
Value: null,
EditableValue: dataItem.EditableValue,
Type: string.Empty,
Category: DkmEvaluationResultCategory.Data,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: dataItem.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: dataItem));
break;
case ExpansionKind.ResultsView:
completionRoutine(CreateEvaluationResult(
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
dataItem.Value,
dataItem.Name,
typeName: string.Empty,
display: Resources.ResultsViewValueWarning,
dataItem: dataItem));
stackFrame,
Name: dataItem.Name,
FullName: dataItem.FullName,
Flags: dataItem.Flags,
Value: Resources.ResultsViewValueWarning,
EditableValue: null,
Type: string.Empty,
Category: DkmEvaluationResultCategory.Method,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: dataItem.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: dataItem));
break;
case ExpansionKind.TypeVariables:
var value = dataItem.Value;
case ExpansionKind.TypeVariable:
completionRoutine(DkmSuccessEvaluationResult.Create(
inspectionContext,
stackFrame,
......@@ -172,17 +256,17 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
dataItem.DisplayValue,
EditableValue: null,
Type: dataItem.DisplayValue,
Category: dataItem.Category,
Access: value.Access,
StorageType: value.StorageType,
TypeModifierFlags: value.TypeModifierFlags,
Address: value.Address,
Category: DkmEvaluationResultCategory.Data,
Access: DkmEvaluationResultAccessType.None,
StorageType: DkmEvaluationResultStorageType.None,
TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
Address: dataItem.Value.Address,
CustomUIVisualizers: null,
ExternalModules: null,
DataItem: dataItem));
break;
default:
Debug.Assert((dataItem.Kind == ExpansionKind.Default) || (dataItem.Kind == ExpansionKind.PointerDereference));
case ExpansionKind.PointerDereference:
case ExpansionKind.Default:
// This call will evaluate DebuggerDisplayAttributes.
GetResultAndContinue(
dataItem,
......@@ -192,6 +276,8 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
parent: dataItem.Parent,
completionRoutine: completionRoutine);
break;
default:
throw ExceptionUtilities.UnexpectedValue(dataItem.Kind);
}
}
......@@ -216,22 +302,6 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
Type: typeName,
DataItem: dataItem);
}
else if (dataItem.Kind == ExpansionKind.NativeView)
{
// For Native View, create a DkmIntermediateEvaluationResult. This will allow the C++ EE
// to take over expansion.
DkmProcess process = inspectionContext.RuntimeInstance.Process;
DkmLanguage cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
return DkmIntermediateEvaluationResult.Create(
InspectionContext: inspectionContext,
StackFrame: value.StackFrame,
Name: Resources.NativeView,
FullName: dataItem.FullName,
Expression: dataItem.Name,
IntermediateLanguage: cpp,
TargetRuntime: process.GetNativeRuntimeInstance(),
DataItem: dataItem);
}
else
{
ReadOnlyCollection<DkmCustomUIVisualizerInfo> customUIVisualizers = null;
......@@ -245,7 +315,7 @@ private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, Work
}
}
// If the EvalResultData item doesn't specify a particular category, we'll just propagate DkmClrValue.Category,
// If the EvalResultDataItem doesn't specify a particular category, we'll just propagate DkmClrValue.Category,
// which typically appears to be set to the default value ("Other").
var category = (dataItem.Category != DkmEvaluationResultCategory.Other) ? dataItem.Category : value.Category;
......
......@@ -25,7 +25,7 @@ public class DkmClrRuntimeInstance : DkmRuntimeInstance
internal readonly DkmClrModuleInstance[] Modules;
private readonly DkmClrModuleInstance _defaultModule;
private readonly DkmClrAppDomain _appDomain; // exactly one for now
private readonly GetMemberValueDelegate _getMemberValue;
internal readonly GetMemberValueDelegate GetMemberValue;
internal DkmClrRuntimeInstance(
Assembly[] assemblies,
......@@ -42,7 +42,7 @@ public class DkmClrRuntimeInstance : DkmRuntimeInstance
this.Modules = assemblies.Select(a => getModule(this, a)).Where(m => m != null).ToArray();
_defaultModule = getModule(this, null);
_appDomain = new DkmClrAppDomain(this);
_getMemberValue = getMemberValue;
this.GetMemberValue = getMemberValue;
}
internal DkmClrModuleInstance DefaultModule
......@@ -87,14 +87,5 @@ internal DkmClrModuleInstance FindClrModuleInstance(Guid mvid)
{
return this.Modules.FirstOrDefault(m => m.Mvid == mvid) ?? _defaultModule;
}
internal DkmClrValue GetMemberValue(DkmClrValue value, string memberName)
{
if (_getMemberValue != null)
{
return _getMemberValue(value, memberName);
}
return null;
}
}
}
......@@ -32,21 +32,25 @@ public class DkmClrValue : DkmDataContainer
IDkmClrFormatter formatter,
DkmEvaluationResultFlags evalFlags,
DkmClrValueFlags valueFlags,
bool isComObject = false)
DkmEvaluationResultCategory category = default(DkmEvaluationResultCategory),
DkmEvaluationResultAccessType access = default(DkmEvaluationResultAccessType),
ulong nativeComPointer = 0)
{
Debug.Assert(!type.GetLmrType().IsTypeVariables() || (valueFlags == DkmClrValueFlags.Synthetic));
Debug.Assert((alias == null) || evalFlags.Includes(DkmEvaluationResultFlags.HasObjectId));
// The "real" DkmClrValue will always have a value of zero for null pointers.
Debug.Assert(!type.GetLmrType().IsPointer || (value != null));
_rawValue = value;
this.RawValue = value;
this.HostObjectValue = hostObjectValue;
this.Type = type;
_formatter = formatter;
this.Alias = alias;
this.EvalFlags = evalFlags;
this.ValueFlags = valueFlags;
this.NativeComPointer = isComObject ? 1UL : 0;
this.Category = category;
this.Access = access;
this.NativeComPointer = nativeComPointer;
}
public readonly DkmEvaluationResultFlags EvalFlags;
......@@ -63,7 +67,11 @@ public class DkmClrValue : DkmDataContainer
public readonly ulong NativeComPointer;
private readonly IDkmClrFormatter _formatter;
private readonly object _rawValue;
internal readonly object RawValue;
public void Close()
{
}
public DkmClrValue Dereference(DkmInspectionContext inspectionContext)
{
......@@ -72,7 +80,7 @@ public DkmClrValue Dereference(DkmInspectionContext inspectionContext)
throw new ArgumentNullException("inspectionContext");
}
if (_rawValue == null)
if (RawValue == null)
{
throw new InvalidOperationException("Cannot dereference invalid value");
}
......@@ -82,7 +90,7 @@ public DkmClrValue Dereference(DkmInspectionContext inspectionContext)
object value;
try
{
var intPtr = Environment.Is64BitProcess ? new IntPtr((long)_rawValue) : new IntPtr((int)_rawValue);
var intPtr = Environment.Is64BitProcess ? new IntPtr((long)RawValue) : new IntPtr((int)RawValue);
value = Dereference(intPtr, elementType);
}
catch (Exception e)
......@@ -98,7 +106,9 @@ public DkmClrValue Dereference(DkmInspectionContext inspectionContext)
alias: null,
formatter: _formatter,
evalFlags: evalFlags,
valueFlags: valueFlags);
valueFlags: valueFlags,
category: DkmEvaluationResultCategory.Other,
access: DkmEvaluationResultAccessType.None);
}
public bool IsNull
......@@ -112,7 +122,7 @@ public bool IsNull
throw new InvalidOperationException();
}
var lmrType = Type.GetLmrType();
return ((_rawValue == null) && !lmrType.IsValueType) || (lmrType.IsPointer && (Convert.ToInt64(_rawValue) == 0));
return ((RawValue == null) && !lmrType.IsValueType) || (lmrType.IsPointer && (Convert.ToInt64(RawValue) == 0));
}
}
......@@ -187,7 +197,7 @@ public string EvaluateToString(DkmInspectionContext inspectionContext)
type = type.BaseType;
}
var rawValue = _rawValue;
var rawValue = RawValue;
Debug.Assert(rawValue != null || this.Type.GetLmrType().IsVoid(), "In our mock system, this should only happen for void.");
return rawValue == null ? null : rawValue.ToString();
}
......@@ -250,7 +260,7 @@ public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionCon
var field = type.GetField(name, bindingFlags);
if (field != null)
{
var fieldValue = field.GetValue(_rawValue);
var fieldValue = field.GetValue(RawValue);
exprValue = new DkmClrValue(
fieldValue,
fieldValue,
......@@ -265,7 +275,7 @@ public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionCon
var property = type.GetProperty(name, bindingFlags);
if (property != null)
{
var propertyValue = property.GetValue(_rawValue);
var propertyValue = property.GetValue(RawValue);
exprValue = new DkmClrValue(
propertyValue,
propertyValue,
......@@ -288,7 +298,7 @@ public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionCon
// we'll return error if there wasn't at least an open paren...
if ((openParenIndex >= 0) && method != null)
{
var methodValue = method.Invoke(_rawValue, new object[] { });
var methodValue = method.Invoke(RawValue, new object[] { });
exprValue = new DkmClrValue(
methodValue,
methodValue,
......@@ -343,11 +353,14 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
}
var runtime = this.Type.RuntimeInstance;
var memberValue = runtime.GetMemberValue(this, MemberName);
if (memberValue != null)
var getMemberValue = runtime.GetMemberValue;
if (getMemberValue != null)
{
return memberValue;
var memberValue = getMemberValue(this, MemberName);
if (memberValue != null)
{
return memberValue;
}
}
var declaringType = this.Type.GetLmrType();
......@@ -364,7 +377,7 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
{
// In our mock implementation, RawValue is null for null nullables,
// so we have to compute HasValue some other way.
var boolValue = _rawValue != null;
var boolValue = RawValue != null;
var boolType = runtime.GetType((TypeImpl)typeof(bool));
return new DkmClrValue(
boolValue,
......@@ -373,28 +386,34 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
alias: null,
formatter: _formatter,
evalFlags: DkmEvaluationResultFlags.None,
valueFlags: DkmClrValueFlags.None);
valueFlags: DkmClrValueFlags.None,
category: DkmEvaluationResultCategory.Property,
access: DkmEvaluationResultAccessType.Public);
}
else if (MemberName == InternalWellKnownMemberNames.NullableValue)
{
// In our mock implementation, RawValue is of type T rather than
// Nullable<T> for nullables, so we'll just return that value
// (no need to unwrap by getting "value" field).
var valueType = runtime.GetType((TypeImpl)_rawValue.GetType());
var valueType = runtime.GetType((TypeImpl)RawValue.GetType());
return new DkmClrValue(
_rawValue,
_rawValue,
RawValue,
RawValue,
type: valueType,
alias: null,
formatter: _formatter,
evalFlags: DkmEvaluationResultFlags.None,
valueFlags: DkmClrValueFlags.None);
valueFlags: DkmClrValueFlags.None,
category: DkmEvaluationResultCategory.Property,
access: DkmEvaluationResultAccessType.Public);
}
}
Type declaredType;
object value;
var evalFlags = DkmEvaluationResultFlags.None;
var category = DkmEvaluationResultCategory.Other;
var access = DkmEvaluationResultAccessType.None;
const BindingFlags bindingFlags =
BindingFlags.DeclaredOnly |
......@@ -408,13 +427,15 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
case MemberTypes.Field:
var field = declaringType.GetField(MemberName, bindingFlags);
declaredType = field.FieldType;
category = DkmEvaluationResultCategory.Data;
access = GetFieldAccess(field);
if (field.Attributes.HasFlag(System.Reflection.FieldAttributes.Literal) || field.Attributes.HasFlag(System.Reflection.FieldAttributes.InitOnly))
{
evalFlags |= DkmEvaluationResultFlags.ReadOnly;
}
try
{
value = field.GetValue(_rawValue);
value = field.GetValue(RawValue);
}
catch (System.Reflection.TargetInvocationException e)
{
......@@ -426,19 +447,23 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
alias: null,
formatter: _formatter,
evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown,
valueFlags: DkmClrValueFlags.None);
valueFlags: DkmClrValueFlags.None,
category: category,
access: access);
}
break;
case MemberTypes.Property:
var property = declaringType.GetProperty(MemberName, bindingFlags);
declaredType = property.PropertyType;
category = DkmEvaluationResultCategory.Property;
access = GetPropertyAccess(property);
if (property.GetSetMethod(nonPublic: true) == null)
{
evalFlags |= DkmEvaluationResultFlags.ReadOnly;
}
try
{
value = property.GetValue(_rawValue, bindingFlags, null, null, null);
value = property.GetValue(RawValue, bindingFlags, null, null, null);
}
catch (System.Reflection.TargetInvocationException e)
{
......@@ -450,7 +475,9 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
alias: null,
formatter: _formatter,
evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown,
valueFlags: DkmClrValueFlags.None);
valueFlags: DkmClrValueFlags.None,
category: category,
access: access);
}
break;
default:
......@@ -489,7 +516,9 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare
alias: null,
formatter: _formatter,
evalFlags: evalFlags,
valueFlags: DkmClrValueFlags.None);
valueFlags: DkmClrValueFlags.None,
category: category,
access: access);
}
public DkmClrValue GetArrayElement(int[] indices, DkmInspectionContext inspectionContext)
......@@ -499,7 +528,7 @@ public DkmClrValue GetArrayElement(int[] indices, DkmInspectionContext inspectio
throw new ArgumentNullException("inspectionContext");
}
var array = (System.Array)_rawValue;
var array = (System.Array)RawValue;
var element = array.GetValue(indices);
var type = DkmClrType.Create(this.Type.AppDomain, (TypeImpl)((element == null) ? array.GetType().GetElementType() : element.GetType()));
return new DkmClrValue(
......@@ -516,7 +545,7 @@ public ReadOnlyCollection<int> ArrayDimensions
{
get
{
var array = (Array)_rawValue;
var array = (Array)RawValue;
if (array == null)
{
return null;
......@@ -536,7 +565,7 @@ public ReadOnlyCollection<int> ArrayLowerBounds
{
get
{
var array = (Array)_rawValue;
var array = (Array)RawValue;
if (array == null)
{
return null;
......@@ -567,7 +596,7 @@ public DkmClrValue InstantiateProxyType(DkmInspectionContext inspectionContext,
BindingFlags.NonPublic |
BindingFlags.Public;
var constructor = lmrType.GetConstructors(bindingFlags).Single();
var value = constructor.Invoke(bindingFlags, null, new[] { _rawValue }, null);
var value = constructor.Invoke(bindingFlags, null, new[] { RawValue }, null);
return new DkmClrValue(
value,
value,
......@@ -688,8 +717,49 @@ private unsafe static object Dereference(IntPtr ptr, Type elementType)
}
}
public void Close()
private static DkmEvaluationResultAccessType GetFieldAccess(Microsoft.VisualStudio.Debugger.Metadata.FieldInfo field)
{
if (field.IsPrivate)
{
return DkmEvaluationResultAccessType.Private;
}
else if (field.IsFamily)
{
return DkmEvaluationResultAccessType.Protected;
}
else if (field.IsAssembly)
{
return DkmEvaluationResultAccessType.Internal;
}
else
{
return DkmEvaluationResultAccessType.Public;
}
}
private static DkmEvaluationResultAccessType GetPropertyAccess(Microsoft.VisualStudio.Debugger.Metadata.PropertyInfo property)
{
return GetMethodAccess(property.GetGetMethod(nonPublic: true));
}
private static DkmEvaluationResultAccessType GetMethodAccess(Microsoft.VisualStudio.Debugger.Metadata.MethodBase method)
{
if (method.IsPrivate)
{
return DkmEvaluationResultAccessType.Private;
}
else if (method.IsFamily)
{
return DkmEvaluationResultAccessType.Protected;
}
else if (method.IsAssembly)
{
return DkmEvaluationResultAccessType.Internal;
}
else
{
return DkmEvaluationResultAccessType.Public;
}
}
}
}
......@@ -10,10 +10,34 @@ namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public abstract class DkmEvaluationResult : DkmDataContainer
{
public string FullName { get; internal set; }
public string Name { get; internal set; }
public DkmInspectionContext InspectionContext { get; internal set; }
public DkmStackWalkFrame StackFrame { get; internal set; }
public readonly DkmInspectionContext InspectionContext;
public readonly DkmStackWalkFrame StackFrame;
public readonly string Name;
public readonly string FullName;
public readonly DkmEvaluationResultFlags Flags;
public readonly string Type;
internal DkmEvaluationResult(
DkmInspectionContext InspectionContext,
DkmStackWalkFrame StackFrame,
string Name,
string FullName,
DkmEvaluationResultFlags Flags,
string Type,
DkmDataItem DataItem)
{
this.InspectionContext = InspectionContext;
this.StackFrame = StackFrame;
this.Name = Name;
this.FullName = FullName;
this.Flags = Flags;
this.Type = Type;
if (DataItem != null)
{
this.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
}
}
public virtual void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine)
{
......
......@@ -9,28 +9,41 @@ namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public class DkmFailedEvaluationResult : DkmEvaluationResult
{
public string ErrorMessage { get; private set; }
public DkmEvaluationResultFlags Flags { get; private set; }
public string Type { get; private set; }
public readonly string ErrorMessage;
public static DkmFailedEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, string ErrorMessage, DkmEvaluationResultFlags Flags, string Type, DkmDataItem DataItem)
private DkmFailedEvaluationResult(
DkmInspectionContext inspectionContext,
DkmStackWalkFrame stackFrame,
string name,
string fullName,
string errorMessage,
DkmEvaluationResultFlags flags,
string type,
DkmDataItem dataItem) :
base(inspectionContext, stackFrame, name, fullName, flags, type, dataItem)
{
DkmFailedEvaluationResult result = new DkmFailedEvaluationResult
{
InspectionContext = InspectionContext,
Name = Name,
FullName = FullName,
ErrorMessage = ErrorMessage,
Flags = Flags,
Type = Type
};
if (DataItem != null)
{
result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
}
this.ErrorMessage = errorMessage;
}
return result;
public static DkmFailedEvaluationResult Create(
DkmInspectionContext InspectionContext,
DkmStackWalkFrame StackFrame,
string Name,
string FullName,
string ErrorMessage,
DkmEvaluationResultFlags Flags,
string Type,
DkmDataItem DataItem)
{
return new DkmFailedEvaluationResult(
InspectionContext,
StackFrame,
Name,
FullName,
ErrorMessage,
Flags,
Type,
DataItem);
}
}
}
......@@ -9,28 +9,45 @@ namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public class DkmIntermediateEvaluationResult : DkmEvaluationResult
{
public string Expression { get; private set; }
public DkmLanguage IntermediateLanguage { get; private set; }
public DkmRuntimeInstance TargetRuntime { get; private set; }
public static DkmIntermediateEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, string Expression, DkmLanguage IntermediateLanguage, DkmRuntimeInstance TargetRuntime, DkmDataItem DataItem)
{
DkmIntermediateEvaluationResult result = new DkmIntermediateEvaluationResult
{
InspectionContext = InspectionContext,
Name = Name,
FullName = FullName,
Expression = Expression,
IntermediateLanguage = IntermediateLanguage,
TargetRuntime = TargetRuntime
};
public readonly string Expression;
public readonly DkmLanguage IntermediateLanguage;
public readonly DkmRuntimeInstance TargetRuntime;
if (DataItem != null)
{
result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
}
private DkmIntermediateEvaluationResult(
DkmInspectionContext inspectionContext,
DkmStackWalkFrame stackFrame,
string name,
string fullName,
string expression,
DkmLanguage intermediateLanguage,
DkmRuntimeInstance targetRuntime,
DkmDataItem dataItem) :
base(inspectionContext, stackFrame, name, fullName, DkmEvaluationResultFlags.None, null, dataItem)
{
this.Expression = expression;
this.IntermediateLanguage = intermediateLanguage;
this.TargetRuntime = targetRuntime;
}
return result;
public static DkmIntermediateEvaluationResult Create(
DkmInspectionContext InspectionContext,
DkmStackWalkFrame StackFrame,
string Name,
string FullName,
string Expression,
DkmLanguage IntermediateLanguage,
DkmRuntimeInstance TargetRuntime,
DkmDataItem DataItem)
{
return new DkmIntermediateEvaluationResult(
InspectionContext,
StackFrame,
Name,
FullName,
Expression,
IntermediateLanguage,
TargetRuntime,
DataItem);
}
}
}
......@@ -27,9 +27,17 @@ public enum DkmDataCreationDisposition
namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public enum DkmEvaluationResultAccessType { }
public enum DkmEvaluationResultStorageType { }
public enum DkmEvaluationResultTypeModifierFlags { }
public enum DkmEvaluationResultAccessType
{
None = 0,
Public,
Private,
Protected,
Internal,
}
public enum DkmEvaluationResultStorageType { None = 0 }
public enum DkmEvaluationResultTypeModifierFlags { None = 0 }
public class DkmDataAddress { }
}
......
......@@ -10,34 +10,77 @@ namespace Microsoft.VisualStudio.Debugger.Evaluation
{
public class DkmSuccessEvaluationResult : DkmEvaluationResult
{
public DkmEvaluationResultCategory Category { get; private set; }
public string EditableValue { get; private set; }
public DkmEvaluationResultFlags Flags { get; private set; }
public string Type { get; private set; }
public string Value { get; private set; }
public ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers { get; private set; }
public readonly string Value;
public readonly string EditableValue;
public readonly DkmEvaluationResultCategory Category;
public readonly DkmEvaluationResultAccessType Access;
public readonly DkmEvaluationResultStorageType StorageType;
public readonly DkmEvaluationResultTypeModifierFlags TypeModifierFlags;
public readonly ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers;
public static DkmSuccessEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, DkmEvaluationResultFlags Flags, string Value, string EditableValue, string Type, DkmEvaluationResultCategory Category, DkmEvaluationResultAccessType Access, DkmEvaluationResultStorageType StorageType, DkmEvaluationResultTypeModifierFlags TypeModifierFlags, DkmDataAddress Address, ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers, ReadOnlyCollection<DkmModuleInstance> ExternalModules, DkmDataItem DataItem)
private DkmSuccessEvaluationResult(
DkmInspectionContext inspectionContext,
DkmStackWalkFrame stackFrame,
string name,
string fullName,
DkmEvaluationResultFlags flags,
string value,
string editableValue,
string type,
DkmEvaluationResultCategory category,
DkmEvaluationResultAccessType access,
DkmEvaluationResultStorageType storageType,
DkmEvaluationResultTypeModifierFlags typeModifierFlags,
DkmDataAddress address,
ReadOnlyCollection<DkmCustomUIVisualizerInfo> customUIVisualizers,
ReadOnlyCollection<DkmModuleInstance> externalModules,
DkmDataItem dataItem) :
base(inspectionContext, stackFrame, name, fullName, flags, type, dataItem)
{
DkmSuccessEvaluationResult result = new DkmSuccessEvaluationResult
{
InspectionContext = InspectionContext,
Name = Name,
FullName = FullName,
Flags = Flags,
Value = Value,
Type = Type,
Category = Category,
EditableValue = EditableValue,
CustomUIVisualizers = CustomUIVisualizers
};
if (DataItem != null)
{
result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
}
this.Value = value;
this.EditableValue = editableValue;
this.Category = category;
this.Access = access;
this.StorageType = storageType;
this.TypeModifierFlags = typeModifierFlags;
this.CustomUIVisualizers = customUIVisualizers;
}
return result;
public static DkmSuccessEvaluationResult Create(
DkmInspectionContext InspectionContext,
DkmStackWalkFrame StackFrame,
string Name,
string FullName,
DkmEvaluationResultFlags Flags,
string Value,
string EditableValue,
string Type,
DkmEvaluationResultCategory Category,
DkmEvaluationResultAccessType Access,
DkmEvaluationResultStorageType StorageType,
DkmEvaluationResultTypeModifierFlags TypeModifierFlags,
DkmDataAddress Address,
ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers,
ReadOnlyCollection<DkmModuleInstance> ExternalModules,
DkmDataItem DataItem)
{
return new DkmSuccessEvaluationResult(
InspectionContext,
StackFrame,
Name,
FullName,
Flags,
Value,
EditableValue,
Type,
Category,
Access,
StorageType,
TypeModifierFlags,
Address,
CustomUIVisualizers,
ExternalModules,
DataItem);
}
}
}
......@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.ComponentInterfaces;
......@@ -55,7 +56,7 @@ internal ResultProviderTestBase(ResultProvider resultProvider, DkmInspectionCont
string alias = null,
DkmEvaluationResultFlags evalFlags = DkmEvaluationResultFlags.None,
DkmClrValueFlags valueFlags = DkmClrValueFlags.None,
bool isComObject = false)
ulong nativeComPointer = 0)
{
return new DkmClrValue(
value,
......@@ -65,7 +66,7 @@ internal ResultProviderTestBase(ResultProvider resultProvider, DkmInspectionCont
_formatter,
evalFlags,
valueFlags,
isComObject);
nativeComPointer: nativeComPointer);
}
internal DkmClrValue CreateErrorValue(
......@@ -237,13 +238,17 @@ internal DkmEvaluationResult[] GetItems(DkmEvaluationResultEnumContext enumConte
return getItemsResult.Items;
}
private const DkmEvaluationResultCategory UnspecifiedCategory = (DkmEvaluationResultCategory)(-1);
private const DkmEvaluationResultAccessType UnspecifiedAccessType = (DkmEvaluationResultAccessType)(-1);
internal static DkmEvaluationResult EvalResult(
string name,
string value,
string type,
string fullName,
DkmEvaluationResultFlags flags = DkmEvaluationResultFlags.None,
DkmEvaluationResultCategory category = DkmEvaluationResultCategory.Other,
DkmEvaluationResultCategory category = UnspecifiedCategory,
DkmEvaluationResultAccessType access = UnspecifiedAccessType,
string editableValue = null,
DkmCustomUIVisualizerInfo[] customUIVisualizerInfo = null)
{
......@@ -257,7 +262,7 @@ internal DkmEvaluationResult[] GetItems(DkmEvaluationResultEnumContext enumConte
editableValue,
type,
category,
default(DkmEvaluationResultAccessType),
access,
default(DkmEvaluationResultStorageType),
default(DkmEvaluationResultTypeModifierFlags),
null,
......@@ -314,36 +319,83 @@ internal static void Verify(IReadOnlyList<DkmEvaluationResult> actual, params Dk
}
catch
{
foreach (DkmSuccessEvaluationResult result in actual)
foreach (var result in actual)
{
var optionalArgumentsTemplate = string.Empty;
if (result.Flags != DkmEvaluationResultFlags.None)
{
optionalArgumentsTemplate += ", {4}";
}
if (result.Category != DkmEvaluationResultCategory.Other)
{
optionalArgumentsTemplate += ", {5}";
}
if (result.EditableValue != null)
{
optionalArgumentsTemplate += ", editableValue: {6}";
}
var evalResultTemplate = "EvalResult({0}, {1}, {2}, {3}" + optionalArgumentsTemplate + "),";
var resultValue = (result.Value == null) ? "null" : Quote(Escape(result.Value));
Console.WriteLine(evalResultTemplate,
Quote(result.Name),
resultValue, Quote(result.Type),
(result.FullName != null) ? Quote(Escape(result.FullName)) : "null",
FormatEnumValue(result.Flags),
FormatEnumValue(result.Category),
Quote(result.EditableValue));
Console.WriteLine("{0}, ", ToString(result));
}
throw;
}
}
private static string ToString(DkmEvaluationResult result)
{
var success = result as DkmSuccessEvaluationResult;
return (success != null) ? ToString(success) : ToString((DkmFailedEvaluationResult)result);
}
private static string ToString(DkmSuccessEvaluationResult result)
{
var pooledBuilder = PooledStringBuilder.GetInstance();
var builder = pooledBuilder.Builder;
builder.Append("EvalResult(");
builder.Append(Quote(result.Name));
builder.Append(", ");
builder.Append((result.Value == null) ? "null" : Quote(Escape(result.Value)));
builder.Append(", ");
builder.Append(Quote(result.Type));
builder.Append(", ");
builder.Append((result.FullName != null) ? Quote(Escape(result.FullName)) : "null");
if (result.Flags != DkmEvaluationResultFlags.None)
{
builder.Append(", ");
builder.Append(FormatEnumValue(result.Flags));
}
if (result.Category != DkmEvaluationResultCategory.Other)
{
builder.Append(", ");
builder.Append(FormatEnumValue(result.Category));
}
if (result.Access != DkmEvaluationResultAccessType.None)
{
builder.Append(", ");
builder.Append(FormatEnumValue(result.Access));
}
if (result.EditableValue != null)
{
builder.Append(", ");
builder.Append(Quote(result.EditableValue));
}
builder.Append(")");
return pooledBuilder.ToStringAndFree();
}
private static string ToString(DkmFailedEvaluationResult result)
{
var pooledBuilder = PooledStringBuilder.GetInstance();
var builder = pooledBuilder.Builder;
builder.Append("EvalFailedResult(");
builder.Append(Quote(result.Name));
builder.Append(", ");
builder.Append(Quote(result.ErrorMessage));
if (result.Type != null)
{
builder.Append(", ");
builder.Append(Quote(result.Type));
}
if (result.FullName != null)
{
builder.Append(", ");
builder.Append(Quote(Escape(result.FullName)));
}
if (result.Flags != DkmEvaluationResultFlags.None)
{
builder.Append(", ");
builder.Append(FormatEnumValue(result.Flags));
}
builder.Append(")");
return pooledBuilder.ToStringAndFree();
}
private static string Escape(string str)
{
return str.Replace("\"", "\\\"");
......@@ -373,9 +425,15 @@ internal static void Verify(DkmEvaluationResult actual, DkmEvaluationResult expe
Assert.Equal(expectedSuccess.Value, actualSuccess.Value);
Assert.Equal(expectedSuccess.Type, actualSuccess.Type);
Assert.Equal(expectedSuccess.Flags, actualSuccess.Flags);
Assert.Equal(expectedSuccess.Category, actualSuccess.Category);
if (expectedSuccess.Category != UnspecifiedCategory)
{
Assert.Equal(expectedSuccess.Category, actualSuccess.Category);
}
if (expectedSuccess.Access != UnspecifiedAccessType)
{
Assert.Equal(expectedSuccess.Access, actualSuccess.Access);
}
Assert.Equal(expectedSuccess.EditableValue, actualSuccess.EditableValue);
// Verify the DebuggerVisualizerAttribute
Assert.True(
(expectedSuccess.CustomUIVisualizers == actualSuccess.CustomUIVisualizers) ||
(expectedSuccess.CustomUIVisualizers != null && actualSuccess.CustomUIVisualizers != null &&
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册