Exemple #1
0
        internal static DkmClrCustomTypeInfo GetCustomTypeInfo(
            this IList <CustomAttributeData> attributes
            )
        {
            ReadOnlyCollection <byte>   dynamicFlags      = null;
            ReadOnlyCollection <string> tupleElementNames = null;

            foreach (var attribute in attributes)
            {
                var attributeType = attribute.Constructor.DeclaringType;
                if (attributeType.IsType("System.Runtime.CompilerServices", "DynamicAttribute"))
                {
                    dynamicFlags = GetDynamicFlags(attribute);
                }
                else if (
                    attributeType.IsType(
                        "System.Runtime.CompilerServices",
                        "TupleElementNamesAttribute"
                        )
                    )
                {
                    tupleElementNames = GetTupleElementNames(attribute);
                }
            }
            return(CustomTypeInfo.Create(dynamicFlags, tupleElementNames));
        }
Exemple #2
0
        /// <returns>The qualified name (i.e. including containing types and namespaces) of a named,
        /// pointer, or array type.</returns>
        internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIdentifiers, out bool sawInvalidIdentifier)
        {
            var type = typeAndInfo.Type;

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            ReadOnlyCollection <byte>   dynamicFlags      = null;
            ReadOnlyCollection <string> tupleElementNames = null;
            var typeInfo = typeAndInfo.Info;

            if (typeInfo != null)
            {
                CustomTypeInfo.Decode(typeInfo.PayloadTypeId, typeInfo.Payload, out dynamicFlags, out tupleElementNames);
            }

            var dynamicFlagIndex  = 0;
            var tupleElementIndex = 0;
            var pooled            = PooledStringBuilder.GetInstance();

            AppendQualifiedTypeName(
                pooled.Builder,
                type,
                dynamicFlags,
                ref dynamicFlagIndex,
                tupleElementNames,
                ref tupleElementIndex,
                escapeKeywordIdentifiers,
                out sawInvalidIdentifier);
            return(pooled.ToStringAndFree());
        }
Exemple #3
0
        internal DkmClrCustomTypeInfo SubstituteCustomTypeInfo(
            Type type,
            DkmClrCustomTypeInfo customInfo
            )
        {
            if (_typeDefinition == null)
            {
                return(customInfo);
            }

            ReadOnlyCollection <byte>   dynamicFlags      = null;
            ReadOnlyCollection <string> tupleElementNames = null;

            if (customInfo != null)
            {
                CustomTypeInfo.Decode(
                    customInfo.PayloadTypeId,
                    customInfo.Payload,
                    out dynamicFlags,
                    out tupleElementNames
                    );
            }

            var substitutedFlags = SubstituteDynamicFlags(type, dynamicFlags);
            var substitutedNames = SubstituteTupleElementNames(type, tupleElementNames);

            return(CustomTypeInfo.Create(substitutedFlags, substitutedNames));
        }
            internal InspectionContextImpl Add(string id, string typeName, CustomTypeInfo customTypeInfo = default(CustomTypeInfo))
            {
                var builder = ArrayBuilder <Alias> .GetInstance();

                builder.AddRange(_variables);
                builder.Add(new Alias(GetPseudoVariableKind(id), id, id, typeName, customTypeInfo));
                return(new InspectionContextImpl(new ReadOnlyCollection <Alias>(builder.ToArrayAndFree())));
            }
Exemple #5
0
        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;
            int nameIndex = tupleElementIndex;

            tupleElementIndex += cardinality;
            builder.Append('(');
            bool any = false;

            while (true)
            {
                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];
            }
            builder.Append(')');
        }
        internal Alias(DkmClrAliasKind kind, string name, string fullName, string type, CustomTypeInfo customTypeInfo)
        {
            Debug.Assert(!string.IsNullOrEmpty(fullName));
            Debug.Assert(!string.IsNullOrEmpty(type));

            this.Kind = kind;
            this.Name = name;
            this.FullName = fullName;
            this.Type = type;
            this.CustomTypeInfo = customTypeInfo;
        }
        internal Alias(AliasKind kind, string name, string fullName, string type, CustomTypeInfo customTypeInfo)
        {
            Debug.Assert(kind != AliasKind.None);
            Debug.Assert(!string.IsNullOrEmpty(fullName));
            Debug.Assert(!string.IsNullOrEmpty(type));

            this.Kind           = kind;
            this.Name           = name;
            this.FullName       = fullName;
            this.Type           = type;
            this.CustomTypeInfo = customTypeInfo;
        }
