Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConstructedGenericTypeSpec"/> class.
        /// </summary>
        /// <param name="unconstructedType">The unconstructed type.</param>
        /// <param name="arguments">The generic type arguments.</param>
        public ConstructedGenericTypeSpec(NamedTypeSpec unconstructedType, TypeSpec[] arguments)
        {
            if (unconstructedType is null)
            {
                throw new ArgumentNullException(nameof(unconstructedType));
            }

            if (arguments is null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }

            if (unconstructedType.Arity != arguments.Length)
            {
                throw new ArgumentException($"Invalid number of arguments {arguments.Length} provided while constructing generic type of arity {unconstructedType.Arity}: {unconstructedType}", nameof(arguments));
            }

            foreach (var arg in arguments)
            {
                if (arg is null)
                {
                    throw new ArgumentNullException(nameof(arguments), "Cannot construct a generic type using a null argument");
                }
            }

            UnconstructedType = unconstructedType;
            Arguments         = arguments;
        }
Example #2
0
            static void GetQualifiedNameInternal(NamedTypeSpec n, StringBuilder b)
            {
                if (n.ContainingType is not null)
                {
                    GetQualifiedNameInternal(n.ContainingType, b);
                    _ = b.Append('+');
                }

                _ = b.Append(n.Name);
            }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NamedTypeSpec"/> class.
        /// </summary>
        /// <param name="containingType">The containing type.</param>
        /// <param name="name">The type name.</param>
        /// <param name="arity">The generic arity of the type, which must be greater than or equal to the generic arity of the containing type.</param>
        public NamedTypeSpec(NamedTypeSpec containingType, string name, int arity)
        {
            ContainingType = containingType;
            Name           = name;
            if (containingType is NamedTypeSpec c && c.Arity > arity)
            {
                throw new ArgumentException("A named type cannot have an arity less than that of its containing type", nameof(arity));
            }

            if (arity < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(arity), "A type cannot have a negative arity");
            }

            Arity = arity;
        }
        private static TypeSpec ParseInternal(ref ReadOnlySpan <char> input)
        {
            TypeSpec     result;
            char         c;
            BufferReader 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);
        }