Ejemplo n.º 1
0
        /// <summary>
        /// Parses the reflection name starting at pos.
        /// If local is true, only parses local type names, not assembly qualified type names.
        /// </summary>
        static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, bool local = false)
        {
            if (pos == reflectionTypeName.Length)
            {
                throw new ReflectionNameParseException(pos, "Unexpected end");
            }
            ITypeReference reference;

            if (reflectionTypeName[pos] == '`')
            {
                // type parameter reference
                pos++;
                if (pos == reflectionTypeName.Length)
                {
                    throw new ReflectionNameParseException(pos, "Unexpected end");
                }
                if (reflectionTypeName[pos] == '`')
                {
                    // method type parameter reference
                    pos++;
                    int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
                    reference = TypeParameterReference.Create(SymbolKind.Method, index);
                }
                else
                {
                    // class type parameter reference
                    int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
                    reference = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
                }
            }
            else
            {
                // not a type parameter reference: read the actual type name
                string typeName     = ReadTypeName(reflectionTypeName, ref pos, out int tpc);
                string assemblyName = local ? null : SkipAheadAndReadAssemblyName(reflectionTypeName, pos);
                reference = CreateGetClassTypeReference(assemblyName, typeName, tpc);
            }
            // read type suffixes
            while (pos < reflectionTypeName.Length)
            {
                switch (reflectionTypeName[pos++])
                {
                case '+':
                    int    tpc;
                    string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
                    reference = new NestedTypeReference(reference, typeName, tpc);
                    break;

                case '*':
                    reference = new PointerTypeReference(reference);
                    break;

                case '&':
                    reference = new ByReferenceTypeReference(reference);
                    break;

                case '[':
                    // this might be an array or a generic type
                    if (pos == reflectionTypeName.Length)
                    {
                        throw new ReflectionNameParseException(pos, "Unexpected end");
                    }
                    if (reflectionTypeName[pos] != ']' && reflectionTypeName[pos] != ',')
                    {
                        // it's a generic type
                        List <ITypeReference> typeArguments = new List <ITypeReference>();
                        bool first = true;
                        while (first || pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',')
                        {
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                pos++;                                         // skip ','
                            }
                            if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[')
                            {
                                // non-local type names are enclosed in another set of []
                                pos++;

                                typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos));

                                if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
                                {
                                    pos++;
                                }
                                else
                                {
                                    throw new ReflectionNameParseException(pos, "Expected end of type argument");
                                }
                            }
                            else
                            {
                                // local type names occur directly in the outer []
                                typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, local: true));
                            }
                        }

                        if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
                        {
                            pos++;
                            reference = new ParameterizedTypeReference(reference, typeArguments);
                        }
                        else
                        {
                            throw new ReflectionNameParseException(pos, "Expected end of generic type");
                        }
                    }
                    else
                    {
                        // it's an array
                        int dimensions = 1;
                        while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',')
                        {
                            dimensions++;
                            pos++;
                        }
                        if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
                        {
                            pos++;                                     // end of array
                            reference = new ArrayTypeReference(reference, dimensions);
                        }
                        else
                        {
                            throw new ReflectionNameParseException(pos, "Invalid array modifier");
                        }
                    }
                    break;

                case ',' when !local:
                    // assembly qualified name, ignore everything up to the end/next ']'
                    while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']')
                    {
                        pos++;
                    }
                    break;

                default:
                    pos--;                             // reset pos to the character we couldn't read
                    if (reflectionTypeName[pos] == ']' || reflectionTypeName[pos] == ',')
                    {
                        return(reference);                                // return from a nested generic
                    }
                    else
                    {
                        throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'");
                    }
                }
            }
            return(reference);
        }
Ejemplo n.º 2
0
        bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
        {
            ArrayTypeReference o = other as ArrayTypeReference;

            return(o != null && elementType == o.elementType && dimensions == o.dimensions);
        }