Beispiel #1
0
        internal DynamicFlagsCustomTypeInfo SubstituteDynamicFlags(Type type, DynamicFlagsCustomTypeInfo originalDynamicFlags)
        {
            if (_typeDefinition == null)
            {
                return originalDynamicFlags;
            }

            var substitutedFlags = ArrayBuilder<bool>.GetInstance();
            int f = 0;

            foreach (Type curr in new TypeWalker(type))
            {
                if (curr.IsGenericParameter && curr.DeclaringType.Equals(_typeDefinition))
                {
                    AppendFlagsFor(curr, substitutedFlags);
                }
                else
                {
                    substitutedFlags.Add(originalDynamicFlags[f]);
                }

                f++;
            }

            var result = DynamicFlagsCustomTypeInfo.Create(substitutedFlags);
            substitutedFlags.Free();
            return result;
        }
 protected override void AppendTupleElement(
     StringBuilder builder,
     Type type,
     string nameOpt,
     ReadOnlyCollection<byte> dynamicFlags,
     ref int dynamicFlagIndex,
     ReadOnlyCollection<string> tupleElementNames,
     ref int tupleElementIndex,
     bool escapeKeywordIdentifiers,
     out bool sawInvalidIdentifier)
 {
     sawInvalidIdentifier = false;
     bool sawSingleInvalidIdentifier;
     AppendQualifiedTypeName(
         builder,
         type,
         dynamicFlags,
         ref dynamicFlagIndex,
         tupleElementNames,
         ref tupleElementIndex,
         escapeKeywordIdentifiers,
         sawInvalidIdentifier: out sawSingleInvalidIdentifier);
     Debug.Assert(!sawSingleInvalidIdentifier);
     if (!string.IsNullOrEmpty(nameOpt))
     {
         builder.Append(' ');
         AppendIdentifier(builder, escapeKeywordIdentifiers, nameOpt, out sawSingleInvalidIdentifier);
         sawInvalidIdentifier |= sawSingleInvalidIdentifier;
     }
 }
        public EvalResultDataItem(
            string name,
            Type typeDeclaringMember,
            Type declaredType,
            DkmClrValue value,
            Expansion expansion,
            bool childShouldParenthesize,
            string fullName,
            string childFullNamePrefixOpt,
            ReadOnlyCollection<string> formatSpecifiers,
            DkmEvaluationResultCategory category,
            DkmEvaluationResultFlags flags,
            string editableValue)
        {
            Debug.Assert(formatSpecifiers != null);
            Debug.Assert((flags & DkmEvaluationResultFlags.Expandable) == 0);

            this.NameOpt = name;
            this.TypeDeclaringMember = typeDeclaringMember;
            this.DeclaredType = declaredType;
            this.Value = value;
            this.ChildShouldParenthesize = childShouldParenthesize;
            this.FullNameWithoutFormatSpecifiers = fullName;
            this.ChildFullNamePrefix = childFullNamePrefixOpt;
            this.FormatSpecifiers = formatSpecifiers;
            this.Category = category;
            this.EditableValue = editableValue;
            this.Flags = flags | GetFlags(value) | ((expansion == null) ? DkmEvaluationResultFlags.None : DkmEvaluationResultFlags.Expandable);
            this.Expansion = expansion;
        }
        protected override void AppendGenericTypeArgumentList(
            StringBuilder builder,
            Type[] typeArguments,
            int typeArgumentOffset,
            DynamicFlagsCustomTypeInfo dynamicFlags,
            ref int index,
            int arity,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            sawInvalidIdentifier = false;
            builder.Append('<');
            for (int i = 0; i < arity; i++)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }

                Type typeArgument = typeArguments[typeArgumentOffset + i];
                bool sawSingleInvalidIdentifier;
                AppendQualifiedTypeName(builder, typeArgument, dynamicFlags, ref index, escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
            }
            builder.Append('>');
        }
 private void AppendEnumTypeAndName(StringBuilder builder, Type typeToDisplayOpt, string name)
 {
     if (typeToDisplayOpt != null)
     {
         // We're showing the type of a value, so "dynamic" does not apply.
         bool unused;
         int index1 = 0;
         int index2 = 0;
         AppendQualifiedTypeName(
             builder,
             typeToDisplayOpt,
             null,
             ref index1,
             null,
             ref index2,
             escapeKeywordIdentifiers: true,
             sawInvalidIdentifier: out unused);
         builder.Append('.');
         AppendIdentifierEscapingPotentialKeywords(builder, name, sawInvalidIdentifier: out unused);
     }
     else
     {
         builder.Append(name);
     }
 }
