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; }
static void GetQualifiedNameInternal(NamedTypeSpec n, StringBuilder b) { if (n.ContainingType is object) { GetQualifiedNameInternal(n.ContainingType, b); _ = b.Append('+'); } _ = b.Append(n.Name); }
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); }