예제 #1
0
        /// <summary>
        /// Create a unique name for the get method that gets the value of the given field/property/ctor argument.
        /// </summary>
        private static string CreateGetMethodName(string memberName, AttributeAnnotationInterface attributeAnnotationInterface)
        {
            string memberNameBase = memberName;
            int    index          = 0;

            while (true)
            {
                bool unique = attributeAnnotationInterface.FieldToGetMethodMap.Values.All(x => x.Name != memberName) &&
                              attributeAnnotationInterface.PropertyToGetMethodMap.Values.All(x => x.Name != memberName);
                if (unique)
                {
                    return(memberName);
                }
                memberName = memberNameBase + (index++);
            }
        }
예제 #2
0
        /// <summary>
        /// Create an annotation with default values.
        /// </summary>
        private static Annotation CreateDefaultAnnotation(AttributeAnnotationInterface mapping)
        {
            // Create annotation
            Annotation annotation = new Annotation {
                Visibility = AnnotationVisibility.Runtime
            };

            annotation.Type = mapping.AnnotationInterfaceClass;

            // Add field default values
            foreach (KeyValuePair <Mono.Cecil.FieldDefinition, MethodDefinition> entry in mapping.FieldToGetMethodMap)
            {
                string name = entry.Value.Name;
                Mono.Cecil.TypeReference type = entry.Key.FieldType;
                annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
            }

            // Add property default values
            foreach (KeyValuePair <PropertyDefinition, MethodDefinition> entry in mapping.PropertyToGetMethodMap)
            {
                string name = entry.Value.Name;
                Mono.Cecil.TypeReference type = entry.Key.PropertyType;
                annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
            }

            // Add ctor argument default values
            foreach (KeyValuePair <Mono.Cecil.MethodDefinition, AttributeCtorMapping> entry in mapping.CtorMap)
            {
                Mono.Cecil.MethodDefinition ctor = entry.Key;
                for (int i = 0; i < ctor.Parameters.Count; i++)
                {
                    string name = entry.Value.ArgumentGetters[i].Name;
                    Mono.Cecil.TypeReference type = entry.Key.Parameters[i].ParameterType;
                    annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
                }
            }

            // Wrap it in a dalvik.annotation.AnnotationDefault
            Annotation defAnnotation = new Annotation {
                Visibility = AnnotationVisibility.System
            };

            defAnnotation.Type = new ClassReference("dalvik.annotation.AnnotationDefault");
            defAnnotation.Arguments.Add(new AnnotationArgument("value", annotation));
            return(defAnnotation);
        }
