package com.oracle.svm.hosted.annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.graalvm.collections.Pair;
import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
public class CustomSubstitution<T extends CustomSubstitutionType<?, ?>> extends SubstitutionProcessor {
protected final MetaAccessProvider metaAccess;
protected final Map<ResolvedJavaType, T> typeSubstitutions;
public CustomSubstitution(MetaAccessProvider metaAccess) {
this.metaAccess = metaAccess;
this.typeSubstitutions = new HashMap<>();
}
protected T getSubstitutionType(ResolvedJavaType original) {
return typeSubstitutions.get(original);
}
protected void addSubstitutionType(ResolvedJavaType orignal, T substitution) {
assert substitution != null;
typeSubstitutions.put(orignal, substitution);
}
protected static String canonicalMethodName(ResolvedJavaMethod method) {
String result = method.getName();
while (result.endsWith("*")) {
result = result.substring(0, result.length() - 1);
}
return result;
}
protected static List<Pair<String, ResolvedJavaType>> findAttributes(ResolvedJavaType annotationType) {
List<Pair<String, ResolvedJavaType>> attributes = new ArrayList<>();
for (ResolvedJavaMethod method : annotationType.getDeclaredMethods()) {
String methodName = canonicalMethodName(method);
if (methodName.equals("equals") || methodName.equals("hashCode") || methodName.equals("toString") || methodName.equals("annotationType")) {
} else {
ResolvedJavaType returnType = (ResolvedJavaType) method.getSignature().getReturnType(null);
attributes.add(Pair.create(methodName, returnType));
}
}
Collections.sort(attributes, Comparator.comparing(Pair::getLeft));
return attributes;
}
protected static ResolvedJavaMethod findMethod(ResolvedJavaType declaringType, String name, ResolvedJavaType... argumentTypes) {
ResolvedJavaMethod result = null;
outer: for (ResolvedJavaMethod method : declaringType.getDeclaredMethods()) {
if (canonicalMethodName(method).equals(name) && method.getSignature().getParameterCount(false) == argumentTypes.length) {
Signature sig = method.getSignature();
for (int i = 0; i < argumentTypes.length; i++) {
if (!sig.getParameterType(i, null).resolve(null).isAssignableFrom(argumentTypes[i])) {
continue outer;
}
}
assert result == null : "more than one matching method found";
result = method;
}
}
assert result != null : "no matching method found";
return result;
}
protected static ResolvedJavaField findField(ResolvedJavaType declaringType, String name) {
ResolvedJavaField result = null;
for (ResolvedJavaField field : declaringType.getInstanceFields(false)) {
if (field.getName().equals(name)) {
assert result == null : "more than one matching field found";
result = field;
}
}
assert result != null : "no matching field found";
return result;
}
}