internal DkmClrValue WithInspectionContext(DkmInspectionContext inspectionContext) { return new DkmClrValue( _rawValue, this.HostObjectValue, this.Type, this.Alias, _formatter, this.EvalFlags, this.ValueFlags, inspectionContext); }
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, formatter: _formatter, evalFlags: evalFlags, valueFlags: valueFlags, category: DkmEvaluationResultCategory.Other, access: DkmEvaluationResultAccessType.None); }
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); }
public string GetUnderlyingString(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } return _formatter.GetUnderlyingString(this, inspectionContext); }
public bool HasUnderlyingString(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException("inspectionContext"); } return _formatter.HasUnderlyingString(this, inspectionContext); }
void IDkmClrResultProvider.GetChildren(DkmEvaluationResult evaluationResult, DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmGetChildrenAsyncResult> completionRoutine) { var dataItem = evaluationResult.GetDataItem <EvalResultDataItem>(); if (dataItem == null) { // We don't know about this result. Call next implementation evaluationResult.GetChildren(workList, initialRequestSize, inspectionContext, completionRoutine); return; } var stackFrame = evaluationResult.StackFrame; GetChildrenAndContinue(dataItem, workList, stackFrame, initialRequestSize, inspectionContext, completionRoutine); }
private void GetChildrenAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmStackWalkFrame stackFrame, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmGetChildrenAsyncResult> completionRoutine) { var expansion = dataItem.Expansion; var rows = ArrayBuilder <EvalResultDataItem> .GetInstance(); int index = 0; if (expansion != null) { expansion.GetRows(this, rows, inspectionContext, dataItem, dataItem.Value, 0, initialRequestSize, visitAll: true, index: ref index); } var numRows = rows.Count; Debug.Assert(index >= numRows); Debug.Assert(initialRequestSize >= numRows); var initialChildren = new DkmEvaluationResult[numRows]; var wl = new WorkList(workList, e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e))); GetEvaluationResultsAndContinue(rows, initialChildren, 0, numRows, wl, inspectionContext, stackFrame, () => wl.ContinueWith( () => { var enumContext = DkmEvaluationResultEnumContext.Create(index, stackFrame, inspectionContext, new EnumContextDataItem(dataItem)); completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext)); rows.Free(); })); wl.Execute(); }
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 { 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); } } }
public DkmClrValue InstantiateDynamicViewProxy(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } var module = new DkmClrModuleInstance( this.Type.AppDomain.RuntimeInstance, typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly, new DkmModule("Microsoft.CSharp.dll")); var proxyType = module.ResolveTypeName( "Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView", s_noArguments); return this.InstantiateProxyType(inspectionContext, proxyType); }
/// <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()))); }
private DebuggerTypeProxyExpansion( DkmInspectionContext inspectionContext, DkmClrValue proxyValue, string name, TypeAndCustomInfo typeDeclaringMemberAndInfoOpt, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, bool childShouldParenthesize, string fullName, string childFullNamePrefix, ReadOnlyCollection <string> formatSpecifiers, DkmEvaluationResultFlags flags, string editableValue, Formatter formatter) { Debug.Assert(proxyValue != null); var proxyType = proxyValue.Type.GetLmrType(); var proxyTypeAndInfo = new TypeAndCustomInfo(proxyType); var proxyMembers = MemberExpansion.CreateExpansion( inspectionContext, proxyTypeAndInfo, proxyValue, ExpansionFlags.IncludeBaseMembers, TypeHelpers.IsPublic, formatter); if (proxyMembers != null) { string proxyMemberFullNamePrefix = null; if (childFullNamePrefix != null) { bool sawInvalidIdentifier; var proxyTypeName = formatter.GetTypeName(proxyTypeAndInfo, escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier); if (!sawInvalidIdentifier) { proxyMemberFullNamePrefix = formatter.GetObjectCreationExpression(proxyTypeName, childFullNamePrefix); } } _proxyItem = new EvalResultDataItem( ExpansionKind.Default, name: string.Empty, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: proxyTypeAndInfo, parent: null, value: proxyValue, displayValue: null, expansion: proxyMembers, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: proxyMemberFullNamePrefix, formatSpecifiers: Formatter.NoFormatSpecifiers, category: default(DkmEvaluationResultCategory), flags: default(DkmEvaluationResultFlags), editableValue: null, inspectionContext: inspectionContext); } _name = name; _typeDeclaringMemberAndInfoOpt = typeDeclaringMemberAndInfoOpt; _declaredTypeAndInfo = declaredTypeAndInfo; _value = value; _childShouldParenthesize = childShouldParenthesize; _fullName = fullName; _childFullNamePrefix = childFullNamePrefix; _formatSpecifiers = formatSpecifiers; _flags = flags; _editableValue = editableValue; }
internal static Expansion CreateExpansion( ResultProvider resultProvider, DkmInspectionContext inspectionContext, string name, TypeAndCustomInfo typeDeclaringMemberAndInfoOpt, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, bool childShouldParenthesize, string fullName, string childFullNamePrefix, ReadOnlyCollection <string> formatSpecifiers, DkmEvaluationResultFlags flags, string editableValue) { Debug.Assert((inspectionContext.EvaluationFlags & DkmEvaluationFlags.NoExpansion) == 0); // Note: The native EE uses the proxy type, even for // null instances, so statics on the proxy type are // displayed. That case is not supported currently. if (!value.IsNull) { var proxyType = value.Type.GetProxyType(); if (proxyType != null) { if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.ShowValueRaw) != 0) { var rawView = CreateRawView(resultProvider, inspectionContext, declaredTypeAndInfo, value); Debug.Assert(rawView != null); return(rawView); } DkmClrValue proxyValue; try { proxyValue = value.InstantiateProxyType(inspectionContext, proxyType); } catch { proxyValue = null; } if (proxyValue != null) { return(new DebuggerTypeProxyExpansion( inspectionContext, proxyValue, name, typeDeclaringMemberAndInfoOpt, declaredTypeAndInfo, value, childShouldParenthesize, fullName, childFullNamePrefix, formatSpecifiers, flags, editableValue, resultProvider.Formatter)); } } } return(null); }
private static EvalResult GetMemberRow( ResultProvider resultProvider, DkmInspectionContext inspectionContext, DkmClrValue value, Field field, EvalResultDataItem parent, int cardinality ) { var fullNameProvider = resultProvider.FullNameProvider; var parentFullName = parent.ChildFullNamePrefix; if (parentFullName != null) { if (parent.ChildShouldParenthesize) { parentFullName = parentFullName.Parenthesize(); } var parentRuntimeType = parent.Value.Type; if (!parent.DeclaredTypeAndInfo.Type.Equals(parentRuntimeType.GetLmrType())) { parentFullName = fullNameProvider.GetClrCastExpression( inspectionContext, parentFullName, parentRuntimeType, customTypeInfo: null, castExpressionOptions: DkmClrCastExpressionOptions.ParenthesizeEntireExpression ); } } // Ideally if the caller requests multiple items in a nested tuple // we should only evaluate Rest once, and should only calculate // the full name for Rest once. string fullName; var fieldValue = GetValueAndFullName( fullNameProvider, inspectionContext, value, field, parentFullName, out fullName ); var name = field.Name; var typeDeclaringMemberAndInfo = default(TypeAndCustomInfo); var declaredTypeAndInfo = field.FieldTypeAndInfo; var flags = fieldValue.EvalFlags; var formatSpecifiers = Formatter.NoFormatSpecifiers; if (field.IsRest) { var displayValue = fieldValue.GetValueString( inspectionContext, Formatter.NoFormatSpecifiers ); var displayType = ResultProvider.GetTypeName( inspectionContext, fieldValue, declaredTypeAndInfo.ClrType, declaredTypeAndInfo.Info, isPointerDereference: false ); var expansion = new TupleExpansion( declaredTypeAndInfo, cardinality - (TypeHelpers.TupleFieldRestPosition - 1), useRawView: true ); return new EvalResult( ExpansionKind.Explicit, name, typeDeclaringMemberAndInfo, declaredTypeAndInfo, useDebuggerDisplay: false, value: fieldValue, displayValue: displayValue, expansion: expansion, childShouldParenthesize: false, fullName: fullName, childFullNamePrefixOpt: flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName, formatSpecifiers: Formatter.AddFormatSpecifier(formatSpecifiers, "raw"), category: DkmEvaluationResultCategory.Other, flags: flags, editableValue: null, inspectionContext: inspectionContext, displayName: name, displayType: displayType ); } return resultProvider.CreateDataItem( inspectionContext, name, typeDeclaringMemberAndInfo: typeDeclaringMemberAndInfo, declaredTypeAndInfo: declaredTypeAndInfo, value: fieldValue, useDebuggerDisplay: false, expansionFlags: ExpansionFlags.All, childShouldParenthesize: false, fullName: fullName, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: flags, evalFlags: DkmEvaluationFlags.None, canFavorite: false, isFavorite: false, supportsFavorites: true ); }
public static string GetTypeName(this System.Type type, DkmClrCustomTypeInfo typeInfo = null, 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 ReprOptions(DkmInspectionContext inspectionContext) : this(inspectionContext.Thread.Process) { HexadecimalDisplay = (inspectionContext.Radix == 16); }
private void GetFrameName( DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine <DkmGetFrameNameAsyncResult> completionRoutine, TMethodSymbol method ) { var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types); var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names); if (argumentFlags.Includes(DkmVariableInfoFlags.Values)) { // No need to compute the Expandable bit on // argument values since that can be expensive. inspectionContext = DkmInspectionContext.Create( inspectionContext.InspectionSession, inspectionContext.RuntimeInstance, inspectionContext.Thread, inspectionContext.Timeout, inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoExpansion, inspectionContext.FuncEvalFlags, inspectionContext.Radix, inspectionContext.Language, inspectionContext.ReturnValue, inspectionContext.AdditionalVisualizationData, inspectionContext.AdditionalVisualizationDataPriority, inspectionContext.ReturnValues ); // GetFrameArguments returns an array of formatted argument values. We'll pass // ourselves (GetFrameName) as the continuation of the GetFrameArguments call. inspectionContext.GetFrameArguments( workList, frame, result => { // DkmGetFrameArgumentsAsyncResult.Arguments will throw if ErrorCode != 0. var argumentValues = (result.ErrorCode == 0) ? result.Arguments : null; try { ArrayBuilder <string?>?builder = null; if (argumentValues != null) { builder = ArrayBuilder <string?> .GetInstance(); foreach (var argument in argumentValues) { var formattedArgument = argument as DkmSuccessEvaluationResult; // Not expecting Expandable bit, at least not from this EE. Debug.Assert( (formattedArgument == null) || ( formattedArgument.Flags & DkmEvaluationResultFlags.Expandable ) == 0 ); builder.Add(formattedArgument?.Value); } } var frameName = _instructionDecoder.GetName( method, includeParameterTypes, includeParameterNames, argumentValues: builder ); builder?.Free(); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } catch (Exception e) { completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e)); } finally { if (argumentValues != null) { foreach (var argument in argumentValues) { argument.Close(); } } } } ); } else { var frameName = _instructionDecoder.GetName( method, includeParameterTypes, includeParameterNames, argumentValues: null ); completionRoutine(new DkmGetFrameNameAsyncResult(frameName)); } }
public DkmClrValue GetMemberValue(string MemberName, int MemberType, string ParentTypeName, DkmInspectionContext InspectionContext) { if (InspectionContext == null) { throw new ArgumentNullException("inspectionContext"); } var runtime = this.Type.RuntimeInstance; var memberValue = runtime.GetMemberValue(this, MemberName); if (memberValue != null) { return(memberValue); } var declaringType = this.Type.GetLmrType(); if (ParentTypeName != null) { declaringType = GetAncestorType(declaringType, ParentTypeName); Debug.Assert(declaringType != null); } // Special cases for nullables if (declaringType.IsNullable()) { if (MemberName == InternalWellKnownMemberNames.NullableHasValue) { // In our mock implementation, RawValue is null for null nullables, // so we have to compute HasValue some other way. var boolValue = _rawValue != null; var boolType = runtime.GetType((TypeImpl)typeof(bool)); return(new DkmClrValue( boolValue, boolValue, type: boolType, alias: null, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None)); } else if (MemberName == InternalWellKnownMemberNames.NullableValue) { // In our mock implementation, RawValue is of type T rather than // Nullable<T> for nullables, so we'll just return that value // (no need to unwrap by getting "value" field). var valueType = runtime.GetType((TypeImpl)_rawValue.GetType()); return(new DkmClrValue( _rawValue, _rawValue, type: valueType, alias: null, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None)); } } Type declaredType; object value; var evalFlags = DkmEvaluationResultFlags.None; const BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; switch ((MemberTypes)MemberType) { case MemberTypes.Field: var field = declaringType.GetField(MemberName, bindingFlags); declaredType = field.FieldType; if (field.Attributes.HasFlag(FieldAttributes.Literal) || field.Attributes.HasFlag(FieldAttributes.InitOnly)) { evalFlags |= DkmEvaluationResultFlags.ReadOnly; } try { value = field.GetValue(_rawValue); } catch (TargetInvocationException e) { var exception = e.InnerException; return(new DkmClrValue( exception, exception, type: runtime.GetType((TypeImpl)exception.GetType()), alias: null, formatter: _formatter, evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown, valueFlags: DkmClrValueFlags.None)); } break; case MemberTypes.Property: var property = declaringType.GetProperty(MemberName, bindingFlags); declaredType = property.PropertyType; if (property.GetSetMethod(nonPublic: true) == null) { evalFlags |= DkmEvaluationResultFlags.ReadOnly; } try { value = property.GetValue(_rawValue, bindingFlags, null, null, null); } catch (TargetInvocationException e) { var exception = e.InnerException; return(new DkmClrValue( exception, exception, type: runtime.GetType((TypeImpl)exception.GetType()), alias: null, formatter: _formatter, evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown, valueFlags: DkmClrValueFlags.None)); } break; default: throw ExceptionUtilities.UnexpectedValue((MemberTypes)MemberType); } Type type; if (value is Pointer) { unsafe { if (Marshal.SizeOf(typeof(void *)) == 4) { value = (int)Pointer.Unbox(value); } else { value = (long)Pointer.Unbox(value); } } type = declaredType; } else if (value == null || declaredType.IsNullable()) { type = declaredType; } else { type = (TypeImpl)value.GetType(); } return(new DkmClrValue( value, value, type: runtime.GetType(type), alias: null, formatter: _formatter, evalFlags: evalFlags, 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("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; // Ignore any format specifiers. int commaIndex = name.IndexOf(','); if (commaIndex >= 0) { name = name.Substring(0, commaIndex); } var type = ((TypeImpl)this.Type.GetLmrType()).Type; var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | 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, formatter: _formatter, 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, formatter: _formatter, 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, formatter: _formatter, 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, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.Error); } } } builder.Append(exprValue.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers)); // 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 void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine <DkmEvaluationResult> completionRoutine) { switch (dataItem.Kind) { case ExpansionKind.Error: completionRoutine(DkmFailedEvaluationResult.Create( inspectionContext, StackFrame: stackFrame, Name: dataItem.Name, FullName: dataItem.FullName, ErrorMessage: dataItem.DisplayValue, Flags: DkmEvaluationResultFlags.None, Type: null, DataItem: null)); break; case ExpansionKind.NonPublicMembers: case ExpansionKind.StaticMembers: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, dataItem.Name, typeName: string.Empty, display: null, dataItem: dataItem)); break; case ExpansionKind.RawView: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, Resources.RawView, typeName: string.Empty, display: null, dataItem: dataItem)); break; case ExpansionKind.ResultsView: completionRoutine(CreateEvaluationResult( inspectionContext, dataItem.Value, dataItem.Name, typeName: string.Empty, display: Resources.ResultsViewValueWarning, dataItem: dataItem)); break; case ExpansionKind.TypeVariables: var value = dataItem.Value; completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, dataItem.Name, dataItem.FullName, dataItem.Flags, dataItem.DisplayValue, EditableValue: null, Type: dataItem.DisplayValue, Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); break; default: Debug.Assert((dataItem.Kind == ExpansionKind.Default) || (dataItem.Kind == ExpansionKind.PointerDereference)); // This call will evaluate DebuggerDisplayAttributes. GetResultAndContinue( dataItem, workList, declaredType: DkmClrType.Create(dataItem.Value.Type.AppDomain, dataItem.DeclaredType), inspectionContext: inspectionContext, parent: dataItem.Parent, completionRoutine: completionRoutine); break; } }
public DkmClrValue GetArrayElement(int[] indices, DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } 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( element, element, type: type, alias: null, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None); }
void IDkmClrResultProvider.GetResult(DkmClrValue value, DkmWorkList workList, DkmClrType declaredType, DkmInspectionContext inspectionContext, ReadOnlyCollection <string> formatSpecifiers, string resultName, string resultFullName, DkmCompletionRoutine <DkmEvaluationAsyncResult> completionRoutine) { // TODO: Use full name GetRootResultAndContinue(value, workList, declaredType, inspectionContext, resultName, result => ContinueWithExceptionHandling( () => completionRoutine(new DkmEvaluationAsyncResult(result)), e => completionRoutine(DkmEvaluationAsyncResult.CreateErrorResult(e)))); }
private static bool UsesHexadecimalNumbers(DkmInspectionContext inspectionContext) { Debug.Assert(inspectionContext != null); return(inspectionContext.Radix == 16); }
internal void GetResultAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmClrType declaredType, 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)); value.EvaluateDebuggerDisplayStringAndContinue(workList, inspectionContext, targetType, attribute.Name, displayName => ContinueWithExceptionHandling( () => value.EvaluateDebuggerDisplayStringAndContinue(workList, inspectionContext, targetType, attribute.Value, displayValue => ContinueWithExceptionHandling( () => value.EvaluateDebuggerDisplayStringAndContinue(workList, inspectionContext, targetType, attribute.TypeName, displayType => ContinueWithExceptionHandling( () => completionRoutine(GetResult(inspectionContext, dataItem, declaredType, displayName.Result, displayValue.Result, displayType.Result, parent)), onException)), onException)), onException)); } else { completionRoutine(GetResult(inspectionContext, dataItem, declaredType, displayName: null, displayValue: null, displayType: null, parent: parent)); } }
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) { if (typeDeclaringMemberAndInfo.Type.IsInterface) { var interfaceTypeName = this.Formatter.GetTypeName(typeDeclaringMemberAndInfo, escapeKeywordIdentifiers: true); 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)); builder.Append(')'); name = pooled.ToStringAndFree(); } } var value = dataItem.Value; string display; if (value.HasExceptionThrown()) { display = dataItem.DisplayValue ?? value.GetExceptionMessage(dataItem.FullNameWithoutFormatSpecifiers, 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)); }
private void StoreResultAndContinue(DkmEvaluationResult result, ArrayBuilder <EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine) { results[index] = result; index++; if (index < numRows) { GetEvaluationResultsAndContinue(rows, results, index, numRows, workList, inspectionContext, stackFrame, completionRoutine); } else { completionRoutine(); } }
private void GetItemsAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, int startIndex, int count, DkmInspectionContext inspectionContext, DkmCompletionRoutine <DkmEvaluationEnumAsyncResult> completionRoutine) { var expansion = dataItem.Expansion; var value = dataItem.Value; var rows = ArrayBuilder <EvalResultDataItem> .GetInstance(); if (expansion != null) { int index = 0; expansion.GetRows(this, rows, inspectionContext, dataItem, value, startIndex, count, visitAll: false, index: ref index); } var numRows = rows.Count; Debug.Assert(count >= numRows); var results = new DkmEvaluationResult[numRows]; var wl = new WorkList(workList, e => completionRoutine(DkmEvaluationEnumAsyncResult.CreateErrorResult(e))); GetEvaluationResultsAndContinue(rows, results, 0, numRows, wl, inspectionContext, value.StackFrame, () => wl.ContinueWith( () => { completionRoutine(new DkmEvaluationEnumAsyncResult(results)); rows.Free(); })); wl.Execute(); }
private void GetEvaluationResultsAndContinue(ArrayBuilder <EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, DkmWorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine) { if (index >= numRows) { completionRoutine(); } else { CreateEvaluationResultAndContinue(rows[index], workList, inspectionContext, stackFrame, result => ContinueWithExceptionHandling( () => StoreResultAndContinue(result, rows, results, index, numRows, workList, inspectionContext, stackFrame, completionRoutine), e => { // If we fail to store a result, just stop enumerating rows (rather than attempting to store // an error message in the current row, etc). This is because it may have been the act of // indexing into the results store that threw (so it would just throw again here). The user // experience is less than ideal (there's no real indication that something went wrong), // however, it seems like it's better to enumerate/display some rows than none. We will // receive a non-fatal Watson report in this case, so the problem won't go unnoticed. completionRoutine(); })); } }
private void GetEvaluationResultsAndContinue(ArrayBuilder <EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, WorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine) { if (index < numRows) { CreateEvaluationResultAndContinue(rows[index], workList, inspectionContext, stackFrame, result => workList.ContinueWith( () => { results[index] = result; GetEvaluationResultsAndContinue(rows, results, index + 1, numRows, workList, inspectionContext, stackFrame, completionRoutine); })); } else { completionRoutine(); } }
private static DkmEvaluationResult CreateEvaluationResultFromException(Exception e, EvalResultDataItem dataItem, DkmInspectionContext inspectionContext) { return(DkmFailedEvaluationResult.Create( inspectionContext, dataItem.Value.StackFrame, Name: dataItem.Name, FullName: null, ErrorMessage: e.Message, Flags: DkmEvaluationResultFlags.None, Type: null, DataItem: null)); }
public string GetValueString(DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } // The real version does some sort of dynamic dispatch that ultimately calls this method. return _formatter.GetValueString(this, inspectionContext, formatSpecifiers); }
public string GetValueString(DkmInspectionContext inspectionContext, ReadOnlyCollection<string> formatSpecifiers) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } return inspectionContext.InspectionSession.InvokeFormatter(this, MethodId.GetValueString, f => f.GetValueString(this, inspectionContext, formatSpecifiers)); }
internal static Expansion CreateExpansion( DkmInspectionContext inspectionContext, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, ExpansionFlags flags, Predicate <MemberInfo> predicate, Formatter formatter) { // For members of type DynamicProperty (part of Dynamic View expansion), we want // to expand the underlying value (not the members of the DynamicProperty type). var type = value.Type; var isDynamicProperty = type.GetLmrType().IsDynamicProperty(); if (isDynamicProperty) { Debug.Assert(!value.IsNull); value = value.GetFieldValue("value", inspectionContext); } var runtimeType = type.GetLmrType(); // Primitives, enums and null values with a declared type that is an interface have no visible members. Debug.Assert(!runtimeType.IsInterface || value.IsNull); if (formatter.IsPredefinedType(runtimeType) || runtimeType.IsEnum || runtimeType.IsInterface) { return(null); } // As in the old C# EE, DynamicProperty members are only expandable if they have a Dynamic View expansion. var dynamicViewExpansion = DynamicViewExpansion.CreateExpansion(inspectionContext, value, formatter); if (isDynamicProperty && (dynamicViewExpansion == null)) { return(null); } var dynamicFlagsMap = DynamicFlagsMap.Create(declaredTypeAndInfo); var expansions = ArrayBuilder <Expansion> .GetInstance(); // From the members, collect the fields and properties, // separated into static and instance members. var staticMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); var instanceMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); var appDomain = value.Type.AppDomain; // Expand members. (Ideally, this should be done lazily.) var allMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); var includeInherited = (flags & ExpansionFlags.IncludeBaseMembers) == ExpansionFlags.IncludeBaseMembers; var hideNonPublic = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.HideNonPublicMembers) == DkmEvaluationFlags.HideNonPublicMembers; runtimeType.AppendTypeMembers(allMembers, predicate, declaredTypeAndInfo.Type, appDomain, includeInherited, hideNonPublic); foreach (var member in allMembers) { var name = member.Name; if (name.IsCompilerGenerated()) { continue; } if (member.IsStatic) { staticMembers.Add(member); } else if (!value.IsNull) { instanceMembers.Add(member); } } allMembers.Free(); // Public and non-public instance members. Expansion publicInstanceExpansion; Expansion nonPublicInstanceExpansion; GetPublicAndNonPublicMembers( instanceMembers, dynamicFlagsMap, out publicInstanceExpansion, out nonPublicInstanceExpansion); // Public and non-public static members. Expansion publicStaticExpansion; Expansion nonPublicStaticExpansion; GetPublicAndNonPublicMembers( staticMembers, dynamicFlagsMap, out publicStaticExpansion, out nonPublicStaticExpansion); if (publicInstanceExpansion != null) { expansions.Add(publicInstanceExpansion); } if ((publicStaticExpansion != null) || (nonPublicStaticExpansion != null)) { var staticExpansions = ArrayBuilder <Expansion> .GetInstance(); if (publicStaticExpansion != null) { staticExpansions.Add(publicStaticExpansion); } if (nonPublicStaticExpansion != null) { staticExpansions.Add(nonPublicStaticExpansion); } Debug.Assert(staticExpansions.Count > 0); var staticMembersExpansion = new StaticMembersExpansion( runtimeType, AggregateExpansion.CreateExpansion(staticExpansions)); staticExpansions.Free(); expansions.Add(staticMembersExpansion); } if (value.NativeComPointer != 0) { expansions.Add(NativeViewExpansion.Instance); } if (nonPublicInstanceExpansion != null) { expansions.Add(nonPublicInstanceExpansion); } // Include Results View if necessary. if ((flags & ExpansionFlags.IncludeResultsView) != 0) { var resultsViewExpansion = ResultsViewExpansion.CreateExpansion(inspectionContext, value, formatter); if (resultsViewExpansion != null) { expansions.Add(resultsViewExpansion); } } if (dynamicViewExpansion != null) { expansions.Add(dynamicViewExpansion); } var result = AggregateExpansion.CreateExpansion(expansions); expansions.Free(); return(result); }
internal string FormatPrimitive(DkmClrValue value, ObjectDisplayOptions options, DkmInspectionContext inspectionContext) { Debug.Assert(value != null); object obj; if (value.Type.GetLmrType().IsDateTime()) { DkmClrValue dateDataValue = value.GetFieldValue(DateTimeUtilities.DateTimeDateDataFieldName, inspectionContext); Debug.Assert(dateDataValue.HostObjectValue != null); obj = DateTimeUtilities.ToDateTime((ulong)dateDataValue.HostObjectValue); } else { Debug.Assert(value.HostObjectValue != null); obj = value.HostObjectValue; } return(FormatPrimitiveObject(obj, options)); }
internal static DkmClrValue GetFieldValue(this DkmClrValue value, string name, DkmInspectionContext inspectionContext) { return(value.GetMemberValue(name, (int)MemberTypes.Field, ParentTypeName: null, InspectionContext: inspectionContext)); }
internal static DkmClrValue GetNullableValue(this DkmClrValue value, Type nullableTypeArg, DkmInspectionContext inspectionContext) { var valueType = value.Type.GetLmrType(); if (valueType.Equals(nullableTypeArg)) { return(value); } return(value.GetNullableValue(inspectionContext)); }
public string GetUnderlyingString(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } return inspectionContext.InspectionSession.InvokeFormatter(this, MethodId.GetUnderlyingString, f => f.GetUnderlyingString(this, inspectionContext)); }
internal static void GetTupleFieldValues(this DkmClrValue tuple, int cardinality, ArrayBuilder <string> values, DkmInspectionContext inspectionContext) { while (true) { int n = Math.Min(cardinality, TupleFieldRestPosition - 1); for (int i = 0; i < n; i++) { var value = GetFieldValue(tuple, TupleFieldItemNamePrefix + (i + 1), inspectionContext); var str = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers); values.Add(str); } cardinality -= n; if (cardinality == 0) { return; } tuple = GetFieldValue(tuple, TupleFieldRestName, inspectionContext); } }
public string EvaluateToString(DkmInspectionContext inspectionContext) { if (inspectionContext == null) { throw new ArgumentNullException(nameof(inspectionContext)); } // This is a rough approximation of the real functionality. Basically, // if object.ToString is not overridden, we return null and it is the // caller's responsibility to compute a string. var type = this.Type.GetLmrType(); while (type != null) { if (type.IsObject() || type.IsValueType()) { return null; } // We should check the signature and virtual-ness, but this is // close enough for testing. if (type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Any(m => m.Name == "ToString")) { break; } type = type.BaseType; } 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(); }
private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, WorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine <DkmEvaluationResult> completionRoutine) { switch (dataItem.Kind) { case ExpansionKind.Error: completionRoutine(DkmFailedEvaluationResult.Create( inspectionContext, StackFrame: stackFrame, Name: dataItem.Name, FullName: dataItem.FullName, ErrorMessage: dataItem.DisplayValue, Flags: DkmEvaluationResultFlags.None, Type: null, 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(DkmSuccessEvaluationResult.Create( inspectionContext, 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(DkmSuccessEvaluationResult.Create( inspectionContext, 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(DkmSuccessEvaluationResult.Create( inspectionContext, 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.TypeVariable: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, dataItem.Name, dataItem.FullName, dataItem.Flags, dataItem.DisplayValue, EditableValue: null, Type: dataItem.DisplayValue, 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.PointerDereference: case ExpansionKind.Default: // This call will evaluate DebuggerDisplayAttributes. GetResultAndContinue( dataItem, workList, declaredType: DkmClrType.Create(dataItem.Value.Type.AppDomain, dataItem.DeclaredTypeAndInfo.Type), declaredTypeInfo: dataItem.DeclaredTypeAndInfo.Info, inspectionContext: inspectionContext, parent: dataItem.Parent, completionRoutine: completionRoutine); break; default: throw ExceptionUtilities.UnexpectedValue(dataItem.Kind); } }
public DkmClrValue GetMemberValue(string MemberName, int MemberType, string ParentTypeName, DkmInspectionContext InspectionContext) { if (InspectionContext == null) { throw new ArgumentNullException(nameof(InspectionContext)); } if (this.IsError()) { throw new InvalidOperationException(); } var runtime = this.Type.RuntimeInstance; var getMemberValue = runtime.GetMemberValue; if (getMemberValue != null) { var memberValue = getMemberValue(this, MemberName); if (memberValue != null) { return memberValue; } } var declaringType = this.Type.GetLmrType(); if (ParentTypeName != null) { declaringType = GetAncestorType(declaringType, ParentTypeName); Debug.Assert(declaringType != null); } // Special cases for nullables if (declaringType.IsNullable()) { if (MemberName == InternalWellKnownMemberNames.NullableHasValue) { // In our mock implementation, RawValue is null for null nullables, // so we have to compute HasValue some other way. var boolValue = RawValue != null; var boolType = runtime.GetType((TypeImpl)typeof(bool)); return new DkmClrValue( boolValue, boolValue, type: boolType, alias: null, evalFlags: DkmEvaluationResultFlags.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<T> for nullables, so we'll just return that value // (no need to unwrap by getting "value" field). var valueType = runtime.GetType((TypeImpl)RawValue.GetType()); return new DkmClrValue( RawValue, RawValue, type: valueType, alias: null, evalFlags: DkmEvaluationResultFlags.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 | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; switch ((MemberTypes)MemberType) { 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); } catch (System.Reflection.TargetInvocationException e) { var exception = e.InnerException; return new DkmClrValue( exception, exception, type: runtime.GetType((TypeImpl)exception.GetType()), alias: null, evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown, 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); } catch (System.Reflection.TargetInvocationException e) { var exception = e.InnerException; return new DkmClrValue( exception, exception, type: runtime.GetType((TypeImpl)exception.GetType()), alias: null, evalFlags: evalFlags | DkmEvaluationResultFlags.ExceptionThrown, valueFlags: DkmClrValueFlags.None, category: category, access: access); } break; default: throw ExceptionUtilities.UnexpectedValue((MemberTypes)MemberType); } Type type; if (value is System.Reflection.Pointer) { value = UnboxPointer(value); type = declaredType; } else if (value == null || declaredType.IsNullable()) { type = declaredType; } else { type = (TypeImpl)value.GetType(); } return new DkmClrValue( value, value, type: runtime.GetType(type), alias: null, evalFlags: evalFlags, valueFlags: DkmClrValueFlags.None, category: category, access: access); }
internal EvalResultDataItem CreateDataItem( DkmInspectionContext inspectionContext, string name, TypeAndCustomInfo typeDeclaringMemberAndInfo, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, EvalResultDataItem parent, ExpansionFlags expansionFlags, bool childShouldParenthesize, string fullName, ReadOnlyCollection <string> formatSpecifiers, DkmEvaluationResultCategory category, DkmEvaluationResultFlags flags, DkmEvaluationFlags evalFlags) { if ((evalFlags & DkmEvaluationFlags.ShowValueRaw) != 0) { formatSpecifiers = Formatter.AddFormatSpecifier(formatSpecifiers, "raw"); } Expansion expansion; // If the declared type is Nullable<T>, the value should // have no expansion if null, or be expanded as a T. var declaredType = declaredTypeAndInfo.Type; var lmrNullableTypeArg = declaredType.GetNullableTypeArgument(); if (lmrNullableTypeArg != null && !value.HasExceptionThrown()) { Debug.Assert(value.Type.GetProxyType() == null); DkmClrValue nullableValue; if (value.IsError()) { expansion = null; } else if ((nullableValue = value.GetNullableValue(inspectionContext)) == null) { Debug.Assert(declaredType.Equals(value.Type.GetLmrType())); // No expansion of "null". expansion = null; } else { value = nullableValue; Debug.Assert(lmrNullableTypeArg.Equals(value.Type.GetLmrType())); // If this is not the case, add a test for includeRuntimeTypeIfNecessary. // CONSIDER: The DynamicAttribute for the type argument should just be Skip(1) of the original flag array. expansion = this.GetTypeExpansion(inspectionContext, new TypeAndCustomInfo(lmrNullableTypeArg), value, ExpansionFlags.IncludeResultsView); } } else if (value.IsError() || (inspectionContext.EvaluationFlags & DkmEvaluationFlags.NoExpansion) != 0) { expansion = null; } else { expansion = DebuggerTypeProxyExpansion.CreateExpansion( this, inspectionContext, name, typeDeclaringMemberAndInfo, declaredTypeAndInfo, value, childShouldParenthesize, fullName, flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName, formatSpecifiers, flags, this.Formatter.GetEditableValue(value, inspectionContext)); if (expansion == null) { expansion = value.HasExceptionThrown() ? this.GetTypeExpansion(inspectionContext, new TypeAndCustomInfo(value.Type), value, expansionFlags) : this.GetTypeExpansion(inspectionContext, declaredTypeAndInfo, value, expansionFlags); } } return(new EvalResultDataItem( ExpansionKind.Default, name, typeDeclaringMemberAndInfo, declaredTypeAndInfo, parent: parent, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: childShouldParenthesize, fullName: fullName, childFullNamePrefixOpt: flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName, formatSpecifiers: formatSpecifiers, category: category, flags: flags, editableValue: this.Formatter.GetEditableValue(value, inspectionContext), inspectionContext: inspectionContext)); }
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); }
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(); }
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); }
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, Formatter.NoFormatSpecifiers)), flags)); }