5

I am writing an app that has a form with text fields that take numbers. To check whether the input is valid I decided to use Hamcrest Matchers. I defined:

public static <T> boolean checkThat(T actual, Matcher<? super T> matcher) {
    return matcher.matches(actual);
}

such that I can use stuff like:

if(checkThat(doubleFromText,greaterThan(0.0)) doSomething();

Now this works perfectly fine in debug mode, but when I enable proguard for production release the application crashes immediately with the following message (obtained with retrace):

java.lang.Error: Cannot determine correct type for matchesSafely() method.
        at org.hamcrest.internal.ReflectiveTypeFinder.findExpectedType(Unknown Source)
                                                      canObtainExpectedTypeFrom
        at org.hamcrest.TypeSafeMatcher.<init>(Unknown Source)
        at org.hamcrest.TypeSafeMatcher.<init>(Unknown Source)
        at org.hamcrest.number.OrderingComparison.<init>(Unknown Source)
        at org.hamcrest.number.OrderingComparison.greaterThan(Unknown Source)
                                                  matchesSafely
        at org.hamcrest.Matchers.greaterThan(Unknown Source)

How can I fix this?

I made a minimal example demonstrating the problem: https://github.com/burgerga/HamcrestMatchersWithProguard


Notes:

  • I added -dontwarn java.beans.** to my proguard rules to get it to compile.
  • Before you start telling me I should just use if(doubleFromText > 0), the example I gave was simplified. In my code I use something like

    checkThat(textIn(myEditText),parsesToDouble(greaterThan(0.0)));
    

    where parsesToDouble is a simple matcher I wrote. I think this is a very flexible and clear way to state my intent, and I'm simply interested in how to get it working with proguard.

Gerhard Burger
  • 1,379
  • 1
  • 16
  • 25

1 Answers1

5

Because Hamcrest uses reflection, some methods get deleted in the shrinking phase that shouldn't be deleted. I was able to get it working again by adding

-keepclasseswithmembers class org.hamcrest.number.** { *** matchesSafely(...); }

to the proguard rules. If you don't care about a slightly larger apk you can add

-keep class org.hamcrest.** { *; }

to make sure nothing from hamcrest gets deleted.

Androiderson
  • 16,865
  • 6
  • 62
  • 72
Gerhard Burger
  • 1,379
  • 1
  • 16
  • 25