/// <summary> /// Convert a type from the debugger's type system into X# type system /// </summary> /// <param name="lmrType">LMR Type</param> /// <returns>X# type</returns> public static XSharpType GetXSharpTypeForLmrType(Type lmrType) { if (lmrType.IsPrimitive) { return(XSharpType.Create(lmrType.FullName)); } else if (lmrType.IsArray) { XSharpType elementType = GetXSharpTypeForLmrType(lmrType.GetElementType()); return(elementType.MakeArrayType()); } else if (lmrType.IsByRef) { XSharpType elementType = GetXSharpTypeForLmrType(lmrType.GetElementType()); return(elementType.MakeByRefType()); } else if (lmrType.FullName.Equals("System.String")) { return(XSharpType.String); } // Unknown return(XSharpType.Create(lmrType.FullName)); }
/// <summary> /// Convert a type from the debugger's type system into X# type system /// </summary> /// <param name="lmrType">LMR Type</param> /// <returns>X# type</returns> public static XSharpType GetXSharpTypeForLmrType(Type lmrType) { if (lmrType.IsPrimitive) { return(XSharpType.Create(lmrType.FullName)); } else if (lmrType.IsArray) { XSharpType elementType = GetXSharpTypeForLmrType(lmrType.GetElementType()); return(elementType.MakeArrayType()); } else if (lmrType.IsByRef) { XSharpType elementType = GetXSharpTypeForLmrType(lmrType.GetElementType()); return(elementType.MakeByRefType()); } else if (lmrType.IsGenericType) { var args = lmrType.GetGenericArguments(); var td = lmrType.GetGenericTypeDefinition(); return(XSharpType.Create(td, args)); } else if (lmrType.FullName.Equals("System.String")) { return(XSharpType.String); } // Unknown return(XSharpType.Create(lmrType.FullName)); }
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()); }
/// <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 "<Anonymous Type>. /// 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(); } }
/// <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 "<Anonymous Type>. /// 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?"); AppendQualifiedTypeNameInternal(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, out sawInvalidIdentifier); 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(); }
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('{'); builder.Append(GetTypeName(lmrType)); // 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()); }
/// <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 "<Anonymous Type>. /// 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, bool escapeKeywordIdentifiers) { 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) { type = type.GetElementType(); } int pointerCount = 0; while (type.IsPointer) { pointerCount++; type = type.GetElementType(); } int nullableCount = 0; Type typeArg; while ((typeArg = type.GetNullableTypeArgument()) != null) { 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, escapeKeywordIdentifiers); 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(); } }
/// <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); }
/// <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; }
internal Expansion GetTypeExpansion(DkmInspectionContext inspectionContext, Type declaredType, DkmClrValue value, ExpansionFlags flags) { 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; return(ArrayExpansion.CreateExpansion(sizes, lowerBounds)); } if (this.Formatter.IsPredefinedType(runtimeType)) { return(null); } if (declaredType.IsPointer) { return(!value.IsNull ? new PointerDereferenceExpansion(declaredType.GetElementType()) : null); } 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, declaredType, value, flags, TypeHelpers.IsVisibleMember, this.Formatter)); }
internal Expansion GetTypeExpansion(DkmInspectionContext inspectionContext, Type declaredType, DkmClrValue value, ExpansionFlags flags) { 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; return ArrayExpansion.CreateExpansion(sizes, lowerBounds); } if (this.Formatter.IsPredefinedType(runtimeType)) { return null; } if (declaredType.IsPointer) { return !value.IsNull ? new PointerDereferenceExpansion(declaredType.GetElementType()) : null; } 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(declaredType, value, flags, TypeHelpers.IsVisibleMember, this.Formatter); }