Beispiel #6
0
        /// <summary>
        /// Append the qualified name (i.e. including containing types and namespaces) of a named,
        /// pointer, or array type to <paramref name="builder"/>.
        /// </summary>
        /// <remarks>
        /// Keyword strings are appended for primitive types (e.g. "int" for "System.Int32").
        /// Question mark syntax is used for <see cref="Nullable{T}"/>.
        /// No special handling is required for anonymous types - they are expected to be
        /// emitted with <see cref="DebuggerDisplayAttribute.Type"/> set to "&lt;Anonymous Type&gt;.
        /// This is fortunate, since we don't have a good way to recognize them in metadata.
        /// Does not call itself (directly).
        /// </remarks>
        protected void AppendQualifiedTypeName(
            StringBuilder builder,
            Type type,
            DynamicFlagsCustomTypeInfo dynamicFlags,
            ref int index,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            Type originalType = type;

            // Can have an array of pointers, but not a pointer to an array, so consume these first.
            // We'll reconstruct this information later from originalType.
            while (type.IsArray)
            {
                index++;
                type = type.GetElementType();
            }

            int pointerCount = 0;
            while (type.IsPointer)
            {
                var elementType = type.GetElementType();
                if (elementType == null)
                {
                    // Null for function pointers.
                    break;
                }
                index++;
                pointerCount++;
                type = elementType;
            }

            int nullableCount = 0;
            Type typeArg;
            while ((typeArg = type.GetNullableTypeArgument()) != null)
            {
                index++;
                nullableCount++;
                type = typeArg;
            }
            Debug.Assert(nullableCount < 2, "Benign: someone is nesting nullables.");

            Debug.Assert(pointerCount == 0 || nullableCount == 0, "Benign: pointer to nullable?");

            int oldLength = builder.Length;
            AppendQualifiedTypeNameInternal(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, out sawInvalidIdentifier);
            string name = builder.ToString(oldLength, builder.Length - oldLength);

            builder.Append('?', nullableCount);
            builder.Append('*', pointerCount);

            type = originalType;
            while (type.IsArray)
            {
                AppendRankSpecifier(builder, type.GetArrayRank());

                type = type.GetElementType();
            }
        }
        internal override string GetArrayDisplayString(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(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();
        }
        /// <returns>The qualified name (i.e. including containing types and namespaces) of a named,
        /// pointer, or array type.</returns>
        internal string GetTypeName(Type type, bool escapeKeywordIdentifiers = false)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            var pooled = PooledStringBuilder.GetInstance();
            AppendQualifiedTypeName(pooled.Builder, type, escapeKeywordIdentifiers);
            return pooled.ToStringAndFree();
        }
 private void AppendEnumTypeAndName(StringBuilder builder, Type typeToDisplayOpt, string name)
 {
     if (typeToDisplayOpt != null)
     {
         AppendQualifiedTypeName(builder, typeToDisplayOpt, escapeKeywordIdentifiers: true);
         builder.Append('.');
         AppendIdentifierEscapingPotentialKeywords(builder, name);
     }
     else
     {
         builder.Append(name);
     }
 }
        internal TypeVariablesExpansion(Type declaredType)
        {
            Debug.Assert(declaredType.IsGenericType);
            Debug.Assert(!declaredType.IsGenericTypeDefinition);

            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));
        }
