Пример #1
0
        static bool ParseTypeArguments(string id, ref int index, IGenericParameterProvider?typeParameterContext, List <string> typeArguments)
        {
            index++;             // skip over {

            while (true)
            {
                var type = ParseTypeSymbol(id, ref index, typeParameterContext);

                if (type == null)
                {
                    // if a type argument cannot be identified, argument list is no good
                    return(false);
                }

                // add first one
                typeArguments.Add(type);

                if (PeekNextChar(id, index) == ',')
                {
                    index++;
                    continue;
                }

                break;
            }

            // note: this doesn't require closing }
            if (PeekNextChar(id, index) == '}')
            {
                index++;
            }

            return(true);
        }
Пример #2
0
        static void ParseNamedTypeSymbol(string id, ref int index, IGenericParameterProvider?typeParameterContext, List <string> results)
        {
            Debug.Assert(results.Count == 0);
            var nameBuilder = new StringBuilder();

            // loop for dotted names
            while (true)
            {
                var name = ParseName(id, ref index);
                if (String.IsNullOrEmpty(name))
                {
                    return;
                }

                nameBuilder.Append(name);

                List <string>?typeArguments = null;
                int           arity         = 0;

                // type arguments
                if (PeekNextChar(id, index) == '{')
                {
                    typeArguments = new List <string> ();
                    if (!ParseTypeArguments(id, ref index, typeParameterContext, typeArguments))
                    {
                        continue;
                    }

                    arity = typeArguments.Count;
                }

                if (arity != 0)
                {
                    Debug.Assert(typeArguments != null && typeArguments.Count != 0);
                    nameBuilder.Append('{');
                    bool needsComma = false;
                    foreach (var typeArg in typeArguments)
                    {
                        if (needsComma)
                        {
                            nameBuilder.Append(',');
                        }
                        nameBuilder.Append(typeArg);
                        needsComma = true;
                    }
                    nameBuilder.Append('}');
                }

                if (PeekNextChar(id, index) != '.')
                {
                    break;
                }

                index++;
                nameBuilder.Append('.');
            }

            results.Add(nameBuilder.ToString());
        }
Пример #3
0
        static string?ParseTypeSymbol(string id, ref int index, IGenericParameterProvider?typeParameterContext)
        {
            var results = new List <string> ();

            ParseTypeSymbol(id, ref index, typeParameterContext, results);
            if (results.Count == 1)
            {
                return(results[0]);
            }

            Debug.Assert(results.Count == 0);
            return(null);
        }
Пример #4
0
            private TypeReference?ResolveImpl(ModuleDefinition module, IGenericParameterProvider?context, TypeReference typeRef)
            {
                if (typeRef.IsGenericInstance)
                {
                    throw new WeavingException($"Type is already a generic instance: {typeRef.FullName}");
                }

                if (typeRef.IsByReference || typeRef.IsPointer || typeRef.IsArray)
                {
                    throw new WeavingException("Cannot make a generic instance of a ByRef, pointer or array type");
                }

                var typeDef = typeRef.ResolveRequiredType();

                if (!typeDef.HasGenericParameters)
                {
                    throw new WeavingException($"Not a generic type definition: {typeRef.FullName}");
                }

                if (typeDef.GenericParameters.Count != _genericArgs.Length)
                {
                    throw new WeavingException($"Incorrect number of generic arguments supplied for type {typeRef.FullName} - expected {typeRef.GenericParameters.Count}, but got {_genericArgs.Length}");
                }

                var genericType = new GenericInstanceType(typeRef);

                foreach (var argTypeBuilder in _genericArgs)
                {
                    TypeReference?argTypeRef;

                    if (context != null)
                    {
                        argTypeRef = argTypeBuilder.TryBuild(context);
                        if (argTypeRef == null)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        argTypeRef = argTypeBuilder.Build();
                    }

                    genericType.GenericArguments.Add(argTypeRef);
                }

                return(module.ImportReference(genericType));
            }
Пример #5
0
        static void ParseTypeParameterSymbol(string id, ref int index, IGenericParameterProvider?typeParameterContext, List <string> results)
        {
            // skip the first `
            Debug.Assert(PeekNextChar(id, index) == '`');
            index++;

            Debug.Assert(
                typeParameterContext == null ||
                (typeParameterContext is MethodDefinition && typeParameterContext.GenericParameterType == GenericParameterType.Method) ||
                (typeParameterContext is TypeDefinition && typeParameterContext.GenericParameterType == GenericParameterType.Type)
                );

            if (PeekNextChar(id, index) == '`')
            {
                // `` means this is a method type parameter
                index++;
                var methodTypeParameterIndex = ReadNextInteger(id, ref index);

                if (typeParameterContext is MethodDefinition methodContext)
                {
                    var count = methodContext.HasGenericParameters ? methodContext.GenericParameters.Count : 0;
                    if (count > 0 && methodTypeParameterIndex < count)
                    {
                        results.Add("``" + methodTypeParameterIndex);
                    }
                }
            }
            else
            {
                // regular type parameter
                var typeParameterIndex = ReadNextInteger(id, ref index);

                var typeContext = typeParameterContext is MethodDefinition methodContext
                                        ? methodContext.DeclaringType
                                        : typeParameterContext as TypeDefinition;

                if (typeParameterIndex >= 0 ||
                    typeParameterIndex < typeContext?.GenericParameters.Count)
                {
                    // No need to look at declaring types like Roslyn, because type parameters are redeclared.
                    results.Add("`" + typeParameterIndex);
                }
            }
        }
Пример #6
0
        static void ParseTypeSymbol(string id, ref int index, IGenericParameterProvider?typeParameterContext, List <string> results)
        {
            // Note: Roslyn has a special case that deviates from the language spec, which
            // allows context expressions embedded in a type reference => <context-definition>:<type-parameter>
            // We do not support this special format.

            Debug.Assert(results.Count == 0);

            if (PeekNextChar(id, index) == '`')
            {
                ParseTypeParameterSymbol(id, ref index, typeParameterContext, results);
            }
            else
            {
                ParseNamedTypeSymbol(id, ref index, typeParameterContext, results);
            }

            // apply any array or pointer constructions to results
            var startIndex = index;
            var endIndex   = index;

            for (int i = 0; i < results.Count; i++)
            {
                index = startIndex;
                var typeReference = results[i];

                while (true)
                {
                    if (PeekNextChar(id, index) == '[')
                    {
                        var boundsStartIndex = index;
                        var bounds           = ParseArrayBounds(id, ref index);
                        var boundsEndIndex   = index;
                        Debug.Assert(bounds > 0);
                        // Instead of constructing a representation of the array bounds, we
                        // use the original input to represent the bounds, and later match it
                        // against the generated strings for types in signatures.
                        // This ensures that we will only resolve members with supported array bounds.
                        typeReference += id.Substring(boundsStartIndex, boundsEndIndex - boundsStartIndex);
                        continue;
                    }

                    if (PeekNextChar(id, index) == '*')
                    {
                        index++;
                        typeReference += '*';
                        continue;
                    }

                    break;
                }

                if (PeekNextChar(id, index) == '@')
                {
                    index++;
                    typeReference += '@';
                }

                results[i] = typeReference;
                endIndex   = index;
            }

            index = endIndex;
        }