Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix bug #8112: don't special case Comparable and Comparator methods a…

…nymore.

Before this fix, Comparable.compareTo(Object) and
Comparator.compare(Object,Object) are specially removed and hence only
generic-bound compare() remained in Mono.Android.dll. This resulted in a
side effect that is bug #8112 - when generic information was unavailable,
it still removed Object-based compareTo() and compare(), which were the only
one implementation and resulted in missing method error.

This fix changes the way to lookup methods to save in API XML; only
"really-declared" methods remain. For generic methods JRE automatically
adds overloads for those methods with Object. We now skip them (which
gives consistent output with AOSP XML).
  • Loading branch information...
commit 72a6be606e0eb964bbfd42eb7dc39b53bf0ffb35 1 parent 3a7c404
@atsushieno atsushieno authored
Showing with 33 additions and 27 deletions.
  1. +33 −15 JavaClass.java
  2. +0 −12 README
View
48 JavaClass.java
@@ -435,6 +435,17 @@ String getSignature (Method method)
{
StringBuffer sig = new StringBuffer ();
sig.append (method.getName ());
+ for (Class t : method.getParameterTypes ()) {
+ sig.append (":");
+ sig.append (t.getName ());
+ }
+ return sig.toString ();
+ }
+
+ String getGenericSignature (Method method)
+ {
+ StringBuffer sig = new StringBuffer ();
+ sig.append (method.getName ());
for (Type t : method.getGenericParameterTypes ()) {
sig.append (":");
sig.append (getGenericTypeName (t));
@@ -461,6 +472,20 @@ public void appendToDocument (Document doc, Element parent)
}
}
+ Comparator clscmp = new Comparator<Class> () {
+ public int compare (Class c1, Class c2) {
+ return c1.getName ().compareTo (c2.getName ());
+ }
+ };
+
+ boolean isInPublicInheritanceChain (Class cls)
+ {
+ for (Class c = cls; c != null; c = c.getSuperclass ())
+ if ((c.getModifiers () & Modifier.PUBLIC) == 0)
+ return false;
+ return true;
+ }
+
void doAppendToDocument (Document doc, Element parent)
{
int mods = jclass.getModifiers ();
@@ -519,6 +544,13 @@ else if (iface instanceof ParameterizedType) {
Class base_class = jclass.getSuperclass ();
Map<String, Method> methods = new HashMap <String, Method> ();
for (Method method : jclass.getDeclaredMethods ()) {
+ // Skip "synthetic" methods that is automatically supplied by JRE.
+ // But there is an exception scenario: if the class is derived from non-public class,
+ // don't do that - it results in excessive removal.
+ // e.g. in libcore/luni, StringBuilder inherits non-public AbstractStringBuilder.
+ if (method.isSynthetic () && isInPublicInheritanceChain (jclass))
+ continue;
+
int mmods = method.getModifiers ();
/*
@@ -569,22 +601,8 @@ else if (iface instanceof ParameterizedType) {
}
}
}
-
- Comparator clscmp = new Comparator<Class> () {
- public int compare (Class c1, Class c2) {
- return c1.getName ().compareTo (c2.getName ());
- }
- };
-
- // These special rules are required to filter out incorrectly returned compareTo(Object) Comparable<T> implementation (maybe it is due to "erased generics").
- if (Arrays.binarySearch (jclass.getInterfaces (), Comparable.class, clscmp) >= 0 && method.getName ().equals ("compareTo") && ptypes [0].equals (Object.class)
- // IF this worked in Java ... <code>if (... && ptypes [0] != jclass.GetGenericArguments () [0])</code>
- && !jclass.equals (java.io.ObjectStreamField.class))
- continue;
- if (Arrays.binarySearch (jclass.getInterfaces (), Comparator.class, clscmp) >= 0 && method.getName ().equals ("compare") && ptypes.length == 2 && ptypes [0].equals (Object.class) && ptypes [1].equals (Object.class))
- continue;
- String key = getSignature (method);
+ String key = getGenericSignature (method);
if (methods.containsKey (key)) {
Type method_type = method.getGenericReturnType ();
Method hashed = methods.get (key);
View
12 README
@@ -308,15 +308,3 @@ Now we use ASM to solve the issues below:
android.view.MotionEvent.getSource() is also missing.
</maybe-historical>
-
-** Erased generic issues
-
-<workarounded>
-- extraneous "CompareTo(Object)" method
- - e.g. android.net.Uri, java.util.Calendar, java.util.Date, java.util.UUID, java.nio.Charset and so on.
- - They implement Comparable<T> and since either <T> went away in
- android.jar or jar2xml ignores generic type arguments and treats T
- arg as Object, this extra method is returned.
-- similarly, Comparator<T> brings extra Compare(Object, Object) overloads.
-
-</workarounded>
Please sign in to comment.
Something went wrong with that request. Please try again.