Beispiel #11
0
        private DynamicFlagsMap(
            Type typeDefinition,
            DynamicFlagsCustomTypeInfo dynamicFlagsArray,
            int[] startIndices)
        {
            Debug.Assert(typeDefinition != null);
            Debug.Assert(startIndices != null);

            Debug.Assert(typeDefinition.IsGenericTypeDefinition);
            Debug.Assert(startIndices.Length == typeDefinition.GetGenericArguments().Length + 1);

            _typeDefinition = typeDefinition;
            _dynamicFlags = dynamicFlagsArray;
            _startIndices = startIndices;
        }
        protected override void AppendGenericTypeArgumentList(StringBuilder builder, Type[] typeArguments, int typeArgumentOffset, int arity, bool escapeKeywordIdentifiers)
        {
            builder.Append('<');
            for (int i = 0; i < arity; i++)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }

                Type typeArgument = typeArguments[typeArgumentOffset + i];
                AppendQualifiedTypeName(builder, typeArgument, escapeKeywordIdentifiers);
            }
            builder.Append('>');
        }
 private void AppendEnumTypeAndName(StringBuilder builder, Type typeToDisplayOpt, string name)
 {
     if (typeToDisplayOpt != null)
     {
         // We're showing the type of a value, so "dynamic" does not apply.
         int index = 0;
         AppendQualifiedTypeName(builder, typeToDisplayOpt, default(DynamicFlagsCustomTypeInfo), ref index, escapeKeywordIdentifiers: true);
         builder.Append('.');
         AppendIdentifierEscapingPotentialKeywords(builder, name);
     }
     else
     {
         builder.Append(name);
     }
 }
        /// <summary>
        /// Convert a type from the debugger's type system into Iris's type system
        /// </summary>
        /// <param name="lmrType">LMR Type</param>
        /// <returns>Iris type</returns>
        public static IrisType GetIrisTypeForLmrType(Type lmrType)
        {
            if (lmrType.IsPrimitive)
            {
                switch (lmrType.FullName)
                {
                    case "System.Int32":
                        return IrisType.Integer;
                    case "System.Boolean":
                        return IrisType.Boolean;
                }
            }
            else if (lmrType.IsArray)
            {
                if (lmrType.GetArrayRank() != 1)
                    return IrisType.Invalid;

                IrisType elementType = GetIrisTypeForLmrType(lmrType.GetElementType());
                if (elementType == IrisType.Invalid)
                    return IrisType.Invalid;

                return elementType.MakeArrayType();
            }
            else if (lmrType.IsByRef)
            {
                IrisType elementType = GetIrisTypeForLmrType(lmrType.GetElementType());
                if (elementType == IrisType.Invalid)
                    return IrisType.Invalid;

                return elementType.MakeByRefType();
            }
            else if (lmrType.FullName.Equals("System.String"))
            {
                return IrisType.String;
            }

            // Unknown
            return IrisType.Invalid;
        }
        protected override bool AppendSpecialTypeName(StringBuilder builder, Type type, bool escapeKeywordIdentifiers)
        {
            if (type.IsPredefinedType())
            {
                builder.Append(type.GetPredefinedTypeName()); // Not an identifier, does not require escaping.
                return true;
            }

            if (type.IsGenericParameter)
            {
                AppendIdentifier(builder, escapeKeywordIdentifiers, type.Name);
                return true;
            }

            if (type.IsVoid())
            {
                builder.Append("void"); // Not an identifier, does not require escaping.
                return true;
            }

            return false;
        }
        protected override bool AppendSpecialTypeName(StringBuilder builder, Type type, bool isDynamic)
        {
            if (isDynamic)
            {
                Debug.Assert(type.IsObject());
                builder.Append("dynamic"); // Not a keyword, does not require escaping.
                return true;
            }

            if (type.IsPredefinedType())
            {
                builder.Append(type.GetPredefinedTypeName()); // Not an identifier, does not require escaping.
                return true;
            }

            if (type.IsVoid())
            {
                builder.Append("void"); // Not an identifier, does not require escaping.
                return true;
            }

            return false;
        }
        protected override void AppendGenericTypeArguments(
            StringBuilder builder,
            Type[] typeArguments,
            int typeArgumentOffset,
            ReadOnlyCollection<byte> dynamicFlags,
            ref int dynamicFlagIndex,
            ReadOnlyCollection<string> tupleElementNames,
            ref int tupleElementIndex,
            int arity,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            sawInvalidIdentifier = false;
            builder.Append('<');
            for (int i = 0; i < arity; i++)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }

                Type typeArgument = typeArguments[typeArgumentOffset + i];
                bool sawSingleInvalidIdentifier;
                AppendQualifiedTypeName(
                    builder,
                    typeArgument,
                    dynamicFlags,
                    ref dynamicFlagIndex,
                    tupleElementNames,
                    ref tupleElementIndex,
                    escapeKeywordIdentifiers,
                    out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
            }
            builder.Append('>');
        }
Beispiel #18
0
#pragma warning disable RS0010
        /// <remarks>
        /// The corresponding native code is in EEUserStringBuilder::ErrTryAppendConstantEnum.
        /// The corresponding roslyn code is in
        /// <see cref="M:Microsoft.CodeAnalysis.SymbolDisplay.AbstractSymbolDisplayVisitor`1.AddEnumConstantValue(Microsoft.CodeAnalysis.INamedTypeSymbol, System.Object, System.Boolean)"/>.
        /// NOTE: no curlies for enum values.
        /// </remarks>
#pragma warning restore RS0010
        private string GetEnumDisplayString(Type lmrType, DkmClrValue value, ObjectDisplayOptions options, bool includeTypeName, DkmInspectionContext inspectionContext)
        {
            Debug.Assert(lmrType.IsEnum);
            Debug.Assert(value != null);

            object underlyingValue = value.HostObjectValue;

            Debug.Assert(underlyingValue != null);

            string displayString;

            ArrayBuilder <EnumField> fields = ArrayBuilder <EnumField> .GetInstance();

            FillEnumFields(fields, lmrType);
            // We will normalize/extend all enum values to ulong to ensure that we are always comparing the full underlying value.
            ulong valueForComparison = ConvertEnumUnderlyingTypeToUInt64(underlyingValue, Type.GetTypeCode(lmrType));
            var   typeToDisplayOpt   = includeTypeName ? lmrType : null;

            if (valueForComparison != 0 && IsFlagsEnum(lmrType))
            {
                displayString = GetNamesForFlagsEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt);
            }
            else
            {
                displayString = GetNameForEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt);
            }
            fields.Free();

            return(displayString ?? FormatPrimitive(value, options, inspectionContext));
        }
Beispiel #19
0
 internal override bool IsPredefinedType(Type type)
 {
     return(type.IsPredefinedType());
 }
Beispiel #20
0
        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 override bool IsPredefinedType(Type type)
 {
     return type.IsPredefinedType();
 }
