/// <summary> /// Lookup a type within the assembly using its canonical CLR metadata name. /// </summary> /// <param name="metadataName"></param> /// <param name="includeReferences"> /// If search within assembly fails, lookup in assemblies referenced by the primary module. /// For source assembly, this is equivalent to all assembly references given to compilation. /// </param> /// <param name="isWellKnownType"> /// Extra restrictions apply when searching for a well-known type. In particular, the type must be public. /// </param> /// <param name="useCLSCompliantNameArityEncoding"> /// While resolving the name, consider only types following CLS-compliant generic type names and arity encoding (ECMA-335, section 10.7.2). /// I.e. arity is inferred from the name and matching type must have the same emitted name and arity. /// </param> /// <param name="warnings"> /// A diagnostic bag to receive warnings if we should allow multiple definitions and pick one. /// </param> /// <param name="ignoreCorLibraryDuplicatedTypes"> /// In case duplicate types are found, ignore the one from corlib. This is useful for any kind of compilation at runtime /// (EE/scripting/Powershell) using a type that is being migrated to corlib. /// </param> /// <param name="conflicts"> /// In cases a type could not be found because of ambiguity, we return two of the candidates that caused the ambiguity. /// </param> /// <returns>Null if the type can't be found.</returns> internal NamedTypeSymbol GetTypeByMetadataName( string metadataName, bool includeReferences, bool isWellKnownType, out (AssemblySymbol, AssemblySymbol) conflicts, bool useCLSCompliantNameArityEncoding = false, DiagnosticBag warnings = null, bool ignoreCorLibraryDuplicatedTypes = false) { NamedTypeSymbol type; MetadataTypeName mdName; if (metadataName.IndexOf('+') >= 0) { var parts = metadataName.Split(s_nestedTypeNameSeparators); Debug.Assert(parts.Length > 0); mdName = MetadataTypeName.FromFullName(parts[0], useCLSCompliantNameArityEncoding); type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, conflicts: out conflicts, warnings: warnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); for (int i = 1; (object)type != null && !type.IsErrorType() && i < parts.Length; i++) { mdName = MetadataTypeName.FromTypeName(parts[i]); NamedTypeSymbol temp = type.LookupMetadataType(ref mdName); type = (!isWellKnownType || IsValidWellKnownType(temp)) ? temp : null; } } else { mdName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding); type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, conflicts: out conflicts, warnings: warnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); } return(((object)type == null || type.IsErrorType()) ? null : type); }
/// <summary> /// Resolves <see cref="System.Type"/> to a <see cref="TypeSymbol"/> available in this assembly /// its referenced assemblies. /// </summary> /// <param name="type">The type to resolve.</param> /// <param name="includeReferences">Use referenced assemblies for resolution.</param> /// <returns>The resolved symbol if successful or null on failure.</returns> internal TypeSymbol GetTypeByReflectionType(Type type, bool includeReferences) { System.Reflection.TypeInfo typeInfo = type.GetTypeInfo(); Debug.Assert(!typeInfo.IsByRef); // not supported rigth now (we don't accept open types as submission results nor host types): Debug.Assert(!typeInfo.ContainsGenericParameters); if (typeInfo.IsArray) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } int rank = typeInfo.GetArrayRank(); return(new ArrayTypeSymbol(this, symbol, ImmutableArray <CustomModifier> .Empty, rank)); } else if (typeInfo.IsPointer) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } return(new PointerTypeSymbol(symbol)); } else if (typeInfo.DeclaringType != null) { Debug.Assert(!typeInfo.IsArray); // consolidated generic arguments (includes arguments of all declaring types): Type[] genericArguments = typeInfo.GenericTypeArguments; int typeArgumentIndex = 0; var currentTypeInfo = typeInfo.IsGenericType ? typeInfo.GetGenericTypeDefinition().GetTypeInfo() : typeInfo; var nestedTypes = ArrayBuilder <System.Reflection.TypeInfo> .GetInstance(); while (true) { Debug.Assert(currentTypeInfo.IsGenericTypeDefinition || !currentTypeInfo.IsGenericType); nestedTypes.Add(currentTypeInfo); if (currentTypeInfo.DeclaringType == null) { break; } currentTypeInfo = currentTypeInfo.DeclaringType.GetTypeInfo(); } int i = nestedTypes.Count - 1; var symbol = (NamedTypeSymbol)GetTypeByReflectionType(nestedTypes[i].AsType(), includeReferences); if ((object)symbol == null) { return(null); } while (--i >= 0) { int forcedArity = nestedTypes[i].GenericTypeParameters.Length - nestedTypes[i + 1].GenericTypeParameters.Length; MetadataTypeName mdName = MetadataTypeName.FromTypeName(nestedTypes[i].Name, forcedArity: forcedArity); symbol = symbol.LookupMetadataType(ref mdName); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); if ((object)symbol == null) { return(null); } } nestedTypes.Free(); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } else { AssemblyIdentity assemblyId = AssemblyIdentity.FromAssemblyDefinition(typeInfo.Assembly); MetadataTypeName mdName = MetadataTypeName.FromNamespaceAndTypeName( typeInfo.Namespace ?? string.Empty, typeInfo.Name, forcedArity: typeInfo.GenericTypeArguments.Length); NamedTypeSymbol symbol = GetTopLevelTypeByMetadataName(ref mdName, assemblyId, includeReferences, isWellKnownType: false); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } int typeArgumentIndex = 0; Type[] genericArguments = typeInfo.GenericTypeArguments; symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } }