/// <summary> /// Create the current type as class definition. /// </summary> protected virtual void CreateClassDefinition(DexTargetPackage targetPackage, ClassDefinition parent, TypeDefinition parentType, XTypeDefinition parentXType) { // Create classdef var nsConverter = targetPackage.NameConverter; classDef = new ClassDefinition(); classDef.MapFileId = compiler.GetNextMapFileId(); classDef.Namespace = nsConverter.GetConvertedNamespace(XType); var name = CreateClassName(XType); if ((parentType != null) && parentType.HasDexImportAttribute()) { var fullName = nsConverter.GetConvertedFullName(parentXType) + "_" + name; var index = fullName.LastIndexOf('.'); classDef.Name = (index < 0) ? fullName : fullName.Substring(index + 1); } else { classDef.Name = (parent != null) ? parent.Name + "$" + name : name; } // Set access flags //if (typeDef.IsPublic) classDef.IsPublic = true; //else classDef.IsPrivate = true; classDef.IsPublic = true; if (typeDef.IsSealed) classDef.IsFinal = true; if (typeDef.IsInterface) { classDef.IsInterface = true; classDef.IsAbstract = true; } else if (typeDef.IsAbstract) { classDef.IsAbstract = true; } if ((parent != null) && (!parentType.HasDexImportAttribute())) { // Add to parent if this is a nested type classDef.Owner = parent; parent.AddInnerClass(classDef); } else { // Add to dex if it is a root class // TODO: here we could simplify the names, e.g. remove the scope, as long as no // clashing does occur. targetPackage.DexFile.AddClass(classDef); } }
/// <summary> /// Create an annotation interface. /// </summary> internal static AttributeAnnotationInterface Create( ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, TypeDefinition attributeType, ClassDefinition attributeClass) { // Create class ClassDefinition @interface = new ClassDefinition(); @interface.Name = CreateAnnotationTypeName(attributeClass); @interface.Namespace = attributeClass.Namespace; @interface.AccessFlags = AccessFlags.Public | AccessFlags.Abstract | AccessFlags.Interface | AccessFlags.Annotation; @interface.Owner = attributeClass; attributeClass.AddInnerClass(@interface); // Set super class @interface.SuperClass = FrameworkReferences.Object; // Implement Dot42.Internal.IAttribute @interface.Interfaces.Add(new ClassReference("java/lang/annotation/Annotation")); // Prepare result AttributeAnnotationInterface result = new AttributeAnnotationInterface(@interface); // Add methods from IAttribute XModel.XTypeDefinition baseIntfType = compiler.GetDot42InternalType("IAttribute").Resolve(); foreach (XModel.XMethodDefinition imethod in baseIntfType.Methods) { if (imethod.Parameters.Count > 0) throw new CompilerException(string.Format("Invalid IAttribute method {0}", imethod)); string methodName = NameConverter.GetConvertedName(imethod); TypeReference dfieldType = imethod.ReturnType.GetReference(targetPackage); MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dfieldType)); method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract; @interface.Methods.Add(method); } TypeDefinition currentType = attributeType; while (currentType != null && currentType.FullName != typeof(Attribute).FullName) { // Add field mapping foreach (var field in currentType.Fields.Where(x => x.IsReachable && x.IsPublic)) { string methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result); MethodDefinition method = new MethodDefinition(@interface, methodName, MakePrototype(field.FieldType, targetPackage, compiler.Module)); method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract; result.FieldToGetMethodMap.Add(field, method); @interface.Methods.Add(method); } // Add property mapping foreach (var property in currentType.Properties.Where( x => x.IsReachable && (x.SetMethod != null) && x.SetMethod.IsPublic && x.SetMethod.IsReachable)) { // ignore properties with same name [might be overriden] if (result.PropertyToGetMethodMap.Keys.Any(k => k.Name == property.Name)) continue; string methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result); Mono.Cecil.TypeReference propType = property.PropertyType; MethodDefinition method = new MethodDefinition(@interface, methodName, MakePrototype(propType, targetPackage, compiler.Module)); method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract; result.PropertyToGetMethodMap.Add(property, method); @interface.Methods.Add(method); } if (currentType.BaseType == null || currentType.BaseType.IsSystemObject()) break; currentType = currentType.BaseType.Resolve(); } // Add ctor mapping var argIndex = 0; foreach (var ctor in attributeType.Methods.Where(x => (x.Name == ".ctor") && x.IsReachable)) { // Add methods for the ctor arguments List<Tuple<MethodDefinition, Mono.Cecil.TypeReference>> paramGetMethods = new List<Tuple<MethodDefinition, Mono.Cecil.TypeReference>>(); foreach (ParameterDefinition p in ctor.Parameters) { string methodName = CreateGetMethodName("c" + argIndex++, result); MethodDefinition method = new MethodDefinition(@interface, methodName, MakePrototype(p.ParameterType, targetPackage, compiler.Module)); method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract; @interface.Methods.Add(method); paramGetMethods.Add(Tuple.Create(method, p.ParameterType)); } // Add a builder method MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result); result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods.Select(p=>p.Item1).ToList())); } // Create default values annotation Annotation defAnnotation = CreateDefaultAnnotation(result); result.AnnotationInterfaceClass.Annotations.Add(defAnnotation); return result; }
/// <summary> /// Create the current type as class definition. /// </summary> protected virtual void CreateClassDefinition(Dex target, NameConverter nsConverter, ClassDefinition parent, ClassFile parentClass) { // Create classdef classDef = new ClassDefinition(); classDef.MapFileId = compiler.GetNextMapFileId(); classDef.Namespace = nsConverter.GetConvertedNamespace(typeDef); var name = NameConverter.GetConvertedName(typeDef); classDef.Name = (parent != null) ? parent.Name + "$" + name : name; // Set access flags //if (typeDef.IsPublic) classDef.IsPublic = true; //else classDef.IsPrivate = true; classDef.IsPublic = true; if (typeDef.IsFinal) classDef.IsFinal = true; if (typeDef.IsInterface) { classDef.IsInterface = true; classDef.IsAbstract = true; } else if (typeDef.IsAbstract) { classDef.IsAbstract = true; } if (typeDef.Interfaces.Any(x => x.ClassName == "java/lang/annotation/Annotation")) { classDef.IsAnnotation = true; } classDef.IsEnum = typeDef.IsEnum; if (parent != null) { // Add to parent if this is a nested type classDef.Owner = parent; parent.AddInnerClass(classDef); } else { // Add to dex if it is a root class target.AddClass(classDef); } }