Beispiel #22
0
        internal override string GetNameForEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt)
        {
            foreach (var field in fields)
            {
                // First match wins (deterministic since sorted).
                if (underlyingValue == field.Value)
                {
                    var pooled = PooledStringBuilder.GetInstance();
                    var builder = pooled.Builder;

                    AppendEnumTypeAndName(builder, typeToDisplayOpt, field.Name);

                    return pooled.ToStringAndFree();
                }
            }

            return null;
        }
Beispiel #23
0
 internal abstract string GetNameForEnumValue(ArrayBuilder <EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt);
 internal abstract string GetArrayDisplayString(Type lmrType, ReadOnlyCollection<int> sizes, ReadOnlyCollection<int> lowerBounds, ObjectDisplayOptions options);
Beispiel #25
0
        /// <summary>
        /// Append the name of the type and its type arguments.  Do not append the type's containing type or namespace.
        /// </summary>
        /// <param name="builder">Builder to which the name will be appended.</param>
        /// <param name="type">Type, the name of which will be appended.</param>
        /// <param name="dynamicFlags">Flags indicating which occurrences of &quot;object&quot; need to be replaced by &quot;dynamic&quot;.</param>
        /// <param name="index">Current index into <paramref name="dynamicFlags"/>.</param>
        /// <param name="escapeKeywordIdentifiers">True if identifiers that are also keywords should be prefixed with '@'.</param>
        /// <param name="typeArguments">
        /// The type arguments of the type passed to <see cref="AppendQualifiedTypeNameInternal"/>, which might be nested
        /// within <paramref name="type"/>.  In the Reflection/LMR object model, all type arguments are passed to the
        /// most nested type.  To get back to the C# model, we have to propagate them out to containing types.
        /// </param>
        /// <param name="typeArgumentOffset">
        /// The first position in <paramref name="typeArguments"/> that is a type argument to <paramref name="type"/>,
        /// from a C# perspective.
        /// </param>
        /// <param name="arity">
        /// The number of type parameters of <paramref name="type"/>, from a C# perspective.
        /// </param>
        /// <param name="sawInvalidIdentifier">True if the name includes an invalid identifier (see <see cref="IsValidIdentifier"/>); false otherwise.</param>
        /// <remarks>
        /// We're passing the full array plus bounds, rather than a tailored array, to avoid creating a lot of short-lived
        /// temporary arrays.
        /// </remarks>
        private void AppendUnqualifiedTypeName(
            StringBuilder builder, 
            Type type, 
            DynamicFlagsCustomTypeInfo dynamicFlags, 
            ref int index, 
            bool escapeKeywordIdentifiers, 
            Type[] typeArguments, 
            int typeArgumentOffset, 
            int arity, 
            out bool sawInvalidIdentifier)
        {
            if (typeArguments == null || arity == 0)
            {
                AppendIdentifier(builder, escapeKeywordIdentifiers, type.Name, out sawInvalidIdentifier);
                return;
            }

            var mangledName = type.Name;
            var separatorIndex = mangledName.IndexOf('`');
            var unmangledName = separatorIndex < 0 ? mangledName : mangledName.Substring(0, separatorIndex);
            AppendIdentifier(builder, escapeKeywordIdentifiers, unmangledName, out sawInvalidIdentifier);

            bool argumentsSawInvalidIdentifier;
            AppendGenericTypeArgumentList(builder, typeArguments, typeArgumentOffset, dynamicFlags, ref index, arity, escapeKeywordIdentifiers, out argumentsSawInvalidIdentifier);
            sawInvalidIdentifier |= argumentsSawInvalidIdentifier;
        }
Beispiel #26
0
 protected abstract bool AppendSpecialTypeName(StringBuilder builder, Type type, bool isDynamic);
Beispiel #27
0
 internal abstract bool IsPredefinedType(Type type);
Beispiel #28
0
        internal static string GetPredefinedTypeName(this Type type)
        {
            if (type.IsEnum)
            {
                return(null);
            }

            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Object:
                if (type.IsObject())
                {
                    return("object");
                }
                return(null);

            case TypeCode.Boolean:
                return("bool");

            case TypeCode.Char:
                return("char");

            case TypeCode.SByte:
                return("sbyte");

            case TypeCode.Byte:
                return("byte");

            case TypeCode.Int16:
                return("short");

            case TypeCode.UInt16:
                return("ushort");

            case TypeCode.Int32:
                return("int");

            case TypeCode.UInt32:
                return("uint");

            case TypeCode.Int64:
                return("long");

            case TypeCode.UInt64:
                return("ulong");

            case TypeCode.Single:
                return("float");

            case TypeCode.Double:
                return("double");

            case TypeCode.Decimal:
                return("decimal");

            case TypeCode.String:
                return("string");

            default:
                return(null);
            }
        }
Beispiel #29
0
 public TypeWalker(Type type)
 {
     _type = type;
 }
Beispiel #30
0
        internal override string GetNameForEnumValue(ArrayBuilder <EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt)
        {
            foreach (var field in fields)
            {
                // First match wins (deterministic since sorted).
                if (underlyingValue == field.Value)
                {
                    var pooled  = PooledStringBuilder.GetInstance();
                    var builder = pooled.Builder;

                    AppendEnumTypeAndName(builder, typeToDisplayOpt, field.Name);

                    return(pooled.ToStringAndFree());
                }
            }

            return(null);
        }
