/// <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); }
public static string GetTypeName(this System.Type type, DkmClrCustomTypeInfo typeInfo, bool escapeKeywordIdentifiers = false) { bool sawInvalidIdentifier; var result = CSharpFormatter.Instance.GetTypeName(new TypeAndCustomInfo((TypeImpl)type, typeInfo), escapeKeywordIdentifiers, out sawInvalidIdentifier); Assert.False(sawInvalidIdentifier); return result; }
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))))); }
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); }); }
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; }
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); }
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); }
public DynamicFlagsCustomTypeInfo(DkmClrCustomTypeInfo typeInfo) { if (typeInfo == null || typeInfo.PayloadTypeId != PayloadTypeId) { _bits = null; } else { var builder = ArrayBuilder<byte>.GetInstance(); builder.AddRange(typeInfo.Payload); _bits = new BitArray(builder.ToArrayAndFree()); } }
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); }
/// <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(); }
/// <summary> /// Return a copy of the custom type info with the leading dynamic flag removed. /// There are no changes to tuple element names since this is used for walking /// into an array element type only which does not affect tuple element names. /// </summary> internal static DkmClrCustomTypeInfo SkipOne(DkmClrCustomTypeInfo customInfo) { if (customInfo == null) { return customInfo; } ReadOnlyCollection<byte> dynamicFlags; ReadOnlyCollection<string> tupleElementNames; CustomTypeInfo.Decode( customInfo.PayloadTypeId, customInfo.Payload, out dynamicFlags, out tupleElementNames); if (dynamicFlags == null) { return customInfo; } return Create(DynamicFlagsCustomTypeInfo.SkipOne(dynamicFlags), tupleElementNames); }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo typeInfo, ReadOnlyCollection<string> formatSpecifiers) { return GetTypeName(new TypeAndCustomInfo(type.GetLmrType(), typeInfo)); }
private string GetEditableValue(DkmClrValue value, DkmInspectionContext inspectionContext, DkmClrCustomTypeInfo customTypeInfo) { if (value.IsError()) { return null; } if (value.EvalFlags.Includes(DkmEvaluationResultFlags.ReadOnly)) { return null; } var type = value.Type.GetLmrType(); if (type.IsEnum) { return this.GetValueString(value, inspectionContext, ObjectDisplayOptions.None, GetValueFlags.IncludeTypeName); } else if (type.IsDecimal()) { return this.GetValueString(value, inspectionContext, ObjectDisplayOptions.IncludeTypeSuffix, GetValueFlags.None); } // The legacy EE didn't special-case strings or chars (when ",nq" was used, // you had to manually add quotes when editing) but it makes sense to // always automatically quote (non-null) strings and chars when editing. else if (type.IsString()) { if (!value.IsNull) { return this.GetValueString(value, inspectionContext, ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters, GetValueFlags.None); } } else if (type.IsCharacter()) { return this.GetValueStringForCharacter(value, inspectionContext, ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters); } return null; }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo typeInfo, ReadOnlyCollection<string> formatSpecifiers) { bool unused; return GetTypeName(new TypeAndCustomInfo(type.GetLmrType(), typeInfo), escapeKeywordIdentifiers: false, sawInvalidIdentifier: out unused); }
void IDkmClrResultProvider.GetResult(DkmClrValue clrValue, DkmWorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo customTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine<DkmEvaluationAsyncResult> completionRoutine) { clrValue.GetResult( workList, declaredType, customTypeInfo, inspectionContext, formatSpecifiers, resultName, resultFullName, result => { var type = declaredType.GetLmrType(); if (type.IsPointer) { var r = (DkmSuccessEvaluationResult)result.Result; // TODO: Why aren't modopts for & properties included? r.GetChildren( workList, 1, inspectionContext, children => { var c = (DkmSuccessEvaluationResult)children.InitialChildren[0]; r = DkmSuccessEvaluationResult.Create( c.InspectionContext, c.StackFrame, r.Name, r.FullName, c.Flags, c.Value, r.EditableValue, r.Type, r.Category, r.Access, r.StorageType, r.TypeModifierFlags, null, r.CustomUIVisualizers, null, null); completionRoutine(new DkmEvaluationAsyncResult(r)); }); } else { completionRoutine(result); } }); }
string IDkmClrFullNameProvider.GetClrMemberName( DkmInspectionContext inspectionContext, string parentFullName, DkmClrType declaringType, DkmClrCustomTypeInfo declaringTypeInfo, string memberName, bool memberAccessRequiresExplicitCast, bool memberIsStatic) { return ((IDkmClrFullNameProvider)_fallback).GetClrMemberName(inspectionContext, parentFullName, declaringType, declaringTypeInfo, memberName, memberAccessRequiresExplicitCast, memberIsStatic); }
string IDkmClrFullNameProvider.GetClrObjectCreationExpression(DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, string arguments) { throw new NotImplementedException(); }
string IDkmClrFullNameProvider.GetClrCastExpression(DkmInspectionContext inspectionContext, string argument, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, bool parenthesizeArgument, bool parenthesizeEntireExpression) { throw new NotImplementedException(); }
string IDkmClrFullNameProvider.GetClrTypeName(DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo) { throw new NotImplementedException(); }
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)); } }
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; }); }
string IDkmClrFullNameProvider.GetClrObjectCreationExpression(DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, string arguments) { bool sawInvalidIdentifier; var name = GetTypeName(new TypeAndCustomInfo(type, customTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); if (sawInvalidIdentifier) { return null; } return GetObjectCreationExpression(name, arguments); }
private DkmEvaluationResult GetResult( DkmInspectionContext inspectionContext, EvalResult result, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, string displayName, string displayValue, string displayType, bool useDebuggerDisplay) { var name = result.Name; Debug.Assert(name != null); var typeDeclaringMemberAndInfo = result.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 && useDebuggerDisplay) { name = displayName; } else if (typeDeclaringMemberAndInfo.Type != null) { name = GetQualifiedMemberName(inspectionContext, typeDeclaringMemberAndInfo, name, FullNameProvider); } var value = result.Value; string display; if (value.HasExceptionThrown()) { display = result.DisplayValue ?? value.GetExceptionMessage(inspectionContext, result.FullNameWithoutFormatSpecifiers ?? result.Name); } else if (displayValue != null) { display = value.IncludeObjectId(displayValue); } else { display = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers); } var typeName = displayType ?? GetTypeName(inspectionContext, value, declaredType, declaredTypeInfo, result.Kind); return CreateEvaluationResult(inspectionContext, value, name, typeName, display, result); }
string IDkmClrFullNameProvider.GetClrMemberName( DkmInspectionContext inspectionContext, string parentFullName, DkmClrType declaringType, DkmClrCustomTypeInfo declaringTypeInfo, string memberName, bool memberAccessRequiresExplicitCast, bool memberIsStatic) { string qualifier; if (memberIsStatic) { bool sawInvalidIdentifier; qualifier = GetTypeName(new TypeAndCustomInfo(declaringType, declaringTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); if (sawInvalidIdentifier) { return null; // FullName wouldn't be parseable. } } else if (memberAccessRequiresExplicitCast) { bool sawInvalidIdentifier; var typeName = GetTypeName(new TypeAndCustomInfo(declaringType, declaringTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); if (sawInvalidIdentifier) { return null; // FullName wouldn't be parseable. } qualifier = GetCastExpression( parentFullName, typeName, parenthesizeArgument: false, parenthesizeEntireExpression: true); } else { qualifier = parentFullName; } return $"{qualifier}.{memberName}"; }
/// <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; }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo, ReadOnlyCollection<string> formatSpecifiers) { return inspectionContext.GetTypeName(clrType, customTypeInfo, formatSpecifiers); }
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); } } }
string IDkmClrFormatter2.GetValueString(DkmClrValue value, DkmClrCustomTypeInfo customTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers) { return ((IDkmClrFormatter2)_fallback).GetValueString(value, customTypeInfo, inspectionContext, formatSpecifiers); }
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); }
string IDkmClrFormatter2.GetEditableValueString(DkmClrValue value, DkmInspectionContext inspectionContext, DkmClrCustomTypeInfo customTypeInfo) { return ((IDkmClrFormatter2)_fallback).GetEditableValueString(value, inspectionContext, customTypeInfo); }