Ejemplo n.º 1
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));
        }