internal static EvalResult CreateMemberDataItem( ResultProvider resultProvider, DkmInspectionContext inspectionContext, MemberAndDeclarationInfo member, DkmClrValue memberValue, EvalResultDataItem parent, CustomTypeInfoTypeArgumentMap customTypeInfoMap, ExpansionFlags flags) { 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)); }
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)); }
private MemberExpansion( MemberAndDeclarationInfo[] members, CustomTypeInfoTypeArgumentMap customTypeInfoMap, bool containsFavorites = false ) { Debug.Assert(members != null); Debug.Assert(members.Length > 0); Debug.Assert(customTypeInfoMap != null); _members = members; _customTypeInfoMap = customTypeInfoMap; _containsFavorites = containsFavorites; }
internal TypeVariablesExpansion(TypeAndCustomInfo declaredTypeAndInfo) { var declaredType = declaredTypeAndInfo.Type; Debug.Assert(declaredType.IsGenericType); Debug.Assert(!declaredType.IsGenericTypeDefinition); _customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaredTypeAndInfo); var typeDef = declaredType.GetGenericTypeDefinition(); _typeParameters = typeDef.GetGenericArguments(); _typeArguments = declaredType.GetGenericArguments(); Debug.Assert(_typeParameters.Length == _typeArguments.Length); Debug.Assert(Array.TrueForAll(_typeParameters, t => t.IsGenericParameter)); Debug.Assert(Array.TrueForAll(_typeArguments, t => !t.IsGenericParameter)); }
private static EvalResult GetMemberRow( ResultProvider resultProvider, DkmInspectionContext inspectionContext, DkmClrValue value, MemberAndDeclarationInfo member, EvalResultDataItem parent, CustomTypeInfoTypeArgumentMap customTypeInfoMap) { var memberValue = value.GetMemberValue(member, inspectionContext); return(CreateMemberDataItem( resultProvider, inspectionContext, member, memberValue, parent, customTypeInfoMap, ExpansionFlags.All)); }
internal static DynamicViewExpansion CreateExpansion( DkmInspectionContext inspectionContext, DkmClrValue value, ResultProvider resultProvider ) { if (value.IsError() || value.IsNull || value.HasExceptionThrown()) { return(null); } var type = value.Type.GetLmrType(); if (!(type.IsComObject() || type.IsIDynamicMetaObjectProvider())) { return(null); } var proxyValue = value.InstantiateDynamicViewProxy(inspectionContext); Debug.Assert( (proxyValue == null) || ( !proxyValue.IsNull && !proxyValue.IsError() && !proxyValue.HasExceptionThrown() ) ); // InstantiateDynamicViewProxy may return null (if required assembly is missing, for instance). if (proxyValue == null) { return(null); } // Expansion is based on the 'DynamicMetaObjectProviderDebugView.Items' property. var proxyType = proxyValue.Type; var itemsMemberExpansion = RootHiddenExpansion.CreateExpansion( proxyType.GetMemberByName("Items"), CustomTypeInfoTypeArgumentMap.Create(new TypeAndCustomInfo(proxyType)) ); return(new DynamicViewExpansion(proxyValue, itemsMemberExpansion)); }
internal static Expansion CreateExpansion( DkmInspectionContext inspectionContext, TypeAndCustomInfo declaredTypeAndInfo, DkmClrValue value, ExpansionFlags flags, Predicate <MemberInfo> predicate, ResultProvider resultProvider, bool isProxyType) { // 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; runtimeType.AppendTypeMembers(allMembers, predicate, declaredTypeAndInfo.Type, appDomain, includeInherited, hideNonPublic, isProxyType, includeCompilerGenerated); foreach (var member in allMembers) { 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, 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); }
private static void GetPublicAndNonPublicMembers( ArrayBuilder <MemberAndDeclarationInfo> allMembers, CustomTypeInfoTypeArgumentMap customTypeInfoMap, bool isProxyType, out Expansion publicExpansion, out Expansion nonPublicExpansion ) { var publicExpansions = ArrayBuilder <Expansion> .GetInstance(); var publicMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); var nonPublicMembers = ArrayBuilder <MemberAndDeclarationInfo> .GetInstance(); foreach (var member in allMembers) { if (member.BrowsableState.HasValue) { switch (member.BrowsableState.Value) { case DkmClrDebuggerBrowsableAttributeState.RootHidden: if (publicMembers.Count > 0) { publicExpansions.Add( new MemberExpansion(publicMembers.ToArray(), customTypeInfoMap) ); publicMembers.Clear(); } publicExpansions.Add( new RootHiddenExpansion(member, customTypeInfoMap) ); continue; case DkmClrDebuggerBrowsableAttributeState.Never: continue; } } // The native EE shows proxy type members as public members if they have a // DebuggerBrowsable attribute of any value. Match that behaviour here. if ( member.HideNonPublic && !member.IsPublic && (!isProxyType || !member.BrowsableState.HasValue) ) { nonPublicMembers.Add(member); } else { publicMembers.Add(member); } } if (publicMembers.Count > 0) { publicExpansions.Add( new MemberExpansion(publicMembers.ToArray(), customTypeInfoMap) ); } publicMembers.Free(); publicExpansion = AggregateExpansion.CreateExpansion(publicExpansions); publicExpansions.Free(); nonPublicExpansion = (nonPublicMembers.Count > 0) ? new NonPublicMembersExpansion( members: new MemberExpansion( nonPublicMembers.ToArray(), customTypeInfoMap ) ) : null; nonPublicMembers.Free(); }
internal RootHiddenExpansion(MemberAndDeclarationInfo member, CustomTypeInfoTypeArgumentMap customTypeInfoMap) { _member = member; _customTypeInfoMap = customTypeInfoMap; }
internal static Expansion CreateExpansion( MemberAndDeclarationInfo members, CustomTypeInfoTypeArgumentMap customTypeInfoMap) { return(new RootHiddenExpansion(members, customTypeInfoMap)); }
private static Fields GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality, bool useRawView) { Debug.Assert(declaringTypeAndInfo.Type.GetTupleCardinalityIfAny() == cardinality); var appDomain = declaringTypeAndInfo.ClrType.AppDomain; var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaringTypeAndInfo); var tupleElementNames = customTypeInfoMap.TupleElementNames; var builder = ArrayBuilder <Field> .GetInstance(); Field parent = null; int offset = 0; bool includeRawView = false; while (true) { var declaringType = declaringTypeAndInfo.Type; int n = Math.Min(cardinality, TypeHelpers.TupleFieldRestPosition - 1); for (int index = 0; index < n; index++) { var fieldName = TypeHelpers.GetTupleFieldName(index); var field = declaringType.GetTupleField(fieldName); if (field == null) { // Ignore missing fields. continue; } var fieldTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, field, customTypeInfoMap); if (!useRawView) { var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index); if (name != null) { includeRawView = true; builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent, isRest: false)); continue; } } builder.Add(new Field( declaringTypeAndInfo, fieldTypeAndInfo, field, (offset == 0) ? fieldName : TypeHelpers.GetTupleFieldName(offset + index), parent, isRest: false)); } cardinality -= n; if (cardinality == 0) { break; } var rest = declaringType.GetTupleField(TypeHelpers.TupleFieldRestName); if (rest == null) { // Ignore remaining fields. break; } var restTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, rest, customTypeInfoMap); var restField = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent, isRest: true); if (useRawView) { builder.Add(restField); break; } includeRawView = true; parent = restField; declaringTypeAndInfo = restTypeAndInfo; offset += TypeHelpers.TupleFieldRestPosition - 1; } return(new Fields(builder.ToImmutableAndFree(), includeRawView)); }
private static ReadOnlyCollection <Field> GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality) { Debug.Assert(declaringTypeAndInfo.Type.GetTupleCardinalityIfAny() == cardinality); var appDomain = declaringTypeAndInfo.ClrType.AppDomain; var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaringTypeAndInfo); var tupleElementNames = customTypeInfoMap.TupleElementNames; var builder = ArrayBuilder <Field> .GetInstance(); Field parent = null; int offset = 0; while (true) { var declaringType = declaringTypeAndInfo.Type; int n = Math.Min(cardinality, TypeHelpers.TupleFieldRestPosition - 1); for (int index = 0; index < n; index++) { var fieldName = TypeHelpers.GetTupleFieldName(index); var field = declaringType.GetTupleField(fieldName); if (field == null) { // Ignore missing fields. continue; } var fieldTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, field, customTypeInfoMap); var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index); if (name != null) { builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent)); } builder.Add(new Field( declaringTypeAndInfo, fieldTypeAndInfo, field, (offset == 0) ? fieldName : TypeHelpers.GetTupleFieldName(offset + index), parent)); } cardinality -= n; if (cardinality == 0) { break; } var rest = declaringType.GetTupleField(TypeHelpers.TupleFieldRestName); if (rest == null) { // Ignore remaining fields. break; } var restTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, rest, customTypeInfoMap); parent = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent); declaringTypeAndInfo = restTypeAndInfo; offset += TypeHelpers.TupleFieldRestPosition - 1; } // If there were any nested ValueTuples, // add the Rest field of the outermost. if (parent != null) { while (parent.Parent != null) { parent = parent.Parent; } builder.Add(parent); } return(builder.ToImmutableAndFree()); }