internal static bool IsOrInheritsFrom(this Type type, Type baseType) { Debug.Assert(type != null); Debug.Assert(baseType != null); Debug.Assert(!baseType.IsInterface); if (type.IsInterface) { return(false); } do { if (type.Equals(baseType)) { return(true); } type = type.BaseType; }while (type != null); return(false); }
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); }
private static string MakeFullName( Formatter formatter, string name, Type typeDeclaringMember, bool memberAccessRequiresExplicitCast, bool memberIsStatic, EvalResultDataItem parent) { // If the parent is an exception thrown during evaluation, // there is no valid fullname expression for the child. if (parent.Value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown)) { return(null); } var parentFullName = parent.ChildFullNamePrefix; if (parentFullName == null) { return(null); } if (parent.ChildShouldParenthesize) { parentFullName = $"({parentFullName})"; } if (!typeDeclaringMember.IsInterface) { string qualifier; if (memberIsStatic) { qualifier = formatter.GetTypeName(typeDeclaringMember, escapeKeywordIdentifiers: false); } else if (memberAccessRequiresExplicitCast) { var typeName = formatter.GetTypeName(typeDeclaringMember, escapeKeywordIdentifiers: true); qualifier = formatter.GetCastExpression( parentFullName, typeName, parenthesizeEntireExpression: true); } else { qualifier = parentFullName; } return($"{qualifier}.{name}"); } else { // NOTE: This should never interact with debugger proxy types: // 1) Interfaces cannot have debugger proxy types. // 2) Debugger proxy types cannot be interfaces. if (typeDeclaringMember.Equals(parent.DeclaredType)) { var memberAccessTemplate = parent.ChildShouldParenthesize ? "({0}).{1}" : "{0}.{1}"; return(string.Format(memberAccessTemplate, parent.ChildFullNamePrefix, name)); } else { var interfaceName = formatter.GetTypeName(typeDeclaringMember, escapeKeywordIdentifiers: true); var memberAccessTemplate = parent.ChildShouldParenthesize ? "(({0})({1})).{2}" : "(({0}){1}).{2}"; return(string.Format(memberAccessTemplate, interfaceName, parent.ChildFullNamePrefix, name)); } } }