diff --git a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ExpansionTests.cs b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ExpansionTests.cs index ec5586d95cb0f2d089b970f5f0d184f8a83fa6dd..cab96d4c95d2e80d02aa31b244dc7de77c0c4a42 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ExpansionTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ExpansionTests.cs @@ -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 } /// - /// Do not copy state from parent for base or derived items. + /// Do not copy state from parent. /// [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)] diff --git a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/NativeViewTests.cs b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/NativeViewTests.cs index 42cffc0a00756087567ec97ea30a35df6e6641c9..7958f81bcc54b167c8284a76ad202f8b4c81530e 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/NativeViewTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/NativeViewTests.cs @@ -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 { diff --git a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ResultsViewTests.cs b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ResultsViewTests.cs index a6e88b672b8f19d0ffe0ddb821b001bfe0d58215..13475282863ed529e55a6011d98891e399f3078d 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ResultsViewTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/ResultsViewTests.cs @@ -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"); diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/MemberExpansion.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/MemberExpansion.cs index 0641224f1492083f7600de8e8a83a549679608c4..27435fbcca259af97dfb30db0226940d7b8e134b 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/MemberExpansion.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/MemberExpansion.cs @@ -110,7 +110,7 @@ internal sealed class MemberExpansion : Expansion if (value.NativeComPointer != 0) { - expansions.Add(new NativeViewExpansion()); + expansions.Add(NativeViewExpansion.Instance); } if (nonPublicInstanceExpansion != null) diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/NativeViewExpansion.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/NativeViewExpansion.cs index 0b4eb18e132460bea7dc16c0a65e1af617dfe5be..e1c11f424f821777fe51dd144914fd266282ad3b 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/NativeViewExpansion.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/NativeViewExpansion.cs @@ -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 rows, diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/TypeVariablesExpansion.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/TypeVariablesExpansion.cs index 9b45087fc33cb961d3a87db74b95d4653e03e683..689f7d01295689bcec63cc495987d35a3f17f866 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/TypeVariablesExpansion.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Expansion/TypeVariablesExpansion.cs @@ -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, diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/EvalResultDataItem.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/EvalResultDataItem.cs index 61dec591d2e4ebcdae8017b23087ae474476975f..254e86d4ba4d8f6bb439f2676b3b1412a8771df5 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/EvalResultDataItem.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/EvalResultDataItem.cs @@ -19,7 +19,7 @@ internal enum ExpansionKind RawView, ResultsView, StaticMembers, - TypeVariables + TypeVariable } /// diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/ResultProvider.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/ResultProvider.cs index df2b25e8ee75c05d0a2b63b5cc9b361c7d406694..439d3ac4c5b2bd8202366b1c0532b87e5229a9b8 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/ResultProvider.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/ResultProvider.cs @@ -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 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; diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs index 2e98b073bde892f01b4eeea59cff54b87f8161b3..a36d9603c79cb0b9697747c05823e8024a047745 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs @@ -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; - } } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs index de1c3c8f37908b2b0b3ad1fbeab4fc848d299c7e..521dc3c60c09699b7536882c5179f7eb1130839c 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs @@ -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 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 ArrayDimensions { get { - var array = (Array)_rawValue; + var array = (Array)RawValue; if (array == null) { return null; @@ -536,7 +565,7 @@ public ReadOnlyCollection 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; + } } } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmEvaluationResult.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmEvaluationResult.cs index 2770741466fa64498bfaa7c30d3874acb2c55555..30771940ede7d83e20687ca2993a9dda156904fd 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmEvaluationResult.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmEvaluationResult.cs @@ -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 completionRoutine) { diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmFailedEvaluationResult.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmFailedEvaluationResult.cs index 4369d7e3b96e63de97f05143723b5899e4cb5676..7ee91e80aaaff3f3f54362bb8ef415c18fa58c48 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmFailedEvaluationResult.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmFailedEvaluationResult.cs @@ -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); } } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmIntermediateEvaluationResult.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmIntermediateEvaluationResult.cs index b106ac78a18bf9b425e3e69b9f3030869f6b7918..9f39f390817743b205e7b68effbc53cbe02caa90 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmIntermediateEvaluationResult.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmIntermediateEvaluationResult.cs @@ -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); } } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmMisc.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmMisc.cs index 77e7ab7db9e41aeb9082f5bd019a326ab9947e64..e0c6a7d2f52d918e8a3d3139e3625ae61d3ced56 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmMisc.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmMisc.cs @@ -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 { } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmSuccessEvaluationResult.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmSuccessEvaluationResult.cs index 97b8ec3cff46dba267c909fedbed013ddb99304a..6a7016d6cadfa67bdbaa601d3ecca6082dcefd82 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmSuccessEvaluationResult.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmSuccessEvaluationResult.cs @@ -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 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 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 CustomUIVisualizers, ReadOnlyCollection 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 customUIVisualizers, + ReadOnlyCollection 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 CustomUIVisualizers, + ReadOnlyCollection ExternalModules, + DkmDataItem DataItem) + { + return new DkmSuccessEvaluationResult( + InspectionContext, + StackFrame, + Name, + FullName, + Flags, + Value, + EditableValue, + Type, + Category, + Access, + StorageType, + TypeModifierFlags, + Address, + CustomUIVisualizers, + ExternalModules, + DataItem); } } } diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs index af8ecf0c1b6ac8963a400fb8e0d07c5694a22edf..4558d3ef4bfc86311cb2658aa082158f2c10f10d 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs @@ -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 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 &&