Beispiel #31
0
        internal override string GetNamesForFlagsEnumValue(ArrayBuilder <EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt)
        {
            var usedFields = ArrayBuilder <EnumField> .GetInstance();

            FillUsedEnumFields(usedFields, fields, underlyingValue);

            if (usedFields.Count == 0)
            {
                return(null);
            }

            var pooled  = PooledStringBuilder.GetInstance();
            var builder = pooled.Builder;

            for (int i = usedFields.Count - 1; i >= 0; i--) // Backwards to list smallest first.
            {
                AppendEnumTypeAndName(builder, typeToDisplayOpt, usedFields[i].Name);

                if (i > 0)
                {
                    builder.Append(" | ");
                }
            }

            usedFields.Free();

            return(pooled.ToStringAndFree());
        }
Beispiel #32
0
        /// <summary>
        /// Append the qualified name (i.e. including containing types and namespaces) of a named type
        /// (i.e. not a pointer or array type) to <paramref name="builder"/>.
        /// </summary>
        /// <remarks>
        /// Keyword strings are appended for primitive types (e.g. "int" for "System.Int32").
        /// </remarks>
        /// <remarks>
        /// Does not call itself or <see cref="AppendQualifiedTypeName"/> (directly).
        /// </remarks>
        private void AppendQualifiedTypeNameInternal(
            StringBuilder builder, 
            Type type, 
            DynamicFlagsCustomTypeInfo dynamicFlags, 
            ref int index, 
            bool escapeKeywordIdentifiers, 
            out bool sawInvalidIdentifier)
        {
            var isDynamic = dynamicFlags[index++] && type.IsObject();
            if (AppendSpecialTypeName(builder, type, isDynamic))
            {
                sawInvalidIdentifier = false;
                return;
            }

            Debug.Assert(!isDynamic, $"Dynamic should have been handled by {nameof(AppendSpecialTypeName)}");
            Debug.Assert(!IsPredefinedType(type));

            if (type.IsGenericParameter)
            {
                AppendIdentifier(builder, escapeKeywordIdentifiers, type.Name, out sawInvalidIdentifier);
                return;
            }

            // Note: in the Reflection/LMR object model, all type arguments are on the most nested type.
            var hasTypeArguments = type.IsGenericType;
            var typeArguments = type.IsGenericType
                ? type.GetGenericArguments()
                : null;
            Debug.Assert(hasTypeArguments == (typeArguments != null));

            var numTypeArguments = hasTypeArguments ? typeArguments.Length : 0;

            sawInvalidIdentifier = false;
            bool sawSingleInvalidIdentifier;
            if (type.IsNested)
            {
                // Push from inside, out.
                var stack = ArrayBuilder<Type>.GetInstance();
                {
                    var containingType = type.DeclaringType;
                    while (containingType != null)
                    {
                        stack.Add(containingType);
                        containingType = containingType.DeclaringType;
                    }
                }

                var lastContainingTypeIndex = stack.Count - 1;

                AppendNamespacePrefix(builder, stack[lastContainingTypeIndex], escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;

                var typeArgumentOffset = 0;

                // Pop from outside, in.
                for (int i = lastContainingTypeIndex; i >= 0; i--)
                {
                    var containingType = stack[i];

                    // ACASEY: I explored the type in the debugger and couldn't find the arity stored/exposed separately.
                    int arity = hasTypeArguments ? containingType.GetGenericArguments().Length - typeArgumentOffset : 0;

                    AppendUnqualifiedTypeName(builder, containingType, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, typeArgumentOffset, arity, out sawSingleInvalidIdentifier);
                    sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                    builder.Append('.');

                    typeArgumentOffset += arity;
                }

                stack.Free();

                AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, typeArgumentOffset, numTypeArguments - typeArgumentOffset, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
            }
            else
            {
                AppendNamespacePrefix(builder, type, escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, 0, numTypeArguments, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
            }
        }
        private static void FillEnumFields(ArrayBuilder<EnumField> fields, Type lmrType)
        {
            var fieldInfos = lmrType.GetFields();
            var enumTypeCode = Type.GetTypeCode(lmrType);

            foreach (var info in fieldInfos)
            {
                if (!info.IsSpecialName) // Skip __value.
                {
                    fields.Add(new EnumField(info.Name, ConvertEnumUnderlyingTypeToUInt64(info.GetRawConstantValue(), enumTypeCode)));
                }
            }

            fields.Sort(EnumField.Comparer);
        }
Beispiel #34
0
        /// <summary>
        /// Helper for appending the qualified name of the containing namespace of a type.
        /// NOTE: Unless the qualified name is empty, there will always be a trailing dot.
        /// </summary>
        private void AppendNamespacePrefix(StringBuilder builder, Type type, bool escapeKeywordIdentifiers, out bool sawInvalidIdentifier)
        {
            sawInvalidIdentifier = false;

            var @namespace = type.Namespace;
            if (!string.IsNullOrEmpty(@namespace))
            {
                if (@namespace.Contains("."))
                {
                    bool sawSingleInvalidIdentifier;
                    var pooled = PooledStringBuilder.GetInstance();
                    var identifierBuilder = pooled.Builder;
                    foreach (var ch in @namespace)
                    {
                        if (ch == '.')
                        {
                            AppendIdentifier(builder, escapeKeywordIdentifiers, identifierBuilder.ToString(), out sawSingleInvalidIdentifier);
                            sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                            builder.Append(ch);
                            identifierBuilder.Clear();
                        }
                        else
                        {
                            identifierBuilder.Append(ch);
                        }
                    }
                    AppendIdentifier(builder, escapeKeywordIdentifiers, identifierBuilder.ToString(), out sawSingleInvalidIdentifier);
                    sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                    pooled.Free();
                }
                else
                {
                    AppendIdentifier(builder, escapeKeywordIdentifiers, @namespace, out sawInvalidIdentifier);
                }
                builder.Append('.');
            }
        }
Beispiel #35
0
 internal abstract string GetArrayDisplayString(Type lmrType, ReadOnlyCollection <int> sizes, ReadOnlyCollection <int> lowerBounds, ObjectDisplayOptions options);
Beispiel #36
0
 protected abstract void AppendGenericTypeArgumentList(
     StringBuilder builder, 
     Type[] typeArguments, 
     int typeArgumentOffset,
     DynamicFlagsCustomTypeInfo dynamicFlags,
     ref int index,
     int arity, 
     bool escapeKeywordIdentifiers,
     out bool sawInvalidIdentifier);
Beispiel #37
0
 internal static bool IsPredefinedType(this Type type)
 {
     return(type.GetPredefinedTypeName() != null);
 }
#pragma warning disable RS0010
        /// <remarks>
        /// The corresponding native code is in EEUserStringBuilder::ErrTryAppendConstantEnum.
        /// The corresponding roslyn code is in 
        /// <see cref="M:Microsoft.CodeAnalysis.SymbolDisplay.AbstractSymbolDisplayVisitor`1.AddEnumConstantValue(Microsoft.CodeAnalysis.INamedTypeSymbol, System.Object, System.Boolean)"/>.
        /// NOTE: no curlies for enum values.
        /// </remarks>
#pragma warning restore RS0010
        private string GetEnumDisplayString(Type lmrType, DkmClrValue value, ObjectDisplayOptions options, bool includeTypeName, DkmInspectionContext inspectionContext)
        {
            Debug.Assert(lmrType.IsEnum);
            Debug.Assert(value != null);

            object underlyingValue = value.HostObjectValue;
            Debug.Assert(underlyingValue != null);

            string displayString;

            ArrayBuilder<EnumField> fields = ArrayBuilder<EnumField>.GetInstance();
            FillEnumFields(fields, lmrType);
            // We will normalize/extend all enum values to ulong to ensure that we are always comparing the full underlying value.
            ulong valueForComparison = ConvertEnumUnderlyingTypeToUInt64(underlyingValue, Type.GetTypeCode(lmrType));
            var typeToDisplayOpt = includeTypeName ? lmrType : null;
            if (valueForComparison != 0 && IsFlagsEnum(lmrType))
            {
                displayString = GetNamesForFlagsEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt);
            }
            else
            {
                displayString = GetNameForEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt);
            }
            fields.Free();

            return displayString ?? FormatPrimitive(value, options, inspectionContext);
        }
