Пример #1
0
        private static string GetMangledAndEscapedName(INamedTypeReference namedType)
        {
            var           pooled      = PooledStringBuilder.GetInstance();
            StringBuilder mangledName = pooled.Builder;

            const string needsEscaping = "\\[]*.+,& ";

            foreach (var ch in namedType.Name)
            {
                if (needsEscaping.IndexOf(ch) >= 0)
                {
                    mangledName.Append('\\');
                }

                mangledName.Append(ch);
            }

            if (namedType.MangleName && namedType.GenericParameterCount > 0)
            {
                mangledName.Append(MetadataHelpers.GetAritySuffix(namedType.GenericParameterCount));
            }

            return(pooled.ToStringAndFree());
        }
Пример #2
0
        /// <summary>
        /// Qualified name of namespace.
        /// e.g. "A.B.C"
        /// </summary>
        internal static string BuildQualifiedNamespaceName(INamespace @namespace)
        {
            Debug.Assert(@namespace != null);

            if (@namespace.ContainingNamespace == null)
            {
                return(@namespace.Name);
            }

            var namesReversed = new List <string>();

            do
            {
                string name = @namespace.Name;
                if (name.Length != 0)
                {
                    namesReversed.Add(name);
                }

                @namespace = @namespace.ContainingNamespace;
            }while (@namespace != null);

            var result = PooledStringBuilder.GetInstance();

            for (int i = namesReversed.Count - 1; i >= 0; i--)
            {
                result.Builder.Append(namesReversed[i]);

                if (i > 0)
                {
                    result.Builder.Append('.');
                }
            }

            return(result.ToStringAndFree());
        }
Пример #3
0
            /// <summary>
            /// Decodes a type name.  A type name is a string which is terminated by the end of the string or one of the
            /// delimiters '+', ',', '[', ']'. '+' separates nested classes. '[' and ']'
            /// enclosed generic type arguments.  ',' separates types.
            /// </summary>
            public AssemblyQualifiedTypeName DecodeTypeName(bool isTypeArgument = false, bool isTypeArgumentWithAssemblyName = false)
            {
                Debug.Assert(!isTypeArgumentWithAssemblyName || isTypeArgument);

                string        topLevelType       = null;
                List <string> nestedTypesBuilder = null;

                AssemblyQualifiedTypeName[] typeArguments = null;
                int        pointerCount         = 0;
                List <int> arrayRanksBuilder    = null;
                string     assemblyName         = null;
                bool       decodingTopLevelType = true;
                bool       isGenericTypeName    = false;

                var           pooledStrBuilder = PooledStringBuilder.GetInstance();
                StringBuilder typeNameBuilder  = pooledStrBuilder.Builder;

                while (!EndOfInput)
                {
                    int i = _input.IndexOfAny(s_typeNameDelimiters, _offset);
                    if (i >= 0)
                    {
                        char c = _input[i];

                        // Found name, which could be a generic name with arity.
                        // Generic type parameter count, if any, are handled in DecodeGenericName.
                        string decodedString = DecodeGenericName(i);
                        Debug.Assert(decodedString != null);

                        // Type name is generic if the decoded name of the top level type OR any of the outer types of a nested type had the '`' character.
                        isGenericTypeName = isGenericTypeName || decodedString.IndexOf(GenericTypeNameManglingChar) >= 0;
                        typeNameBuilder.Append(decodedString);

                        switch (c)
                        {
                        case '*':
                            if (arrayRanksBuilder != null)
                            {
                                // Error case, array shape must be specified at the end of the type name.
                                // Process as a regular character and continue.
                                typeNameBuilder.Append(c);
                            }
                            else
                            {
                                pointerCount++;
                            }

                            Advance();
                            break;

                        case '+':
                            if (arrayRanksBuilder != null || pointerCount > 0)
                            {
                                // Error case, array shape must be specified at the end of the type name.
                                // Process as a regular character and continue.
                                typeNameBuilder.Append(c);
                            }
                            else
                            {
                                // Type followed by nested type. Handle nested class separator and collect the nested types.
                                HandleDecodedTypeName(typeNameBuilder.ToString(), decodingTopLevelType, ref topLevelType, ref nestedTypesBuilder);
                                typeNameBuilder.Clear();
                                decodingTopLevelType = false;
                            }

                            Advance();
                            break;

                        case '[':
                            // Is type followed by generic type arguments?
                            if (isGenericTypeName && typeArguments == null)
                            {
                                Advance();
                                if (arrayRanksBuilder != null || pointerCount > 0)
                                {
                                    // Error case, array shape must be specified at the end of the type name.
                                    // Process as a regular character and continue.
                                    typeNameBuilder.Append(c);
                                }
                                else
                                {
                                    // Decode type arguments.
                                    typeArguments = DecodeTypeArguments();
                                }
                            }
                            else
                            {
                                // Decode array shape.
                                DecodeArrayShape(typeNameBuilder, ref arrayRanksBuilder);
                            }

                            break;

                        case ']':
                            if (isTypeArgument)
                            {
                                // End of type arguments.  This occurs when the last type argument is a type in the
                                // current assembly.
                                goto ExitDecodeTypeName;
                            }
                            else
                            {
                                // Error case, process as a regular character and continue.
                                typeNameBuilder.Append(c);
                                Advance();
                                break;
                            }

                        case ',':
                            // A comma may separate a type name from its assembly name or a type argument from
                            // another type argument.
                            // If processing non-type argument or a type argument with assembly name,
                            // process the characters after the comma as an assembly name.
                            if (!isTypeArgument || isTypeArgumentWithAssemblyName)
                            {
                                Advance();
                                if (!EndOfInput && Char.IsWhiteSpace(Current))
                                {
                                    Advance();
                                }

                                assemblyName = DecodeAssemblyName(isTypeArgumentWithAssemblyName);
                            }
                            goto ExitDecodeTypeName;

                        default:
                            throw ExceptionUtilities.UnexpectedValue(c);
                        }
                    }
                    else
                    {
                        typeNameBuilder.Append(DecodeGenericName(_input.Length));
                        goto ExitDecodeTypeName;
                    }
                }

ExitDecodeTypeName:
                HandleDecodedTypeName(typeNameBuilder.ToString(), decodingTopLevelType, ref topLevelType, ref nestedTypesBuilder);
                pooledStrBuilder.Free();

                return(new AssemblyQualifiedTypeName(
                           topLevelType,
                           nestedTypesBuilder?.ToArray(),
                           typeArguments,
                           pointerCount,
                           arrayRanksBuilder?.ToArray(),
                           assemblyName));
            }
