private EvalResult GetRow( DkmInspectionContext inspectionContext, DkmClrValue value, int index, EvalResultDataItem parent) { var typeParameter = _typeParameters[index]; var typeArgument = _typeArguments[index]; var typeArgumentInfo = _customTypeInfoMap.SubstituteCustomTypeInfo(typeParameter, customInfo: null); var formatSpecifiers = Formatter.NoFormatSpecifiers; return new EvalResult( ExpansionKind.TypeVariable, typeParameter.Name, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: new TypeAndCustomInfo(DkmClrType.Create(value.Type.AppDomain, typeArgument), typeArgumentInfo), useDebuggerDisplay: parent != null, value: value, displayValue: inspectionContext.GetTypeName(DkmClrType.Create(value.Type.AppDomain, typeArgument), typeArgumentInfo, formatSpecifiers), expansion: null, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: 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(); }
internal string GetValueString(DkmClrValue value, DkmInspectionContext inspectionContext, ObjectDisplayOptions options, GetValueFlags flags) { if (value.IsError()) { return (string)value.HostObjectValue; } if (UsesHexadecimalNumbers(inspectionContext)) { options |= ObjectDisplayOptions.UseHexadecimalNumbers; } var lmrType = value.Type.GetLmrType(); if (IsPredefinedType(lmrType) && !lmrType.IsObject()) { if (lmrType.IsString()) { var stringValue = (string)value.HostObjectValue; if (stringValue == null) { return _nullString; } return IncludeObjectId( value, FormatString(stringValue, options), flags); } else if (lmrType.IsCharacter()) { return IncludeObjectId( value, FormatLiteral((char)value.HostObjectValue, options | ObjectDisplayOptions.IncludeCodePoints), flags); } else { return IncludeObjectId( value, FormatPrimitive(value, options & ~ObjectDisplayOptions.UseQuotes, inspectionContext), flags); } } else if (value.IsNull && !lmrType.IsPointer) { return _nullString; } else if (lmrType.IsEnum) { return IncludeObjectId( value, GetEnumDisplayString(lmrType, value, options, (flags & GetValueFlags.IncludeTypeName) != 0, inspectionContext), flags); } else if (lmrType.IsArray) { return IncludeObjectId( value, GetArrayDisplayString(lmrType, value.ArrayDimensions, value.ArrayLowerBounds, options), flags); } else if (lmrType.IsPointer) { // NOTE: the HostObjectValue will have a size corresponding to the process bitness // and FormatPrimitive will adjust accordingly. var tmp = FormatPrimitive(value, ObjectDisplayOptions.UseHexadecimalNumbers, inspectionContext); // Always in hex. Debug.Assert(tmp != null); return tmp; } else if (lmrType.IsNullable()) { var nullableValue = value.GetNullableValue(inspectionContext); // It should be impossible to nest nullables, so this recursion should introduce only a single extra stack frame. return nullableValue == null ? _nullString : GetValueString(nullableValue, inspectionContext, ObjectDisplayOptions.None, GetValueFlags.IncludeTypeName); } // "value.EvaluateToString()" will check "Call string-conversion function on objects in variables windows" // (Tools > Options setting) and call "value.ToString()" if appropriate. return IncludeObjectId( value, string.Format(_defaultFormat, value.EvaluateToString(inspectionContext) ?? inspectionContext.GetTypeName(value.Type, CustomTypeInfo: null, FormatSpecifiers: NoFormatSpecifiers)), flags); }
/// <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; }
/// <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 it /// differs from the declared type.</returns> private static string GetTypeName(DkmInspectionContext inspectionContext, DkmClrType declaredType, DkmClrType runtimeType) { var declaredTypeName = inspectionContext.GetTypeName(declaredType); var declaredLmrType = declaredType.GetLmrType(); var runtimeLmrType = runtimeType.GetLmrType(); return declaredLmrType.Equals(runtimeLmrType) || declaredLmrType.IsPointer ? declaredTypeName : string.Format("{0} {{{1}}}", declaredTypeName, inspectionContext.GetTypeName(runtimeType)); }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo, ReadOnlyCollection<string> formatSpecifiers) { return inspectionContext.GetTypeName(clrType, customTypeInfo, formatSpecifiers); }
internal static string GetExceptionMessage(this DkmClrValue value, DkmInspectionContext inspectionContext, string fullNameWithoutFormatSpecifiers) { var typeName = inspectionContext.GetTypeName(value.Type, null, Formatter.NoFormatSpecifiers); return string.Format(Resources.ExceptionThrown, fullNameWithoutFormatSpecifiers, typeName); }
private static string GetQualifiedMemberName( DkmInspectionContext inspectionContext, TypeAndCustomInfo typeDeclaringMember, string memberName, IDkmClrFullNameProvider fullNameProvider) { var typeName = fullNameProvider.GetClrTypeName(inspectionContext, typeDeclaringMember.ClrType, typeDeclaringMember.Info) ?? inspectionContext.GetTypeName(typeDeclaringMember.ClrType, typeDeclaringMember.Info, Formatter.NoFormatSpecifiers); return typeDeclaringMember.Type.IsInterface ? $"{typeName}.{memberName}" : $"{memberName} ({typeName})"; }
/// <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> internal static string GetTypeName( DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, bool isPointerDereference) { var declaredLmrType = declaredType.GetLmrType(); var runtimeType = value.Type; var declaredTypeName = inspectionContext.GetTypeName(declaredType, declaredTypeInfo, Formatter.NoFormatSpecifiers); // Include the runtime type if distinct. if (!declaredLmrType.IsPointer && !isPointerDereference && (!declaredLmrType.IsNullable() || value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown))) { // Generate the declared type name without tuple element names. var declaredTypeInfoNoTupleElementNames = declaredTypeInfo.WithNoTupleElementNames(); var declaredTypeNameNoTupleElementNames = (declaredTypeInfo == declaredTypeInfoNoTupleElementNames) ? declaredTypeName : inspectionContext.GetTypeName(declaredType, declaredTypeInfoNoTupleElementNames, Formatter.NoFormatSpecifiers); // Generate the runtime type name with no tuple element names and no dynamic. var runtimeTypeName = inspectionContext.GetTypeName(runtimeType, null, FormatSpecifiers: Formatter.NoFormatSpecifiers); // If the two names are distinct, include both. if (!string.Equals(declaredTypeNameNoTupleElementNames, runtimeTypeName, StringComparison.Ordinal)) // Names will reflect "dynamic", types will not. { return string.Format("{0} {{{1}}}", declaredTypeName, runtimeTypeName); } } return declaredTypeName; }