// This shouldn't be necessary, but CCI is putting a nonzero TypeDefId in the ExportedTypes table // for nested types if NamespaceAliasForType.AliasedType is set to an ITypeDefinition // so we make an ITypeReference copy as a workaround. private static INamedTypeReference ConvertDefinitionToReferenceIfTypeIsNested(INamedTypeDefinition typeDef, IMetadataHost host) { var nestedTypeDef = typeDef as INestedTypeDefinition; if (nestedTypeDef == null) { return(typeDef); } var typeRef = new NestedTypeReference(); typeRef.Copy(nestedTypeDef, host.InternFactory); return(typeRef); }
private MetadataTypeReference GetTypeReferenceForForwardedType(NameSpec fullName) { if (assemblyReferencesByForwardedType == null) { assemblyReferencesByForwardedType = new Dictionary <NameSpec, AssemblyReferenceHandle>(); foreach (var handle in reader.ExportedTypes) { var exportedType = reader.GetExportedType(handle); if (!exportedType.IsForwarder) { continue; } if (exportedType.Implementation.Kind != HandleKind.AssemblyReference) { throw new NotImplementedException(exportedType.Implementation.Kind.ToString()); } assemblyReferencesByForwardedType.Add( new NameSpec( reader.GetString(exportedType.Namespace), reader.GetString(exportedType.Name), nestedNames: null), (AssemblyReferenceHandle)exportedType.Implementation); } } if (assemblyReferencesByForwardedType.TryGetValue(new NameSpec(fullName.Namespace, fullName.TopLevelName, null), out var assemblyReferenceHandle)) { var current = (MetadataTypeReference) new TopLevelTypeReference( reader .GetAssemblyReference(assemblyReferenceHandle) .GetAssemblyName(reader), fullName.Namespace, fullName.TopLevelName); if (fullName.NestedNames != null) { foreach (var nestedName in fullName.NestedNames) { current = new NestedTypeReference(current, nestedName); } } return(current); } return(null); }
static int AppendParameterizedTypeName(StringBuilder b, ITypeReference type, IList <ITypeReference> typeArguments, ITypeResolveContext context) { GetClassTypeReference gctr = type as GetClassTypeReference; if (gctr != null) { if (!string.IsNullOrEmpty(gctr.Namespace)) { b.Append(gctr.Namespace); b.Append('.'); } b.Append(gctr.Name); if (gctr.TypeParameterCount > 0) { b.Append('{'); for (int i = 0; i < gctr.TypeParameterCount && i < typeArguments.Count; i++) { if (i > 0) { b.Append(','); } AppendTypeName(b, typeArguments[i], context); } b.Append('}'); } return(gctr.TypeParameterCount); } else { NestedTypeReference ntr = (NestedTypeReference)type; int outerTpc = AppendParameterizedTypeName(b, ntr.DeclaringTypeReference, typeArguments, context); b.Append('.'); if (ntr.AdditionalTypeParameterCount > 0) { b.Append('{'); for (int i = 0; i < ntr.AdditionalTypeParameterCount && i + outerTpc < typeArguments.Count; i++) { if (i > 0) { b.Append(','); } AppendTypeName(b, typeArguments[i + outerTpc], context); } b.Append('}'); } return(outerTpc + ntr.AdditionalTypeParameterCount); } }
private static MetadataTypeReference GetTypeFromTypeReferenceHandle(MetadataReader reader, TypeReferenceHandle handle) { var nestedTypeNames = new List <StringHandle>(); var type = reader.GetTypeReference(handle); while (type.ResolutionScope.Kind == HandleKind.TypeReference) { nestedTypeNames.Add(type.Name); type = reader.GetTypeReference((TypeReferenceHandle)type.ResolutionScope); } MetadataAssemblyReference assemblyReference; switch (type.ResolutionScope.Kind) { case HandleKind.ModuleReference: assemblyReference = null; break; case HandleKind.AssemblyReference: assemblyReference = reader.GetAssemblyReference((AssemblyReferenceHandle)type.ResolutionScope) .GetAssemblyName(reader); break; default: throw new NotImplementedException(); } MetadataTypeReference current = new TopLevelTypeReference( assemblyReference, reader.GetString(type.Namespace), reader.GetString(type.Name)); for (var i = nestedTypeNames.Count - 1; i >= 0; i--) { current = new NestedTypeReference(current, reader.GetString(nestedTypeNames[i])); } return(current); }
static ITypeReference ParseTypeName(string typeName, ref int pos) { string reflectionTypeName = typeName; if (pos == typeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } ITypeReference result; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.Method, index); } else { // class type parameter reference int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name List <ITypeReference> typeArguments = new List <ITypeReference>(); int typeParameterCount; string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments); result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount); while (pos < typeName.Length && typeName[pos] == '.') { pos++; string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments); result = new NestedTypeReference(result, nestedTypeName, typeParameterCount); } if (typeArguments.Count > 0) { result = new ParameterizedTypeReference(result, typeArguments); } } while (pos < typeName.Length) { switch (typeName[pos]) { case '[': int dimensions = 1; do { pos++; if (pos == typeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (typeName[pos] == ',') { dimensions++; } } while (typeName[pos] != ']'); result = new ArrayTypeReference(result, dimensions); break; case '*': result = new PointerTypeReference(result); break; case '@': result = new ByReferenceTypeReference(result); break; default: return(result); } pos++; } return(result); }
static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity) { if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); IMethod method = entity as IMethod; if (method != null && index >= 0 && index < method.TypeParameters.Count) { return(method.TypeParameters[index]); } else { return(SharedTypes.UnknownType); } } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); if (c != null && index >= 0 && index < c.TypeParameters.Count) { return(c.TypeParameters[index]); } else { return(SharedTypes.UnknownType); } } } // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); ITypeReference reference = new GetClassTypeReference(typeName, tpc); // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '[') { // it's a generic type List <ITypeReference> typeArguments = new List <ITypeReference>(tpc); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected another type argument"); } typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') { pos++; } break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') { return(reference); // return from a nested generic } else { throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } } return(reference); }
// This shouldn't be necessary, but CCI is putting a nonzero TypeDefId in the ExportedTypes table // for nested types if NamespaceAliasForType.AliasedType is set to an ITypeDefinition // so we make an ITypeReference copy as a workaround. private static INamedTypeReference ConvertDefinitionToReferenceIfTypeIsNested(INamedTypeDefinition typeDef, IMetadataHost host) { var nestedTypeDef = typeDef as INestedTypeDefinition; if (nestedTypeDef == null) return typeDef; var typeRef = new NestedTypeReference(); typeRef.Copy(nestedTypeDef, host.InternFactory); return typeRef; }
static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos) { if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } ITypeReference reference; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.Method, index); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); } // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '[') { // it's a generic type List <ITypeReference> typeArguments = new List <ITypeReference>(); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected another type argument"); } typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') { pos++; } break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') { return(reference); // return from a nested generic } else { throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } } return(reference); }
static void AppendTypeName(StringBuilder b, ITypeReference type, ITypeResolveContext context) { IType resolvedType = type as IType; if (resolvedType != null) { AppendTypeName(b, resolvedType); return; } GetClassTypeReference gctr = type as GetClassTypeReference; if (gctr != null) { if (!string.IsNullOrEmpty(gctr.Namespace)) { b.Append(gctr.Namespace); b.Append('.'); } b.Append(gctr.Name); if (gctr.TypeParameterCount > 0) { b.Append('`'); b.Append(gctr.TypeParameterCount); } return; } NestedTypeReference ntr = type as NestedTypeReference; if (ntr != null) { AppendTypeName(b, ntr.DeclaringTypeReference, context); b.Append('.'); b.Append(ntr.Name); if (ntr.AdditionalTypeParameterCount > 0) { b.Append('`'); b.Append(ntr.AdditionalTypeParameterCount); } return; } ParameterizedTypeReference pt = type as ParameterizedTypeReference; if (pt != null && IsGetClassTypeReference(pt.GenericType)) { AppendParameterizedTypeName(b, pt.GenericType, pt.TypeArguments, context); return; } ArrayTypeReference array = type as ArrayTypeReference; if (array != null) { AppendTypeName(b, array.ElementType, context); b.Append('['); if (array.Dimensions > 1) { for (int i = 0; i < array.Dimensions; i++) { if (i > 0) { b.Append(','); } b.Append("0:"); } } b.Append(']'); return; } PointerTypeReference ptr = type as PointerTypeReference; if (ptr != null) { AppendTypeName(b, ptr.ElementType, context); b.Append('*'); return; } ByReferenceTypeReference brtr = type as ByReferenceTypeReference; if (brtr != null) { AppendTypeName(b, brtr.ElementType, context); b.Append('@'); return; } if (context == null) { b.Append('?'); } else { AppendTypeName(b, type.Resolve(context)); } }
public ImmutableNode <string> Visit(NestedTypeReference nestedTypeReference) { return(new ImmutableNode <string>(nestedTypeReference.DeclaringType.Accept(this), ".", BuildNameWithArity(nestedTypeReference.Name))); }