private DebuggerTypeProxyExpansion( DkmInspectionContext inspectionContext, DkmClrValue proxyValue, string name, Type typeDeclaringMemberOpt, Type declaredType, 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 proxyMembers = MemberExpansion.CreateExpansion( inspectionContext, proxyType, proxyValue, ExpansionFlags.IncludeBaseMembers, TypeHelpers.IsPublic, formatter); if (proxyMembers != null) { var proxyMemberFullNamePrefix = (childFullNamePrefix == null) ? null : formatter.GetObjectCreationExpression(formatter.GetTypeName(proxyType, escapeKeywordIdentifiers: true), childFullNamePrefix); _proxyItem = new EvalResultDataItem( ExpansionKind.Default, name: string.Empty, typeDeclaringMember: null, declaredType: proxyType, 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; _typeDeclaringMemberOpt = typeDeclaringMemberOpt; _declaredType = declaredType; _value = value; _childShouldParenthesize = childShouldParenthesize; _fullName = fullName; _childFullNamePrefix = childFullNamePrefix; _formatSpecifiers = formatSpecifiers; _flags = flags; _editableValue = editableValue; }
private static ResultsViewExpansion CreateExpansion( DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType enumerableType, ResultProvider resultProvider ) { var proxyValue = value.InstantiateResultsViewProxy(inspectionContext, enumerableType); // InstantiateResultsViewProxy may return null (if required assembly is missing, for instance). if (proxyValue == null) { return(null); } var proxyMembers = MemberExpansion.CreateExpansion( inspectionContext, new TypeAndCustomInfo(proxyValue.Type), proxyValue, flags: ExpansionFlags.None, predicate: TypeHelpers.IsPublic, resultProvider: resultProvider, isProxyType: false, supportsFavorites: false ); return(new ResultsViewExpansion(proxyValue, proxyMembers)); }
internal Expansion GetTypeExpansion(DkmInspectionContext inspectionContext, Type declaredType, DkmClrValue value, ExpansionFlags flags) { 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; return(ArrayExpansion.CreateExpansion(sizes, lowerBounds)); } if (this.Formatter.IsPredefinedType(runtimeType)) { return(null); } if (declaredType.IsPointer) { return(!value.IsNull ? new PointerDereferenceExpansion(declaredType.GetElementType()) : null); } 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, declaredType, value, flags, TypeHelpers.IsVisibleMember, this.Formatter)); }
internal override void GetRows( ResultProvider resultProvider, ArrayBuilder <EvalResult> rows, DkmInspectionContext inspectionContext, EvalResultDataItem parent, DkmClrValue value, int startIndex, int count, bool visitAll, ref int index) { var memberValue = value.GetMemberValue(_member, inspectionContext); var isDynamicDebugViewEmptyException = memberValue.Type.GetLmrType().IsDynamicDebugViewEmptyException(); if (isDynamicDebugViewEmptyException || memberValue.IsError()) { if (InRange(startIndex, count, index)) { if (isDynamicDebugViewEmptyException) { var emptyMember = memberValue.Type.GetMemberByName("Empty"); memberValue = memberValue.GetMemberValue(emptyMember, inspectionContext); } var row = new EvalResult(Resources.ErrorName, (string)memberValue.HostObjectValue, inspectionContext); rows.Add(row); } index++; } else { var other = MemberExpansion.CreateMemberDataItem( resultProvider, inspectionContext, _member, memberValue, parent, _customTypeInfoMap, ExpansionFlags.IncludeBaseMembers | ExpansionFlags.IncludeResultsView, supportsFavorites: false); var expansion = other.Expansion; if (expansion != null) { expansion.GetRows(resultProvider, rows, inspectionContext, other.ToDataItem(), other.Value, startIndex, count, visitAll, ref index); } } }
private static ResultsViewExpansion CreateExpansion(DkmClrValue value, DkmClrType enumerableType, Formatter formatter) { var proxyValue = value.InstantiateResultsViewProxy(enumerableType); // InstantiateResultsViewProxy may return null // (if assembly is missing for instance). if (proxyValue == null) { return(null); } var proxyMembers = MemberExpansion.CreateExpansion( proxyValue.Type.GetLmrType(), proxyValue, ExpansionFlags.None, TypeHelpers.IsPublic, formatter); return(new ResultsViewExpansion(proxyValue, proxyMembers)); }
private static ResultsViewExpansion CreateExpansion(DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType enumerableType, Formatter formatter) { var proxyValue = value.InstantiateResultsViewProxy(inspectionContext, enumerableType); // InstantiateResultsViewProxy may return null // (if assembly is missing for instance). if (proxyValue == null) { return(null); } var proxyMembers = MemberExpansion.CreateExpansion( inspectionContext, new TypeAndCustomInfo(proxyValue.Type), proxyValue, flags: ExpansionFlags.None, predicate: TypeHelpers.IsPublic, formatter: formatter); return(new ResultsViewExpansion(proxyValue, proxyMembers)); }
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, ResultProvider resultProvider) { Debug.Assert(proxyValue != null); var proxyType = proxyValue.Type; var proxyTypeAndInfo = new TypeAndCustomInfo(proxyType); var proxyMembers = MemberExpansion.CreateExpansion( inspectionContext, proxyTypeAndInfo, proxyValue, ExpansionFlags.IncludeBaseMembers, TypeHelpers.IsPublic, resultProvider, isProxyType: true); if (proxyMembers != null) { string proxyMemberFullNamePrefix = null; if (childFullNamePrefix != null) { proxyMemberFullNamePrefix = resultProvider.FullNameProvider.GetClrObjectCreationExpression( inspectionContext, proxyTypeAndInfo.ClrType, proxyTypeAndInfo.Info, new[] { childFullNamePrefix }); } _proxyItem = new EvalResult( ExpansionKind.Default, name: string.Empty, typeDeclaringMemberAndInfo: default(TypeAndCustomInfo), declaredTypeAndInfo: proxyTypeAndInfo, useDebuggerDisplay: false, 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 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 static Expansion CreateExpansion( DkmInspectionContext inspectionContext, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, ExpansionFlags flags, Predicate <MemberInfo> predicate, ResultProvider resultProvider, bool isProxyType, bool supportsFavorites ) { // 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 runtimeType = type.GetLmrType(); var isDynamicProperty = runtimeType.IsDynamicProperty(); if (isDynamicProperty) { Debug.Assert(!value.IsNull); value = value.GetFieldValue("value", inspectionContext); } // Primitives, enums, function pointers, IntPtr, UIntPtr and null values with a declared type that is an interface have no visible members. Debug.Assert(!runtimeType.IsInterface || value.IsNull); if ( resultProvider.IsPrimitiveType(runtimeType) || runtimeType.IsEnum || runtimeType.IsInterface || runtimeType.IsFunctionPointer() || runtimeType.IsIntPtr() || runtimeType.IsUIntPtr() ) { 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, resultProvider ); if (isDynamicProperty && (dynamicViewExpansion == null)) { return(null); } var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaredTypeAndInfo); var expansions = ArrayBuilder <Expansion> .GetInstance(); // Expand members. TODO: Ideally, this would be done lazily (https://github.com/dotnet/roslyn/issues/32800) // 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; var allMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); var includeInherited = (flags & ExpansionFlags.IncludeBaseMembers) == ExpansionFlags.IncludeBaseMembers; var hideNonPublic = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.HideNonPublicMembers) == DkmEvaluationFlags.HideNonPublicMembers; var includeCompilerGenerated = (inspectionContext.EvaluationFlags & DkmEvaluationFlags.ShowValueRaw) == DkmEvaluationFlags.ShowValueRaw; var favoritesInfo = supportsFavorites ? type.GetFavorites() : null; runtimeType.AppendTypeMembers( allMembers, predicate, declaredTypeAndInfo.Type, appDomain, includeInherited, hideNonPublic, isProxyType, includeCompilerGenerated, supportsFavorites, favoritesInfo ); var favoritesMembersByName = new Dictionary <string, MemberAndDeclarationInfo>(); foreach (var member in allMembers) { // Favorites are currently never static if (member.IsFavorite && !value.IsNull) { favoritesMembersByName.Add(member.Name, member); } else if (member.IsStatic) { staticMembers.Add(member); } else if (!value.IsNull) { instanceMembers.Add(member); } } allMembers.Free(); // Favorites members. Expansion favoritesExpansion = null; if (favoritesMembersByName.Count > 0) { var favoritesMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); foreach (string name in favoritesInfo.Favorites) { if (favoritesMembersByName.TryGetValue(name, out var memberAndDeclarationInfo)) { favoritesMembers.Add(memberAndDeclarationInfo); } } if (favoritesMembers.Count > 0) { favoritesExpansion = new MemberExpansion( favoritesMembers.ToArrayAndFree(), customTypeInfoMap, containsFavorites: true ); } } if (favoritesExpansion != null) { expansions.Add(favoritesExpansion); // Check if we are only expanding favorites. if ( (inspectionContext.EvaluationFlags & DkmEvaluationFlags.FilterToFavorites) == DkmEvaluationFlags.FilterToFavorites ) { instanceMembers.Free(); staticMembers.Free(); expansions.Free(); return(favoritesExpansion); } } // Public and non-public instance members. Expansion publicInstanceExpansion; Expansion nonPublicInstanceExpansion; GetPublicAndNonPublicMembers( instanceMembers, customTypeInfoMap, isProxyType, out publicInstanceExpansion, out nonPublicInstanceExpansion ); // Public and non-public static members. Expansion publicStaticExpansion; Expansion nonPublicStaticExpansion; GetPublicAndNonPublicMembers( staticMembers, customTypeInfoMap, isProxyType, 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( type, AggregateExpansion.CreateExpansion(staticExpansions) ); staticExpansions.Free(); expansions.Add(staticMembersExpansion); } instanceMembers.Free(); staticMembers.Free(); 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, resultProvider ); if (resultsViewExpansion != null) { expansions.Add(resultsViewExpansion); } } if (dynamicViewExpansion != null) { expansions.Add(dynamicViewExpansion); } var result = AggregateExpansion.CreateExpansion(expansions); expansions.Free(); return(result); }