File: system\reflection\emit\aqnbuilder.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// <OWNER>Microsoft</OWNER>
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Runtime.InteropServices;
using System.Security;
 
namespace System.Reflection.Emit
{
    // TypeNameBuilder is NOT thread safe NOR reliable
    internal class TypeNameBuilder
    {
        internal enum Format
        {
            ToString,
            FullName,
            AssemblyQualifiedName,
        }
        
        #region QCalls
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern IntPtr CreateTypeNameBuilder();
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void ReleaseTypeNameBuilder(IntPtr pAQN);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void OpenGenericArguments(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void CloseGenericArguments(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void OpenGenericArgument(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void CloseGenericArgument(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddName(IntPtr tnb, string name);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddPointer(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddByRef(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddSzArray(IntPtr tnb);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddArray(IntPtr tnb, int rank);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void AddAssemblySpec(IntPtr tnb, string assemblySpec);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void ToString(IntPtr tnb, StringHandleOnStack retString);
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern void Clear(IntPtr tnb);
        #endregion
 
        #region Static Members
 
        // TypeNameBuilder is NOT thread safe NOR reliable
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static string ToString(Type type, Format format)
        {
            if (format == Format.FullName || format == Format.AssemblyQualifiedName)
            {
                if (!type.IsGenericTypeDefinition && type.ContainsGenericParameters)
                    return null;
            }
            
            TypeNameBuilder tnb = new TypeNameBuilder(CreateTypeNameBuilder());
            tnb.Clear();
            tnb.ConstructAssemblyQualifiedNameWorker(type, format);
            string toString = tnb.ToString();
            tnb.Dispose();
            return toString;
        }
        #endregion
 
        #region Private Data Members
        private IntPtr m_typeNameBuilder;
        #endregion
 
        #region Constructor
        private TypeNameBuilder(IntPtr typeNameBuilder) { m_typeNameBuilder = typeNameBuilder; }
        [System.Security.SecurityCritical]  // auto-generated
        internal void Dispose() { ReleaseTypeNameBuilder(m_typeNameBuilder); }
        #endregion
 
        #region private Members
        [System.Security.SecurityCritical]  // auto-generated
        private void AddElementType(Type elementType)
        {
            if (elementType.HasElementType)
                AddElementType(elementType.GetElementType());
                
            if (elementType.IsPointer)
                AddPointer();
 
            else if (elementType.IsByRef)
                AddByRef();
 
            else if (elementType.IsSzArray)
                AddSzArray();
 
            else if (elementType.IsArray)
                AddArray(elementType.GetArrayRank());
        }
        
        [System.Security.SecurityCritical]  // auto-generated
        private void ConstructAssemblyQualifiedNameWorker(Type type, Format format)
        {
            Type rootType = type;
 
            while (rootType.HasElementType)
                rootType = rootType.GetElementType();
 
            // Append namespace + nesting + name
            List<Type> nestings = new List<Type>();
            for (Type t = rootType; t != null; t = t.IsGenericParameter ? null : t.DeclaringType)
                nestings.Add(t);
            
            for (int i = nestings.Count - 1; i >= 0; i--)
            {
                Type enclosingType = nestings[i];
                string name = enclosingType.Name;
 
                if (i == nestings.Count - 1  && enclosingType.Namespace != null && enclosingType.Namespace.Length != 0)
                    name = enclosingType.Namespace + "." + name;
 
                AddName(name);
            }
 
            // Append generic arguments
            if (rootType.IsGenericType && (!rootType.IsGenericTypeDefinition || format == Format.ToString))
            {
                Type[] genericArguments = rootType.GetGenericArguments();
 
                OpenGenericArguments();
                for (int i = 0; i < genericArguments.Length; i++)
                {
                    Format genericArgumentsFormat = format == Format.FullName ? Format.AssemblyQualifiedName : format;
                   
                    OpenGenericArgument();
                    ConstructAssemblyQualifiedNameWorker(genericArguments[i], genericArgumentsFormat);
                    CloseGenericArgument();
                }
                CloseGenericArguments();
            }
 
            // Append pointer, byRef and array qualifiers
            AddElementType(type);
 
            if (format == Format.AssemblyQualifiedName)
                AddAssemblySpec(type.Module.Assembly.FullName);
        }
        
        [System.Security.SecurityCritical]  // auto-generated
        private void OpenGenericArguments() { OpenGenericArguments(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void CloseGenericArguments() { CloseGenericArguments(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void OpenGenericArgument() { OpenGenericArgument(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void CloseGenericArgument() { CloseGenericArgument(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddName(string name) { AddName(m_typeNameBuilder, name); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddPointer() { AddPointer(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddByRef() { AddByRef(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddSzArray() { AddSzArray(m_typeNameBuilder); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddArray(int rank) { AddArray(m_typeNameBuilder, rank); }
        [System.Security.SecurityCritical]  // auto-generated
        private void AddAssemblySpec(string assemblySpec) { AddAssemblySpec(m_typeNameBuilder, assemblySpec); }
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override string ToString() { string ret = null; ToString(m_typeNameBuilder, JitHelpers.GetStringHandleOnStack(ref ret)); return ret; }
        [System.Security.SecurityCritical]  // auto-generated
        private void Clear() { Clear(m_typeNameBuilder); }
        #endregion
    }
}