/// <summary> /// Mark all properties with the given name reachable. /// </summary> internal static void MarkPropertiesReachable(this TypeReference type, string propertyName, ReachableContext context) { while ((type != null) && (context.Contains(type))) { TypeDefinition typeDef = context.GetTypeDefinition(type); if (typeDef != null) { if (typeDef.HasProperties) { foreach (PropertyDefinition prop in typeDef.Properties) { if (prop.Name == propertyName) { prop.MarkReachable(context); } } } type = typeDef.BaseType; } else { type = null; } } }
/// <summary> /// Mark all fields with the given name reachable. /// </summary> internal static void MarkFieldsReachable(this TypeReference type, string fieldName, ReachableContext context) { while ((type != null) && (context.Contains(type))) { TypeDefinition typeDef = context.GetTypeDefinition(type); if (typeDef != null) { if (typeDef.HasFields) { foreach (FieldDefinition field in typeDef.Fields) { if (field.Name == fieldName) { field.MarkReachable(context); } } } type = typeDef.BaseType; } else { type = null; } } }
/// <summary> /// Mark all eachable items in argument as such. /// </summary> private static void Walk(ReachableContext context, MethodDefinition method) { method.DeclaringClass.MarkReachable(context); method.ReturnType.MarkReachable(context); // All parameters foreach (var param in method.Parameters) { param.MarkReachable(context); } // Base methods if (!method.IsStatic && !method.IsFinal) { MethodDefinition baseMethod; if ((baseMethod = method.GetBaseMethod()) != null) { if (context.Contains(baseMethod.DeclaringClass)) { baseMethod.MarkReachable(context); } } } Walk(context, method.Body); }
/// <summary> /// Resolve type reference into type defition. /// Generic instance types are resolved to their element type. /// </summary> internal static TypeDefinition Resolve(this TypeReference type, ReachableContext context) { if (context.Contains(type)) { var typeDef = type as TypeDefinition; if (typeDef != null) { return typeDef; } var git = type as GenericInstanceType; if (git != null) { return git.ElementType.Resolve(context); } return context.GetTypeDefinition(type); } // Type not in project, don't care about it. return null; }
/// <summary> /// Resolve type reference into type defition. /// Generic instance types are resolved to their element type. /// </summary> internal static TypeDefinition Resolve(this TypeReference type, ReachableContext context) { if (context.Contains(type)) { var typeDef = type as TypeDefinition; if (typeDef != null) { return(typeDef); } var git = type as GenericInstanceType; if (git != null) { return(git.ElementType.Resolve(context)); } return(context.GetTypeDefinition(type)); } // Type not in project, don't care about it. return(null); }
/// <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); } }
/// <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); } }