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)); }
private static DkmClrType GetEnumerableType(DkmClrValue value) { Debug.Assert(!value.IsError()); if (value.IsNull) { return(null); } var valueType = value.Type.GetLmrType(); // Do not support Results View for strings // or arrays. (Matches legacy EE.) if (valueType.IsString() || valueType.IsArray) { return(null); } var enumerableType = valueType.GetIEnumerableImplementationIfAny(); if (enumerableType == null) { return(null); } return(DkmClrType.Create(value.Type.AppDomain, enumerableType)); }
internal static DkmClrType GetProxyType(this DkmClrType type) { // CONSIDER: If needed, we could probably compute a new DynamicAttribute for // the proxy type based on the DynamicAttribute of the argument. DkmClrType attributeTarget; DkmClrDebuggerTypeProxyAttribute attribute; if (type.TryGetEvalAttribute(out attributeTarget, out attribute)) { var targetedType = attributeTarget.GetLmrType(); var proxyType = attribute.ProxyType; var underlyingProxy = proxyType.GetLmrType(); if (underlyingProxy.IsGenericType && targetedType.IsGenericType) { var typeArgs = targetedType.GetGenericArguments(); // Drop the proxy type if the arity does not match. if (typeArgs.Length != underlyingProxy.GetGenericArguments().Length) { return(null); } // Substitute target type arguments for proxy type arguments. var constructedProxy = underlyingProxy.Substitute(underlyingProxy, typeArgs); proxyType = DkmClrType.Create(type.AppDomain, constructedProxy); } return(proxyType); } return(null); }
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)); }
internal override string GetArrayDisplayString(DkmClrAppDomain appDomain, Type lmrType, ReadOnlyCollection <int> sizes, ReadOnlyCollection <int> lowerBounds, ObjectDisplayOptions options) { Debug.Assert(lmrType.IsArray); Type originalLmrType = lmrType; // Strip off all array types. We'll process them at the end. while (lmrType.IsArray) { lmrType = lmrType.GetElementType(); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; builder.Append('{'); // We're showing the type of a value, so "dynamic" does not apply. bool unused; builder.Append(GetTypeName(new TypeAndCustomInfo(DkmClrType.Create(appDomain, lmrType)), escapeKeywordIdentifiers: false, sawInvalidIdentifier: out unused)); // NOTE: call our impl directly, since we're coupled anyway. var numSizes = sizes.Count; builder.Append('['); for (int i = 0; i < numSizes; i++) { if (i > 0) { builder.Append(", "); } var lowerBound = lowerBounds[i]; var size = sizes[i]; if (lowerBound == 0) { builder.Append(FormatLiteral(size, options)); } else { builder.Append(FormatLiteral(lowerBound, options)); builder.Append(".."); builder.Append(FormatLiteral(size + lowerBound - 1, options)); } } builder.Append(']'); lmrType = originalLmrType.GetElementType(); // Strip off one layer (already handled). while (lmrType.IsArray) { builder.Append('['); builder.Append(',', lmrType.GetArrayRank() - 1); builder.Append(']'); lmrType = lmrType.GetElementType(); } builder.Append('}'); return(pooled.ToStringAndFree()); }
internal static Type GetBaseTypeOrNull(this Type underlyingType, DkmClrAppDomain appDomain, out DkmClrType type) { Debug.Assert((underlyingType.BaseType != null) || underlyingType.IsPointer || underlyingType.IsArray, "BaseType should only return null if the underlyingType is a pointer or array."); underlyingType = underlyingType.BaseType; type = (underlyingType != null) ? DkmClrType.Create(appDomain, underlyingType) : null; return(underlyingType); }
internal static EvalResult CreateMemberDataItem( ResultProvider resultProvider, DkmInspectionContext inspectionContext, MemberAndDeclarationInfo member, DkmClrValue memberValue, EvalResultDataItem parent, CustomTypeInfoTypeArgumentMap customTypeInfoMap, ExpansionFlags flags, bool supportsFavorites) { var fullNameProvider = resultProvider.FullNameProvider; var declaredType = member.Type; var declaredTypeInfo = customTypeInfoMap.SubstituteCustomTypeInfo(member.OriginalDefinitionType, member.TypeInfo); string memberName; // Considering, we're not handling the case of a member inherited from a generic base type. var typeDeclaringMember = member.GetExplicitlyImplementedInterface(out memberName) ?? member.DeclaringType; var typeDeclaringMemberInfo = typeDeclaringMember.IsInterface ? customTypeInfoMap.SubstituteCustomTypeInfo(typeDeclaringMember.GetInterfaceListEntry(member.DeclaringType), customInfo: null) : null; var memberNameForFullName = fullNameProvider.GetClrValidIdentifier(inspectionContext, memberName); var appDomain = memberValue.Type.AppDomain; string fullName; if (memberNameForFullName == null) { fullName = null; } else { memberName = memberNameForFullName; fullName = MakeFullName( fullNameProvider, inspectionContext, memberNameForFullName, new TypeAndCustomInfo(DkmClrType.Create(appDomain, typeDeclaringMember), typeDeclaringMemberInfo), // Note: Won't include DynamicAttribute. member.RequiresExplicitCast, member.IsStatic, parent); } return(resultProvider.CreateDataItem( inspectionContext, memberName, typeDeclaringMemberAndInfo: (member.IncludeTypeInMemberName || typeDeclaringMember.IsInterface) ? new TypeAndCustomInfo(DkmClrType.Create(appDomain, typeDeclaringMember), typeDeclaringMemberInfo) : default(TypeAndCustomInfo), // Note: Won't include DynamicAttribute. declaredTypeAndInfo: new TypeAndCustomInfo(DkmClrType.Create(appDomain, declaredType), declaredTypeInfo), value: memberValue, useDebuggerDisplay: parent != null, expansionFlags: flags, childShouldParenthesize: false, fullName: fullName, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: memberValue.EvalFlags, evalFlags: DkmEvaluationFlags.None, canFavorite: member.CanFavorite, isFavorite: member.IsFavorite, supportsFavorites: supportsFavorites)); }
private static TypeAndCustomInfo GetTupleFieldTypeAndInfo( DkmClrAppDomain appDomain, FieldInfo field, CustomTypeInfoTypeArgumentMap customTypeInfoMap) { var declaringTypeDef = field.DeclaringType.GetGenericTypeDefinition(); var fieldDef = declaringTypeDef.GetTupleField(field.Name); var fieldType = DkmClrType.Create(appDomain, field.FieldType); var fieldTypeInfo = customTypeInfoMap.SubstituteCustomTypeInfo(fieldDef.FieldType, null); return(new TypeAndCustomInfo(fieldType, fieldTypeInfo)); }
public DkmClrValue GetArrayElement(int[] indices) { 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, formatter: _formatter, evalFlags: DkmEvaluationResultFlags.None, valueFlags: DkmClrValueFlags.None, inspectionContext: this.InspectionContext)); }
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)); }
private DkmEvaluationResult GetRow(ResultProvider resultProvider, DkmClrValue value, int index, EvalResultDataItem parent) { var inspectionContext = value.InspectionContext; var appDomain = value.Type.AppDomain; var typeParameter = _typeParameters[index]; var typeArgument = _typeArguments[index]; var type = DkmClrType.Create(appDomain, typeArgument); var name = typeParameter.Name; var dataItem = new EvalResultDataItem( name, typeDeclaringMember: null, declaredType: typeArgument, value: null, expansion: null, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null); var typeName = inspectionContext.GetTypeName(DkmClrType.Create(appDomain, typeArgument)); return(DkmSuccessEvaluationResult.Create( inspectionContext, value.StackFrame, name, dataItem.FullName, dataItem.Flags, Value: typeName, EditableValue: null, Type: typeName, Category: dataItem.Category, Access: value.Access, StorageType: value.StorageType, TypeModifierFlags: value.TypeModifierFlags, Address: value.Address, CustomUIVisualizers: null, ExternalModules: null, DataItem: dataItem)); }
private static DkmEvaluationResult GetMemberRow( ResultProvider resultProvider, DkmInspectionContext inspectionContext, DkmClrValue value, MemberAndDeclarationInfo member, EvalResultDataItem parent) { var memberValue = GetMemberValue(value, member); var dataItem = CreateMemberDataItem( resultProvider, inspectionContext, member, memberValue, parent, ExpansionFlags.All); return(resultProvider.GetResult( dataItem, memberValue.Type, DkmClrType.Create(memberValue.Type.AppDomain, member.Type), parent)); }
private EvalResultDataItem GetRow(ResultProvider resultProvider, DkmInspectionContext inspectionContext, DkmClrValue value, int index, EvalResultDataItem parent) { var typeParameter = _typeParameters[index]; var typeArgument = _typeArguments[index]; var formatSpecifiers = Formatter.NoFormatSpecifiers; return(new EvalResultDataItem( ExpansionKind.TypeVariables, typeParameter.Name, typeDeclaringMember: null, declaredType: typeArgument, parent: parent, value: value, displayValue: inspectionContext.GetTypeName(DkmClrType.Create(value.Type.AppDomain, typeArgument), formatSpecifiers), expansion: null, childShouldParenthesize: false, fullName: null, childFullNamePrefixOpt: null, formatSpecifiers: formatSpecifiers, category: DkmEvaluationResultCategory.Data, flags: DkmEvaluationResultFlags.ReadOnly, editableValue: null, inspectionContext: inspectionContext)); }
internal static void AppendTypeMembers( this Type type, ArrayBuilder <MemberAndDeclarationInfo> includedMembers, Predicate <MemberInfo> predicate, Type declaredType, DkmClrAppDomain appDomain, bool includeInherited, bool hideNonPublic) { Debug.Assert(!type.IsInterface); var memberLocation = DeclarationInfo.FromSubTypeOfDeclaredType; var previousDeclarationMap = includeInherited ? new Dictionary <string, DeclarationInfo>() : null; int inheritanceLevel = 0; while (!type.IsObject()) { if (type.Equals(declaredType)) { Debug.Assert(memberLocation == DeclarationInfo.FromSubTypeOfDeclaredType); memberLocation = DeclarationInfo.FromDeclaredTypeOrBase; } // Get the state from DebuggerBrowsableAttributes for the members of the current type. var browsableState = DkmClrType.Create(appDomain, type).GetDebuggerBrowsableAttributeState(); // Hide non-public members if hideNonPublic is specified (intended to reflect the // DkmInspectionContext's DkmEvaluationFlags), and the type is from an assembly // with no symbols. var hideNonPublicBehavior = DeclarationInfo.None; if (hideNonPublic) { var moduleInstance = appDomain.FindClrModuleInstance(type.Module.ModuleVersionId); if (moduleInstance == null || moduleInstance.Module == null) { // Synthetic module or no symbols loaded. hideNonPublicBehavior = DeclarationInfo.HideNonPublic; } } foreach (var member in type.GetMembers(MemberBindingFlags)) { if (!predicate(member)) { continue; } var memberName = member.Name; // This represents information about the immediately preceding (more derived) // declaration with the same name as the current member. var previousDeclaration = DeclarationInfo.None; var memberNameAlreadySeen = false; if (includeInherited) { memberNameAlreadySeen = previousDeclarationMap.TryGetValue(memberName, out previousDeclaration); if (memberNameAlreadySeen) { // There was a name conflict, so we'll need to include the declaring // type of the member to disambiguate. previousDeclaration |= DeclarationInfo.IncludeTypeInMemberName; } // Update previous member with name hiding (casting) and declared location information for next time. previousDeclarationMap[memberName] = (previousDeclaration & ~(DeclarationInfo.RequiresExplicitCast | DeclarationInfo.FromSubTypeOfDeclaredType)) | member.AccessingBaseMemberWithSameNameRequiresExplicitCast() | memberLocation; } Debug.Assert(memberNameAlreadySeen != (previousDeclaration == DeclarationInfo.None)); // Decide whether to include this member in the list of members to display. if (!memberNameAlreadySeen || previousDeclaration.IsSet(DeclarationInfo.RequiresExplicitCast)) { DkmClrDebuggerBrowsableAttributeState?browsableStateValue = null; if (browsableState != null) { DkmClrDebuggerBrowsableAttributeState value; if (browsableState.TryGetValue(memberName, out value)) { browsableStateValue = value; } } if (memberLocation.IsSet(DeclarationInfo.FromSubTypeOfDeclaredType)) { // If the current type is a sub-type of the declared type, then // we always need to insert a cast to access the member previousDeclaration |= DeclarationInfo.RequiresExplicitCast; } else if (previousDeclaration.IsSet(DeclarationInfo.FromSubTypeOfDeclaredType)) { // If the immediately preceding member (less derived) was // declared on a sub-type of the declared type, then we'll // ignore the casting bit. Accessing a member through the // declared type is the same as casting to that type, so // the cast would be redundant. previousDeclaration &= ~DeclarationInfo.RequiresExplicitCast; } previousDeclaration |= hideNonPublicBehavior; includedMembers.Add(new MemberAndDeclarationInfo(member, browsableStateValue, previousDeclaration, inheritanceLevel)); } } if (!includeInherited) { break; } type = type.BaseType; inheritanceLevel++; } includedMembers.Sort(MemberAndDeclarationInfo.Comparer); }
/// <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(_formatter, 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, 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, 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 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; } }
/// <remarks> /// Very simple expression evaluation (may not support all syntax supported by Concord). /// </remarks> public string EvaluateDebuggerDisplayString(string formatString) { Debug.Assert(!this.IsNull, "Not supported by VIL"); 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, inspectionContext: this.InspectionContext); } 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, inspectionContext: this.InspectionContext); } 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, inspectionContext: this.InspectionContext); } 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, inspectionContext: this.InspectionContext); } } } builder.Append(exprValue.GetValueString()); // 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)); } return(pooled.ToStringAndFree()); }
internal Expansion GetTypeExpansion( DkmInspectionContext inspectionContext, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, ExpansionFlags flags) { var declaredType = declaredTypeAndInfo.Type; Debug.Assert(!declaredType.IsTypeVariables()); if ((inspectionContext.EvaluationFlags & DkmEvaluationFlags.NoExpansion) != 0) { return(null); } var runtimeType = value.Type.GetLmrType(); // If the value is an array, expand the array elements. if (runtimeType.IsArray) { var sizes = value.ArrayDimensions; if (sizes == null) { // Null array. No expansion. return(null); } var lowerBounds = value.ArrayLowerBounds; Type elementType; DkmClrCustomTypeInfo elementTypeInfo; if (declaredType.IsArray) { elementType = declaredType.GetElementType(); elementTypeInfo = CustomTypeInfo.SkipOne(declaredTypeAndInfo.Info); } else { elementType = runtimeType.GetElementType(); elementTypeInfo = null; } return(ArrayExpansion.CreateExpansion(new TypeAndCustomInfo(DkmClrType.Create(declaredTypeAndInfo.ClrType.AppDomain, elementType), elementTypeInfo), sizes, lowerBounds)); } if (this.IsPrimitiveType(runtimeType)) { return(null); } if (declaredType.IsFunctionPointer()) { // Function pointers have no expansion return(null); } if (declaredType.IsPointer) { // If this assert fails, the element type info is just .SkipOne(). Debug.Assert(declaredTypeAndInfo.Info?.PayloadTypeId != CustomTypeInfo.PayloadTypeId); var elementType = declaredType.GetElementType(); return(value.IsNull || elementType.IsVoid() ? null : new PointerDereferenceExpansion(new TypeAndCustomInfo(DkmClrType.Create(declaredTypeAndInfo.ClrType.AppDomain, elementType)))); } if (value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown) && runtimeType.IsEmptyResultsViewException()) { // The value is an exception thrown expanding an empty // IEnumerable. Use the runtime type of the exception and // skip base types. (This matches the native EE behavior // to expose a single property from the exception.) flags &= ~ExpansionFlags.IncludeBaseMembers; } return(MemberExpansion.CreateExpansion(inspectionContext, declaredTypeAndInfo, value, flags, TypeHelpers.IsVisibleMember, this)); }
internal EvalResult CreateDataItem( DkmInspectionContext inspectionContext, string name, TypeAndCustomInfo typeDeclaringMemberAndInfo, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, bool useDebuggerDisplay, 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(lmrNullableTypeArg, 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(DkmClrType.Create(declaredTypeAndInfo.ClrType.AppDomain, 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, Formatter2.GetEditableValueString(value, inspectionContext, declaredTypeAndInfo.Info)); if (expansion == null) { expansion = value.HasExceptionThrown() ? this.GetTypeExpansion(inspectionContext, new TypeAndCustomInfo(value.Type), value, expansionFlags) : this.GetTypeExpansion(inspectionContext, declaredTypeAndInfo, value, expansionFlags); } } return(new EvalResult( ExpansionKind.Default, name, typeDeclaringMemberAndInfo, declaredTypeAndInfo, useDebuggerDisplay: useDebuggerDisplay, value: value, displayValue: null, expansion: expansion, childShouldParenthesize: childShouldParenthesize, fullName: fullName, childFullNamePrefixOpt: flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName, formatSpecifiers: formatSpecifiers, category: category, flags: flags, editableValue: Formatter2.GetEditableValueString(value, inspectionContext, declaredTypeAndInfo.Info), inspectionContext: inspectionContext)); }
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.DynamicView: case ExpansionKind.ResultsView: completionRoutine(DkmSuccessEvaluationResult.Create( inspectionContext, stackFrame, dataItem.Name, dataItem.FullName, dataItem.Flags, dataItem.DisplayValue, 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); } }
private static DkmEvaluationResult GetRow( ResultProvider resultProvider, DkmInspectionContext inspectionContext, DkmClrValue pointer, Type elementType, EvalResultDataItem parent) { var value = pointer.Dereference(); var valueType = value.Type.GetLmrType(); var wasExceptionThrown = value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown); string debuggerDisplayName; string debuggerDisplayValue; string debuggerDisplayType; value.GetDebuggerDisplayStrings(out debuggerDisplayName, out debuggerDisplayValue, out debuggerDisplayType); var declaredType = elementType; var typeName = debuggerDisplayType ?? pointer.InspectionContext.GetTypeName(DkmClrType.Create(pointer.Type.AppDomain, declaredType)); var expansion = wasExceptionThrown ? null : resultProvider.GetTypeExpansion(inspectionContext, declaredType, value, ExpansionFlags.None); var fullName = string.Format("*{0}", parent.ChildFullNamePrefix); var editableValue = resultProvider.Formatter.GetEditableValue(value); // NB: Full name is based on the real (i.e. not DebuggerDisplay) name. This is a change from dev12, // which used the DebuggerDisplay name, causing surprising results in "Add Watch" scenarios. var dataItem = new EvalResultDataItem( name: null, // Okay for pointer dereferences. typeDeclaringMember: null, declaredType: declaredType, value: value, expansion: expansion, childShouldParenthesize: true, fullName: fullName, childFullNamePrefixOpt: fullName, formatSpecifiers: Formatter.NoFormatSpecifiers, category: DkmEvaluationResultCategory.Other, flags: DkmEvaluationResultFlags.None, editableValue: editableValue); var name = debuggerDisplayName ?? fullName; var display = debuggerDisplayValue ?? (wasExceptionThrown ? string.Format(Resources.InvalidPointerDereference, fullName) : value.GetValueString()); return(ResultProvider.CreateEvaluationResult( value, name, typeName, display, dataItem)); }