Beispiel #1
0
        private static MethodDefinition CreateFactoryMethod(AssemblyCompiler compiler, DexTargetPackage targetPackage, CustomAttribute attribute, AttributeAnnotationMapping mapping)
        {
            var             targetClass      = mapping.AttributeClass; // is this really the right place for the factory methods?
            ISourceLocation seqp             = null;
            var             attributeTypeDef = attribute.AttributeType.Resolve();

            // create method
            string           methodName = CreateAttributeFactoryMethodName(targetClass);
            MethodDefinition method     = new MethodDefinition(targetClass, methodName, new Prototype(mapping.AttributeClass));

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

            // create method body
            MethodBody body = new MethodBody(null);
            // Allocate attribute
            Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object);

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

            // collect ctor arguments
            List <Register> ctorArgRegs = new List <Register>()
            {
                attributeReg
            };

            foreach (var p in attribute.ConstructorArguments)
            {
                XTypeReference xType     = XBuilder.AsTypeReference(compiler.Module, p.Type);
                Register[]     valueRegs = CreateInitializeValueInstructions(seqp, body, xType, p, compiler, targetPackage);
                ctorArgRegs.AddRange(valueRegs);
            }
            // Invoke ctor
            DexLib.MethodReference dctor = attribute.Constructor.GetReference(targetPackage, compiler.Module);
            body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, ctorArgRegs.ToArray());

            // set field values
            foreach (var p in attribute.Fields)
            {
                var field  = GetField(attributeTypeDef, p.Name);
                var xField = XBuilder.AsFieldReference(compiler.Module, field);

                Register[] valueRegs = CreateInitializeValueInstructions(seqp, body, xField.FieldType, p.Argument, compiler, targetPackage);
                body.Instructions.Add(seqp, xField.FieldType.IPut(), xField.GetReference(targetPackage),
                                      valueRegs[0], attributeReg);
            }

            // set property values
            foreach (var p in attribute.Properties)
            {
                PropertyDefinition property = GetSettableProperty(attributeTypeDef, p.Name);
                XTypeReference     xType    = XBuilder.AsTypeReference(compiler.Module, property.PropertyType);

                Register[]        valueRegs  = CreateInitializeValueInstructions(seqp, body, xType, p.Argument, compiler, targetPackage);
                XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod);
                body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null),
                                      xSetMethod.GetReference(targetPackage),
                                      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);
        }
Beispiel #2
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);
        }