Beispiel #39
0
 internal override bool IsPrimitiveType(Type type)
 {
     return type.IsPredefinedType();
 }
        private static bool IsFlagsEnum(Type lmrType)
        {
            Debug.Assert(lmrType.IsEnum);

            var attributes = lmrType.GetCustomAttributesData();
            foreach (var attribute in attributes)
            {
                // NOTE: AttributeType is not available in 2.0
                if (attribute.Constructor.DeclaringType.FullName == "System.FlagsAttribute")
                {
                    return true;
                }
            }

            return false;
        }
 protected abstract bool AppendSpecialTypeName(StringBuilder builder, Type type, bool isDynamic);
 internal abstract string GetNameForEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt);
Beispiel #43
0
        internal EvalResultDataItem CreateDataItem(
            DkmInspectionContext inspectionContext,
            string name,
            Type typeDeclaringMember,
            Type declaredType,
            DkmClrValue value,
            EvalResultDataItem parent,
            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 lmrNullableTypeArg = declaredType.GetNullableTypeArgument();

            if (lmrNullableTypeArg != null && !value.HasExceptionThrown(parent))
            {
                Debug.Assert(value.Type.GetProxyType() == null);

                var nullableValue = value.GetNullableValue();
                if (nullableValue == 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.
                    expansion = this.GetTypeExpansion(inspectionContext, lmrNullableTypeArg, value, ExpansionFlags.IncludeResultsView);
                }
            }
            else if (value.IsError() || (inspectionContext.EvaluationFlags & DkmEvaluationFlags.NoExpansion) != 0)
            {
                expansion = null;
            }
            else
            {
                expansion = DebuggerTypeProxyExpansion.CreateExpansion(
                    this,
                    inspectionContext,
                    name,
                    typeDeclaringMember,
                    declaredType,
                    value,
                    childShouldParenthesize,
                    fullName,
                    flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName,
                    formatSpecifiers,
                    flags,
                    this.Formatter.GetEditableValue(value, inspectionContext));
                if (expansion == null)
                {
                    var expansionType = value.HasExceptionThrown(parent) ? value.Type.GetLmrType() : declaredType;
                    expansion = this.GetTypeExpansion(inspectionContext, expansionType, value, expansionFlags);
                }
            }

            return(new EvalResultDataItem(
                       ExpansionKind.Default,
                       name,
                       typeDeclaringMember,
                       declaredType,
                       parent: parent,
                       value: value,
                       displayValue: null,
                       expansion: expansion,
                       childShouldParenthesize: childShouldParenthesize,
                       fullName: fullName,
                       childFullNamePrefixOpt: flags.Includes(DkmEvaluationResultFlags.ExceptionThrown) ? null : fullName,
                       formatSpecifiers: formatSpecifiers,
                       category: category,
                       flags: flags,
                       editableValue: this.Formatter.GetEditableValue(value, inspectionContext),
                       inspectionContext: inspectionContext));
        }
