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 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; }
/// <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; } }
/// <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) { var isDynamic = dynamicFlags[index++] && type.IsObject(); if (AppendSpecialTypeName(builder, type, isDynamic, escapeKeywordIdentifiers)) { return; } Debug.Assert(!isDynamic, $"Dynamic should have been handled by {nameof(AppendSpecialTypeName)}"); Debug.Assert(!IsPredefinedType(type)); // 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; 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); 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); builder.Append('.'); typeArgumentOffset += arity; } stack.Free(); AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, typeArgumentOffset, numTypeArguments - typeArgumentOffset); } else { AppendNamespacePrefix(builder, type, escapeKeywordIdentifiers); AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, 0, numTypeArguments); } }
/// <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, 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; }
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); } }