Exemplo n.º 1
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            if (type == null)
                return;

            if (type.IsArray)
            {
                var aType = (ArrayTypeReference)type;
                Walk(context, aType.ElementType);
            }
            else if (type.IsObjectType)
            {
                var oType = (ObjectTypeReference)type;
                foreach (var typeArg in oType.Arguments)
                {
                    Walk(context, typeArg.Signature);
                }
                ClassFile classFile;
                if (context.TryLoadClass(oType.ClassName, out classFile))
                {
                    classFile.MarkReachable(context);
                }
            }
            else if (type.IsBaseType || type.IsVoid || type.IsTypeVariable)
            {
                // Not need to mark anything
            }
            else
            {
                throw new ArgumentException("Unknown type: " + type);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            if (type == null)
            {
                return;
            }

            if (type.IsArray)
            {
                var aType = (ArrayTypeReference)type;
                Walk(context, aType.ElementType);
            }
            else if (type.IsObjectType)
            {
                var oType = (ObjectTypeReference)type;
                foreach (var typeArg in oType.Arguments)
                {
                    Walk(context, typeArg.Signature);
                }
                ClassFile classFile;
                if (context.TryLoadClass(oType.ClassName, out classFile))
                {
                    classFile.MarkReachable(context);
                }
            }
            else if (type.IsBaseType || type.IsVoid || type.IsTypeVariable)
            {
                // Not need to mark anything
            }
            else
            {
                throw new ArgumentException("Unknown type: " + type);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, FieldReference field)
        {
            // Field type
            field.FieldType.MarkReachable(context);

            var fieldDef = field as FieldDefinition;

            if (fieldDef != null)
            {
                // Custom attributes
                Walk(context, (ICustomAttributeProvider)fieldDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = fieldDef.GetJavaImportAttribute()) != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    javaImportAttr.GetDexOrJavaImportNames(fieldDef, out memberName, out descriptor, out className);
                    ClassFile javaClass;
                    if (context.TryLoadClass(className, out javaClass))
                    {
                        var javaField = javaClass.Fields.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor));
                        javaClass.MarkReachable(context);
                        javaField.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                field.Resolve(context).MarkReachable(context);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            // Generic parameters
            Walk(context, (IGenericParameterProvider)type);

            TypeDefinition typeDef;
            TypeSpecification typeSpec;
            GenericParameter genericParam;
            if ((typeDef = type as TypeDefinition) != null)
            {
                var isUsedInSerialization = typeDef.IsUsedInSerialization && !type.IsPrimitive && !typeDef.IsEnum 
                                            && !type.Namespace.StartsWith("System");

                // Mark base type reachable
                typeDef.BaseType.MarkReachable(context, isUsedInSerialization);

                // Mark declaring type reachable
                typeDef.DeclaringType.MarkReachable(context);

                // Mark implemented interfaces reachable
                if (typeDef.HasInterfaces)
                {
                    foreach (var intf in typeDef.Interfaces.Select(x => x.Interface))
                    {
                        intf.MarkReachable(context);
                    }
                }

                // If this is an attribute, include related types
                if (typeDef.IsAttribute())
                {
                    GetDot42InternalType(context, "IAttribute").MarkReachable(context);
                    GetDot42InternalType(context, "IAttributes").MarkReachable(context);
                }
                else if (typeDef.IsEnum)
                {
                    var boxingType = GetDot42InternalType(context, "Boxing");
                    boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context));
                }

                // Default & class ctor
                typeDef.FindDefaultCtor().MarkReachable(context);
                typeDef.GetClassCtor().MarkReachable(context);

                // Visit externally visible members
                if (typeDef.HasEvents)
                {
                    foreach (var evt in typeDef.Events)
                    {
                        if ((!evt.IsReachable) && context.Include(evt))
                        {
                            evt.MarkReachable(context); 
                        }
                    }
                }
                if (typeDef.HasFields)
                {
                    foreach (var field in typeDef.Fields)
                    {
                        // only public fields, so we don't pull any compiler generated stuff.
                        var isSerializable = isUsedInSerialization && !field.IsStatic && field.IsPublic;

                        if ((!field.IsReachable && context.Include(field)) || (!field.IsUsedInSerialization && isSerializable))
                        {                                                               
                            field.MarkReachable(context, isUsedInSerialization); 
                        }
                    }
                }
                if (typeDef.HasMethods)
                {
                    foreach (var method in typeDef.Methods)
                    {
                        if ((!method.IsReachable) && context.Include(method))
                        {
                            method.MarkReachable(context); 
                        }
                    }
                }
                if (typeDef.HasProperties)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        var isSerializable = isUsedInSerialization && prop.HasThis;
                        if ((!prop.IsReachable && context.Include(prop) || (!prop.IsUsedInSerialization && isSerializable)))
                        {
                            prop.MarkReachable(context, isUsedInSerialization); 
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)typeDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null)
                {
                    var javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value;
                    ClassFile javaClass;
                    if (context.TryLoadClass(javaClassName, out javaClass))
                    {
                        javaClass.MarkReachable(context);
                    }
                }

                // Dex imported interfaces should have all their methods marked reachable.
                if (typeDef.IsInterface && typeDef.HasDexImportAttribute())
                {
                    typeDef.Methods.ForEach(x => x.MarkReachable(context));
                }

                // Record in context 
                context.RecordReachableType(typeDef);
            }
            else if ((typeSpec = type as TypeSpecification) != null)
            {
                // Element
                typeSpec.ElementType.MarkReachable(context, typeSpec.IsUsedInSerialization);

                // Generic instance
                GenericInstanceType git;
                FunctionPointerType fpt;
                RequiredModifierType reqModType;
                OptionalModifierType optModType;
                if ((git = typeSpec as GenericInstanceType) != null)
                {
                    if (git.ElementType.IsNullableT())
                    {
                        var typeofT = git.GenericArguments[0].Resolve(context);
                        if (typeofT != null && !typeofT.UsedInNullableT)
                        {
                            typeofT.UsedInNullableT = true;
                            DLog.Debug(DContext.CompilerAssemblyResolver, "found System.Nullable<{0}>", typeofT.FullName);
                        }
                    }
                    Walk(context, (IGenericInstance)git);
                }
                else if ((fpt = typeSpec as FunctionPointerType) != null)
                {
                    Walk(context, fpt.ReturnType);
                }
                else if ((reqModType = typeSpec as RequiredModifierType) != null)
                {
                    reqModType.ModifierType.MarkReachable(context);
                }
                else if ((optModType = typeSpec as OptionalModifierType) != null)
                {
                    optModType.ModifierType.MarkReachable(context);
                }
            }
            else if ((genericParam = type as GenericParameter) != null)
            {
                genericParam.IsSerializedParameter = genericParam.HasSerializedParameterAttribute();

                // Owner
                var owner = (MemberReference)genericParam.Owner;
                owner.MarkReachable(context);

                // Constraints
                if (genericParam.HasConstraints)
                {
                    foreach (TypeReference constraint in genericParam.Constraints)
                    {
                        constraint.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                type.Resolve(context).MarkReachable(context, type.IsUsedInSerialization);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Mark all reachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, MethodReference method)
        {
            method.ReturnType.MarkReachable(context);

            // All parameters
            if (method.HasParameters)
            {
                foreach (ParameterDefinition param in method.Parameters)
                {
                    Walk(context, (ParameterReference)param);
                }
            }

            // Generic parameters
            Walk(context, (IGenericParameterProvider)method);

            // Method definition?
            MethodDefinition methodDef;
            MethodSpecification methodSpec;
            if ((methodDef = method as MethodDefinition) != null)
            {
                // Code
                Walk(context, methodDef.Body);

                // Overrides
                foreach (MethodReference methodRef in methodDef.Overrides)
                {
                    methodRef.MarkReachable(context);
                }

                // Base methods
                if (methodDef.IsVirtual)
                {
                    MethodDefinition baseMethod;
                    if ((baseMethod = methodDef.GetBaseMethod()) != null)
                    {
                        if (context.Contains(baseMethod.DeclaringType))
                        {
                            baseMethod.MarkReachable(context);
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)methodDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = methodDef.GetJavaImportAttribute()) != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    javaImportAttr.GetDexOrJavaImportNames(methodDef, out memberName, out descriptor, out className);
                    ClassFile javaClass;
                    if (context.TryLoadClass(className, out javaClass))
                    {
                        var javaMethod = javaClass.Methods.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor));
                        javaClass.MarkReachable(context);
                        javaMethod.MarkReachable(context);
                    }
                }

                // If this method is a property accessor, include the property also
                if (methodDef.SemanticsAttributes.HasFlag(MethodSemanticsAttributes.Getter))
                {
                    var prop = methodDef.DeclaringType.Properties.FirstOrDefault(x => x.GetMethod == methodDef);
                    prop.MarkReachable(context);
                }
                if (methodDef.SemanticsAttributes.HasFlag(MethodSemanticsAttributes.Setter))
                {
                    var prop = methodDef.DeclaringType.Properties.FirstOrDefault(x => x.SetMethod == methodDef);
                    prop.MarkReachable(context);
                }
            }
            else if ((methodSpec = method as MethodSpecification) != null)
            {
                // Method
                var elementRef = methodSpec.ElementMethod;
                elementRef.MarkReachable(context);

                // Generic arguments
                var gim = methodSpec as GenericInstanceMethod;
                if (gim != null)
                {
                    var elementDef = elementRef.Resolve();

                    for (int i = 0; i < gim.GenericArguments.Count; ++i)
                    {
                        bool isSerialized = elementDef.GenericParameters[i].IsSerializedParameter;
                        gim.GenericArguments[i].MarkReachable(context, isSerialized);
                    }
                }
            }
            else
            {
                // Try to resolve
                method.Resolve(context).MarkReachable(context);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Mark all reachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, FieldReference field)
        {
            // Field type
            field.FieldType.MarkReachable(context, field.IsUsedInSerialization);

            var fieldDef = field as FieldDefinition;
            if (fieldDef != null)
            {
                // Custom attributes
                Walk(context, (ICustomAttributeProvider)fieldDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = fieldDef.GetJavaImportAttribute()) != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    javaImportAttr.GetDexOrJavaImportNames(fieldDef, out memberName, out descriptor, out className);
                    ClassFile javaClass;
                    if (context.TryLoadClass(className, out javaClass))
                    {
                        var javaField = javaClass.Fields.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor));
                        javaClass.MarkReachable(context);
                        javaField.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                field.Resolve(context).MarkReachable(context, field.IsUsedInSerialization);
            }
        }
        /// <summary>
        /// Is our <see cref="instanceOfCondition"/> an interface implemented by the given type (or one of it's base types)?
        /// </summary>
        private bool Implements(ReachableContext context, ClassFile javaClass)
        {
            while (javaClass != null)
            {
                if (javaClass.ClassName == className)
                    return true;

                if (javaClass.Interfaces != null)
                {
                    foreach (var intfRef in javaClass.Interfaces)
                    {
                        ClassFile intf;
                        if (context.TryLoadClass(intfRef.ClassName, out intf))
                        {
                            if (Implements(context, intf))
                                return true;
                        }
                    }
                }

                ClassFile superClass;
                if (!javaClass.TryGetSuperClass(out superClass))
                    return false;
                javaClass = superClass;
            }
            return false;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            // Generic parameters
            Walk(context, (IGenericParameterProvider)type);

            TypeDefinition typeDef;
            TypeSpecification typeSpec;
            GenericParameter genericParam;
            if ((typeDef = type as TypeDefinition) != null)
            {
                // Mark base type reachable
                typeDef.BaseType.MarkReachable(context);

                // Mark declaring type reachable
                typeDef.DeclaringType.MarkReachable(context);

                // Mark implemented interfaces reachable
                if (typeDef.HasInterfaces)
                {
                    foreach (var intf in typeDef.Interfaces.Select(x => x.Interface))
                    {
                        intf.MarkReachable(context);
                    }
                }

                // If is an an attribute include related types
                if (typeDef.IsAttribute())
                {
                    GetDot42InternalType(context, "IAttribute").MarkReachable(context);
                    GetDot42InternalType(context, "IAttributes").MarkReachable(context);
                    GetDot42InternalType(context, "IAnnotationType").MarkReachable(context);
                }
                else if (typeDef.IsEnum)
                {
                    var boxingType = GetDot42InternalType(context, "Boxing");
                    boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context));
                }

                // Default & class ctor
                typeDef.FindDefaultCtor().MarkReachable(context);
                typeDef.GetClassCtor().MarkReachable(context);

                // Visit externally visible members
                if (typeDef.HasEvents)
                {
                    foreach (var evt in typeDef.Events)
                    {
                        if ((!evt.IsReachable) && context.Include(evt))
                        {
                            evt.MarkReachable(context); 
                        }
                    }
                }
                if (typeDef.HasFields)
                {
                    foreach (var field in typeDef.Fields)
                    {
                        if ((!field.IsReachable) && context.Include(field))
                        {
                            field.MarkReachable(context); 
                        }
                    }
                }
                if (typeDef.HasMethods)
                {
                    foreach (var method in typeDef.Methods)
                    {
                        if ((!method.IsReachable) && context.Include(method))
                        {
                            method.MarkReachable(context); 
                        }
                    }
                }
                if (typeDef.HasProperties)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        if ((!prop.IsReachable) && context.Include(prop))
                        {
                            prop.MarkReachable(context); 
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)typeDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null)
                {
                    var javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value;
                    ClassFile javaClass;
                    if (context.TryLoadClass(javaClassName, out javaClass))
                    {
                        javaClass.MarkReachable(context);
                    }
                }

                // Dex imported interfaces should have all their methods marked reachable.
                if (typeDef.IsInterface && typeDef.HasDexImportAttribute())
                {
                    typeDef.Methods.ForEach(x => x.MarkReachable(context));
                }

                // Record in context and create class builder
                context.RecordReachableType(typeDef);
            }
            else if ((typeSpec = type as TypeSpecification) != null)
            {
                // Element
                typeSpec.ElementType.MarkReachable(context);

                // Generic instance
                GenericInstanceType git;
                FunctionPointerType fpt;
                RequiredModifierType reqModType;
                OptionalModifierType optModType;
                if ((git = typeSpec as GenericInstanceType) != null)
                {
                    if (git.ElementType.IsNullableT())
                    {
                        var typeofT = git.GenericArguments[0].Resolve(context);
                        if (typeofT != null)
                        {
                            typeofT.UsedInNullableT = true;
                        }
                    }
                    Walk(context, (IGenericInstance)git);
                }
                else if ((fpt = typeSpec as FunctionPointerType) != null)
                {
                    Walk(context, fpt.ReturnType);
                }
                else if ((reqModType = typeSpec as RequiredModifierType) != null)
                {
                    reqModType.ModifierType.MarkReachable(context);
                }
                else if ((optModType = typeSpec as OptionalModifierType) != null)
                {
                    optModType.ModifierType.MarkReachable(context);
                }
            }
            else if ((genericParam = type as GenericParameter) != null)
            {
                // Owner
                var owner = (MemberReference)genericParam.Owner;
                owner.MarkReachable(context);

                // Constraints
                if (genericParam.HasConstraints)
                {
                    foreach (TypeReference constraint in genericParam.Constraints)
                    {
                        constraint.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                type.Resolve(context).MarkReachable(context);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            // Generic parameters
            Walk(context, (IGenericParameterProvider)type);

            TypeDefinition    typeDef;
            TypeSpecification typeSpec;
            GenericParameter  genericParam;

            if ((typeDef = type as TypeDefinition) != null)
            {
                // Mark base type reachable
                typeDef.BaseType.MarkReachable(context);

                // Mark declaring type reachable
                typeDef.DeclaringType.MarkReachable(context);

                // Mark implemented interfaces reachable
                if (typeDef.HasInterfaces)
                {
                    foreach (var intf in typeDef.Interfaces.Select(x => x.Interface))
                    {
                        intf.MarkReachable(context);
                    }
                }

                // If is an an attribute include related types
                if (typeDef.IsAttribute())
                {
                    GetDot42InternalType(context, "IAttribute").MarkReachable(context);
                    GetDot42InternalType(context, "IAttributes").MarkReachable(context);
                    GetDot42InternalType(context, "IAnnotationType").MarkReachable(context);
                }
                else if (typeDef.IsEnum)
                {
                    var boxingType = GetDot42InternalType(context, "Boxing");
                    boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context));
                }

                // Default & class ctor
                typeDef.FindDefaultCtor().MarkReachable(context);
                typeDef.GetClassCtor().MarkReachable(context);

                // Visit externally visible members
                if (typeDef.HasEvents)
                {
                    foreach (var evt in typeDef.Events)
                    {
                        if ((!evt.IsReachable) && context.Include(evt))
                        {
                            evt.MarkReachable(context);
                        }
                    }
                }
                if (typeDef.HasFields)
                {
                    foreach (var field in typeDef.Fields)
                    {
                        if ((!field.IsReachable) && context.Include(field))
                        {
                            field.MarkReachable(context);
                        }
                    }
                }
                if (typeDef.HasMethods)
                {
                    foreach (var method in typeDef.Methods)
                    {
                        if ((!method.IsReachable) && context.Include(method))
                        {
                            method.MarkReachable(context);
                        }
                    }
                }
                if (typeDef.HasProperties)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        if ((!prop.IsReachable) && context.Include(prop))
                        {
                            prop.MarkReachable(context);
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)typeDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null)
                {
                    var       javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value;
                    ClassFile javaClass;
                    if (context.TryLoadClass(javaClassName, out javaClass))
                    {
                        javaClass.MarkReachable(context);
                    }
                }

                // Dex imported interfaces should have all their methods marked reachable.
                if (typeDef.IsInterface && typeDef.HasDexImportAttribute())
                {
                    typeDef.Methods.ForEach(x => x.MarkReachable(context));
                }

                // Record in context and create class builder
                context.RecordReachableType(typeDef);
            }
            else if ((typeSpec = type as TypeSpecification) != null)
            {
                // Element
                typeSpec.ElementType.MarkReachable(context);

                // Generic instance
                GenericInstanceType  git;
                FunctionPointerType  fpt;
                RequiredModifierType reqModType;
                OptionalModifierType optModType;
                if ((git = typeSpec as GenericInstanceType) != null)
                {
                    if (git.ElementType.IsNullableT())
                    {
                        var typeofT = git.GenericArguments[0].Resolve(context);
                        if (typeofT != null)
                        {
                            typeofT.UsedInNullableT = true;
                        }
                    }
                    Walk(context, (IGenericInstance)git);
                }
                else if ((fpt = typeSpec as FunctionPointerType) != null)
                {
                    Walk(context, fpt.ReturnType);
                }
                else if ((reqModType = typeSpec as RequiredModifierType) != null)
                {
                    reqModType.ModifierType.MarkReachable(context);
                }
                else if ((optModType = typeSpec as OptionalModifierType) != null)
                {
                    optModType.ModifierType.MarkReachable(context);
                }
            }
            else if ((genericParam = type as GenericParameter) != null)
            {
                // Owner
                var owner = (MemberReference)genericParam.Owner;
                owner.MarkReachable(context);

                // Constraints
                if (genericParam.HasConstraints)
                {
                    foreach (TypeReference constraint in genericParam.Constraints)
                    {
                        constraint.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                type.Resolve(context).MarkReachable(context);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Mark all eachable items in argument as such.
        /// </summary>
        private static void Walk(ReachableContext context, MethodReference method)
        {
            method.ReturnType.MarkReachable(context);

            // All parameters
            if (method.HasParameters)
            {
                foreach (ParameterDefinition param in method.Parameters)
                {
                    Walk(context, (ParameterReference)param);
                }
            }

            // Generic parameters
            Walk(context, (IGenericParameterProvider)method);

            // Method definition?
            MethodDefinition    methodDef;
            MethodSpecification methodSpec;

            if ((methodDef = method as MethodDefinition) != null)
            {
                // Code
                Walk(context, methodDef.Body);

                // Overrides
                foreach (MethodReference methodRef in methodDef.Overrides)
                {
                    methodRef.MarkReachable(context);
                }

                // Base methods
                if (methodDef.IsVirtual)
                {
                    MethodDefinition baseMethod;
                    if ((baseMethod = methodDef.GetBaseMethod()) != null)
                    {
                        if (context.Contains(baseMethod.DeclaringType))
                        {
                            baseMethod.MarkReachable(context);
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)methodDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = methodDef.GetJavaImportAttribute()) != null)
                {
                    string className;
                    string memberName;
                    string descriptor;
                    javaImportAttr.GetDexOrJavaImportNames(methodDef, out memberName, out descriptor, out className);
                    ClassFile javaClass;
                    if (context.TryLoadClass(className, out javaClass))
                    {
                        var javaMethod = javaClass.Methods.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor));
                        javaClass.MarkReachable(context);
                        javaMethod.MarkReachable(context);
                    }
                }

                // If this method is a property accessor, include the property also
                if (methodDef.SemanticsAttributes.HasFlag(MethodSemanticsAttributes.Getter))
                {
                    var prop = methodDef.DeclaringType.Properties.FirstOrDefault(x => x.GetMethod == methodDef);
                    prop.MarkReachable(context);
                }
                if (methodDef.SemanticsAttributes.HasFlag(MethodSemanticsAttributes.Setter))
                {
                    var prop = methodDef.DeclaringType.Properties.FirstOrDefault(x => x.SetMethod == methodDef);
                    prop.MarkReachable(context);
                }
            }
            else if ((methodSpec = method as MethodSpecification) != null)
            {
                // Method
                methodSpec.ElementMethod.MarkReachable(context);

                // Generic arguments
                var gim = methodSpec as GenericInstanceMethod;
                if (gim != null)
                {
                    Walk(context, (IGenericInstance)gim);
                }
            }
            else
            {
                // Try to resolve
                method.Resolve(context).MarkReachable(context);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Mark all base types and externally visible members reachable
        /// </summary>
        private static void Walk(ReachableContext context, TypeReference type)
        {
            // Generic parameters
            Walk(context, (IGenericParameterProvider)type);

            TypeDefinition    typeDef;
            TypeSpecification typeSpec;
            GenericParameter  genericParam;

            if ((typeDef = type as TypeDefinition) != null)
            {
                var isUsedInSerialization = typeDef.IsUsedInSerialization && !type.IsPrimitive && !typeDef.IsEnum &&
                                            !type.Namespace.StartsWith("System");

                // Mark base type reachable
                typeDef.BaseType.MarkReachable(context, isUsedInSerialization);

                // Mark declaring type reachable
                typeDef.DeclaringType.MarkReachable(context);

                // Mark implemented interfaces reachable
                if (typeDef.HasInterfaces)
                {
                    foreach (var intf in typeDef.Interfaces.Select(x => x.InterfaceType))
                    {
                        intf.MarkReachable(context);
                    }
                }

                // If this is an attribute, include related types
                if (typeDef.IsAttribute())
                {
                    GetDot42InternalType(context, "IAttribute").MarkReachable(context);
                    GetDot42InternalType(context, "IAttributes").MarkReachable(context);
                }
                else if (typeDef.IsEnum)
                {
                    var boxingType = GetDot42InternalType(context, "Boxing");
                    boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context));
                }

                // Default & class ctor
                typeDef.FindDefaultCtor().MarkReachable(context);
                typeDef.GetClassCtor().MarkReachable(context);

                // Visit externally visible members
                if (typeDef.HasEvents)
                {
                    foreach (var evt in typeDef.Events)
                    {
                        if ((!evt.IsReachable) && context.Include(evt))
                        {
                            evt.MarkReachable(context);
                        }
                    }
                }
                if (typeDef.HasFields)
                {
                    foreach (var field in typeDef.Fields)
                    {
                        // only public fields, so we don't pull any compiler generated stuff.
                        var isSerializable = isUsedInSerialization && !field.IsStatic && field.IsPublic;

                        if ((!field.IsReachable && context.Include(field)) || (!field.IsUsedInSerialization && isSerializable))
                        {
                            field.MarkReachable(context, isUsedInSerialization);
                        }
                    }
                }
                if (typeDef.HasMethods)
                {
                    foreach (var method in typeDef.Methods)
                    {
                        if ((!method.IsReachable) && context.Include(method))
                        {
                            method.MarkReachable(context);
                        }
                    }
                }
                if (typeDef.HasProperties)
                {
                    foreach (var prop in typeDef.Properties)
                    {
                        var isSerializable = isUsedInSerialization && prop.HasThis;
                        if ((!prop.IsReachable && context.Include(prop) || (!prop.IsUsedInSerialization && isSerializable)))
                        {
                            prop.MarkReachable(context, isUsedInSerialization);
                        }
                    }
                }

                // Custom attributes
                Walk(context, (ICustomAttributeProvider)typeDef);

                // Walk imported java classes
                CustomAttribute javaImportAttr;
                if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null)
                {
                    var       javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value;
                    ClassFile javaClass;
                    if (context.TryLoadClass(javaClassName, out javaClass))
                    {
                        javaClass.MarkReachable(context);
                    }
                }

                // Dex imported interfaces should have all their methods marked reachable.
                if (typeDef.IsInterface && typeDef.HasDexImportAttribute())
                {
                    typeDef.Methods.ForEach(x => x.MarkReachable(context));
                }

                // Record in context
                context.RecordReachableType(typeDef);
            }
            else if ((typeSpec = type as TypeSpecification) != null)
            {
                // Element
                typeSpec.ElementType.MarkReachable(context, typeSpec.IsUsedInSerialization);

                // Generic instance
                GenericInstanceType  git;
                FunctionPointerType  fpt;
                RequiredModifierType reqModType;
                OptionalModifierType optModType;
                if ((git = typeSpec as GenericInstanceType) != null)
                {
                    if (git.ElementType.IsNullableT())
                    {
                        var typeofT = git.GenericArguments[0].Resolve(context);
                        if (typeofT != null && !typeofT.UsedInNullableT)
                        {
                            typeofT.UsedInNullableT = true;
                            DLog.Debug(DContext.CompilerAssemblyResolver, "found System.Nullable<{0}>", typeofT.FullName);
                        }
                    }
                    Walk(context, (IGenericInstance)git);
                }
                else if ((fpt = typeSpec as FunctionPointerType) != null)
                {
                    Walk(context, fpt.ReturnType);
                }
                else if ((reqModType = typeSpec as RequiredModifierType) != null)
                {
                    reqModType.ModifierType.MarkReachable(context);
                }
                else if ((optModType = typeSpec as OptionalModifierType) != null)
                {
                    optModType.ModifierType.MarkReachable(context);
                }
            }
            else if ((genericParam = type as GenericParameter) != null)
            {
                genericParam.IsSerializedParameter = genericParam.HasSerializedParameterAttribute();

                // Owner
                var owner = (MemberReference)genericParam.Owner;
                owner.MarkReachable(context);

                // Constraints
                if (genericParam.HasConstraints)
                {
                    foreach (TypeReference constraint in genericParam.Constraints)
                    {
                        constraint.MarkReachable(context);
                    }
                }
            }
            else
            {
                // Try to resolve
                type.Resolve(context).MarkReachable(context, type.IsUsedInSerialization);
            }
        }