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; }
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); }
internal static EvalResultDataItem CreateResultsOnlyRow( DkmInspectionContext inspectionContext, string name, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmClrValue value, Formatter formatter) { string errorMessage; if (value.IsError()) { errorMessage = (string)value.HostObjectValue; } else if (value.HasExceptionThrown()) { errorMessage = value.GetExceptionMessage(name, formatter); } else { var enumerableType = GetEnumerableType(value); if (enumerableType != null) { var expansion = CreateExpansion(inspectionContext, value, enumerableType, formatter); if (expansion != null) { return expansion.CreateResultsViewRow( inspectionContext, name, new TypeAndCustomInfo(declaredType.GetLmrType(), declaredTypeInfo), value, includeResultsFormatSpecifier: true, formatter: formatter); } errorMessage = Resources.ResultsViewNoSystemCore; } else { errorMessage = Resources.ResultsViewNotEnumerable; } } Debug.Assert(errorMessage != null); return new EvalResultDataItem(name, errorMessage); }
/// <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 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); }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo typeInfo, ReadOnlyCollection<string> formatSpecifiers) { return GetTypeName(new TypeAndCustomInfo(type.GetLmrType(), typeInfo)); }
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); }
private DkmEvaluationResult GetRootResult(DkmClrValue value, DkmClrType declaredType, string resultName) { var type = value.Type.GetLmrType(); if (type.IsTypeVariables()) { var expansion = new TypeVariablesExpansion(type); var dataItem = new EvalResultDataItem( resultName, typeDeclaringMember: null, declaredType: type, value: value, expansion: expansion, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null); 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). return DkmSuccessEvaluationResult.Create( InspectionContext: value.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 { var inspectionContext = value.InspectionContext; if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ResultsOnly) != 0) { return ResultsViewExpansion.CreateResultsOnly(resultName, declaredType, value, null, this.Formatter); } ReadOnlyCollection<string> formatSpecifiers; var fullName = this.Formatter.TrimAndGetFormatSpecifiers(resultName, out formatSpecifiers); var dataItem = CreateDataItem( inspectionContext, resultName, typeDeclaringMember: null, declaredType: declaredType.GetLmrType(), 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); return GetResult(dataItem, value.Type, declaredType, parent: null); } }
/// <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)); }
public TypeAndCustomInfo(DkmClrType type) : this(type.GetLmrType(), null) { }
public DkmClrValue InstantiateProxyType(DkmClrType proxyType) { 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, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None, inspectionContext: this.InspectionContext); }
/// <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); }
private static DkmClrType GetEnumerableType(DkmClrValue value, DkmClrType valueType, bool requireExactInterface) { if (!IsEnumerableCandidate(value)) { return null; } var type = valueType.GetLmrType(); Type enumerableType; if (requireExactInterface) { if (!type.IsIEnumerable() && !type.IsIEnumerableOfT()) { return null; } enumerableType = type; } else { enumerableType = type.GetIEnumerableImplementationIfAny(); if (enumerableType == null) { return null; } } return DkmClrType.Create(valueType.AppDomain, enumerableType); }
string IDkmClrFormatter.GetTypeName(DkmInspectionContext inspectionContext, DkmClrType clrType) { return GetTypeName(clrType.GetLmrType()); }
/// <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; }
/// <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; }
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); } } }
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); } }); }