internal static void BuildJavaClass(TypeDefinition cilType, JavaClass parentClass) { CilMain.Where.Push($"class '{cilType.FullName}'"); var genericMark = CilMain.GenericStack.Mark(); var myType = CilMain.GenericStack.EnterType(cilType); var jclass = new JavaClass(); jclass.Name = myType.JavaName; jclass.Flags = AttributesToAccessFlags(cilType.Attributes, myType.IsInterface); if (myType.IsInterface) { jclass.Super = JavaType.ObjectType.ClassName; // java.lang.Object } else if (cilType.BaseType != null) { var myBaseType = CilType.From(cilType.BaseType); jclass.Super = myBaseType.Equals(JavaType.ObjectType) ? JavaType.ObjectType.ClassName // java.lang.Object : myBaseType.JavaName; } else { throw CilMain.Where.Exception("missing base class"); } var myInterfaces = ImportInterfaces(jclass, myType, cilType); int numCastableInterfaces = myType.IsGenericThisOrSuper ? InterfaceBuilder.CastableInterfaceCount(myInterfaces) : 0; ImportFields(jclass, cilType, myType.IsRetainName); ImportMethods(jclass, cilType, numCastableInterfaces); if (myType.JavaName == "system.Convert") { DiscardBase64MethodsInConvertClass(jclass); } ValueUtil.InitializeStaticFields(jclass, myType); if (myType.IsValueClass) { ValueUtil.MakeValueClass(jclass, myType, numCastableInterfaces); } else if (myType.IsEnum) { ValueUtil.MakeEnumClass(jclass, myType, cilType.HasCustomAttribute("System.FlagsAttribute", true)); } else if (myType.IsDelegate) { var delegateInterface = Delegate.FixClass(jclass, myType); CilMain.JavaClasses.Add(delegateInterface); } // if derives directly from object, and does not implement ToString CodeBuilder.CreateToStringMethod(jclass); ResetFieldReferences(jclass); LinkClasses(jclass, parentClass, cilType); var interfaceClasses = InterfaceBuilder.BuildProxyMethods( myInterfaces, cilType, myType, jclass); if (interfaceClasses != null) { foreach (var childClass in interfaceClasses) { CilMain.JavaClasses.Add(childClass); } } if (myType.HasGenericParameters) { JavaClass dataClass; if (!myType.IsInterface) { dataClass = GenericUtil.MakeGenericClass(jclass, myType); if (dataClass != null) { CilMain.JavaClasses.Add(dataClass); } } else { dataClass = null; } JavaClass infoClass = jclass; if (myType.IsInterface) { // Android 'D8' desugars static methods on an interface by // moving into a separate class, so we do it ourselves. // see also system.RuntimeType.CreateGeneric() in baselib infoClass = CilMain.CreateInnerClass(jclass, jclass.Name + "$$info"); CilMain.JavaClasses.Add(infoClass); } GenericUtil.CreateGenericInfoMethod(infoClass, dataClass, myType); GenericUtil.CreateGenericVarianceField(infoClass, myType, cilType); } if (myType.IsGenericThisOrSuper) { jclass.Signature = GenericUtil.MakeGenericSignature(cilType, jclass.Super); if (!myInterfaces.Exists(x => x.InterfaceType.JavaName == "system.IGenericObject")) { if (!myType.IsInterface) { // create IGenericObject methods GetType and TryCast // only if class did not already implement IGenericObject if (!myType.HasGenericParameters) { GenericUtil.BuildGetTypeMethod(jclass, myType); } InterfaceBuilder.BuildTryCastMethod( myInterfaces, myType, numCastableInterfaces, jclass); } } } CilMain.GenericStack.Release(genericMark); CilMain.Where.Pop(); }