Exemplo n.º 1
0
        /// <summary>
        /// Extracts information from the first <see cref="DebuggerDisplayAttribute"/> on the runtime type of <paramref name="value"/>, if there is one.
        /// </summary>
        internal static bool TryGetDebuggerDisplayInfo(this DkmClrValue value, out DebuggerDisplayInfo displayInfo)
        {
            displayInfo = null;

            // The native EE does not consider DebuggerDisplayAttribute
            // on null or error instances.
            if (value.IsError() || value.IsNull)
            {
                return(false);
            }

            var clrType = value.Type;

            displayInfo = new DebuggerDisplayInfo(clrType);

            DkmClrObjectFavoritesInfo favoritesInfo = clrType.GetFavorites();

            if (favoritesInfo != null)
            {
                displayInfo = displayInfo.WithFavoritesInfo(favoritesInfo);
            }

            DkmClrType attributeTarget;
            DkmClrDebuggerDisplayAttribute attribute;

            if (clrType.TryGetEvalAttribute(out attributeTarget, out attribute)) // First, as in dev12.
            {
                displayInfo = displayInfo.WithDebuggerDisplayAttribute(attribute, attributeTarget);
            }

            return(displayInfo.HasValues);
        }
Exemplo n.º 2
0
        public DebuggerDisplayInfo WithFavoritesInfo(DkmClrObjectFavoritesInfo favoritesInfo)
        {
            var value       = m_value;
            var simpleValue = m_simpleValue;

            if (favoritesInfo.DisplayString != null)
            {
                value       = new DebuggerDisplayItemInfo(favoritesInfo.DisplayString, m_targetType);
                simpleValue =
                    favoritesInfo.SimpleDisplayString != null
                        ? new DebuggerDisplayItemInfo(
                        favoritesInfo.SimpleDisplayString,
                        m_targetType
                        )
                        : null;
            }

            return(new DebuggerDisplayInfo(
                       targetType: m_targetType,
                       name: Name,
                       value: value,
                       simpleValue: simpleValue,
                       typeName: TypeName,
                       hasFavoritesInfo: true
                       ));
        }
Exemplo n.º 3
0
 internal DkmClrType(DkmClrModuleInstance module, DkmClrAppDomain appDomain, Type lmrType, DkmClrObjectFavoritesInfo favorites = null)
 {
     _module         = module;
     _appDomain      = appDomain;
     _lmrType        = lmrType;
     _evalAttributes = GetEvalAttributes(lmrType);
     _favorites      = favorites;
 }
Exemplo n.º 4
0
        private DkmClrObjectFavoritesInfo GetObjectFavoritesInfo(Type type)
        {
            DkmClrObjectFavoritesInfo favorites = null;

            if (_favoritesByTypeName != null)
            {
                if (type.IsGenericType)
                {
                    type = type.GetGenericTypeDefinition();
                }

                _favoritesByTypeName.TryGetValue(type.FullName, out favorites);
            }

            return(favorites);
        }
Exemplo n.º 5
0
        internal static void AppendTypeMembers(
            this Type type,
            ArrayBuilder <MemberAndDeclarationInfo> includedMembers,
            Predicate <MemberInfo> predicate,
            Type declaredType,
            DkmClrAppDomain appDomain,
            bool includeInherited,
            bool hideNonPublic,
            bool isProxyType,
            bool includeCompilerGenerated,
            bool supportsFavorites,
            DkmClrObjectFavoritesInfo favoritesInfo)
        {
            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();

                // Disable favorites if any of the members have a browsable state of RootHidden
                if (supportsFavorites && browsableState != null)
                {
                    foreach (var browsableStateValue in browsableState.Values)
                    {
                        if (browsableStateValue == DkmClrDebuggerBrowsableAttributeState.RootHidden)
                        {
                            supportsFavorites = false;
                            break;
                        }
                    }
                }

                // Get the favorites information if it is supported.
                // NOTE: Using a Dictionary since Hashset is not available in .net 2.0
                Dictionary <string, object> favoritesMemberNames = null;
                if (supportsFavorites && favoritesInfo?.Favorites != null)
                {
                    favoritesMemberNames = new Dictionary <string, object>(favoritesInfo.Favorites.Count);

                    foreach (var favorite in favoritesInfo.Favorites)
                    {
                        favoritesMemberNames.Add(favorite, null);
                    }
                }

                // 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))
                {
                    var memberName = member.Name;
                    if (!includeCompilerGenerated && memberName.IsCompilerGenerated())
                    {
                        continue;
                    }

                    // The native EE shows proxy members regardless of accessibility if they have a
                    // DebuggerBrowsable attribute of any value. Match that behaviour here.
                    if (!isProxyType || browsableState == null || !browsableState.ContainsKey(memberName))
                    {
                        if (!predicate(member))
                        {
                            continue;
                        }
                    }

                    // 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,
                                canFavorite: supportsFavorites,
                                isFavorite: favoritesMemberNames?.ContainsKey(memberName) == true));
                    }
                }

                if (!includeInherited)
                {
                    break;
                }

                type = type.BaseType;
                inheritanceLevel++;
            }

            includedMembers.Sort(MemberAndDeclarationInfo.Comparer);
        }