Exemple #1
0
        /// <summary>
        /// Parses the string '<paramref name="name"/>' and returns the type corresponding to the parsed type name.
        /// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard.
        /// This is the inverse of what <see cref="CustomAttributeTypeNameFormatter"/> does.
        /// </summary>
        public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name, bool throwIfNotFound = true, Func <string, ModuleDesc, bool, MetadataType> resolver = null)
        {
            TypeDesc loadedType;

            StringBuilder genericTypeDefName = new StringBuilder(name.Length);

            var ch      = name.Begin();
            var nameEnd = name.End();

            for (; ch < nameEnd; ++ch)
            {
                // Always pass escaped characters through.
                if (ch.Current == '\\')
                {
                    genericTypeDefName.Append(ch.Current);
                    ++ch;
                    if (ch < nameEnd)
                    {
                        genericTypeDefName.Append(ch.Current);
                    }
                    continue;
                }

                // The type def name ends if

                // The start of a generic argument list
                if (ch.Current == '[')
                {
                    break;
                }

                // Indication that the type is a pointer
                if (ch.Current == '*')
                {
                    break;
                }

                // Indication that the type is a reference
                if (ch.Current == '&')
                {
                    break;
                }

                // A comma that indicates that the rest of the name is an assembly reference
                if (ch.Current == ',')
                {
                    break;
                }

                genericTypeDefName.Append(ch.Current);
            }

            ModuleDesc   homeModule   = module;
            AssemblyName homeAssembly = FindAssemblyIfNamePresent(name);

            if (homeAssembly != null)
            {
                homeModule = module.Context.ResolveAssembly(homeAssembly);
            }
            MetadataType typeDef = resolver != null?resolver(genericTypeDefName.ToString(), homeModule, throwIfNotFound) :
                                       ResolveCustomAttributeTypeDefinitionName(genericTypeDefName.ToString(), homeModule, throwIfNotFound);

            if (typeDef == null)
            {
                return(null);
            }

            ArrayBuilder <TypeDesc> genericArgs = new ArrayBuilder <TypeDesc>();

            // Followed by generic instantiation parameters (but check for the array case)
            if (ch < nameEnd && ch.Current == '[' && (ch + 1) < nameEnd && (ch + 1).Current != ']' && (ch + 1).Current != ',')
            {
                ch++;                                                                   // truncate the '['
                var genericInstantiationEnd = ch + ReadTypeArgument(ch, nameEnd, true); // find the end of the instantiation list
                while (ch < genericInstantiationEnd)
                {
                    if (ch.Current == ',')
                    {
                        ch++;
                    }

                    int    argLen = ReadTypeArgument(ch, name.End(), false);
                    string typeArgName;
                    if (ch.Current == '[')
                    {
                        // This type argument name is stringified,
                        // we need to remove the [] from around it
                        ch++;
                        typeArgName = StringIterator.Substring(ch, ch + (argLen - 2));
                        ch         += argLen - 1;
                    }
                    else
                    {
                        typeArgName = StringIterator.Substring(ch, ch + argLen);
                        ch         += argLen;
                    }

                    TypeDesc argType = module.GetTypeByCustomAttributeTypeName(typeArgName, throwIfNotFound, resolver);
                    if (argType == null)
                    {
                        return(null);
                    }
                    genericArgs.Add(argType);
                }

                Debug.Assert(ch == genericInstantiationEnd);
                ch++;

                loadedType = typeDef.MakeInstantiatedType(genericArgs.ToArray());
            }
            else
            {
                // Non-generic type
                loadedType = typeDef;
            }

            // At this point the characters following may be any number of * characters to indicate pointer depth
            while (ch < nameEnd)
            {
                if (ch.Current == '*')
                {
                    loadedType = loadedType.MakePointerType();
                }
                else
                {
                    break;
                }
                ch++;
            }

            // Followed by any number of "[]" or "[,*]" pairs to indicate arrays
            int  commasSeen  = 0;
            bool bracketSeen = false;

            while (ch < nameEnd)
            {
                if (ch.Current == '[')
                {
                    ch++;
                    commasSeen  = 0;
                    bracketSeen = true;
                }
                else if (ch.Current == ']')
                {
                    if (!bracketSeen)
                    {
                        break;
                    }

                    ch++;
                    if (commasSeen == 0)
                    {
                        loadedType = loadedType.MakeArrayType();
                    }
                    else
                    {
                        loadedType = loadedType.MakeArrayType(commasSeen + 1);
                    }

                    bracketSeen = false;
                }
                else if (ch.Current == ',')
                {
                    if (!bracketSeen)
                    {
                        break;
                    }
                    ch++;
                    commasSeen++;
                }
                else
                {
                    break;
                }
            }

            // Followed by at most one & character to indicate a byref.
            if (ch < nameEnd)
            {
                if (ch.Current == '&')
                {
                    loadedType = loadedType.MakeByRefType();
                    ch++;
                }
            }

            return(loadedType);
        }
Exemple #2
0
        private void ProcessTypeDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, XElement typeElement)
        {
            var typeNameAttribute = typeElement.Attribute("Name");
            if (typeNameAttribute == null)
                throw new Exception();

            var dynamicDegreeAttribute = typeElement.Attribute("Dynamic");
            if (dynamicDegreeAttribute != null)
            {
                if (dynamicDegreeAttribute.Value != "Required All")
                    throw new NotSupportedException();
            }

            string typeName = typeNameAttribute.Value;

            TypeDesc type = containingModule.GetTypeByCustomAttributeTypeName(typeName);
            rootProvider.AddCompilationRoot(type, "RD.XML root");

            if (type.IsDefType)
            {
                foreach (var method in type.GetMethods())
                {
                    if (method.IsAbstract || method.HasInstantiation)
                        continue;

                    rootProvider.AddCompilationRoot(method, "RD.XML root");
                }
            }
        }