Add matcher helpers to 2.2 branch
Fixed: 187090274
Change-Id: I382a64d6c9270f3c97335c59407fc7577570c7cb
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
index 86a21c1..2f81351 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeMatchers.java
@@ -6,7 +6,9 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
+import java.util.List;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
@@ -71,10 +73,98 @@
};
}
+ public static Matcher<MethodSubject> invokesMethod(
+ String returnType, String holderType, String methodName, List<String> parameterTypes) {
+ return new TypeSafeMatcher<MethodSubject>() {
+ @Override
+ protected boolean matchesSafely(MethodSubject subject) {
+ if (!subject.isPresent()) {
+ return false;
+ }
+ if (!subject.getMethod().hasCode()) {
+ return false;
+ }
+ return subject
+ .streamInstructions()
+ .anyMatch(isInvokeWithTarget(returnType, holderType, methodName, parameterTypes));
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ StringBuilder text =
+ new StringBuilder("invokes method `")
+ .append(returnType != null ? returnType : "*")
+ .append(" ")
+ .append(holderType != null ? holderType : "*")
+ .append(".")
+ .append(methodName != null ? methodName : "*")
+ .append("(");
+ if (parameterTypes != null) {
+ text.append(
+ parameterTypes.stream()
+ .map(parameterType -> parameterType != null ? parameterType : "*")
+ .collect(Collectors.joining(", ")));
+ } else {
+ text.append("...");
+ }
+ text.append(")`");
+ description.appendText(text.toString());
+ }
+
+ @Override
+ public void describeMismatchSafely(final MethodSubject subject, Description description) {
+ description.appendText("method did not");
+ }
+ };
+ }
+
+ public static Matcher<MethodSubject> invokesMethodWithHolderAndName(
+ String holderType, String name) {
+ return invokesMethod(null, holderType, name, null);
+ }
+
+ public static Matcher<MethodSubject> invokesMethodWithName(String name) {
+ return invokesMethod(null, null, name, null);
+ }
+
public static Predicate<InstructionSubject> isInvokeWithTarget(DexMethod target) {
return instruction -> instruction.isInvoke() && instruction.getMethod() == target;
}
+ public static Predicate<InstructionSubject> isInvokeWithTarget(
+ String returnType, String holderType, String methodName, List<String> parameterTypes) {
+ return instruction -> {
+ if (!instruction.isInvoke()) {
+ return false;
+ }
+ DexMethod invokedMethod = instruction.getMethod();
+ if (returnType != null
+ && !invokedMethod.getReturnType().toSourceString().equals(returnType)) {
+ return false;
+ }
+ if (holderType != null
+ && !invokedMethod.getHolderType().toSourceString().equals(holderType)) {
+ return false;
+ }
+ if (methodName != null && !invokedMethod.getName().toSourceString().equals(methodName)) {
+ return false;
+ }
+ if (parameterTypes != null) {
+ if (parameterTypes.size() != invokedMethod.getArity()) {
+ return false;
+ }
+ for (int i = 0; i < parameterTypes.size(); i++) {
+ String parameterType = parameterTypes.get(i);
+ if (parameterType != null
+ && !invokedMethod.getParameters().get(i).toSourceString().equals(parameterType)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+ }
+
public static Predicate<InstructionSubject> isFieldAccessWithTarget(DexField target) {
return instruction -> instruction.isFieldAccess() && instruction.getField() == target;
}