blob: 37deccca6b42f91bf185986e1e966e53d78400ea [file] [log] [blame]
// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import static com.android.tools.r8.utils.ClassReferenceUtils.getClassReferenceComparator;
import static com.android.tools.r8.utils.TypeReferenceUtils.getTypeReferenceComparator;
import com.android.tools.r8.references.ArrayReference;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.google.common.collect.ImmutableList;
import java.util.Comparator;
import java.util.Iterator;
public class MethodReferenceUtils {
private static final Comparator<MethodReference> COMPARATOR =
(method, other) -> {
CompareResult holderClassCompareResult =
CompareResult.compare(
method.getHolderClass(), other.getHolderClass(), getClassReferenceComparator());
if (!holderClassCompareResult.isEqual()) {
return holderClassCompareResult.getComparisonResult();
}
CompareResult methodNameCompareResult =
CompareResult.compare(method.getMethodName(), other.getMethodName());
if (!methodNameCompareResult.isEqual()) {
return methodNameCompareResult.getComparisonResult();
}
CompareResult returnTypeCompareResult =
CompareResult.compare(
method.getReturnType(), other.getReturnType(), getTypeReferenceComparator());
if (!returnTypeCompareResult.isEqual()) {
return returnTypeCompareResult.getComparisonResult();
}
for (int i = 0;
i < Math.min(method.getFormalTypes().size(), other.getFormalTypes().size());
i++) {
CompareResult formalTypeCompareResult =
CompareResult.compare(
method.getFormalTypes().get(i),
other.getFormalTypes().get(i),
getTypeReferenceComparator());
if (!formalTypeCompareResult.isEqual()) {
return formalTypeCompareResult.getComparisonResult();
}
}
return method.getFormalTypes().size() - other.getFormalTypes().size();
};
public static int compare(MethodReference methodReference, ClassReference other) {
return ClassReferenceUtils.compare(other, methodReference) * -1;
}
public static int compare(MethodReference methodReference, FieldReference other) {
return FieldReferenceUtils.compare(other, methodReference) * -1;
}
public static int compare(MethodReference methodReference, MethodReference other) {
return getMethodReferenceComparator().compare(methodReference, other);
}
public static Comparator<MethodReference> getMethodReferenceComparator() {
return COMPARATOR;
}
public static MethodReference mainMethod(Class<?> clazz) {
return mainMethod(Reference.classFromClass(clazz));
}
public static MethodReference mainMethod(ClassReference type) {
ArrayReference stringArrayType = Reference.array(Reference.classFromClass(String.class), 1);
return Reference.method(type, "main", ImmutableList.of(stringArrayType), null);
}
public static MethodReference methodFromMethod(
Class<?> clazz, String name, Class<?>... parameterTypes) {
try {
return Reference.methodFromMethod(clazz.getDeclaredMethod(name, parameterTypes));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static String toSourceStringWithoutHolderAndReturnType(MethodReference methodReference) {
return toSourceString(methodReference, false, false);
}
public static String toSourceString(MethodReference methodReference) {
return toSourceString(methodReference, true, true);
}
public static String toSourceString(
MethodReference methodReference, boolean includeHolder, boolean includeReturnType) {
StringBuilder builder = new StringBuilder();
if (includeReturnType) {
builder
.append(
methodReference.getReturnType() != null
? methodReference.getReturnType().getTypeName()
: "void")
.append(" ");
}
if (includeHolder) {
builder.append(methodReference.getHolderClass().getTypeName()).append(".");
}
builder.append(methodReference.getMethodName()).append("(");
Iterator<TypeReference> formalTypesIterator = methodReference.getFormalTypes().iterator();
if (formalTypesIterator.hasNext()) {
builder.append(formalTypesIterator.next().getTypeName());
while (formalTypesIterator.hasNext()) {
builder.append(", ").append(formalTypesIterator.next().getTypeName());
}
}
return builder.append(")").toString();
}
}