protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) { TypeSpec spec; if (import_cache.TryGetValue (type, out spec)) { if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) { if (dtype.IsDynamicObject ()) return module.Compiler.BuiltinTypes.Dynamic; return spec; } if (!spec.IsGeneric || type.IsGenericTypeDefinition) return spec; if (!dtype.HasDynamicAttribute ()) return spec; // We've found same object in the cache but this one has a dynamic custom attribute // and it's most likely dynamic version of same type IFoo<object> agains IFoo<dynamic> // Do type resolve process again in that case // TODO: Handle cases where they still unify } if (IsMissingType (type)) { spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC); spec.MemberCache = MemberCache.Empty; import_cache.Add (type, spec); return spec; } if (type.IsGenericType && !type.IsGenericTypeDefinition) { var type_def = type.GetGenericTypeDefinition (); // Generic type definition can also be forwarded if (compiled_types.TryGetValue (type_def, out spec)) return spec; var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); if (targs == null) return null; if (declaringType == null) { // Simple case, no nesting spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType); spec = spec.MakeGenericType (module, targs); } else { // // Nested type case, converting .NET types like // A`1.B`1.C`1<int, long, string> to typespec like // A<int>.B<long>.C<string> // var nested_hierarchy = new List<TypeSpec> (); while (declaringType.IsNested) { nested_hierarchy.Add (declaringType); declaringType = declaringType.DeclaringType; } int targs_pos = 0; if (declaringType.Arity > 0) { spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ()); targs_pos = spec.Arity; } else { spec = declaringType; } for (int i = nested_hierarchy.Count; i != 0; --i) { var t = nested_hierarchy [i - 1]; if (t.Kind == MemberKind.MissingType) spec = t; else spec = MemberCache.FindNestedType (spec, t.Name, t.Arity); if (t.Arity > 0) { spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ()); targs_pos += t.Arity; } } if (spec.Kind == MemberKind.MissingType) { spec = new TypeSpec (MemberKind.MissingType, spec, new ImportedTypeDefinition (type_def, this), type_def, Modifiers.PUBLIC); spec.MemberCache = MemberCache.Empty; } else { if ((type_def.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && IgnorePrivateMembers) return null; string name = type.Name; int index = name.IndexOf ('`'); if (index > 0) name = name.Substring (0, index); spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos); if (spec.Arity > 0) { spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ()); } } } // Don't add generic type with dynamic arguments, they can interfere with same type // using object type arguments if (!spec.HasDynamicElement) { // Add to reading cache to speed up reading if (!import_cache.ContainsKey (type)) import_cache.Add (type, spec); } return spec; } Modifiers mod; MemberKind kind; var ma = type.Attributes; switch (ma & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: mod = Modifiers.PUBLIC; break; case TypeAttributes.NestedPrivate: mod = Modifiers.PRIVATE; break; case TypeAttributes.NestedFamily: mod = Modifiers.PROTECTED; break; case TypeAttributes.NestedFamORAssem: mod = Modifiers.PROTECTED | Modifiers.INTERNAL; break; default: mod = Modifiers.INTERNAL; break; } if ((ma & TypeAttributes.Interface) != 0) { kind = MemberKind.Interface; } else if (type.IsGenericParameter) { kind = MemberKind.TypeParameter; } else { var base_type = type.BaseType; if (base_type == null || (ma & TypeAttributes.Abstract) != 0) { kind = MemberKind.Class; } else { kind = DetermineKindFromBaseType (base_type); if (kind == MemberKind.Struct || kind == MemberKind.Delegate) { mod |= Modifiers.SEALED; } } if (kind == MemberKind.Class) { if ((ma & TypeAttributes.Sealed) != 0) { if ((ma & TypeAttributes.Abstract) != 0) mod |= Modifiers.STATIC; else mod |= Modifiers.SEALED; } else if ((ma & TypeAttributes.Abstract) != 0) { mod |= Modifiers.ABSTRACT; } } } var definition = new ImportedTypeDefinition (type, this); TypeSpec pt; if (kind == MemberKind.Enum) { const BindingFlags underlying_member = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var type_members = type.GetFields (underlying_member); foreach (var type_member in type_members) { spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod); break; } if (spec == null) kind = MemberKind.Class; } else if (kind == MemberKind.TypeParameter) { spec = CreateTypeParameter (type, declaringType); } else if (type.IsGenericTypeDefinition) { definition.TypeParameters = CreateGenericParameters (type, declaringType); } else if (compiled_types.TryGetValue (type, out pt)) { // // Same type was found in inside compiled types. It's // either build-in type or forward referenced typed // which point into just compiled assembly. // spec = pt; BuiltinTypeSpec bts = pt as BuiltinTypeSpec; if (bts != null) bts.SetDefinition (definition, type, mod); } if (spec == null) spec = new TypeSpec (kind, declaringType, definition, type, mod); import_cache.Add (type, spec); if (kind == MemberKind.TypeParameter) { if (canImportBaseType) ImportTypeParameterTypeConstraints ((TypeParameterSpec) spec, type); return spec; } // // Two stage setup as the base type can be inflated declaring type or // another nested type inside same declaring type which has not been // loaded, therefore we can import a base type of nested types once // the types have been imported // if (canImportBaseType) ImportTypeBase (spec, type); return spec; }
public Enum (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) : base (parent, name, attrs, MemberKind.Enum) { underlying_type_expr = type; var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE; ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report); spec = new EnumSpec (null, this, null, null, ModFlags); }