예제 #3
0
        /// <summary>
        /// Implemented all fields and methods.
        /// </summary>
        protected override void CreateMembers(DexTargetPackage targetPackage)
        {
            // Create normal members
            base.CreateMembers(targetPackage);

            if(!Type.IsAbstract)
            {
                // Create annotation interface and attribute build methods
                mapping = AttributeAnnotationInterfaceBuilder.Create(null, Compiler, targetPackage, Type, Class);
                Compiler.Record(Type, mapping);

                // Add IAnnotationType annotation
                var annotationTypeRef = Compiler.GetDot42InternalType("IAnnotationType");
                var typeAnnotation = new Annotation
                {
                    Type = annotationTypeRef.GetClassReference(targetPackage),
                    Visibility = AnnotationVisibility.Runtime
                };
                typeAnnotation.Arguments.Add(new AnnotationArgument("AnnotationType", mapping.AnnotationInterfaceClass));
                Class.Annotations.Add(typeAnnotation);
            }
        }
        /// <summary>
        /// Create an annotation with default values.
        /// </summary>
        private static Annotation CreateDefaultAnnotation(AttributeAnnotationInterface mapping)
        {
            // Create annotation
            Annotation annotation = new Annotation { Visibility = AnnotationVisibility.Runtime };
            annotation.Type = mapping.AnnotationInterfaceClass;

            // Add field default values
            foreach (KeyValuePair<Mono.Cecil.FieldDefinition, MethodDefinition> entry in mapping.FieldToGetMethodMap)
            {
                string name = entry.Value.Name;
                Mono.Cecil.TypeReference type = entry.Key.FieldType;
                annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
            }

            // Add property default values
            foreach (KeyValuePair<PropertyDefinition, MethodDefinition> entry in mapping.PropertyToGetMethodMap)
            {
                string name = entry.Value.Name;
                Mono.Cecil.TypeReference type = entry.Key.PropertyType;
                annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
            }

            // Add ctor argument default values
            foreach (KeyValuePair<Mono.Cecil.MethodDefinition,AttributeCtorMapping> entry in mapping.CtorMap)
            {
                Mono.Cecil.MethodDefinition ctor = entry.Key;
                for (int i = 0; i < ctor.Parameters.Count; i++)
                {
                    string name = entry.Value.ArgumentGetters[i].Name;
                    Mono.Cecil.TypeReference type = entry.Key.Parameters[i].ParameterType;
                    annotation.Arguments.Add(new AnnotationArgument(name, GetDefaultValue(type)));
                }
            }

            // Wrap it in a dalvik.annotation.AnnotationDefault
            Annotation defAnnotation = new Annotation { Visibility = AnnotationVisibility.System };
            defAnnotation.Type = new ClassReference("dalvik.annotation.AnnotationDefault");
            defAnnotation.Arguments.Add(new AnnotationArgument("value", annotation));
            return defAnnotation;
        }
 /// <summary>
 /// Create a unique name for the get method that gets the value of the given field/property/ctor argument.
 /// </summary>
 private static string CreateGetMethodName(string memberName, AttributeAnnotationInterface attributeAnnotationInterface)
 {
     string memberNameBase = memberName;
     int index = 0;
     while (true)
     {
         bool unique = attributeAnnotationInterface.FieldToGetMethodMap.Values.All(x => x.Name != memberName) &&
                       attributeAnnotationInterface.PropertyToGetMethodMap.Values.All(x => x.Name !=  memberName);
         if (unique)
             return memberName;
         memberName = memberNameBase + (index++);
     }
 }
        /// <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 a method definition for the builder method that builds a custom attribute from an annotation.
        /// </summary>
        private static MethodDefinition CreateBuildMethod(
            ISourceLocation seqp,
            Mono.Cecil.MethodDefinition ctor,
            List<Tuple<MethodDefinition, Mono.Cecil.TypeReference>> paramGetMethods,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            ClassDefinition attributeClass,
            AttributeAnnotationInterface mapping)
        {
            // Create method definition
            string name = CreateBuildMethodName(attributeClass);
            TypeReference attributeTypeRef = ctor.DeclaringType.GetReference(targetPackage, compiler.Module);
            MethodDefinition method = new MethodDefinition(attributeClass, name, new Prototype(attributeTypeRef, new Parameter(mapping.AnnotationInterfaceClass, "ann")));
            method.AccessFlags = AccessFlags.Public | AccessFlags.Static | AccessFlags.Synthetic;
            attributeClass.Methods.Add(method);

            // Create method body
            MethodBody body = new MethodBody(null);
            Register annotationReg = body.AllocateRegister(RCategory.Argument, RType.Object);
            //body.Instructions.Add(seqp, RCode.Check_cast, mapping.AnnotationInterfaceClass, annotationReg);

            // Allocate attribute
            Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object);
            body.Instructions.Add(seqp, RCode.New_instance, attributeClass, attributeReg);

            // Get ctor arguments
            List<Register> ctorArgRegs = new List<Register>();
            foreach (var p in paramGetMethods)
            {
                Instruction branchIfNotSet; // this can not happen, but lets keep the code below simple.
                
                XModel.XTypeReference xType = XBuilder.AsTypeReference(compiler.Module, p.Item2);

                Register[] valueRegs = CreateLoadValueSequence(seqp, body, xType, annotationReg, p.Item1, compiler, targetPackage, out branchIfNotSet);
                branchIfNotSet.Operand = body.Instructions.Add(seqp, RCode.Nop);

                ctorArgRegs.AddRange(valueRegs);
            }

            // Invoke ctor
            DexLib.MethodReference dctor = ctor.GetReference(targetPackage, compiler.Module);
            body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, new[] { attributeReg }.Concat(ctorArgRegs).ToArray());

            // Get field values
            foreach (var fieldMap in mapping.FieldToGetMethodMap)
            {
                var field = fieldMap.Key;
                XModel.XTypeReference xFieldType = XBuilder.AsTypeReference(compiler.Module, field.FieldType);
                
                MethodDefinition getter = fieldMap.Value;
                Instruction branchIfNotSet;
                
                Register[] valueRegs = CreateLoadValueSequence(seqp, body, xFieldType, annotationReg, getter, compiler, targetPackage, out branchIfNotSet);
              
                var put = body.Instructions.Add(seqp, xFieldType.IPut(), valueRegs[0], attributeReg);
                
                mapping.FixOperands.Add(Tuple.Create(put, (MemberReference)field));

                branchIfNotSet.Operand = body.Instructions.Add(seqp, RCode.Nop);
            }

            // Get property values
            foreach (var propertyMap in mapping.PropertyToGetMethodMap)
            {
                PropertyDefinition property = propertyMap.Key;
                XTypeReference xType = XBuilder.AsTypeReference(compiler.Module, property.PropertyType);

                MethodDefinition getter = propertyMap.Value;
                Instruction branchIfNotSet;

                Register[] valueRegs = CreateLoadValueSequence(seqp, body, xType, annotationReg, getter, compiler, targetPackage, out branchIfNotSet);
                
                XModel.XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod);
                
                var set = body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null), null, new[] { attributeReg }.Concat(valueRegs).ToArray());

                mapping.FixOperands.Add(Tuple.Create(set, (MemberReference)property.SetMethod));

                branchIfNotSet.Operand = body.Instructions.Add(seqp, RCode.Nop);
            }

            // Return attribute
            body.Instructions.Add(seqp, RCode.Return_object, attributeReg);

            // Register method body
            targetPackage.Record(new CompiledMethod() { DexMethod = method, RLBody = body });

            // Return method
            return method;
        }