Beispiel #44
0
        internal override string GetNamesForFlagsEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt)
        {
            var usedFields = ArrayBuilder<EnumField>.GetInstance();
            FillUsedEnumFields(usedFields, fields, underlyingValue);

            if (usedFields.Count == 0)
            {
                return null;
            }

            var pooled = PooledStringBuilder.GetInstance();
            var builder = pooled.Builder;

            for (int i = usedFields.Count - 1; i >= 0; i--) // Backwards to list smallest first.
            {
                AppendEnumTypeAndName(builder, typeToDisplayOpt, usedFields[i].Name);

                if (i > 0)
                {
                    builder.Append(" | ");
                }
            }

            usedFields.Free();

            return pooled.ToStringAndFree();
        }
        protected void AppendQualifiedTypeName(
            StringBuilder builder,
            Type type,
            ReadOnlyCollection <byte> dynamicFlags,
            ref int dynamicFlagIndex,
            ReadOnlyCollection <string> tupleElementNames,
            ref int tupleElementIndex,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            Type originalType = type;

            // Can have an array of pointers, but not a pointer to an array, so consume these first.
            // We'll reconstruct this information later from originalType.
            while (type.IsArray)
            {
                dynamicFlagIndex++;
                type = type.GetElementType();
            }

            int pointerCount = 0;

            while (type.IsPointer)
            {
                var elementType = type.GetElementType();
                if (elementType == null)
                {
                    // Null for function pointers.
                    break;
                }
                dynamicFlagIndex++;
                pointerCount++;
                type = elementType;
            }

            int  nullableCount = 0;
            Type typeArg;

            while ((typeArg = type.GetNullableTypeArgument()) != null)
            {
                dynamicFlagIndex++;
                nullableCount++;
                type = typeArg;
            }
            Debug.Assert(nullableCount < 2, "Benign: someone is nesting nullables.");

            Debug.Assert(pointerCount == 0 || nullableCount == 0, "Benign: pointer to nullable?");

            AppendQualifiedTypeNameInternal(
                builder,
                type,
                dynamicFlags,
                ref dynamicFlagIndex,
                tupleElementNames,
                ref tupleElementIndex,
                escapeKeywordIdentifiers,
                out sawInvalidIdentifier);

            builder.Append('?', nullableCount);
            builder.Append('*', pointerCount);

            type = originalType;
            while (type.IsArray)
            {
                AppendRankSpecifier(builder, type.GetArrayRank());

                type = type.GetElementType();
            }
        }
        private void AppendTupleElements(
            StringBuilder builder,
            Type type,
            int cardinality,
            ReadOnlyCollection <byte> dynamicFlags,
            ref int dynamicFlagIndex,
            ReadOnlyCollection <string> tupleElementNames,
            ref int tupleElementIndex,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            sawInvalidIdentifier = false;
#if DEBUG
            int lastNameIndex = tupleElementIndex + cardinality;
#endif
            int nameIndex = tupleElementIndex;
            builder.Append('(');
            bool any = false;
            while (true)
            {
                tupleElementIndex += cardinality;
                var typeArguments = type.GetGenericArguments();
                int nTypeArgs     = typeArguments.Length;
                Debug.Assert(nTypeArgs > 0);
                Debug.Assert(nTypeArgs <= TypeHelpers.TupleFieldRestPosition);
                int nFields = Math.Min(nTypeArgs, TypeHelpers.TupleFieldRestPosition - 1);
                for (int i = 0; i < nFields; i++)
                {
                    if (any)
                    {
                        builder.Append(", ");
                    }
                    bool sawSingleInvalidIdentifier;
                    var  name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, nameIndex);
                    nameIndex++;
                    AppendTupleElement(
                        builder,
                        typeArguments[i],
                        name,
                        dynamicFlags,
                        ref dynamicFlagIndex,
                        tupleElementNames,
                        ref tupleElementIndex,
                        escapeKeywordIdentifiers,
                        sawInvalidIdentifier: out sawSingleInvalidIdentifier);
                    sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                    any = true;
                }
                if (nTypeArgs < TypeHelpers.TupleFieldRestPosition)
                {
                    break;
                }
                Debug.Assert(!DynamicFlagsCustomTypeInfo.GetFlag(dynamicFlags, dynamicFlagIndex));
                dynamicFlagIndex++;
                type        = typeArguments[nTypeArgs - 1];
                cardinality = type.GetTupleCardinalityIfAny();
            }
