Beispiel #1
0
        /// <summary>
        /// Create the current type as class definition.
        /// </summary>
        public virtual void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage)
        {
            // Find xfield
            xField = XBuilder.AsFieldDefinition(compiler.Module, field);

            // Create field definition
            dfield      = new Dot42.DexLib.FieldDefinition();
            dfield.Name = NameConverter.GetConvertedName(field);
            AddFieldToDeclaringClass(declaringClass, dfield, targetPackage);
            targetPackage.NameConverter.Record(xField, dfield);

            // Set access flags
            SetAccessFlags(dfield, field);

            // Give warning if static in generic class.
            // This could of cause also be handled automagically be the compiler,
            // with mixture of whats done in the Interlocked converter and whats
            // done in the GenericInstanceConverter.
            if (field.IsStatic && declaringType.IsGenericClass)
            {
                if (!field.HasSuppressMessageAttribute("StaticFieldInGenericType") &&
                    !field.DeclaringType.HasSuppressMessageAttribute("StaticFieldInGenericType"))
                {
                    string msg;
                    if (field.Name.Contains("CachedAnonymousMethodDelegate"))
                    {
                        msg = "The compiler generated a static field '{0}' in generic type '{1}'. This is not supported " +
                              "in Dot42 if the anonymous delegate accesses a generic class parameter. A workaround " +
                              "is to convert the anonymous static delegate to a normal method.\n";
                    }
                    else
                    {
                        msg = "Static field '{0}' in generic type {1}: All generic instances will share " +
                              "the same static field, contrary on how CLR operates. A workaround is to " +
                              "use ConcurrentDictionaries to access the values dependent on the type.\n";
                    }

                    msg += "You can suppress this warning with a [SuppressMessage(\"dot42\"," +
                           " \"StaticFieldInGenericType\")] attribute, either on the field or on the class.";

                    var body = field.DeclaringType.Methods.Select(m => m.Body)
                               .FirstOrDefault(m => m != null &&
                                               m.Instructions.Any(i => i.SequencePoint(m) != null));
                    if (body != null)
                    {
                        var seqPoint = body.Instructions.Select(i => i.SequencePoint(body)).First(i => i != null);
                        DLog.Warning(DContext.CompilerILConverter, seqPoint.Document.Url, seqPoint.StartColumn, seqPoint.StartLine, msg, field.Name, declaringType.FullName);
                    }
                    else
                    {
                        DLog.Warning(DContext.CompilerILConverter, msg, field.Name, declaringType.FullName);
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Create the current type as class definition.
        /// </summary>
        public void Create(ClassDefinition declaringClass, DexTargetPackage targetPackage)
        {
            // Find xField
            xField = XBuilder.AsFieldDefinition(compiler.Module, field);

            // Create field definition
            dfield      = new Dot42.DexLib.FieldDefinition();
            dfield.Name = NameConverter.GetConvertedName(field);
            AddFieldToDeclaringClass(declaringClass, dfield, targetPackage);
            targetPackage.NameConverter.Record(xField, dfield);

            // Set access flags
            SetAccessFlags(dfield, field);
        }
Beispiel #3
0
        /// <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);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Perform name conversion
        /// </summary>
        protected virtual string GetMethodName(MethodDefinition method, DexTargetPackage targetPackage)
        {
            // Handle special names
            switch (method.Name)
            {
            case ".ctor":
                return("<init>");

            case ".cctor":
                return("<clinit>");
            }

            // Handle regular names
            // Test for overrides of dex/java imported methods
            var javaBaseMethod = method.GetDexImportBaseMethod() ?? method.GetJavaImportBaseMethod();

            if (javaBaseMethod != null)
            {
                var javaMethodRef = javaBaseMethod.GetReference(targetPackage, compiler.Module);
                return(javaMethodRef.Name);
            }

            // Test for overrides of interface methods
            var interfaceJavaBaseMethod = method.GetDexImportBaseInterfaceMethod() ?? method.GetJavaImportBaseInterfaceMethod();

            if (interfaceJavaBaseMethod != null)
            {
                var javaMethodRef = interfaceJavaBaseMethod.GetReference(targetPackage, compiler.Module);
                return(javaMethodRef.Name);
            }

            // If a dex name is specified, use that
            var dexName = method.GetDexNameAttribute();

            if (dexName != null)
            {
                return((string)dexName.ConstructorArguments[0].Value);
            }

            return(NameConverter.GetConvertedName(xMethod));
        }
Beispiel #5
0
            /// <summary>
            /// Convert the given interface method if it has explicit implementations.
            /// </summary>
            private void ConvertInterfaceMethod(TypeDefinition iType, MethodDefinition iMethod)
            {
                var implementations = GetImplementations(iMethod);
                var iMethodIsJavaWithGenericParams = iMethod.IsJavaMethodWithGenericParams();
                var iMethodContainsGenericParams   = iMethod.ContainsGenericParameter;

                if (!iMethodIsJavaWithGenericParams && !iMethodContainsGenericParams && (!implementations.Any(x => x.IsExplicitImplementation())))
                {
                    // There are no explicit implementation.
                    // No need to convert
                    return;
                }

                // Rename method
                string newName;
                bool   createExplicitStubs = true;
                var    oldName             = iMethod.Name;
                var    attr = iMethod.GetDexOrJavaImportAttribute();

                if (attr != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    attr.GetDexOrJavaImportNames(iMethod, out memberName, out descriptor, out className);
                    newName = memberName;
                }
                else if ((attr = iMethod.GetDexNameAttribute()) != null)
                {
                    newName             = (string)(attr.ConstructorArguments[0].Value);
                    createExplicitStubs = false;
                }
                else
                {
                    var module = reachableContext.Compiler.Module;
                    var xiType = XBuilder.AsTypeReference(module, iType);
                    newName = methodNames.GetUniqueName(NameConverter.GetConvertedName(xiType) + "_" + iMethod.Name);
                    oldName = newName;
                }
                Rename(iMethod, newName);


                // Update implementations
                foreach (var impl in implementations)
                {
                    if (impl.IsExplicitImplementation())
                    {
                        // Convert to implicit
                        impl.IsPublic = true;

                        // Rename
                        Rename(impl, newName);
                        // Update names of overrides
                        foreach (var @override in impl.Overrides)
                        {
                            @override.Name = newName;
                        }
                    }
                    else if (!(impl.HasDexImportAttribute() || impl.HasJavaImportAttribute()))
                    {
                        // Add stub redirecting explicit implementation to implicit implementation
                        if (createExplicitStubs)
                        {
                            CreateExplicitStub(impl, newName, oldName, iMethod, iMethodIsJavaWithGenericParams /*|| iMethodContainsGenericParams*/);
                        }
                    }
                }
            }
Beispiel #6
0
 /// <summary>
 /// Create the name of the class.
 /// </summary>
 protected virtual string CreateClassName(XTypeDefinition xType)
 {
     return(NameConverter.GetConvertedName(XType));
 }
Beispiel #7
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);
        }
Beispiel #8
0
        /// <summary>
        /// Gets a class reference for the given type reference.
        /// </summary>
        internal static TypeReference GetReference(this XTypeReference type, DexTargetPackage targetPackage)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            type = type.GetWithoutModifiers();

            // Handle array's
            if (type.IsArray)
            {
                var arrType    = (XArrayType)type;
                var dimensions = arrType.Dimensions.Count() - 1;
                var dArrayType = new ArrayType(GetReference(type.ElementType, targetPackage));
                while (dimensions > 0)
                {
                    dArrayType = new ArrayType(dArrayType);
                    dimensions--;
                }
                return(dArrayType);
            }

            // Handle generic parameters
            if (type.IsGenericParameter || (type.IsByReference && type.ElementType.IsGenericParameter))
            {
                if (type.IsByReference) // this should be possible as well, but would need some more code at some other places.
                {
                    return(new ByReferenceType(FrameworkReferences.Object));
                }

                var gp = (XGenericParameter)type;
                if (gp.AllowConstraintAsTypeReference())
                {
                    return(gp.Constraints[0].GetReference(targetPackage));
                }

                return(FrameworkReferences.Object);
            }

            // Handle out/ref types
            if (type.IsByReference)
            {
                var byRefType = (XByReferenceType)type;
                return(new ByReferenceType(GetReference(byRefType.ElementType, targetPackage)));
            }

            // Handle Nullable<T>
            if (type.IsGenericInstance)
            {
                var git = (XGenericInstanceType)type;
                if (git.ElementType.IsNullableT())
                {
                    var arg = git.GenericArguments[0];
                    if (arg.IsBoolean())
                    {
                        return(new ClassReference("java/lang/Boolean"));
                    }
                    if (arg.IsByte() || arg.IsSByte())
                    {
                        return(new ClassReference("java/lang/Byte"));
                    }
                    if (arg.IsChar())
                    {
                        return(new ClassReference("java/lang/Character"));
                    }
                    if (arg.IsInt16() || arg.IsUInt16())
                    {
                        return(new ClassReference("java/lang/Short"));
                    }
                    if (arg.IsInt32() || arg.IsUInt32())
                    {
                        return(new ClassReference("java/lang/Integer"));
                    }
                    if (arg.IsInt64() || arg.IsUInt64())
                    {
                        return(new ClassReference("java/lang/Long"));
                    }
                    if (arg.IsDouble())
                    {
                        return(new ClassReference("java/lang/Double"));
                    }
                    if (arg.IsFloat())
                    {
                        return(new ClassReference("java/lang/Float"));
                    }


                    var typeofT = git.GenericArguments[0];

                    if (typeofT.IsGenericParameter) // use object.
                    {
                        return(FrameworkReferences.Object);
                    }

                    XTypeDefinition typeofTDef;
                    if (!typeofT.TryResolve(out typeofTDef))
                    {
                        throw new XResolutionException(typeofT);
                    }

                    var className = targetPackage.NameConverter.GetConvertedFullName(typeofTDef);
                    var classDef  = targetPackage.DexFile.GetClass(className);

                    // Use nullable base class of T, if enum.
                    if (classDef.IsEnum)
                    {
                        return(classDef.SuperClass);
                    }

                    // I like the base class concept for enums. unfortunately it seems to be
                    // impossible for structs and/or might have performance implications.
                    // Just return the type for structs.
                    return(classDef);
                }
            }

            var primType = GetPrimitiveType(type);

            if (primType != null)
            {
                return(primType);
            }

            // Resolve the type to a type definition
            XTypeDefinition typeDef;

            if (type.GetElementType().TryResolve(out typeDef))
            {
                // Handle primitive types
                primType = GetPrimitiveType(typeDef);
                if (primType != null)
                {
                    return(primType);
                }

                string className;
                if (typeDef.TryGetDexImportNames(out className))
                {
                    // type is a framework type
                    return(new ClassReference(className));
                }

                // Handle enums

                /* Enums Are Normal classes now
                 * if (typeDef.IsEnum)
                 * {
                 *  // Convert to primitive type
                 *  //return typeDef.GetEnumUnderlyingType().GetReference(target, nsConverter);
                 * }*/

                // Handle nested types of java types
                string convertedFullName;
                if (typeDef.IsNested && typeDef.DeclaringType.HasDexImportAttribute())
                {
                    // Nested type that is not imported, but it's declaring type is imported.
                    convertedFullName = targetPackage.NameConverter.GetConvertedFullName(typeDef.DeclaringType) + "_" +
                                        NameConverter.GetConvertedName(typeDef);
                }
                else if (typeDef.TryGetJavaImportNames(out className))
                {
                    convertedFullName = className.Replace('/', '.');
                }
                else
                {
                    convertedFullName = targetPackage.NameConverter.GetConvertedFullName(typeDef);
                }

                // type is in the assembly itself
                var result = targetPackage.DexFile.GetClass(convertedFullName);
                if (result == null)
                {
                    throw new ArgumentException(string.Format("Cannot find type {0}", convertedFullName));
                }
                return(result);
            }

            var javaType = type as XModel.Java.XBuilder.JavaTypeReference;

            if (javaType != null)
            {
                return(new ClassReference(javaType.JavaClassName));
            }

            throw new ResolveException(string.Format("Type {0} not found", type.FullName));
        }