void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { if (formatSpecifiers == null) { formatSpecifiers = Formatter.NoFormatSpecifiers; } if (resultFullName != null) { ReadOnlyCollection<string> otherSpecifiers; resultFullName = FullNameProvider.GetClrExpressionAndFormatSpecifiers(inspectionContext, resultFullName, out otherSpecifiers); foreach (var formatSpecifier in otherSpecifiers) { formatSpecifiers = Formatter.AddFormatSpecifier(formatSpecifiers, formatSpecifier); } } var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e))); wl.ContinueWith( () => GetRootResultAndContinue( value, wl, declaredType, declaredTypeInfo, inspectionContext, resultName, resultFullName, formatSpecifiers, result => wl.ContinueWith(() => completionRoutine(new DkmEvaluationAsyncResult(result))))); }
/// <summary> /// Generate a Results Only row if the value is a synthesized /// value declared as IEnumerable or IEnumerable<T>. /// </summary> internal static EvalResultDataItem CreateResultsOnlyRowIfSynthesizedEnumerable( DkmInspectionContext inspectionContext, string name, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmClrValue value, Formatter formatter) { if ((value.ValueFlags & DkmClrValueFlags.Synthetic) == 0) { return null; } // Must be declared as IEnumerable or IEnumerable<T>, not a derived type. var enumerableType = GetEnumerableType(value, declaredType, requireExactInterface: true); if (enumerableType == null) { return null; } var expansion = CreateExpansion(inspectionContext, value, enumerableType, formatter); if (expansion == null) { return null; } return expansion.CreateResultsViewRow( inspectionContext, name, new TypeAndCustomInfo(declaredType.GetLmrType(), declaredTypeInfo), value, includeResultsFormatSpecifier: false, formatter: formatter); }
string IDkmClrFullNameProvider.GetClrTypeName(DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo) { Debug.Assert(inspectionContext != null); bool sawInvalidIdentifier; var name = GetTypeName(new TypeAndCustomInfo(clrType, customTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); return sawInvalidIdentifier ? null : name; }
internal DkmClrValue( object value, object hostObjectValue, DkmClrType type, string alias, DkmEvaluationResultFlags evalFlags, DkmClrValueFlags valueFlags, DkmEvaluationResultCategory category = default(DkmEvaluationResultCategory), DkmEvaluationResultAccessType access = default(DkmEvaluationResultAccessType), ulong nativeComPointer = 0) { Debug.Assert((type == null) || !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 == null) || !type.GetLmrType().IsPointer || (value != null)); this.RawValue = value; this.HostObjectValue = hostObjectValue; this.Type = type; this.Alias = alias; this.EvalFlags = evalFlags; this.ValueFlags = valueFlags; this.Category = category; this.Access = access; this.NativeComPointer = nativeComPointer; }
public void MultipleExpansions() { var expression = "o"; dynamic o = new ExpandoObject(); o.Answer = 42; var type = new DkmClrType((TypeImpl)o.GetType()); var value = CreateDkmClrValue((object)o, type); // Dynamic View should appear after all other expansions. var result = FormatResult(expression, value); Verify(result, EvalResult(expression, "{System.Dynamic.ExpandoObject}", "System.Dynamic.ExpandoObject", expression, DkmEvaluationResultFlags.Expandable)); Verify(GetChildren(result), EvalResult("Class", "{System.Dynamic.ExpandoClass}", "System.Dynamic.ExpandoClass", "o.Class", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.Internal), EvalResult("LockObject", "{object}", "object", "o.LockObject", DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Internal), EvalResult("System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>.Count", "1", "int", "((System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>)o).Count", DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.Private), EvalResult("System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>.IsReadOnly", "false", "bool", "((System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>)o).IsReadOnly", DkmEvaluationResultFlags.Boolean | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.Private), EvalResult("System.Collections.Generic.IDictionary<string, object>.Keys", "Count = 1", "System.Collections.Generic.ICollection<string> {System.Dynamic.ExpandoObject.KeyCollection}", "((System.Collections.Generic.IDictionary<string, object>)o).Keys", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.Private), EvalResult("System.Collections.Generic.IDictionary<string, object>.Values", "Count = 1", "System.Collections.Generic.ICollection<object> {System.Dynamic.ExpandoObject.ValueCollection}", "((System.Collections.Generic.IDictionary<string, object>)o).Values", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Property, DkmEvaluationResultAccessType.Private), EvalResult("_count", "1", "int", "o._count", category: DkmEvaluationResultCategory.Data, access: DkmEvaluationResultAccessType.Private), EvalResult("_data", "{System.Dynamic.ExpandoObject.ExpandoData}", "System.Dynamic.ExpandoObject.ExpandoData", "o._data", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Private), EvalResult("_propertyChanged", "null", "System.ComponentModel.PropertyChangedEventHandler", "o._propertyChanged", category: DkmEvaluationResultCategory.Data, access: DkmEvaluationResultAccessType.Private), EvalResult(Resources.StaticMembers, null, "", "System.Dynamic.ExpandoObject", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class), EvalResult(Resources.DynamicView, Resources.DynamicViewValueWarning, "", "o, dynamic", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Method)); }
internal DkmClrType MakeGenericType(params DkmClrType[] genericArguments) { var type = new DkmClrType( _module, _appDomain, _lmrType.MakeGenericType(genericArguments.Select(t => t._lmrType).ToArray())); type._lazyGenericArguments = new ReadOnlyCollection<DkmClrType>(genericArguments); return type; }
string IDkmClrFullNameProvider.GetClrCastExpression(DkmInspectionContext inspectionContext, string argument, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, bool parenthesizeArgument, bool parenthesizeEntireExpression) { bool sawInvalidIdentifier; var name = GetTypeName(new TypeAndCustomInfo(type, customTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); if (sawInvalidIdentifier) { return null; } return GetCastExpression(argument, name, parenthesizeArgument, parenthesizeEntireExpression); }
internal DkmEvaluationResult GetResult(DkmClrValue value, DkmClrType declaredType, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName) { // TODO: Use full name try { return GetRootResult(value, declaredType, resultName); } catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e)) { throw ExceptionUtilities.Unreachable; } }
public static string GetTypeName(this System.Type type, DkmClrCustomTypeInfo typeInfo, bool escapeKeywordIdentifiers = false, DkmInspectionContext inspectionContext = null) { var formatter = new CSharpFormatter(); var clrType = new DkmClrType((TypeImpl)type); if (inspectionContext == null) { var inspectionSession = new DkmInspectionSession(ImmutableArray.Create<IDkmClrFormatter>(formatter), ImmutableArray.Create<IDkmClrResultProvider>(new CSharpResultProvider())); inspectionContext = new DkmInspectionContext(inspectionSession, DkmEvaluationFlags.None, radix: 10, runtimeInstance: null); } return escapeKeywordIdentifiers ? ((IDkmClrFullNameProvider)formatter).GetClrTypeName(inspectionContext, clrType, typeInfo) : inspectionContext.GetTypeName(clrType, typeInfo, Formatter.NoFormatSpecifiers); }
void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { // TODO: Use full name var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e))); GetRootResultAndContinue( value, wl, declaredType, declaredTypeInfo, inspectionContext, resultName, result => wl.ContinueWith(() => completionRoutine(new DkmEvaluationAsyncResult(result)))); wl.Execute(); }
internal static EvalResult CreateResultsOnlyRow( DkmInspectionContext inspectionContext, string name, string fullName, ReadOnlyCollection<string> formatSpecifiers, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmClrValue value, ResultProvider resultProvider) { string errorMessage; if (value.IsError()) { errorMessage = (string)value.HostObjectValue; } else if (value.HasExceptionThrown()) { errorMessage = value.GetExceptionMessage(inspectionContext, name); } else { var enumerableType = GetEnumerableType(value); if (enumerableType != null) { var expansion = CreateExpansion(inspectionContext, value, enumerableType, resultProvider); if (expansion != null) { return expansion.CreateResultsViewRow( inspectionContext, name, fullName, formatSpecifiers, new TypeAndCustomInfo(declaredType, declaredTypeInfo), value, includeResultsFormatSpecifier: true, fullNameProvider: resultProvider.FullNameProvider); } errorMessage = Resources.ResultsViewNoSystemCore; } else { errorMessage = Resources.ResultsViewNotEnumerable; } } Debug.Assert(errorMessage != null); return new EvalResult(name, errorMessage, inspectionContext); }
internal static DkmEvaluationResult CreateResultsOnly( string name, DkmClrType declaredType, DkmClrValue value, EvalResultDataItem parent, Formatter formatter) { string errorMessage; if (value.IsError()) { errorMessage = (string)value.HostObjectValue; } else if (value.HasExceptionThrown(parent)) { errorMessage = value.GetExceptionMessage(name, formatter); } else { var enumerableType = GetEnumerableType(value); if (enumerableType != null) { var expansion = CreateExpansion(value, enumerableType, formatter); if (expansion != null) { return expansion.CreateEvaluationResult(name, parent, formatter); } errorMessage = Resources.ResultsViewNoSystemCore; } else { errorMessage = Resources.ResultsViewNotEnumerable; } } Debug.Assert(errorMessage != null); return DkmFailedEvaluationResult.Create( InspectionContext: value.InspectionContext, StackFrame: value.StackFrame, Name: name, FullName: null, ErrorMessage: errorMessage, Flags: DkmEvaluationResultFlags.None, Type: null, DataItem: null); }
internal DkmClrType GetType(string typeName, params System.Type[] typeArguments) { foreach (var module in this.Modules) { var assembly = module.Assembly; var type = assembly.GetType(typeName); if (type != null) { var result = new DkmClrType(module, _appDomain, (TypeImpl)type); if (typeArguments.Length > 0) { result = result.MakeGenericType(typeArguments.Select(this.GetType).ToArray()); } return result; } } return null; }
public void ExceptionTypeMember() { var expression = "o"; dynamic o = new ExpandoObject(); var exception = new NotImplementedException(); o.Member = exception; var type = new DkmClrType((TypeImpl)o.GetType()); var value = CreateDkmClrValue((object)o, type); var result = FormatResult(expression, value); Verify(result, EvalResult(expression, "{System.Dynamic.ExpandoObject}", "System.Dynamic.ExpandoObject", expression, DkmEvaluationResultFlags.Expandable)); var dynamicView = GetChildren(result).Last(); Verify(dynamicView, EvalResult(Resources.DynamicView, Resources.DynamicViewValueWarning, "", "o, dynamic", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly)); Verify(GetChildren(dynamicView), EvalResult("Member", $"{{{exception.ToString()}}}", "System.NotImplementedException", "new Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView(o).Items[0]", DkmEvaluationResultFlags.ReadOnly)); }
/// <summary> /// This method is called by the debug engine to populate the text representing the type of /// a result. /// </summary> /// <param name="inspectionContext">Context of the evaluation. This contains options/flags /// to be used during compilation. It also contains the InspectionSession. The inspection /// session is the object that provides lifetime management for our objects. When the user /// steps or continues the process, the debug engine will dispose of the inspection session</param> /// <param name="clrType">This is the raw type we want to format</param> /// <param name="customTypeInfo">If Expression Compiler passed any additional information /// about the type that doesn't exist in metadata, this parameter contais that information.</param> /// <param name="formatSpecifiers">A list of custom format specifiers that the debugger did /// not understand. If you want special format specifiers for your language, handle them /// here. The formatter should ignore any format specifiers it does not understand.</param> /// <returns>The text of the type name to display</returns> string IDkmClrFormatter.GetTypeName( DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo, ReadOnlyCollection<string> formatSpecifiers) { // Get the LMR type for the DkmClrType. LMR Types (Microsoft.VisualStudio.Debugger.Metadata.Type) // are similar to System.Type, but represent types that live in the process being debugged. Type lmrType = clrType.GetLmrType(); IrisType irisType = Utility.GetIrisTypeForLmrType(lmrType); if (irisType == IrisType.Invalid) { // We don't know about this type. Delegate to the C# Formatter to format the // type name. return inspectionContext.GetTypeName(clrType, customTypeInfo, formatSpecifiers); } return irisType.ToString(); }
public void SpecialTypes() { var objectType = new DkmClrType((TypeImpl)typeof(object)); DkmClrValue value; // int value = CreateDkmClrValue(value: 1, type: typeof(int), alias: "$1", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("i", value, objectType), EvalResult("i", "1 {$1}", "object {int}", "i", DkmEvaluationResultFlags.HasObjectId)); // char value = CreateDkmClrValue(value: 'c', type: typeof(char), alias: "$2", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("c", value, objectType), EvalResult("c", "99 'c' {$2}", "object {char}", "c", DkmEvaluationResultFlags.HasObjectId, editableValue: "'c'")); // char (hex) value = CreateDkmClrValue(value: 'c', type: typeof(char), alias: "$3", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("c", value, objectType, inspectionContext: CreateDkmInspectionContext(radix: 16)), EvalResult("c", "0x0063 'c' {$3}", "object {char}", "c", DkmEvaluationResultFlags.HasObjectId, editableValue: "'c'")); // enum value = CreateDkmClrValue(value: DkmEvaluationResultFlags.HasObjectId, type: typeof(DkmEvaluationResultFlags), alias: "$Four", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("e", value, objectType), EvalResult("e", "HasObjectId {$Four}", "object {Microsoft.VisualStudio.Debugger.Evaluation.DkmEvaluationResultFlags}", "e", DkmEvaluationResultFlags.HasObjectId, editableValue: "Microsoft.VisualStudio.Debugger.Evaluation.DkmEvaluationResultFlags.HasObjectId")); // string value = CreateDkmClrValue(value: "str", type: typeof(string), alias: "$5", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("s", value), EvalResult("s", "\"str\" {$5}", "string", "s", DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.HasObjectId, editableValue: "\"str\"")); // decimal value = CreateDkmClrValue(value: 6m, type: typeof(decimal), alias: "$6", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("d", value, objectType), EvalResult("d", "6 {$6}", "object {decimal}", "d", DkmEvaluationResultFlags.HasObjectId, editableValue: "6M")); // array value = CreateDkmClrValue(value: new int[] { 1, 2 }, type: typeof(int[]), alias: "$7", evalFlags: DkmEvaluationResultFlags.HasObjectId); Verify( FormatResult("a", value, objectType), EvalResult("a", "{int[2]} {$7}", "object {int[]}", "a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.HasObjectId)); }
public void MultipleMembers() { var expression = "o"; dynamic o = new ExpandoObject(); o.Philosophers = new object[] { "Pythagoras", "Lucretius", "Zeno" }; o.WhatsForDinner = "Crab Cakes"; o.NumForks = 2; var type = new DkmClrType((TypeImpl)o.GetType()); var value = CreateDkmClrValue((object)o, type); var result = FormatResult(expression, value); Verify(result, EvalResult(expression, "{System.Dynamic.ExpandoObject}", "System.Dynamic.ExpandoObject", expression, DkmEvaluationResultFlags.Expandable)); var dynamicView = GetChildren(result).Last(); Verify(dynamicView, EvalResult(Resources.DynamicView, Resources.DynamicViewValueWarning, "", "o, dynamic", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly)); Verify(GetChildren(dynamicView), EvalResult("NumForks", "2", "System.Int32", "new Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView(o).Items[0]", DkmEvaluationResultFlags.ReadOnly), EvalResult("Philosophers", "{object[3]}", "System.Object[]", "new Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView(o).Items[1]", DkmEvaluationResultFlags.ReadOnly), EvalResult("WhatsForDinner", "\"Crab Cakes\"", "System.String", "new Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView(o).Items[2]", DkmEvaluationResultFlags.ReadOnly)); }
internal DkmClrValue( object value, object hostObjectValue, DkmClrType type, string alias, IDkmClrFormatter formatter, DkmEvaluationResultFlags evalFlags, DkmClrValueFlags valueFlags, DkmInspectionContext inspectionContext) { 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.HostObjectValue = hostObjectValue; this.Type = type; _formatter = formatter; this.Alias = alias; this.EvalFlags = evalFlags; this.ValueFlags = valueFlags; this.InspectionContext = inspectionContext ?? new DkmInspectionContext(formatter, DkmEvaluationFlags.None, 10); }
/// <returns> /// The qualified name (i.e. including containing types and namespaces) of a named, pointer, /// or array type followed by the qualified name of the actual runtime type, if provided. /// </returns> private static string GetTypeName(DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, ExpansionKind kind) { var declaredLmrType = declaredType.GetLmrType(); var runtimeType = value.Type; var runtimeLmrType = runtimeType.GetLmrType(); var declaredTypeName = inspectionContext.GetTypeName(declaredType, declaredTypeInfo, Formatter.NoFormatSpecifiers); var runtimeTypeName = inspectionContext.GetTypeName(runtimeType, CustomTypeInfo: null, FormatSpecifiers: Formatter.NoFormatSpecifiers); var includeRuntimeTypeName = !string.Equals(declaredTypeName, runtimeTypeName, StringComparison.OrdinalIgnoreCase) && // Names will reflect "dynamic", types will not. !declaredLmrType.IsPointer && (kind != ExpansionKind.PointerDereference) && (!declaredLmrType.IsNullable() || value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown)); return includeRuntimeTypeName ? string.Format("{0} {{{1}}}", declaredTypeName, runtimeTypeName) : declaredTypeName; }
public DkmClrValue Dereference(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } if (RawValue == null) { throw new InvalidOperationException("Cannot dereference invalid value"); } var elementType = this.Type.GetLmrType().GetElementType(); var evalFlags = DkmEvaluationResultFlags.None; var valueFlags = DkmClrValueFlags.None; object value; try { var intPtr = Environment.Is64BitProcess ? new IntPtr((long)RawValue) : new IntPtr((int)RawValue); value = Dereference(intPtr, elementType); } catch (Exception e) { value = e; evalFlags |= DkmEvaluationResultFlags.ExceptionThrown; } var valueType = new DkmClrType(this.Type.RuntimeInstance, (value == null || elementType.IsPointer) ? elementType : (TypeImpl)value.GetType()); return new DkmClrValue( value, value, valueType, alias: null, evalFlags: evalFlags, valueFlags: valueFlags, category: DkmEvaluationResultCategory.Other, access: DkmEvaluationResultAccessType.None); }
public DkmClrValue InstantiateResultsViewProxy(DkmInspectionContext inspectionContext, DkmClrType enumerableType) { if (EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown)) { throw new InvalidOperationException(); } if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var appDomain = enumerableType.AppDomain; var module = GetModule(appDomain, "System.Core.dll"); if (module == null) { return null; } var typeArgs = enumerableType.GenericArguments; Debug.Assert(typeArgs.Count <= 1); var proxyTypeName = (typeArgs.Count == 0) ? "System.Linq.SystemCore_EnumerableDebugView" : "System.Linq.SystemCore_EnumerableDebugView`1"; DkmClrType proxyType; try { proxyType = module.ResolveTypeName(proxyTypeName, typeArgs); } catch (ArgumentException) { // ResolveTypeName throws ArgumentException if type is not found. return null; } return this.InstantiateProxyType(inspectionContext, proxyType); }
public DkmClrValue InstantiateProxyType(DkmInspectionContext inspectionContext, DkmClrType proxyType) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var lmrType = proxyType.GetLmrType(); Debug.Assert(!lmrType.IsGenericTypeDefinition); const BindingFlags bindingFlags = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; var constructor = lmrType.GetConstructors(bindingFlags).Single(); var value = constructor.Invoke(bindingFlags, null, new[] { RawValue }, null); return new DkmClrValue( value, value, type: proxyType, alias: null, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None); }
/// <remarks> /// Very simple expression evaluation (may not support all syntax supported by Concord). /// </remarks> public void EvaluateDebuggerDisplayString(DkmWorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string formatString, DkmCompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine) { Debug.Assert(!this.IsNull, "Not supported by VIL"); if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; int openPos = -1; int length = formatString.Length; for (int i = 0; i < length; i++) { char ch = formatString[i]; if (ch == '{') { if (openPos >= 0) { throw new ArgumentException(string.Format("Nested braces in '{0}'", formatString)); } openPos = i; } else if (ch == '}') { if (openPos < 0) { throw new ArgumentException(string.Format("Unmatched closing brace in '{0}'", formatString)); } string name = formatString.Substring(openPos + 1, i - openPos - 1); openPos = -1; var formatSpecifiers = Formatter.NoFormatSpecifiers; int commaIndex = name.IndexOf(','); if (commaIndex >= 0) { var rawFormatSpecifiers = name.Substring(commaIndex + 1).Split(','); var trimmedFormatSpecifiers = ArrayBuilder<string>.GetInstance(rawFormatSpecifiers.Length); trimmedFormatSpecifiers.AddRange(rawFormatSpecifiers.Select(fs => fs.Trim())); formatSpecifiers = trimmedFormatSpecifiers.ToImmutableAndFree(); foreach (var formatSpecifier in formatSpecifiers) { if (formatSpecifier == "nq") { inspectionContext = new DkmInspectionContext(inspectionContext.InspectionSession, inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoQuotes, inspectionContext.Radix, inspectionContext.RuntimeInstance); } // If we need to support additional format specifiers, add them here... } name = name.Substring(0, commaIndex); } var type = ((TypeImpl)this.Type.GetLmrType()).Type; const System.Reflection.BindingFlags bindingFlags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static; DkmClrValue exprValue; var appDomain = this.Type.AppDomain; var field = type.GetField(name, bindingFlags); if (field != null) { var fieldValue = field.GetValue(RawValue); exprValue = new DkmClrValue( fieldValue, fieldValue, DkmClrType.Create(appDomain, (TypeImpl)((fieldValue == null) ? field.FieldType : fieldValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(fieldValue), valueFlags: DkmClrValueFlags.None); } else { var property = type.GetProperty(name, bindingFlags); if (property != null) { var propertyValue = property.GetValue(RawValue); exprValue = new DkmClrValue( propertyValue, propertyValue, DkmClrType.Create(appDomain, (TypeImpl)((propertyValue == null) ? property.PropertyType : propertyValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(propertyValue), valueFlags: DkmClrValueFlags.None); } else { var openParenIndex = name.IndexOf('('); if (openParenIndex >= 0) { name = name.Substring(0, openParenIndex); } var method = type.GetMethod(name, bindingFlags); // The real implementation requires parens on method invocations, so // 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[] { }); exprValue = new DkmClrValue( methodValue, methodValue, DkmClrType.Create(appDomain, (TypeImpl)((methodValue == null) ? method.ReturnType : methodValue.GetType())), alias: null, evalFlags: GetEvaluationResultFlags(methodValue), valueFlags: DkmClrValueFlags.None); } else { var stringValue = "Problem evaluating expression"; var stringType = DkmClrType.Create(appDomain, (TypeImpl)typeof(string)); exprValue = new DkmClrValue( stringValue, stringValue, stringType, alias: null, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.Error); } } } builder.Append(exprValue.GetValueString(inspectionContext, formatSpecifiers)); // Re-enter the formatter. } else if (openPos < 0) { builder.Append(ch); } } if (openPos >= 0) { throw new ArgumentException(string.Format("Unmatched open brace in '{0}'", formatString)); } workList.AddWork(() => completionRoutine(new DkmEvaluateDebuggerDisplayStringAsyncResult(pooled.ToStringAndFree()))); }
public void GetResult( DkmWorkList WorkList, DkmClrType DeclaredType, DkmClrCustomTypeInfo CustomTypeInfo, DkmInspectionContext InspectionContext, ReadOnlyCollection<string> FormatSpecifiers, string ResultName, string ResultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> CompletionRoutine) { InspectionContext.InspectionSession.InvokeResultProvider( this, MethodId.GetResult, r => { r.GetResult( this, WorkList, DeclaredType, CustomTypeInfo, InspectionContext, FormatSpecifiers, ResultName, ResultFullName, CompletionRoutine); return (object)null; }); }
private static void EvaluateDebuggerDisplayStringAndContinue( DkmClrValue value, WorkList workList, DkmInspectionContext inspectionContext, DkmClrType targetType, string str, CompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> onCompleted, CompletionRoutine<Exception> onException) { DkmCompletionRoutine<DkmEvaluateDebuggerDisplayStringAsyncResult> completionRoutine = result => { try { onCompleted(result); } catch (Exception e) { onException(e); } workList.Execute(); }; if (str == null) { completionRoutine(default(DkmEvaluateDebuggerDisplayStringAsyncResult)); } else { value.EvaluateDebuggerDisplayString(workList.InnerWorkList, inspectionContext, targetType, str, completionRoutine); } }
private void GetRootResultAndContinue( DkmClrValue value, WorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, string name, CompletionRoutine<DkmEvaluationResult> completionRoutine) { var type = value.Type.GetLmrType(); if (type.IsTypeVariables()) { Debug.Assert(type.Equals(declaredType.GetLmrType())); var declaredTypeAndInfo = new TypeAndCustomInfo(type, declaredTypeInfo); var expansion = new TypeVariablesExpansion(declaredTypeAndInfo); var dataItem = new EvalResultDataItem( ExpansionKind.Default, name, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: declaredTypeAndInfo, parent: null, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: inspectionContext); Debug.Assert(dataItem.Flags == (DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable)); // Note: We're not including value.EvalFlags in Flags parameter // below (there shouldn't be a reason to do so). completionRoutine(DkmSuccessEvaluationResult.Create( InspectionContext: inspectionContext, StackFrame: value.StackFrame, Name: Resources.TypeVariablesName, FullName: dataItem.FullName, Flags: dataItem.Flags, Value: "", EditableValue: null, Type: "", Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); } else if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ResultsOnly) != 0) { var dataItem = ResultsViewExpansion.CreateResultsOnlyRow( inspectionContext, name, declaredType, declaredTypeInfo, value, this.Formatter); CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.DynamicView) != 0) { var dataItem = DynamicViewExpansion.CreateMembersOnlyRow( inspectionContext, name, value, this.Formatter); CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else { var dataItem = ResultsViewExpansion.CreateResultsOnlyRowIfSynthesizedEnumerable( inspectionContext, name, declaredType, declaredTypeInfo, value, this.Formatter); if (dataItem != null) { CreateEvaluationResultAndContinue( dataItem, workList, inspectionContext, value.StackFrame, completionRoutine); } else { ReadOnlyCollection<string> formatSpecifiers; var fullName = this.Formatter.TrimAndGetFormatSpecifiers(name, out formatSpecifiers); dataItem = CreateDataItem( inspectionContext, name, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: new TypeAndCustomInfo(declaredType.GetLmrType(), declaredTypeInfo), value: value, parent: null, expansionFlags: ExpansionFlags.All, childShouldParenthesize: this.Formatter.NeedsParentheses(fullName), fullName: fullName, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: value.EvalFlags, evalFlags: inspectionContext.EvaluationFlags); GetResultAndContinue(dataItem, workList, declaredType, declaredTypeInfo, inspectionContext, parent: null, completionRoutine: completionRoutine); } } }
private void GetResultAndContinue( EvalResultDataItem dataItem, WorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, EvalResultDataItem parent, CompletionRoutine<DkmEvaluationResult> completionRoutine) { var value = dataItem.Value; // Value may have been replaced (specifically, for Nullable<T>). DebuggerDisplayInfo displayInfo; if (value.TryGetDebuggerDisplayInfo(out displayInfo)) { var targetType = displayInfo.TargetType; var attribute = displayInfo.Attribute; CompletionRoutine<Exception> onException = e => completionRoutine(CreateEvaluationResultFromException(e, dataItem, inspectionContext)); EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.Name, displayName => EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.Value, displayValue => EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.TypeName, displayType => { completionRoutine(GetResult(inspectionContext, dataItem, declaredType, declaredTypeInfo, displayName.Result, displayValue.Result, displayType.Result, parent)); }, onException), onException), onException); } else { completionRoutine(GetResult(inspectionContext, dataItem, declaredType, declaredTypeInfo, displayName: null, displayValue: null, displayType: null, parent: parent)); } }
internal DkmClrDebuggerTypeProxyAttribute(DkmClrType proxyType) : base(null) { this.ProxyType = proxyType; }
private DkmEvaluationResult GetResult( DkmInspectionContext inspectionContext, EvalResultDataItem dataItem, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, string displayName, string displayValue, string displayType, EvalResultDataItem parent) { var name = dataItem.Name; Debug.Assert(name != null); var typeDeclaringMemberAndInfo = dataItem.TypeDeclaringMemberAndInfo; // Note: Don't respect the debugger display name on the root element: // 1) In the Watch window, that's where the user's text goes. // 2) In the Locals window, that's where the local name goes. // Note: Dev12 respects the debugger display name in the Locals window, // but not in the Watch window, but we can't distinguish and this // behavior seems reasonable. if (displayName != null && parent != null) { name = displayName; } else if (typeDeclaringMemberAndInfo.Type != null) { bool unused; if (typeDeclaringMemberAndInfo.Type.IsInterface) { var interfaceTypeName = this.Formatter.GetTypeName(typeDeclaringMemberAndInfo, escapeKeywordIdentifiers: true, sawInvalidIdentifier: out unused); name = string.Format("{0}.{1}", interfaceTypeName, name); } else { var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; builder.Append(name); builder.Append(" ("); builder.Append(this.Formatter.GetTypeName(typeDeclaringMemberAndInfo, escapeKeywordIdentifiers: false, sawInvalidIdentifier: out unused)); builder.Append(')'); name = pooled.ToStringAndFree(); } } var value = dataItem.Value; string display; if (value.HasExceptionThrown()) { display = dataItem.DisplayValue ?? value.GetExceptionMessage(dataItem.FullNameWithoutFormatSpecifiers ?? dataItem.Name, this.Formatter); } else if (displayValue != null) { display = value.IncludeObjectId(displayValue); } else { display = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers); } var typeName = displayType ?? GetTypeName(inspectionContext, value, declaredType, declaredTypeInfo, dataItem.Kind); return CreateEvaluationResult(inspectionContext, value, name, typeName, display, dataItem); }
internal StaticMembersExpansion(DkmClrType type, Expansion members) { _type = type; _members = members; }