#if DEBUG
            Debug.Assert(nameIndex == lastNameIndex);
#endif
            builder.Append(')');
        }
        private void AppendQualifiedTypeNameInternal(
            StringBuilder builder,
            Type type,
            ReadOnlyCollection <byte> dynamicFlags,
            ref int dynamicFlagIndex,
            ReadOnlyCollection <string> tupleElementNames,
            ref int tupleElementIndex,
            bool escapeKeywordIdentifiers,
            out bool sawInvalidIdentifier)
        {
            var isDynamic = DynamicFlagsCustomTypeInfo.GetFlag(dynamicFlags, dynamicFlagIndex++) && type.IsObject();

            if (AppendSpecialTypeName(builder, type, isDynamic))
            {
                sawInvalidIdentifier = false;
                return;
            }

            Debug.Assert(!isDynamic, $"Dynamic should have been handled by {nameof(AppendSpecialTypeName)}");
            Debug.Assert(!IsPredefinedType(type));

            if (type.IsGenericParameter)
            {
                AppendIdentifier(builder, escapeKeywordIdentifiers, type.Name, out sawInvalidIdentifier);
                return;
            }

            int cardinality;

            if (type.IsTupleCompatible(out cardinality))
            {
                if (cardinality == 1)
                {
                    // Not displayed as a tuple but is included in tuple element names.
                    tupleElementIndex++;
                }
                else
                {
                    AppendTupleElements(
                        builder,
                        type,
                        cardinality,
                        dynamicFlags,
                        ref dynamicFlagIndex,
                        tupleElementNames,
                        ref tupleElementIndex,
                        escapeKeywordIdentifiers,
                        out sawInvalidIdentifier);
                    return;
                }
            }

            // Note: in the Reflection/LMR object model, all type arguments are on the most nested type.
            var hasTypeArguments = type.IsGenericType;
            var typeArguments    = hasTypeArguments
                ? type.GetGenericArguments()
                : null;

            Debug.Assert(hasTypeArguments == (typeArguments != null));

            var numTypeArguments = hasTypeArguments ? typeArguments.Length : 0;

            sawInvalidIdentifier = false;
            bool sawSingleInvalidIdentifier;
            var  typeArgumentOffset = 0;

            if (type.IsNested)
            {
                // Push from inside, out.
                var stack = ArrayBuilder <Type> .GetInstance();

                {
                    var containingType = type.DeclaringType;
                    while (containingType != null)
                    {
                        stack.Add(containingType);
                        containingType = containingType.DeclaringType;
                    }
                }

                var lastContainingTypeIndex = stack.Count - 1;

                AppendNamespacePrefix(builder, stack[lastContainingTypeIndex], escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;

                // Pop from outside, in.
                for (int i = lastContainingTypeIndex; i >= 0; i--)
                {
                    var containingType = stack[i];

                    // ACASEY: I explored the type in the debugger and couldn't find the arity stored/exposed separately.
                    int arity = hasTypeArguments ? containingType.GetGenericArguments().Length - typeArgumentOffset : 0;

                    AppendUnqualifiedTypeName(
                        builder,
                        containingType,
                        dynamicFlags,
                        ref dynamicFlagIndex,
                        tupleElementNames,
                        ref tupleElementIndex,
                        escapeKeywordIdentifiers,
                        typeArguments,
                        typeArgumentOffset,
                        arity,
                        out sawSingleInvalidIdentifier);
                    sawInvalidIdentifier |= sawSingleInvalidIdentifier;
                    builder.Append('.');

                    typeArgumentOffset += arity;
                }

                stack.Free();
            }
            else
            {
                AppendNamespacePrefix(builder, type, escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
                sawInvalidIdentifier |= sawSingleInvalidIdentifier;
            }

            AppendUnqualifiedTypeName(
                builder,
                type,
                dynamicFlags,
                ref dynamicFlagIndex,
                tupleElementNames,
                ref tupleElementIndex,
                escapeKeywordIdentifiers,
                typeArguments,
                typeArgumentOffset,
                numTypeArguments - typeArgumentOffset,
                out sawSingleInvalidIdentifier);
            sawInvalidIdentifier |= sawSingleInvalidIdentifier;
        }