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:
Jack Conradson 2018-09-19 12:19:44 -07:00 committed by GitHub
parent c764012347
commit 3df285d9f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 108 deletions

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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() {}

View File

@ -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;

View File

@ -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) {

View File

@ -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) &&
@ -199,7 +199,7 @@ 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<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() {

View File

@ -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.");
}