Пример #4
0
        internal static string GetSerializedTypeName(this ITypeReference typeReference, EmitContext context, ref bool isAssemblyQualified)
        {
            var                 pooled  = PooledStringBuilder.GetInstance();
            StringBuilder       sb      = pooled.Builder;
            IArrayTypeReference arrType = typeReference as IArrayTypeReference;

            if (arrType != null)
            {
                typeReference = arrType.GetElementType(context);
                bool isAssemQual = false;
                AppendSerializedTypeName(sb, typeReference, ref isAssemQual, context);
                if (arrType.IsSZArray)
                {
                    sb.Append("[]");
                }
                else
                {
                    sb.Append('[');
                    if (arrType.Rank == 1)
                    {
                        sb.Append('*');
                    }

                    sb.Append(',', (int)arrType.Rank - 1);

                    sb.Append(']');
                }

                goto done;
            }

            IPointerTypeReference pointer = typeReference as IPointerTypeReference;

            if (pointer != null)
            {
                typeReference = pointer.GetTargetType(context);
                bool isAssemQual = false;
                AppendSerializedTypeName(sb, typeReference, ref isAssemQual, context);
                sb.Append('*');
                goto done;
            }

            INamespaceTypeReference namespaceType = typeReference.AsNamespaceTypeReference;

            if (namespaceType != null)
            {
                var name = namespaceType.NamespaceName;
                if (name.Length != 0)
                {
                    sb.Append(name);
                    sb.Append('.');
                }

                sb.Append(GetMangledAndEscapedName(namespaceType));
                goto done;
            }


            if (typeReference.IsTypeSpecification())
            {
                ITypeReference uninstantiatedTypeReference = typeReference.GetUninstantiatedGenericType(context);

                List <ITypeReference> consolidatedTypeArguments = new List <ITypeReference>();
                typeReference.GetConsolidatedTypeArguments(consolidatedTypeArguments, context);

                bool uninstantiatedTypeIsAssemblyQualified = false;
                sb.Append(GetSerializedTypeName(uninstantiatedTypeReference, context, ref uninstantiatedTypeIsAssemblyQualified));
                sb.Append('[');
                bool first = true;
                foreach (ITypeReference argument in consolidatedTypeArguments)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        sb.Append(',');
                    }

                    bool isAssemQual = true;
                    AppendSerializedTypeName(sb, argument, ref isAssemQual, context);
                }

                sb.Append(']');
                goto done;
            }

            INestedTypeReference nestedType = typeReference.AsNestedTypeReference;

            if (nestedType != null)
            {
                bool nestedTypeIsAssemblyQualified = false;
                sb.Append(GetSerializedTypeName(nestedType.GetContainingType(context), context, ref nestedTypeIsAssemblyQualified));
                sb.Append('+');
                sb.Append(GetMangledAndEscapedName(nestedType));
                goto done;
            }

            // TODO: error
done:
            if (isAssemblyQualified)
            {
                AppendAssemblyQualifierIfNecessary(sb, UnwrapTypeReference(typeReference, context), out isAssemblyQualified, context);
            }

            return(pooled.ToStringAndFree());
        }