Exemple #8
0
        internal static CustomTypeInfoTypeArgumentMap Create(TypeAndCustomInfo typeAndInfo)
        {
            var typeInfo = typeAndInfo.Info;

            if (typeInfo == null)
            {
                return(s_empty);
            }

            var type = typeAndInfo.Type;

            Debug.Assert(type != null);
            if (!type.IsGenericType)
            {
                return(s_empty);
            }

            ReadOnlyCollection <byte>   dynamicFlags;
            ReadOnlyCollection <string> tupleElementNames;

            CustomTypeInfo.Decode(
                typeInfo.PayloadTypeId,
                typeInfo.Payload,
                out dynamicFlags,
                out tupleElementNames
                );
            if (dynamicFlags == null && tupleElementNames == null)
            {
                return(s_empty);
            }

            var typeDefinition = type.GetGenericTypeDefinition();

            Debug.Assert(typeDefinition != null);

            var dynamicFlagStartIndices =
                (dynamicFlags == null) ? null : GetStartIndices(type, t => 1);
            var tupleElementNameStartIndices =
                (tupleElementNames == null)
                    ? null
                    : GetStartIndices(type, TypeHelpers.GetTupleCardinalityIfAny);

            return(new CustomTypeInfoTypeArgumentMap(
                       typeDefinition,
                       dynamicFlags,
                       dynamicFlagStartIndices,
                       tupleElementNames,
                       tupleElementNameStartIndices
                       ));
        }
Exemple #9
0
        internal static DkmClrCustomTypeInfo MakeCustomTypeInfo(params bool[] dynamicFlags)
        {
            if (dynamicFlags == null || dynamicFlags.Length == 0)
            {
                return(null);
            }

            var builder = ArrayBuilder <bool> .GetInstance(dynamicFlags.Length);

            builder.AddRange(dynamicFlags);
            var result = CustomTypeInfo.Create(DynamicFlagsCustomTypeInfo.ToBytes(builder), tupleElementNames: null);

            builder.Free();
            return(result);
        }
Exemple #10
0
        /// <summary>
        /// Return a copy of the custom type info with the leading dynamic flag removed.
        /// There are no changes to tuple element names since this is used for walking
        /// into an array element type only which does not affect tuple element names.
        /// </summary>
        internal static DkmClrCustomTypeInfo SkipOne(DkmClrCustomTypeInfo customInfo)
        {
            if (customInfo == null)
            {
                return(customInfo);
            }

            ReadOnlyCollection <byte>   dynamicFlags;
            ReadOnlyCollection <string> tupleElementNames;

            CustomTypeInfo.Decode(
                customInfo.PayloadTypeId,
                customInfo.Payload,
                out dynamicFlags,
                out tupleElementNames);

            if (dynamicFlags == null)
            {
                return(customInfo);
            }

            return(Create(DynamicFlagsCustomTypeInfo.SkipOne(dynamicFlags), tupleElementNames));
        }
Exemple #11
0
        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));
        }
Exemple #12
0
 public static DynamicFlagsCustomTypeInfo Create(CustomTypeInfo customTypeInfo)
 {
     return(new DynamicFlagsCustomTypeInfo(customTypeInfo.PayloadTypeId == PayloadTypeId ? customTypeInfo.Payload : null));
 }
Exemple #13
0
        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));
        }
Exemple #14
0
        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());
        }
 public static DynamicFlagsCustomTypeInfo Create(CustomTypeInfo customTypeInfo)
 {
     return new DynamicFlagsCustomTypeInfo(customTypeInfo.PayloadTypeId == PayloadTypeId ? customTypeInfo.Payload : null);
 }
 internal static Alias Alias(DkmClrAliasKind kind, string name, string fullName, string type, CustomTypeInfo customTypeInfo)
 {
     return new Alias(kind, name, fullName, type, customTypeInfo);
 }
Exemple #17
0
 private static void VerifyCustomTypeInfo(CustomTypeInfo customTypeInfo, byte[] expectedBytes)
 {
     Assert.Equal(DynamicFlagsCustomTypeInfo.PayloadTypeId, customTypeInfo.PayloadTypeId);
     Assert.Equal(expectedBytes, customTypeInfo.Payload);
 }
 internal InspectionContextImpl Add(string id, Type type, CustomTypeInfo customTypeInfo = default(CustomTypeInfo))
 {
     return(Add(id, type.AssemblyQualifiedName, customTypeInfo));
 }