コード例 #1
0
        /// <summary>
        /// Returns the constructed form of the provided generic type.
        /// </summary>
        public static IdSpan GetConstructed(this TypeConverter formatter, IdSpan unconstructed, params Type[] typeArguments)
        {
            var typeString     = unconstructed.AsSpan();
            var indicatorIndex = typeString.IndexOf((byte)GenericTypeIndicator);
            var arityString    = typeString.Slice(indicatorIndex + 1);

            if (indicatorIndex < 0 || arityString.IndexOf((byte)StartArgument) >= 0)
            {
                throw new InvalidOperationException("Cannot construct an already-constructed type");
            }

            if (!Utf8Parser.TryParse(arityString, out int arity, out var len) || len < arityString.Length || typeArguments.Length != arity)
            {
                throw new InvalidOperationException($"Insufficient number of type arguments, {typeArguments.Length}, provided while constructing type \"{unconstructed}\"");
            }

            var typeSpecs = new TypeSpec[typeArguments.Length];

            for (var i = 0; i < typeArguments.Length; i++)
            {
                typeSpecs[i] = RuntimeTypeNameParser.Parse(formatter.Format(typeArguments[i]));
            }

            var constructed = new ConstructedGenericTypeSpec(new NamedTypeSpec(null, unconstructed.ToStringUtf8(), typeArguments.Length), typeSpecs).Format();

            return(IdSpan.Create(constructed));
        }
コード例 #2
0
        private static (TypeSpec Type, string Assembly) HandleGeneric(ConstructedGenericTypeSpec type, string assemblyName, Func <QualifiedType, QualifiedType> replaceTypeName)
        {
            var(unconstructed, replacementAssembly) = ApplyInner(type.UnconstructedType, assemblyName, replaceTypeName);

            var newArguments = new TypeSpec[type.Arguments.Length];
            var didChange    = false;

            for (var i = 0; i < type.Arguments.Length; i++)
            {
                // Generic type parameters do not inherit the assembly of the generic type.
                var args = ApplyInner(type.Arguments[i], null, replaceTypeName);

                if (args.Assembly is object)
                {
                    newArguments[i] = new AssemblyQualifiedTypeSpec(args.Type, args.Assembly);
                }
                else
                {
                    newArguments[i] = args.Type;
                }

                didChange |= !ReferenceEquals(newArguments[i], type.Arguments[i]);
            }

            if (ReferenceEquals(type.UnconstructedType, unconstructed) && !didChange)
            {
                return(type, replacementAssembly);
            }

            return(new ConstructedGenericTypeSpec((NamedTypeSpec)unconstructed, newArguments), replacementAssembly);
        }
コード例 #3
0
        private static TypeSpec ParseInternal(ref ReadOnlySpan <char> input)
        {
            TypeSpec result;
            char     c;
            Reader   s = default;

            s.Input = input;

            // Read namespace and class name, including generic arity, which is a part of the class name.
            NamedTypeSpec named = null;

            while (true)
            {
                var typeName = ParseTypeName(ref s);
                named = new NamedTypeSpec(named, typeName.ToString(), s.TotalGenericArity);

                if (s.TryPeek(out c) && c == NestedTypeIndicator)
                {
                    // Consume the nested type indicator, then loop to parse the nested type.
                    s.ConsumeCharacter(NestedTypeIndicator);
                    continue;
                }

                break;
            }

            // Parse generic type parameters
            if (s.TotalGenericArity > 0 && s.TryPeek(out c) && c == ArrayStartIndicator)
            {
                s.ConsumeCharacter(ArrayStartIndicator);

                var arguments = new TypeSpec[s.TotalGenericArity];
                for (var i = 0; i < s.TotalGenericArity; i++)
                {
                    if (i > 0)
                    {
                        s.ConsumeCharacter(ParameterSeparator);
                    }

                    // Parse the argument type
                    s.ConsumeCharacter(ArrayStartIndicator);
                    var remaining = s.Remaining;
                    arguments[i] = ParseInternal(ref remaining);
                    var consumed = s.Remaining.Length - remaining.Length;
                    s.Consume(consumed);
                    s.ConsumeCharacter(ArrayEndIndicator);
                }

                s.ConsumeCharacter(ArrayEndIndicator);
                result = new ConstructedGenericTypeSpec(named, arguments);
            }
            else
            {
                // This is not a constructed generic type
                result = named;
            }

            // Parse modifiers
            bool hadModifier;

            do
            {
                hadModifier = false;

                if (!s.TryPeek(out c))
                {
                    break;
                }

                switch (c)
                {
                case ArrayStartIndicator:
                    var dimensions = ParseArraySpecifier(ref s);
                    result      = new ArrayTypeSpec(result, dimensions);
                    hadModifier = true;
                    break;

                case PointerIndicator:
                    result = new PointerTypeSpec(result);
                    s.ConsumeCharacter(PointerIndicator);
                    hadModifier = true;
                    break;

                case ReferenceIndicator:
                    result = new ReferenceTypeSpec(result);
                    s.ConsumeCharacter(ReferenceIndicator);
                    hadModifier = true;
                    break;
                }
            } while (hadModifier);

            // Extract the assembly, if specified.
            if (s.TryPeek(out c) && c == AssemblyIndicator)
            {
                s.ConsumeCharacter(AssemblyIndicator);
                var assembly = ExtractAssemblySpec(ref s);
                result = new AssemblyQualifiedTypeSpec(result, assembly.ToString());
            }

            input = s.Remaining;
            return(result);
        }