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}"); } foreach (var arg in arguments) { if (arg is null) { throw new ArgumentNullException("Cannot construct a generic type using a null argument"); } } this.UnconstructedType = unconstructedType; this.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) { this.ContainingType = containingType; this.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"); } if (arity < 0) { throw new ArgumentOutOfRangeException("A type cannot have a negative arity"); } this.Arity = arity; }
private static (TypeSpec Type, string Assembly) HandleNamedType(NamedTypeSpec type, string assemblyName, Func <QualifiedType, QualifiedType> replaceTypeName) { var nsQualified = type.GetNamespaceQualifiedName(); var names = replaceTypeName(new QualifiedType(assembly: assemblyName, type: nsQualified)); if (!string.Equals(nsQualified, names.Type, StringComparison.Ordinal)) { // Change the type name and potentially the assembly. var resultType = RuntimeTypeNameParser.Parse(names.Type); if (!(resultType is NamedTypeSpec)) { throw new InvalidOperationException($"Replacement type name, \"{names.Type}\", can not deviate from the original type structure of the input, \"{nsQualified}\""); } return(resultType, names.Assembly); } else if (!string.Equals(assemblyName, names.Assembly, StringComparison.Ordinal)) { // Only change the assembly; return(type, names.Assembly); } else if (type.ContainingType is object) { // Give the user an opportunity to change the parent, including the assembly. var replacementParent = ApplyInner(type.ContainingType, assemblyName, replaceTypeName); if (ReferenceEquals(replacementParent.Type, type.ContainingType)) { // No change to the type. return(type, replacementParent.Assembly); } // The parent type changed. var typedReplacement = (NamedTypeSpec)replacementParent.Type; return(new NamedTypeSpec(typedReplacement, type.Name, type.Arity), replacementParent.Assembly); } else { return(type, names.Assembly); } }
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); }