예제 #8
0
 /// <summary>
 /// Record the attribute annotation information for the given attribute type.
 /// </summary>
 internal void Record(TypeDefinition attributeType, AttributeAnnotationInterface attributeAnnotationInterface)
 {
     attributeAnnotationTypes.Add(attributeType, attributeAnnotationInterface);
 }
예제 #9
0
        /// <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.InnerClasses.Add(@interface);

            // Set super class
            @interface.SuperClass = new ClassReference("java/lang/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);
            }

            // Add field mapping
            foreach (var field in attributeType.Fields.Where(x => x.IsReachable && x.IsPublic))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                TypeReference    dfieldType = field.FieldType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.FieldToGetMethodMap.Add(field, method);
                @interface.Methods.Add(method);
            }

            // Add property mapping
            foreach (var property in attributeType.Properties.Where(x => x.IsReachable && (x.SetMethod != null) && (x.SetMethod.IsPublic) && x.SetMethod.IsReachable))
            {
                string           methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                TypeReference    dpropType  = property.PropertyType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dpropType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.PropertyToGetMethodMap.Add(property, method);
                @interface.Methods.Add(method);
            }

            // 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 <MethodDefinition> paramGetMethods = new List <MethodDefinition>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string           methodName = CreateGetMethodName("c" + argIndex++, result);
                    TypeReference    dparamType = p.ParameterType.GetReference(targetPackage, compiler.Module);
                    MethodDefinition method     = new MethodDefinition(@interface, methodName, new Prototype(dparamType));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(method);
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);

            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Create a method definition for the builder method that builds a custom attribute from an annotation.
        /// </summary>
        private static MethodDefinition CreateBuildMethod(
            ISourceLocation seqp,
            Mono.Cecil.MethodDefinition ctor,
            List <MethodDefinition> paramGetMethods,
            AssemblyCompiler compiler,
            DexTargetPackage targetPackage,
            ClassDefinition attributeClass,
            AttributeAnnotationInterface mapping)
        {
            // Create method definition
            string           name             = CreateBuildMethodName(attributeClass);
            TypeReference    attributeTypeRef = ctor.DeclaringType.GetReference(targetPackage, compiler.Module);
            MethodDefinition method           = new MethodDefinition(attributeClass, name, new Prototype(attributeTypeRef, new Parameter(mapping.AnnotationInterfaceClass, "ann")));

            method.AccessFlags = AccessFlags.Public | AccessFlags.Static | AccessFlags.Synthetic;
            attributeClass.Methods.Add(method);

            // Create method body
            MethodBody body          = new MethodBody(null);
            Register   annotationReg = body.AllocateRegister(RCategory.Argument, RType.Object);
            //body.Instructions.Add(seqp, RCode.Check_cast, mapping.AnnotationInterfaceClass, annotationReg);

            // Allocate attribute
            Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object);

            body.Instructions.Add(seqp, RCode.New_instance, attributeClass, attributeReg);

            // Get ctor arguments
            List <Register> ctorArgRegs = new List <Register>();

            foreach (MethodDefinition p in paramGetMethods)
            {
                TypeReference paramType = p.Prototype.ReturnType;
                Register[]    valueRegs = CreateLoadValueSequence(seqp, body, paramType, annotationReg, p);
                ctorArgRegs.AddRange(valueRegs);
            }

            // Invoke ctor
            DexLib.MethodReference dctor = ctor.GetReference(targetPackage, compiler.Module);
            body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, new[] { attributeReg }.Concat(ctorArgRegs).ToArray());

            // Get field values
            foreach (var fieldMap in mapping.FieldToGetMethodMap)
            {
                Mono.Cecil.FieldDefinition field  = fieldMap.Key;
                MethodDefinition           getter = fieldMap.Value;
                Register[]            valueRegs   = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter);
                DexLib.FieldReference dfield      = field.GetReference(targetPackage, compiler.Module);
                XModel.XTypeReference xFieldType  = XBuilder.AsTypeReference(compiler.Module, field.FieldType);
                body.Instructions.Add(seqp, xFieldType.IPut(), dfield, valueRegs[0], attributeReg);
            }

            // Get property values
            foreach (var propertyMap in mapping.PropertyToGetMethodMap)
            {
                PropertyDefinition       property   = propertyMap.Key;
                MethodDefinition         getter     = propertyMap.Value;
                Register[]               valueRegs  = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter);
                DexLib.MethodReference   dmethod    = property.SetMethod.GetReference(targetPackage, compiler.Module);
                XModel.XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod);
                body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null), dmethod, new[] { attributeReg }.Concat(valueRegs).ToArray());
            }

            // Return attribute
            body.Instructions.Add(seqp, RCode.Return_object, attributeReg);

            // Register method body
            targetPackage.Record(new CompiledMethod()
            {
                DexMethod = method, RLBody = body
            });

            // Return method
            return(method);
        }
        /// <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.InnerClasses.Add(@interface);

            // Set super class
            @interface.SuperClass = new ClassReference("java/lang/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);                
            }

            // Add field mapping
            foreach (var field in attributeType.Fields.Where(x => x.IsReachable && x.IsPublic))
            {
                string methodName = CreateGetMethodName(NameConverter.GetConvertedName(field), result);
                TypeReference dfieldType = field.FieldType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dfieldType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.FieldToGetMethodMap.Add(field, method);
                @interface.Methods.Add(method);
            }

            // Add property mapping
            foreach (var property in attributeType.Properties.Where(x => x.IsReachable && (x.SetMethod != null) && (x.SetMethod.IsPublic) && x.SetMethod.IsReachable))
            {
                string methodName = CreateGetMethodName(NameConverter.GetConvertedName(property), result);
                TypeReference dpropType = property.PropertyType.GetReference(targetPackage, compiler.Module);
                MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dpropType));
                method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                result.PropertyToGetMethodMap.Add(property, method);
                @interface.Methods.Add(method);
            }

            // 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<MethodDefinition> paramGetMethods = new List<MethodDefinition>();
                foreach (ParameterDefinition p in ctor.Parameters)
                {
                    string methodName = CreateGetMethodName("c" + argIndex++, result);
                    TypeReference dparamType = p.ParameterType.GetReference(targetPackage, compiler.Module);
                    MethodDefinition method = new MethodDefinition(@interface, methodName, new Prototype(dparamType));
                    method.AccessFlags = AccessFlags.Public | AccessFlags.Abstract;
                    @interface.Methods.Add(method);
                    paramGetMethods.Add(method);
                }

                // Add a builder method
                MethodDefinition buildMethod = CreateBuildMethod(sequencePoint, ctor, paramGetMethods, compiler, targetPackage, attributeClass, result);
                result.CtorMap.Add(ctor, new AttributeCtorMapping(buildMethod, paramGetMethods));
            }

            // Create default values annotation
            Annotation defAnnotation = CreateDefaultAnnotation(result);
            result.AnnotationInterfaceClass.Annotations.Add(defAnnotation);

            return result;
        }