Painless: Rename *Binding classes to *ClassBinding. (#33865)
With the upcoming instance bindings, the singular *Binding name isn't descriptive enough with multiple binding types. This renames the existing *Binding classes to *ClassBinding. Mechanical change (with some error messages changed from binding to class binding by hand).
This commit is contained in:
parent
c764012347
commit
3df285d9f0
|
@ -63,16 +63,16 @@ public final class Whitelist {
|
|||
/** The {@link List} of all the whitelisted static Painless methods. */
|
||||
public final List<WhitelistMethod> whitelistImportedMethods;
|
||||
|
||||
/** The {@link List} of all the whitelisted Painless bindings. */
|
||||
public final List<WhitelistBinding> whitelistBindings;
|
||||
/** The {@link List} of all the whitelisted Painless class bindings. */
|
||||
public final List<WhitelistClassBinding> whitelistClassBindings;
|
||||
|
||||
/** Standard constructor. All values must be not {@code null}. */
|
||||
public Whitelist(ClassLoader classLoader, List<WhitelistClass> whitelistClasses,
|
||||
List<WhitelistMethod> whitelistImportedMethods, List<WhitelistBinding> whitelistBindings) {
|
||||
List<WhitelistMethod> whitelistImportedMethods, List<WhitelistClassBinding> whitelistClassBindings) {
|
||||
|
||||
this.classLoader = Objects.requireNonNull(classLoader);
|
||||
this.whitelistClasses = Collections.unmodifiableList(Objects.requireNonNull(whitelistClasses));
|
||||
this.whitelistImportedMethods = Collections.unmodifiableList(Objects.requireNonNull(whitelistImportedMethods));
|
||||
this.whitelistBindings = Collections.unmodifiableList(Objects.requireNonNull(whitelistBindings));
|
||||
this.whitelistClassBindings = Collections.unmodifiableList(Objects.requireNonNull(whitelistClassBindings));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,23 +23,23 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A binding represents a method call that stores state. Each binding class must have exactly one
|
||||
* public constructor and one public method excluding those inherited directly from {@link Object}.
|
||||
* The canonical type name parameters provided must match those of the constructor and method combined.
|
||||
* The constructor for a binding class will be called when the binding method is called for the first
|
||||
* time at which point state may be stored for the arguments passed into the constructor. The method
|
||||
* for a binding class will be called each time the binding method is called and may use the previously
|
||||
* stored state.
|
||||
* A class binding represents a method call that stores state. Each class binding's Java class must
|
||||
* have exactly one public constructor and one public method excluding those inherited directly
|
||||
* from {@link Object}. The canonical type name parameters provided must match those of the
|
||||
* constructor and method combined. The constructor for a class binding's Java class will be called
|
||||
* when the binding method is called for the first time at which point state may be stored for the
|
||||
* arguments passed into the constructor. The method for a binding class will be called each time
|
||||
* the binding method is called and may use the previously stored state.
|
||||
*/
|
||||
public class WhitelistBinding {
|
||||
public class WhitelistClassBinding {
|
||||
|
||||
/** Information about where this constructor was whitelisted from. */
|
||||
public final String origin;
|
||||
|
||||
/** The Java class name this binding represents. */
|
||||
/** The Java class name this class binding targets. */
|
||||
public final String targetJavaClassName;
|
||||
|
||||
/** The method name for this binding. */
|
||||
/** The method name for this class binding. */
|
||||
public final String methodName;
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ public class WhitelistBinding {
|
|||
public final List<String> canonicalTypeNameParameters;
|
||||
|
||||
/** Standard constructor. All values must be not {@code null}. */
|
||||
public WhitelistBinding(String origin, String targetJavaClassName,
|
||||
public WhitelistClassBinding(String origin, String targetJavaClassName,
|
||||
String methodName, String returnCanonicalTypeName, List<String> canonicalTypeNameParameters) {
|
||||
|
||||
this.origin = Objects.requireNonNull(origin);
|
|
@ -134,7 +134,7 @@ public final class WhitelistLoader {
|
|||
public static Whitelist loadFromResourceFiles(Class<?> resource, String... filepaths) {
|
||||
List<WhitelistClass> whitelistClasses = new ArrayList<>();
|
||||
List<WhitelistMethod> whitelistStatics = new ArrayList<>();
|
||||
List<WhitelistBinding> whitelistBindings = new ArrayList<>();
|
||||
List<WhitelistClassBinding> whitelistClassBindings = new ArrayList<>();
|
||||
|
||||
// Execute a single pass through the whitelist text files. This will gather all the
|
||||
// constructors, methods, augmented methods, and fields for each whitelisted class.
|
||||
|
@ -292,7 +292,7 @@ public final class WhitelistLoader {
|
|||
whitelistStatics.add(new WhitelistMethod(origin, targetJavaClassName,
|
||||
methodName, returnCanonicalTypeName, Arrays.asList(canonicalTypeNameParameters)));
|
||||
} else if ("bound_to".equals(staticImportType)) {
|
||||
whitelistBindings.add(new WhitelistBinding(origin, targetJavaClassName,
|
||||
whitelistClassBindings.add(new WhitelistClassBinding(origin, targetJavaClassName,
|
||||
methodName, returnCanonicalTypeName, Arrays.asList(canonicalTypeNameParameters)));
|
||||
} else {
|
||||
throw new IllegalArgumentException("invalid static import definition: " +
|
||||
|
@ -392,7 +392,7 @@ public final class WhitelistLoader {
|
|||
|
||||
ClassLoader loader = AccessController.doPrivileged((PrivilegedAction<ClassLoader>)resource::getClassLoader);
|
||||
|
||||
return new Whitelist(loader, whitelistClasses, whitelistStatics, whitelistBindings);
|
||||
return new Whitelist(loader, whitelistClasses, whitelistStatics, whitelistClassBindings);
|
||||
}
|
||||
|
||||
private WhitelistLoader() {}
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class PainlessBinding {
|
||||
public class PainlessClassBinding {
|
||||
|
||||
public final Constructor<?> javaConstructor;
|
||||
public final Method javaMethod;
|
||||
|
@ -31,7 +31,7 @@ public class PainlessBinding {
|
|||
public final Class<?> returnType;
|
||||
public final List<Class<?>> typeParameters;
|
||||
|
||||
PainlessBinding(Constructor<?> javaConstructor, Method javaMethod, Class<?> returnType, List<Class<?>> typeParameters) {
|
||||
PainlessClassBinding(Constructor<?> javaConstructor, Method javaMethod, Class<?> returnType, List<Class<?>> typeParameters) {
|
||||
this.javaConstructor = javaConstructor;
|
||||
this.javaMethod = javaMethod;
|
||||
|
|
@ -38,23 +38,23 @@ public final class PainlessLookup {
|
|||
private final Map<Class<?>, PainlessClass> classesToPainlessClasses;
|
||||
|
||||
private final Map<String, PainlessMethod> painlessMethodKeysToImportedPainlessMethods;
|
||||
private final Map<String, PainlessBinding> painlessMethodKeysToPainlessBindings;
|
||||
private final Map<String, PainlessClassBinding> painlessMethodKeysToPainlessClassBindings;
|
||||
|
||||
PainlessLookup(Map<String, Class<?>> canonicalClassNamesToClasses, Map<Class<?>, PainlessClass> classesToPainlessClasses,
|
||||
Map<String, PainlessMethod> painlessMethodKeysToImportedPainlessMethods,
|
||||
Map<String, PainlessBinding> painlessMethodKeysToPainlessBindings) {
|
||||
Map<String, PainlessClassBinding> painlessMethodKeysToPainlessClassBindings) {
|
||||
|
||||
Objects.requireNonNull(canonicalClassNamesToClasses);
|
||||
Objects.requireNonNull(classesToPainlessClasses);
|
||||
|
||||
Objects.requireNonNull(painlessMethodKeysToImportedPainlessMethods);
|
||||
Objects.requireNonNull(painlessMethodKeysToPainlessBindings);
|
||||
Objects.requireNonNull(painlessMethodKeysToPainlessClassBindings);
|
||||
|
||||
this.canonicalClassNamesToClasses = Collections.unmodifiableMap(canonicalClassNamesToClasses);
|
||||
this.classesToPainlessClasses = Collections.unmodifiableMap(classesToPainlessClasses);
|
||||
|
||||
this.painlessMethodKeysToImportedPainlessMethods = Collections.unmodifiableMap(painlessMethodKeysToImportedPainlessMethods);
|
||||
this.painlessMethodKeysToPainlessBindings = Collections.unmodifiableMap(painlessMethodKeysToPainlessBindings);
|
||||
this.painlessMethodKeysToPainlessClassBindings = Collections.unmodifiableMap(painlessMethodKeysToPainlessClassBindings);
|
||||
}
|
||||
|
||||
public boolean isValidCanonicalClassName(String canonicalClassName) {
|
||||
|
@ -182,12 +182,12 @@ public final class PainlessLookup {
|
|||
return painlessMethodKeysToImportedPainlessMethods.get(painlessMethodKey);
|
||||
}
|
||||
|
||||
public PainlessBinding lookupPainlessBinding(String methodName, int arity) {
|
||||
public PainlessClassBinding lookupPainlessClassBinding(String methodName, int arity) {
|
||||
Objects.requireNonNull(methodName);
|
||||
|
||||
String painlessMethodKey = buildPainlessMethodKey(methodName, arity);
|
||||
|
||||
return painlessMethodKeysToPainlessBindings.get(painlessMethodKey);
|
||||
return painlessMethodKeysToPainlessClassBindings.get(painlessMethodKey);
|
||||
}
|
||||
|
||||
public PainlessMethod lookupFunctionalInterfacePainlessMethod(Class<?> targetClass) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package org.elasticsearch.painless.lookup;
|
||||
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.painless.spi.WhitelistBinding;
|
||||
import org.elasticsearch.painless.spi.WhitelistClassBinding;
|
||||
import org.elasticsearch.painless.spi.WhitelistClass;
|
||||
import org.elasticsearch.painless.spi.WhitelistConstructor;
|
||||
import org.elasticsearch.painless.spi.WhitelistField;
|
||||
|
@ -156,14 +156,14 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private static class PainlessBindingCacheKey {
|
||||
private static class PainlessClassBindingCacheKey {
|
||||
|
||||
private final Class<?> targetClass;
|
||||
private final String methodName;
|
||||
private final Class<?> methodReturnType;
|
||||
private final List<Class<?>> methodTypeParameters;
|
||||
|
||||
private PainlessBindingCacheKey(Class<?> targetClass,
|
||||
private PainlessClassBindingCacheKey(Class<?> targetClass,
|
||||
String methodName, Class<?> returnType, List<Class<?>> typeParameters) {
|
||||
|
||||
this.targetClass = targetClass;
|
||||
|
@ -182,7 +182,7 @@ public final class PainlessLookupBuilder {
|
|||
return false;
|
||||
}
|
||||
|
||||
PainlessBindingCacheKey that = (PainlessBindingCacheKey)object;
|
||||
PainlessClassBindingCacheKey that = (PainlessClassBindingCacheKey)object;
|
||||
|
||||
return Objects.equals(targetClass, that.targetClass) &&
|
||||
Objects.equals(methodName, that.methodName) &&
|
||||
|
@ -196,10 +196,10 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private static final Map<PainlessConstructorCacheKey, PainlessConstructor> painlessConstructorCache = new HashMap<>();
|
||||
private static final Map<PainlessMethodCacheKey, PainlessMethod> painlessMethodCache = new HashMap<>();
|
||||
private static final Map<PainlessFieldCacheKey, PainlessField> painlessFieldCache = new HashMap<>();
|
||||
private static final Map<PainlessBindingCacheKey, PainlessBinding> painlessBindingCache = new HashMap<>();
|
||||
private static final Map<PainlessConstructorCacheKey, PainlessConstructor> painlessConstructorCache = new HashMap<>();
|
||||
private static final Map<PainlessMethodCacheKey, PainlessMethod> painlessMethodCache = new HashMap<>();
|
||||
private static final Map<PainlessFieldCacheKey, PainlessField> painlessFieldCache = new HashMap<>();
|
||||
private static final Map<PainlessClassBindingCacheKey, PainlessClassBinding> painlessClassBindingCache = new HashMap<>();
|
||||
|
||||
private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][._a-zA-Z0-9]*$");
|
||||
private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
|
||||
|
@ -251,12 +251,12 @@ public final class PainlessLookupBuilder {
|
|||
whitelistStatic.canonicalTypeNameParameters);
|
||||
}
|
||||
|
||||
for (WhitelistBinding whitelistBinding : whitelist.whitelistBindings) {
|
||||
origin = whitelistBinding.origin;
|
||||
painlessLookupBuilder.addPainlessBinding(
|
||||
whitelist.classLoader, whitelistBinding.targetJavaClassName,
|
||||
whitelistBinding.methodName, whitelistBinding.returnCanonicalTypeName,
|
||||
whitelistBinding.canonicalTypeNameParameters);
|
||||
for (WhitelistClassBinding whitelistClassBinding : whitelist.whitelistClassBindings) {
|
||||
origin = whitelistClassBinding.origin;
|
||||
painlessLookupBuilder.addPainlessClassBinding(
|
||||
whitelist.classLoader, whitelistClassBinding.targetJavaClassName,
|
||||
whitelistClassBinding.methodName, whitelistClassBinding.returnCanonicalTypeName,
|
||||
whitelistClassBinding.canonicalTypeNameParameters);
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
|
@ -270,14 +270,14 @@ public final class PainlessLookupBuilder {
|
|||
private final Map<Class<?>, PainlessClassBuilder> classesToPainlessClassBuilders;
|
||||
|
||||
private final Map<String, PainlessMethod> painlessMethodKeysToImportedPainlessMethods;
|
||||
private final Map<String, PainlessBinding> painlessMethodKeysToPainlessBindings;
|
||||
private final Map<String, PainlessClassBinding> painlessMethodKeysToPainlessClassBindings;
|
||||
|
||||
public PainlessLookupBuilder() {
|
||||
canonicalClassNamesToClasses = new HashMap<>();
|
||||
classesToPainlessClassBuilders = new HashMap<>();
|
||||
|
||||
painlessMethodKeysToImportedPainlessMethods = new HashMap<>();
|
||||
painlessMethodKeysToPainlessBindings = new HashMap<>();
|
||||
painlessMethodKeysToPainlessClassBindings = new HashMap<>();
|
||||
}
|
||||
|
||||
private Class<?> canonicalTypeNameToType(String canonicalTypeName) {
|
||||
|
@ -909,8 +909,8 @@ public final class PainlessLookupBuilder {
|
|||
|
||||
String painlessMethodKey = buildPainlessMethodKey(methodName, typeParametersSize);
|
||||
|
||||
if (painlessMethodKeysToPainlessBindings.containsKey(painlessMethodKey)) {
|
||||
throw new IllegalArgumentException("imported method and binding cannot have the same name [" + methodName + "]");
|
||||
if (painlessMethodKeysToPainlessClassBindings.containsKey(painlessMethodKey)) {
|
||||
throw new IllegalArgumentException("imported method and class binding cannot have the same name [" + methodName + "]");
|
||||
}
|
||||
|
||||
PainlessMethod importedPainlessMethod = painlessMethodKeysToImportedPainlessMethods.get(painlessMethodKey);
|
||||
|
@ -945,7 +945,7 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public void addPainlessBinding(ClassLoader classLoader, String targetJavaClassName,
|
||||
public void addPainlessClassBinding(ClassLoader classLoader, String targetJavaClassName,
|
||||
String methodName, String returnCanonicalTypeName, List<String> canonicalTypeNameParameters) {
|
||||
|
||||
Objects.requireNonNull(classLoader);
|
||||
|
@ -969,7 +969,7 @@ public final class PainlessLookupBuilder {
|
|||
Class<?> typeParameter = canonicalTypeNameToType(canonicalTypeNameParameter);
|
||||
|
||||
if (typeParameter == null) {
|
||||
throw new IllegalArgumentException("type parameter [" + canonicalTypeNameParameter + "] not found for binding " +
|
||||
throw new IllegalArgumentException("type parameter [" + canonicalTypeNameParameter + "] not found for class binding " +
|
||||
"[[" + targetCanonicalClassName + "], [" + methodName + "], " + canonicalTypeNameParameters + "]");
|
||||
}
|
||||
|
||||
|
@ -979,14 +979,14 @@ public final class PainlessLookupBuilder {
|
|||
Class<?> returnType = canonicalTypeNameToType(returnCanonicalTypeName);
|
||||
|
||||
if (returnType == null) {
|
||||
throw new IllegalArgumentException("return type [" + returnCanonicalTypeName + "] not found for binding " +
|
||||
throw new IllegalArgumentException("return type [" + returnCanonicalTypeName + "] not found for class binding " +
|
||||
"[[" + targetCanonicalClassName + "], [" + methodName + "], " + canonicalTypeNameParameters + "]");
|
||||
}
|
||||
|
||||
addPainlessBinding(targetClass, methodName, returnType, typeParameters);
|
||||
addPainlessClassBinding(targetClass, methodName, returnType, typeParameters);
|
||||
}
|
||||
|
||||
public void addPainlessBinding(Class<?> targetClass, String methodName, Class<?> returnType, List<Class<?>> typeParameters) {
|
||||
public void addPainlessClassBinding(Class<?> targetClass, String methodName, Class<?> returnType, List<Class<?>> typeParameters) {
|
||||
|
||||
Objects.requireNonNull(targetClass);
|
||||
Objects.requireNonNull(methodName);
|
||||
|
@ -994,7 +994,7 @@ public final class PainlessLookupBuilder {
|
|||
Objects.requireNonNull(typeParameters);
|
||||
|
||||
if (targetClass == def.class) {
|
||||
throw new IllegalArgumentException("cannot add binding as reserved class [" + DEF_CLASS_NAME + "]");
|
||||
throw new IllegalArgumentException("cannot add class binding as reserved class [" + DEF_CLASS_NAME + "]");
|
||||
}
|
||||
|
||||
String targetCanonicalClassName = typeToCanonicalTypeName(targetClass);
|
||||
|
@ -1005,7 +1005,8 @@ public final class PainlessLookupBuilder {
|
|||
for (Constructor<?> eachJavaConstructor : javaConstructors) {
|
||||
if (eachJavaConstructor.getDeclaringClass() == targetClass) {
|
||||
if (javaConstructor != null) {
|
||||
throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] cannot have multiple constructors");
|
||||
throw new IllegalArgumentException(
|
||||
"class binding [" + targetCanonicalClassName + "] cannot have multiple constructors");
|
||||
}
|
||||
|
||||
javaConstructor = eachJavaConstructor;
|
||||
|
@ -1013,7 +1014,7 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
|
||||
if (javaConstructor == null) {
|
||||
throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] must have exactly one constructor");
|
||||
throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] must have exactly one constructor");
|
||||
}
|
||||
|
||||
int constructorTypeParametersSize = javaConstructor.getParameterCount();
|
||||
|
@ -1023,26 +1024,26 @@ public final class PainlessLookupBuilder {
|
|||
|
||||
if (isValidType(typeParameter) == false) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " +
|
||||
"for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
|
||||
Class<?> javaTypeParameter = javaConstructor.getParameterTypes()[typeParameterIndex];
|
||||
|
||||
if (isValidType(javaTypeParameter) == false) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " +
|
||||
"for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
|
||||
if (javaTypeParameter != typeToJavaType(typeParameter)) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(javaTypeParameter) + "] " +
|
||||
"does not match the specified type parameter [" + typeToCanonicalTypeName(typeParameter) + "] " +
|
||||
"for binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (METHOD_NAME_PATTERN.matcher(methodName).matches() == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid method name [" + methodName + "] for binding [" + targetCanonicalClassName + "].");
|
||||
"invalid method name [" + methodName + "] for class binding [" + targetCanonicalClassName + "].");
|
||||
}
|
||||
|
||||
Method[] javaMethods = targetClass.getMethods();
|
||||
|
@ -1051,7 +1052,7 @@ public final class PainlessLookupBuilder {
|
|||
for (Method eachJavaMethod : javaMethods) {
|
||||
if (eachJavaMethod.getDeclaringClass() == targetClass) {
|
||||
if (javaMethod != null) {
|
||||
throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] cannot have multiple methods");
|
||||
throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] cannot have multiple methods");
|
||||
}
|
||||
|
||||
javaMethod = eachJavaMethod;
|
||||
|
@ -1059,7 +1060,7 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
|
||||
if (javaMethod == null) {
|
||||
throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] must have exactly one method");
|
||||
throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] must have exactly one method");
|
||||
}
|
||||
|
||||
int methodTypeParametersSize = javaMethod.getParameterCount();
|
||||
|
@ -1069,60 +1070,60 @@ public final class PainlessLookupBuilder {
|
|||
|
||||
if (isValidType(typeParameter) == false) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " +
|
||||
"for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
|
||||
Class<?> javaTypeParameter = javaMethod.getParameterTypes()[typeParameterIndex];
|
||||
|
||||
if (isValidType(javaTypeParameter) == false) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " +
|
||||
"for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
|
||||
if (javaTypeParameter != typeToJavaType(typeParameter)) {
|
||||
throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(javaTypeParameter) + "] " +
|
||||
"does not match the specified type parameter [" + typeToCanonicalTypeName(typeParameter) + "] " +
|
||||
"for binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
"for class binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (javaMethod.getReturnType() != typeToJavaType(returnType)) {
|
||||
throw new IllegalArgumentException("return type [" + typeToCanonicalTypeName(javaMethod.getReturnType()) + "] " +
|
||||
"does not match the specified returned type [" + typeToCanonicalTypeName(returnType) + "] " +
|
||||
"for binding [[" + targetClass.getCanonicalName() + "], [" + methodName + "], " +
|
||||
"for class binding [[" + targetClass.getCanonicalName() + "], [" + methodName + "], " +
|
||||
typesToCanonicalTypeNames(typeParameters) + "]");
|
||||
}
|
||||
|
||||
String painlessMethodKey = buildPainlessMethodKey(methodName, constructorTypeParametersSize + methodTypeParametersSize);
|
||||
|
||||
if (painlessMethodKeysToImportedPainlessMethods.containsKey(painlessMethodKey)) {
|
||||
throw new IllegalArgumentException("binding and imported method cannot have the same name [" + methodName + "]");
|
||||
throw new IllegalArgumentException("class binding and imported method cannot have the same name [" + methodName + "]");
|
||||
}
|
||||
|
||||
PainlessBinding painlessBinding = painlessMethodKeysToPainlessBindings.get(painlessMethodKey);
|
||||
PainlessClassBinding painlessClassBinding = painlessMethodKeysToPainlessClassBindings.get(painlessMethodKey);
|
||||
|
||||
if (painlessBinding == null) {
|
||||
if (painlessClassBinding == null) {
|
||||
Constructor<?> finalJavaConstructor = javaConstructor;
|
||||
Method finalJavaMethod = javaMethod;
|
||||
|
||||
painlessBinding = painlessBindingCache.computeIfAbsent(
|
||||
new PainlessBindingCacheKey(targetClass, methodName, returnType, typeParameters),
|
||||
key -> new PainlessBinding(finalJavaConstructor, finalJavaMethod, returnType, typeParameters));
|
||||
painlessClassBinding = painlessClassBindingCache.computeIfAbsent(
|
||||
new PainlessClassBindingCacheKey(targetClass, methodName, returnType, typeParameters),
|
||||
key -> new PainlessClassBinding(finalJavaConstructor, finalJavaMethod, returnType, typeParameters));
|
||||
|
||||
painlessMethodKeysToPainlessBindings.put(painlessMethodKey, painlessBinding);
|
||||
} else if (painlessBinding.javaConstructor.equals(javaConstructor) == false ||
|
||||
painlessBinding.javaMethod.equals(javaMethod) == false ||
|
||||
painlessBinding.returnType != returnType ||
|
||||
painlessBinding.typeParameters.equals(typeParameters) == false) {
|
||||
throw new IllegalArgumentException("cannot have bindings " +
|
||||
painlessMethodKeysToPainlessClassBindings.put(painlessMethodKey, painlessClassBinding);
|
||||
} else if (painlessClassBinding.javaConstructor.equals(javaConstructor) == false ||
|
||||
painlessClassBinding.javaMethod.equals(javaMethod) == false ||
|
||||
painlessClassBinding.returnType != returnType ||
|
||||
painlessClassBinding.typeParameters.equals(typeParameters) == false) {
|
||||
throw new IllegalArgumentException("cannot have class bindings " +
|
||||
"[[" + targetCanonicalClassName + "], " +
|
||||
"[" + methodName + "], " +
|
||||
"[" + typeToCanonicalTypeName(returnType) + "], " +
|
||||
typesToCanonicalTypeNames(typeParameters) + "] and " +
|
||||
"[[" + targetCanonicalClassName + "], " +
|
||||
"[" + methodName + "], " +
|
||||
"[" + typeToCanonicalTypeName(painlessBinding.returnType) + "], " +
|
||||
typesToCanonicalTypeNames(painlessBinding.typeParameters) + "] and " +
|
||||
"[" + typeToCanonicalTypeName(painlessClassBinding.returnType) + "], " +
|
||||
typesToCanonicalTypeNames(painlessClassBinding.typeParameters) + "] and " +
|
||||
"with the same name and arity but different constructors or methods");
|
||||
}
|
||||
}
|
||||
|
@ -1139,7 +1140,7 @@ public final class PainlessLookupBuilder {
|
|||
}
|
||||
|
||||
return new PainlessLookup(canonicalClassNamesToClasses, classesToPainlessClasses,
|
||||
painlessMethodKeysToImportedPainlessMethods, painlessMethodKeysToPainlessBindings);
|
||||
painlessMethodKeysToImportedPainlessMethods, painlessMethodKeysToPainlessClassBindings);
|
||||
}
|
||||
|
||||
private void copyPainlessClassMembers() {
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.elasticsearch.painless.Locals;
|
|||
import org.elasticsearch.painless.Locals.LocalMethod;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.lookup.PainlessBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessClassBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.Type;
|
||||
|
@ -45,9 +45,9 @@ public final class ECallLocal extends AExpression {
|
|||
private final String name;
|
||||
private final List<AExpression> arguments;
|
||||
|
||||
private LocalMethod method = null;
|
||||
private PainlessMethod imported = null;
|
||||
private PainlessBinding binding = null;
|
||||
private LocalMethod localMethod = null;
|
||||
private PainlessMethod importedMethod = null;
|
||||
private PainlessClassBinding classBinding = null;
|
||||
|
||||
public ECallLocal(Location location, String name, List<AExpression> arguments) {
|
||||
super(location);
|
||||
|
@ -65,15 +65,15 @@ public final class ECallLocal extends AExpression {
|
|||
|
||||
@Override
|
||||
void analyze(Locals locals) {
|
||||
method = locals.getMethod(name, arguments.size());
|
||||
localMethod = locals.getMethod(name, arguments.size());
|
||||
|
||||
if (method == null) {
|
||||
imported = locals.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size());
|
||||
if (localMethod == null) {
|
||||
importedMethod = locals.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size());
|
||||
|
||||
if (imported == null) {
|
||||
binding = locals.getPainlessLookup().lookupPainlessBinding(name, arguments.size());
|
||||
if (importedMethod == null) {
|
||||
classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size());
|
||||
|
||||
if (binding == null) {
|
||||
if (classBinding == null) {
|
||||
throw createError(
|
||||
new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() + "] arguments."));
|
||||
}
|
||||
|
@ -82,15 +82,15 @@ public final class ECallLocal extends AExpression {
|
|||
|
||||
List<Class<?>> typeParameters;
|
||||
|
||||
if (method != null) {
|
||||
typeParameters = new ArrayList<>(method.typeParameters);
|
||||
actual = method.returnType;
|
||||
} else if (imported != null) {
|
||||
typeParameters = new ArrayList<>(imported.typeParameters);
|
||||
actual = imported.returnType;
|
||||
} else if (binding != null) {
|
||||
typeParameters = new ArrayList<>(binding.typeParameters);
|
||||
actual = binding.returnType;
|
||||
if (localMethod != null) {
|
||||
typeParameters = new ArrayList<>(localMethod.typeParameters);
|
||||
actual = localMethod.returnType;
|
||||
} else if (importedMethod != null) {
|
||||
typeParameters = new ArrayList<>(importedMethod.typeParameters);
|
||||
actual = importedMethod.returnType;
|
||||
} else if (classBinding != null) {
|
||||
typeParameters = new ArrayList<>(classBinding.typeParameters);
|
||||
actual = classBinding.returnType;
|
||||
} else {
|
||||
throw new IllegalStateException("Illegal tree structure.");
|
||||
}
|
||||
|
@ -111,23 +111,23 @@ public final class ECallLocal extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
writer.writeDebugInfo(location);
|
||||
|
||||
if (method != null) {
|
||||
if (localMethod != null) {
|
||||
for (AExpression argument : arguments) {
|
||||
argument.write(writer, globals);
|
||||
}
|
||||
|
||||
writer.invokeStatic(CLASS_TYPE, new Method(method.name, method.methodType.toMethodDescriptorString()));
|
||||
} else if (imported != null) {
|
||||
writer.invokeStatic(CLASS_TYPE, new Method(localMethod.name, localMethod.methodType.toMethodDescriptorString()));
|
||||
} else if (importedMethod != null) {
|
||||
for (AExpression argument : arguments) {
|
||||
argument.write(writer, globals);
|
||||
}
|
||||
|
||||
writer.invokeStatic(Type.getType(imported.targetClass),
|
||||
new Method(imported.javaMethod.getName(), imported.methodType.toMethodDescriptorString()));
|
||||
} else if (binding != null) {
|
||||
String name = globals.addBinding(binding.javaConstructor.getDeclaringClass());
|
||||
Type type = Type.getType(binding.javaConstructor.getDeclaringClass());
|
||||
int javaConstructorParameterCount = binding.javaConstructor.getParameterCount();
|
||||
writer.invokeStatic(Type.getType(importedMethod.targetClass),
|
||||
new Method(importedMethod.javaMethod.getName(), importedMethod.methodType.toMethodDescriptorString()));
|
||||
} else if (classBinding != null) {
|
||||
String name = globals.addBinding(classBinding.javaConstructor.getDeclaringClass());
|
||||
Type type = Type.getType(classBinding.javaConstructor.getDeclaringClass());
|
||||
int javaConstructorParameterCount = classBinding.javaConstructor.getParameterCount();
|
||||
|
||||
Label nonNull = new Label();
|
||||
|
||||
|
@ -142,18 +142,18 @@ public final class ECallLocal extends AExpression {
|
|||
arguments.get(argument).write(writer, globals);
|
||||
}
|
||||
|
||||
writer.invokeConstructor(type, Method.getMethod(binding.javaConstructor));
|
||||
writer.invokeConstructor(type, Method.getMethod(classBinding.javaConstructor));
|
||||
writer.putField(CLASS_TYPE, name, type);
|
||||
|
||||
writer.mark(nonNull);
|
||||
writer.loadThis();
|
||||
writer.getField(CLASS_TYPE, name, type);
|
||||
|
||||
for (int argument = 0; argument < binding.javaMethod.getParameterCount(); ++argument) {
|
||||
for (int argument = 0; argument < classBinding.javaMethod.getParameterCount(); ++argument) {
|
||||
arguments.get(argument + javaConstructorParameterCount).write(writer, globals);
|
||||
}
|
||||
|
||||
writer.invokeVirtual(type, Method.getMethod(binding.javaMethod));
|
||||
writer.invokeVirtual(type, Method.getMethod(classBinding.javaMethod));
|
||||
} else {
|
||||
throw new IllegalStateException("Illegal tree structure.");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue