Painless: Clean Up PainlessClass Variables (#32380)
Removes the variables name, clazz, and type as they are unnecessary. Renames staticMembers -> staticFields, members -> fields, getters -> getterMethodHandles, and setters -> setterMethodHandles.
This commit is contained in:
parent
3b050194f9
commit
df579f8bce
|
@ -19,11 +19,11 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.spi;
|
package org.elasticsearch.painless.spi;
|
||||||
|
|
||||||
|
import org.elasticsearch.script.ScriptContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.elasticsearch.script.ScriptContext;
|
|
||||||
|
|
||||||
public interface PainlessExtension {
|
public interface PainlessExtension {
|
||||||
|
|
||||||
Map<ScriptContext<?>, List<Whitelist>> getContextWhitelists();
|
Map<ScriptContext<?>, List<Whitelist>> getContextWhitelists();
|
||||||
|
|
|
@ -421,7 +421,7 @@ public final class Def {
|
||||||
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(clazz);
|
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(clazz);
|
||||||
|
|
||||||
if (struct != null) {
|
if (struct != null) {
|
||||||
MethodHandle handle = struct.getters.get(name);
|
MethodHandle handle = struct.getterMethodHandles.get(name);
|
||||||
if (handle != null) {
|
if (handle != null) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -431,7 +431,7 @@ public final class Def {
|
||||||
struct = painlessLookup.getPainlessStructFromJavaClass(iface);
|
struct = painlessLookup.getPainlessStructFromJavaClass(iface);
|
||||||
|
|
||||||
if (struct != null) {
|
if (struct != null) {
|
||||||
MethodHandle handle = struct.getters.get(name);
|
MethodHandle handle = struct.getterMethodHandles.get(name);
|
||||||
if (handle != null) {
|
if (handle != null) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +492,7 @@ public final class Def {
|
||||||
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(clazz);
|
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(clazz);
|
||||||
|
|
||||||
if (struct != null) {
|
if (struct != null) {
|
||||||
MethodHandle handle = struct.setters.get(name);
|
MethodHandle handle = struct.setterMethodHandles.get(name);
|
||||||
if (handle != null) {
|
if (handle != null) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -502,7 +502,7 @@ public final class Def {
|
||||||
struct = painlessLookup.getPainlessStructFromJavaClass(iface);
|
struct = painlessLookup.getPainlessStructFromJavaClass(iface);
|
||||||
|
|
||||||
if (struct != null) {
|
if (struct != null) {
|
||||||
MethodHandle handle = struct.setters.get(name);
|
MethodHandle handle = struct.setterMethodHandles.get(name);
|
||||||
if (handle != null) {
|
if (handle != null) {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.painless;
|
||||||
import org.elasticsearch.painless.api.Debug;
|
import org.elasticsearch.painless.api.Debug;
|
||||||
import org.elasticsearch.painless.lookup.PainlessClass;
|
import org.elasticsearch.painless.lookup.PainlessClass;
|
||||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||||
|
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||||
import org.elasticsearch.script.ScriptException;
|
import org.elasticsearch.script.ScriptException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -58,7 +59,7 @@ public class PainlessExplainError extends Error {
|
||||||
javaClassName = objectToExplain.getClass().getName();
|
javaClassName = objectToExplain.getClass().getName();
|
||||||
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(objectToExplain.getClass());
|
PainlessClass struct = painlessLookup.getPainlessStructFromJavaClass(objectToExplain.getClass());
|
||||||
if (struct != null) {
|
if (struct != null) {
|
||||||
painlessClassName = struct.name;
|
painlessClassName = PainlessLookupUtility.typeToCanonicalTypeName(objectToExplain.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,47 +19,38 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.lookup;
|
package org.elasticsearch.painless.lookup;
|
||||||
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class PainlessClass {
|
public final class PainlessClass {
|
||||||
public final String name;
|
|
||||||
public final Class<?> clazz;
|
|
||||||
public final Type type;
|
|
||||||
|
|
||||||
public final Map<String, PainlessMethod> constructors;
|
public final Map<String, PainlessMethod> constructors;
|
||||||
public final Map<String, PainlessMethod> staticMethods;
|
public final Map<String, PainlessMethod> staticMethods;
|
||||||
public final Map<String, PainlessMethod> methods;
|
public final Map<String, PainlessMethod> methods;
|
||||||
|
|
||||||
public final Map<String, PainlessField> staticMembers;
|
public final Map<String, PainlessField> staticFields;
|
||||||
public final Map<String, PainlessField> members;
|
public final Map<String, PainlessField> fields;
|
||||||
|
|
||||||
public final Map<String, MethodHandle> getters;
|
public final Map<String, MethodHandle> getterMethodHandles;
|
||||||
public final Map<String, MethodHandle> setters;
|
public final Map<String, MethodHandle> setterMethodHandles;
|
||||||
|
|
||||||
public final PainlessMethod functionalMethod;
|
public final PainlessMethod functionalMethod;
|
||||||
|
|
||||||
PainlessClass(String name, Class<?> clazz, Type type,
|
PainlessClass(Map<String, PainlessMethod> constructors,
|
||||||
Map<String, PainlessMethod> constructors, Map<String, PainlessMethod> staticMethods, Map<String, PainlessMethod> methods,
|
Map<String, PainlessMethod> staticMethods, Map<String, PainlessMethod> methods,
|
||||||
Map<String, PainlessField> staticMembers, Map<String, PainlessField> members,
|
Map<String, PainlessField> staticFields, Map<String, PainlessField> fields,
|
||||||
Map<String, MethodHandle> getters, Map<String, MethodHandle> setters,
|
Map<String, MethodHandle> getterMethodHandles, Map<String, MethodHandle> setterMethodHandles,
|
||||||
PainlessMethod functionalMethod) {
|
PainlessMethod functionalMethod) {
|
||||||
this.name = name;
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
this.constructors = Collections.unmodifiableMap(constructors);
|
this.constructors = Collections.unmodifiableMap(constructors);
|
||||||
this.staticMethods = Collections.unmodifiableMap(staticMethods);
|
this.staticMethods = Collections.unmodifiableMap(staticMethods);
|
||||||
this.methods = Collections.unmodifiableMap(methods);
|
this.methods = Collections.unmodifiableMap(methods);
|
||||||
|
|
||||||
this.staticMembers = Collections.unmodifiableMap(staticMembers);
|
this.staticFields = Collections.unmodifiableMap(staticFields);
|
||||||
this.members = Collections.unmodifiableMap(members);
|
this.fields = Collections.unmodifiableMap(fields);
|
||||||
|
|
||||||
this.getters = Collections.unmodifiableMap(getters);
|
this.getterMethodHandles = Collections.unmodifiableMap(getterMethodHandles);
|
||||||
this.setters = Collections.unmodifiableMap(setters);
|
this.setterMethodHandles = Collections.unmodifiableMap(setterMethodHandles);
|
||||||
|
|
||||||
this.functionalMethod = functionalMethod;
|
this.functionalMethod = functionalMethod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,52 +19,39 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless.lookup;
|
package org.elasticsearch.painless.lookup;
|
||||||
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
final class PainlessClassBuilder {
|
final class PainlessClassBuilder {
|
||||||
final String name;
|
|
||||||
final Class<?> clazz;
|
|
||||||
final Type type;
|
|
||||||
|
|
||||||
final Map<String, PainlessMethod> constructors;
|
final Map<String, PainlessMethod> constructors;
|
||||||
final Map<String, PainlessMethod> staticMethods;
|
final Map<String, PainlessMethod> staticMethods;
|
||||||
final Map<String, PainlessMethod> methods;
|
final Map<String, PainlessMethod> methods;
|
||||||
|
|
||||||
final Map<String, PainlessField> staticMembers;
|
final Map<String, PainlessField> staticFields;
|
||||||
final Map<String, PainlessField> members;
|
final Map<String, PainlessField> fields;
|
||||||
|
|
||||||
final Map<String, MethodHandle> getters;
|
final Map<String, MethodHandle> getterMethodHandles;
|
||||||
final Map<String, MethodHandle> setters;
|
final Map<String, MethodHandle> setterMethodHandles;
|
||||||
|
|
||||||
PainlessMethod functionalMethod;
|
PainlessMethod functionalMethod;
|
||||||
|
|
||||||
PainlessClassBuilder(String name, Class<?> clazz, Type type) {
|
PainlessClassBuilder() {
|
||||||
this.name = name;
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
constructors = new HashMap<>();
|
constructors = new HashMap<>();
|
||||||
staticMethods = new HashMap<>();
|
staticMethods = new HashMap<>();
|
||||||
methods = new HashMap<>();
|
methods = new HashMap<>();
|
||||||
|
|
||||||
staticMembers = new HashMap<>();
|
staticFields = new HashMap<>();
|
||||||
members = new HashMap<>();
|
fields = new HashMap<>();
|
||||||
|
|
||||||
getters = new HashMap<>();
|
getterMethodHandles = new HashMap<>();
|
||||||
setters = new HashMap<>();
|
setterMethodHandles = new HashMap<>();
|
||||||
|
|
||||||
functionalMethod = null;
|
functionalMethod = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
PainlessClass build() {
|
PainlessClass build() {
|
||||||
return new PainlessClass(name, clazz, type,
|
return new PainlessClass(constructors, staticMethods, methods, staticFields, fields,
|
||||||
constructors, staticMethods, methods,
|
getterMethodHandles, setterMethodHandles, functionalMethod);
|
||||||
staticMembers, members,
|
|
||||||
getters, setters,
|
|
||||||
functionalMethod);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public final class PainlessLookup {
|
public final class PainlessLookup {
|
||||||
|
|
||||||
public Collection<PainlessClass> getStructs() {
|
public Collection<Class<?>> getStructs() {
|
||||||
return classesToPainlessClasses.values();
|
return classesToPainlessClasses.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Class<?>> canonicalClassNamesToClasses;
|
private final Map<String, Class<?>> canonicalClassNamesToClasses;
|
||||||
|
|
|
@ -179,8 +179,7 @@ public class PainlessLookupBuilder {
|
||||||
classesToPainlessClassBuilders = new HashMap<>();
|
classesToPainlessClassBuilders = new HashMap<>();
|
||||||
|
|
||||||
canonicalClassNamesToClasses.put(DEF_CLASS_NAME, def.class);
|
canonicalClassNamesToClasses.put(DEF_CLASS_NAME, def.class);
|
||||||
classesToPainlessClassBuilders.put(def.class,
|
classesToPainlessClassBuilders.put(def.class, new PainlessClassBuilder());
|
||||||
new PainlessClassBuilder(DEF_CLASS_NAME, Object.class, org.objectweb.asm.Type.getType(Object.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> canonicalTypeNameToType(String canonicalTypeName) {
|
private Class<?> canonicalTypeNameToType(String canonicalTypeName) {
|
||||||
|
@ -234,17 +233,21 @@ public class PainlessLookupBuilder {
|
||||||
throw new IllegalArgumentException("invalid class name [" + canonicalClassName + "]");
|
throw new IllegalArgumentException("invalid class name [" + canonicalClassName + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Class<?> existingClass = canonicalClassNamesToClasses.get(typeToCanonicalTypeName(clazz));
|
||||||
|
|
||||||
|
if (existingClass != null && existingClass != clazz) {
|
||||||
|
throw new IllegalArgumentException("class [" + canonicalClassName + "] " +
|
||||||
|
"cannot represent multiple java classes with the same name from different class loaders");
|
||||||
|
}
|
||||||
|
|
||||||
PainlessClassBuilder existingPainlessClassBuilder = classesToPainlessClassBuilders.get(clazz);
|
PainlessClassBuilder existingPainlessClassBuilder = classesToPainlessClassBuilders.get(clazz);
|
||||||
|
|
||||||
if (existingPainlessClassBuilder == null) {
|
if (existingPainlessClassBuilder == null) {
|
||||||
PainlessClassBuilder painlessClassBuilder =
|
PainlessClassBuilder painlessClassBuilder = new PainlessClassBuilder();
|
||||||
new PainlessClassBuilder(canonicalClassName, clazz, org.objectweb.asm.Type.getType(clazz));
|
|
||||||
|
|
||||||
canonicalClassNamesToClasses.put(canonicalClassName, clazz);
|
canonicalClassNamesToClasses.put(canonicalClassName, clazz);
|
||||||
classesToPainlessClassBuilders.put(clazz, painlessClassBuilder);
|
classesToPainlessClassBuilders.put(clazz, painlessClassBuilder);
|
||||||
} else if (existingPainlessClassBuilder.clazz.equals(clazz) == false) {
|
|
||||||
throw new IllegalArgumentException("class [" + canonicalClassName + "] " +
|
|
||||||
"cannot represent multiple java classes with the same name from different class loaders");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String javaClassName = clazz.getName();
|
String javaClassName = clazz.getName();
|
||||||
|
@ -265,7 +268,7 @@ public class PainlessLookupBuilder {
|
||||||
|
|
||||||
canonicalClassNamesToClasses.put(importedCanonicalClassName, clazz);
|
canonicalClassNamesToClasses.put(importedCanonicalClassName, clazz);
|
||||||
}
|
}
|
||||||
} else if (importedPainlessClass.equals(clazz) == false) {
|
} else if (importedPainlessClass != clazz) {
|
||||||
throw new IllegalArgumentException("imported class [" + importedCanonicalClassName + "] cannot represent multiple " +
|
throw new IllegalArgumentException("imported class [" + importedCanonicalClassName + "] cannot represent multiple " +
|
||||||
"classes [" + canonicalClassName + "] and [" + typeToCanonicalTypeName(importedPainlessClass) + "]");
|
"classes [" + canonicalClassName + "] and [" + typeToCanonicalTypeName(importedPainlessClass) + "]");
|
||||||
} else if (importClassName == false) {
|
} else if (importClassName == false) {
|
||||||
|
@ -504,10 +507,10 @@ public class PainlessLookupBuilder {
|
||||||
|
|
||||||
if (painlessMethod == null) {
|
if (painlessMethod == null) {
|
||||||
org.objectweb.asm.commons.Method asmMethod = org.objectweb.asm.commons.Method.getMethod(javaMethod);
|
org.objectweb.asm.commons.Method asmMethod = org.objectweb.asm.commons.Method.getMethod(javaMethod);
|
||||||
MethodHandle javaMethodHandle;
|
MethodHandle methodHandle;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
javaMethodHandle = MethodHandles.publicLookup().in(targetClass).unreflect(javaMethod);
|
methodHandle = MethodHandles.publicLookup().in(targetClass).unreflect(javaMethod);
|
||||||
} catch (IllegalAccessException iae) {
|
} catch (IllegalAccessException iae) {
|
||||||
throw new IllegalArgumentException("static method handle [[" + targetClass.getCanonicalName() + "], " +
|
throw new IllegalArgumentException("static method handle [[" + targetClass.getCanonicalName() + "], " +
|
||||||
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
|
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
|
||||||
|
@ -516,7 +519,7 @@ public class PainlessLookupBuilder {
|
||||||
painlessMethod = painlessMethodCache.computeIfAbsent(
|
painlessMethod = painlessMethodCache.computeIfAbsent(
|
||||||
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
|
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
|
||||||
key -> new PainlessMethod(methodName, targetClass, null, returnType,
|
key -> new PainlessMethod(methodName, targetClass, null, returnType,
|
||||||
typeParameters, asmMethod, javaMethod.getModifiers(), javaMethodHandle));
|
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
|
||||||
|
|
||||||
painlessClassBuilder.staticMethods.put(painlessMethodKey, painlessMethod);
|
painlessClassBuilder.staticMethods.put(painlessMethodKey, painlessMethod);
|
||||||
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
|
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
|
||||||
|
@ -535,18 +538,18 @@ public class PainlessLookupBuilder {
|
||||||
|
|
||||||
if (painlessMethod == null) {
|
if (painlessMethod == null) {
|
||||||
org.objectweb.asm.commons.Method asmMethod = org.objectweb.asm.commons.Method.getMethod(javaMethod);
|
org.objectweb.asm.commons.Method asmMethod = org.objectweb.asm.commons.Method.getMethod(javaMethod);
|
||||||
MethodHandle javaMethodHandle;
|
MethodHandle methodHandle;
|
||||||
|
|
||||||
if (augmentedClass == null) {
|
if (augmentedClass == null) {
|
||||||
try {
|
try {
|
||||||
javaMethodHandle = MethodHandles.publicLookup().in(targetClass).unreflect(javaMethod);
|
methodHandle = MethodHandles.publicLookup().in(targetClass).unreflect(javaMethod);
|
||||||
} catch (IllegalAccessException iae) {
|
} catch (IllegalAccessException iae) {
|
||||||
throw new IllegalArgumentException("method handle [[" + targetClass.getCanonicalName() + "], " +
|
throw new IllegalArgumentException("method handle [[" + targetClass.getCanonicalName() + "], " +
|
||||||
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
|
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
javaMethodHandle = MethodHandles.publicLookup().in(augmentedClass).unreflect(javaMethod);
|
methodHandle = MethodHandles.publicLookup().in(augmentedClass).unreflect(javaMethod);
|
||||||
} catch (IllegalAccessException iae) {
|
} catch (IllegalAccessException iae) {
|
||||||
throw new IllegalArgumentException("method handle [[" + targetClass.getCanonicalName() + "], " +
|
throw new IllegalArgumentException("method handle [[" + targetClass.getCanonicalName() + "], " +
|
||||||
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found " +
|
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found " +
|
||||||
|
@ -557,7 +560,7 @@ public class PainlessLookupBuilder {
|
||||||
painlessMethod = painlessMethodCache.computeIfAbsent(
|
painlessMethod = painlessMethodCache.computeIfAbsent(
|
||||||
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
|
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
|
||||||
key -> new PainlessMethod(methodName, targetClass, augmentedClass, returnType,
|
key -> new PainlessMethod(methodName, targetClass, augmentedClass, returnType,
|
||||||
typeParameters, asmMethod, javaMethod.getModifiers(), javaMethodHandle));
|
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
|
||||||
|
|
||||||
painlessClassBuilder.methods.put(painlessMethodKey, painlessMethod);
|
painlessClassBuilder.methods.put(painlessMethodKey, painlessMethod);
|
||||||
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
|
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
|
||||||
|
@ -650,7 +653,7 @@ public class PainlessLookupBuilder {
|
||||||
throw new IllegalArgumentException("static field [[" + targetCanonicalClassName + "]. [" + fieldName + "]] must be final");
|
throw new IllegalArgumentException("static field [[" + targetCanonicalClassName + "]. [" + fieldName + "]] must be final");
|
||||||
}
|
}
|
||||||
|
|
||||||
PainlessField painlessField = painlessClassBuilder.staticMembers.get(painlessFieldKey);
|
PainlessField painlessField = painlessClassBuilder.staticFields.get(painlessFieldKey);
|
||||||
|
|
||||||
if (painlessField == null) {
|
if (painlessField == null) {
|
||||||
painlessField = painlessFieldCache.computeIfAbsent(
|
painlessField = painlessFieldCache.computeIfAbsent(
|
||||||
|
@ -658,7 +661,7 @@ public class PainlessLookupBuilder {
|
||||||
key -> new PainlessField(fieldName, javaField.getName(), targetClass,
|
key -> new PainlessField(fieldName, javaField.getName(), targetClass,
|
||||||
typeParameter, javaField.getModifiers(), null, null));
|
typeParameter, javaField.getModifiers(), null, null));
|
||||||
|
|
||||||
painlessClassBuilder.staticMembers.put(painlessFieldKey, painlessField);
|
painlessClassBuilder.staticFields.put(painlessFieldKey, painlessField);
|
||||||
} else if (painlessField.clazz != typeParameter) {
|
} else if (painlessField.clazz != typeParameter) {
|
||||||
throw new IllegalArgumentException("cannot have static fields " +
|
throw new IllegalArgumentException("cannot have static fields " +
|
||||||
"[[" + targetCanonicalClassName + "], [" + fieldName + "], [" +
|
"[[" + targetCanonicalClassName + "], [" + fieldName + "], [" +
|
||||||
|
@ -674,7 +677,7 @@ public class PainlessLookupBuilder {
|
||||||
methodHandleGetter = MethodHandles.publicLookup().unreflectGetter(javaField);
|
methodHandleGetter = MethodHandles.publicLookup().unreflectGetter(javaField);
|
||||||
} catch (IllegalAccessException iae) {
|
} catch (IllegalAccessException iae) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"method handle getter not found for field [[" + targetCanonicalClassName + "], [" + fieldName + "]]");
|
"getter method handle not found for field [[" + targetCanonicalClassName + "], [" + fieldName + "]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodHandle methodHandleSetter;
|
MethodHandle methodHandleSetter;
|
||||||
|
@ -683,10 +686,10 @@ public class PainlessLookupBuilder {
|
||||||
methodHandleSetter = MethodHandles.publicLookup().unreflectSetter(javaField);
|
methodHandleSetter = MethodHandles.publicLookup().unreflectSetter(javaField);
|
||||||
} catch (IllegalAccessException iae) {
|
} catch (IllegalAccessException iae) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"method handle setter not found for field [[" + targetCanonicalClassName + "], [" + fieldName + "]]");
|
"setter method handle not found for field [[" + targetCanonicalClassName + "], [" + fieldName + "]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
PainlessField painlessField = painlessClassBuilder.members.get(painlessFieldKey);
|
PainlessField painlessField = painlessClassBuilder.fields.get(painlessFieldKey);
|
||||||
|
|
||||||
if (painlessField == null) {
|
if (painlessField == null) {
|
||||||
painlessField = painlessFieldCache.computeIfAbsent(
|
painlessField = painlessFieldCache.computeIfAbsent(
|
||||||
|
@ -694,7 +697,7 @@ public class PainlessLookupBuilder {
|
||||||
key -> new PainlessField(fieldName, javaField.getName(), targetClass,
|
key -> new PainlessField(fieldName, javaField.getName(), targetClass,
|
||||||
typeParameter, javaField.getModifiers(), methodHandleGetter, methodHandleSetter));
|
typeParameter, javaField.getModifiers(), methodHandleGetter, methodHandleSetter));
|
||||||
|
|
||||||
painlessClassBuilder.members.put(fieldName, painlessField);
|
painlessClassBuilder.fields.put(fieldName, painlessField);
|
||||||
} else if (painlessField.clazz != typeParameter) {
|
} else if (painlessField.clazz != typeParameter) {
|
||||||
throw new IllegalArgumentException("cannot have fields " +
|
throw new IllegalArgumentException("cannot have fields " +
|
||||||
"[[" + targetCanonicalClassName + "], [" + fieldName + "], [" +
|
"[[" + targetCanonicalClassName + "], [" + fieldName + "], [" +
|
||||||
|
@ -771,14 +774,14 @@ public class PainlessLookupBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, PainlessField> painlessFieldEntry : originalPainlessClassBuilder.members.entrySet()) {
|
for (Map.Entry<String, PainlessField> painlessFieldEntry : originalPainlessClassBuilder.fields.entrySet()) {
|
||||||
String painlessFieldKey = painlessFieldEntry.getKey();
|
String painlessFieldKey = painlessFieldEntry.getKey();
|
||||||
PainlessField newPainlessField = painlessFieldEntry.getValue();
|
PainlessField newPainlessField = painlessFieldEntry.getValue();
|
||||||
PainlessField existingPainlessField = targetPainlessClassBuilder.members.get(painlessFieldKey);
|
PainlessField existingPainlessField = targetPainlessClassBuilder.fields.get(painlessFieldKey);
|
||||||
|
|
||||||
if (existingPainlessField == null || existingPainlessField.target != newPainlessField.target &&
|
if (existingPainlessField == null || existingPainlessField.target != newPainlessField.target &&
|
||||||
existingPainlessField.target.isAssignableFrom(newPainlessField.target)) {
|
existingPainlessField.target.isAssignableFrom(newPainlessField.target)) {
|
||||||
targetPainlessClassBuilder.members.put(painlessFieldKey, newPainlessField);
|
targetPainlessClassBuilder.fields.put(painlessFieldKey, newPainlessField);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -796,34 +799,32 @@ public class PainlessLookupBuilder {
|
||||||
|
|
||||||
if (typeParametersSize == 0 && methodName.startsWith("get") && methodName.length() > 3 &&
|
if (typeParametersSize == 0 && methodName.startsWith("get") && methodName.length() > 3 &&
|
||||||
Character.isUpperCase(methodName.charAt(3))) {
|
Character.isUpperCase(methodName.charAt(3))) {
|
||||||
painlessClassBuilder.getters.putIfAbsent(
|
painlessClassBuilder.getterMethodHandles.putIfAbsent(
|
||||||
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4), painlessMethod.handle);
|
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4), painlessMethod.handle);
|
||||||
} else if (typeParametersSize == 0 && methodName.startsWith("is") && methodName.length() > 2 &&
|
} else if (typeParametersSize == 0 && methodName.startsWith("is") && methodName.length() > 2 &&
|
||||||
Character.isUpperCase(methodName.charAt(2))) {
|
Character.isUpperCase(methodName.charAt(2))) {
|
||||||
painlessClassBuilder.getters.putIfAbsent(
|
painlessClassBuilder.getterMethodHandles.putIfAbsent(
|
||||||
Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3), painlessMethod.handle);
|
Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3), painlessMethod.handle);
|
||||||
} else if (typeParametersSize == 1 && methodName.startsWith("set") && methodName.length() > 3 &&
|
} else if (typeParametersSize == 1 && methodName.startsWith("set") && methodName.length() > 3 &&
|
||||||
Character.isUpperCase(methodName.charAt(3))) {
|
Character.isUpperCase(methodName.charAt(3))) {
|
||||||
painlessClassBuilder.setters.putIfAbsent(
|
painlessClassBuilder.setterMethodHandles.putIfAbsent(
|
||||||
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4), painlessMethod.handle);
|
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4), painlessMethod.handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PainlessField painlessField : painlessClassBuilder.members.values()) {
|
for (PainlessField painlessField : painlessClassBuilder.fields.values()) {
|
||||||
painlessClassBuilder.getters.put(painlessField.name, painlessField.getter);
|
painlessClassBuilder.getterMethodHandles.put(painlessField.name, painlessField.getter);
|
||||||
painlessClassBuilder.setters.put(painlessField.name, painlessField.setter);
|
painlessClassBuilder.setterMethodHandles.put(painlessField.name, painlessField.setter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFunctionalInterfaceMethods() {
|
private void setFunctionalInterfaceMethods() {
|
||||||
for (Map.Entry<Class<?>, PainlessClassBuilder> painlessClassBuilderEntry : classesToPainlessClassBuilders.entrySet()) {
|
for (Map.Entry<Class<?>, PainlessClassBuilder> painlessClassBuilderEntry : classesToPainlessClassBuilders.entrySet()) {
|
||||||
setFunctionalInterfaceMethod(painlessClassBuilderEntry.getValue());
|
setFunctionalInterfaceMethod(painlessClassBuilderEntry.getKey(), painlessClassBuilderEntry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFunctionalInterfaceMethod(PainlessClassBuilder painlessClassBuilder) {
|
private void setFunctionalInterfaceMethod(Class<?> targetClass, PainlessClassBuilder painlessClassBuilder) {
|
||||||
Class<?> targetClass = painlessClassBuilder.clazz;
|
|
||||||
|
|
||||||
if (targetClass.isInterface()) {
|
if (targetClass.isInterface()) {
|
||||||
List<java.lang.reflect.Method> javaMethods = new ArrayList<>();
|
List<java.lang.reflect.Method> javaMethods = new ArrayList<>();
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,8 @@ public final class ENewObj extends AExpression {
|
||||||
constructor.arguments.toArray(types);
|
constructor.arguments.toArray(types);
|
||||||
|
|
||||||
if (constructor.arguments.size() != arguments.size()) {
|
if (constructor.arguments.size() != arguments.size()) {
|
||||||
throw createError(new IllegalArgumentException("When calling constructor on type [" + struct.name + "]" +
|
throw createError(new IllegalArgumentException(
|
||||||
|
"When calling constructor on type [" + PainlessLookupUtility.typeToCanonicalTypeName(actual) + "] " +
|
||||||
"expected [" + constructor.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
|
"expected [" + constructor.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +88,8 @@ public final class ENewObj extends AExpression {
|
||||||
|
|
||||||
statement = true;
|
statement = true;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Unknown new call on type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException(
|
||||||
|
"Unknown new call on type [" + PainlessLookupUtility.typeToCanonicalTypeName(actual) + "]."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,9 @@ public final class PBrace extends AStoreable {
|
||||||
} else if (prefix.actual == def.class) {
|
} else if (prefix.actual == def.class) {
|
||||||
sub = new PSubDefArray(location, index);
|
sub = new PSubDefArray(location, index);
|
||||||
} else if (Map.class.isAssignableFrom(prefix.actual)) {
|
} else if (Map.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubMapShortcut(location, locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual), index);
|
sub = new PSubMapShortcut(location, prefix.actual, index);
|
||||||
} else if (List.class.isAssignableFrom(prefix.actual)) {
|
} else if (List.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubListShortcut(location, locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual), index);
|
sub = new PSubListShortcut(location, prefix.actual, index);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal array access on type " +
|
throw createError(new IllegalArgumentException("Illegal array access on type " +
|
||||||
"[" + PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual) + "]."));
|
"[" + PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual) + "]."));
|
||||||
|
|
|
@ -84,8 +84,8 @@ public final class PCallInvoke extends AExpression {
|
||||||
} else if (prefix.actual == def.class) {
|
} else if (prefix.actual == def.class) {
|
||||||
sub = new PSubDefCall(location, name, arguments);
|
sub = new PSubDefCall(location, name, arguments);
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException(
|
throw createError(new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() + "] arguments " +
|
||||||
"Unknown call [" + name + "] with [" + arguments.size() + "] arguments on type [" + struct.name + "]."));
|
"on type [" + PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual) + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nullSafe) {
|
if (nullSafe) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public final class PField extends AStoreable {
|
||||||
sub = new PSubDefField(location, value);
|
sub = new PSubDefField(location, value);
|
||||||
} else {
|
} else {
|
||||||
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual);
|
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual);
|
||||||
PainlessField field = prefix instanceof EStatic ? struct.staticMembers.get(value) : struct.members.get(value);
|
PainlessField field = prefix instanceof EStatic ? struct.staticFields.get(value) : struct.fields.get(value);
|
||||||
|
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
sub = new PSubField(location, field);
|
sub = new PSubField(location, field);
|
||||||
|
@ -92,11 +92,11 @@ public final class PField extends AStoreable {
|
||||||
index.analyze(locals);
|
index.analyze(locals);
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(prefix.actual)) {
|
if (Map.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubMapShortcut(location, struct, index);
|
sub = new PSubMapShortcut(location, prefix.actual, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (List.class.isAssignableFrom(prefix.actual)) {
|
if (List.class.isAssignableFrom(prefix.actual)) {
|
||||||
sub = new PSubListShortcut(location, struct, index);
|
sub = new PSubListShortcut(location, prefix.actual, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,16 +36,16 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
final class PSubListShortcut extends AStoreable {
|
final class PSubListShortcut extends AStoreable {
|
||||||
|
|
||||||
private final PainlessClass struct;
|
private final Class<?> targetClass;
|
||||||
private AExpression index;
|
private AExpression index;
|
||||||
|
|
||||||
private PainlessMethod getter;
|
private PainlessMethod getter;
|
||||||
private PainlessMethod setter;
|
private PainlessMethod setter;
|
||||||
|
|
||||||
PSubListShortcut(Location location, PainlessClass struct, AExpression index) {
|
PSubListShortcut(Location location, Class<?> targetClass, AExpression index) {
|
||||||
super(location);
|
super(location);
|
||||||
|
|
||||||
this.struct = Objects.requireNonNull(struct);
|
this.targetClass = Objects.requireNonNull(targetClass);
|
||||||
this.index = Objects.requireNonNull(index);
|
this.index = Objects.requireNonNull(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,16 +56,19 @@ final class PSubListShortcut extends AStoreable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
|
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(targetClass);
|
||||||
|
String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(targetClass);
|
||||||
|
|
||||||
getter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("get", 1));
|
getter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("get", 1));
|
||||||
setter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("set", 2));
|
setter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("set", 2));
|
||||||
|
|
||||||
if (getter != null && (getter.rtn == void.class || getter.arguments.size() != 1 ||
|
if (getter != null && (getter.rtn == void.class || getter.arguments.size() != 1 ||
|
||||||
getter.arguments.get(0) != int.class)) {
|
getter.arguments.get(0) != int.class)) {
|
||||||
throw createError(new IllegalArgumentException("Illegal list get shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal list get shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setter != null && (setter.arguments.size() != 2 || setter.arguments.get(0) != int.class)) {
|
if (setter != null && (setter.arguments.size() != 2 || setter.arguments.get(0) != int.class)) {
|
||||||
throw createError(new IllegalArgumentException("Illegal list set shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal list set shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getter != null && setter != null && (!getter.arguments.get(0).equals(setter.arguments.get(0))
|
if (getter != null && setter != null && (!getter.arguments.get(0).equals(setter.arguments.get(0))
|
||||||
|
@ -80,7 +83,7 @@ final class PSubListShortcut extends AStoreable {
|
||||||
|
|
||||||
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal list shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal list shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,16 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
final class PSubMapShortcut extends AStoreable {
|
final class PSubMapShortcut extends AStoreable {
|
||||||
|
|
||||||
private final PainlessClass struct;
|
private final Class<?> targetClass;
|
||||||
private AExpression index;
|
private AExpression index;
|
||||||
|
|
||||||
private PainlessMethod getter;
|
private PainlessMethod getter;
|
||||||
private PainlessMethod setter;
|
private PainlessMethod setter;
|
||||||
|
|
||||||
PSubMapShortcut(Location location, PainlessClass struct, AExpression index) {
|
PSubMapShortcut(Location location, Class<?> targetClass, AExpression index) {
|
||||||
super(location);
|
super(location);
|
||||||
|
|
||||||
this.struct = Objects.requireNonNull(struct);
|
this.targetClass = Objects.requireNonNull(targetClass);
|
||||||
this.index = Objects.requireNonNull(index);
|
this.index = Objects.requireNonNull(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,15 +55,18 @@ final class PSubMapShortcut extends AStoreable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void analyze(Locals locals) {
|
void analyze(Locals locals) {
|
||||||
|
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(targetClass);
|
||||||
|
String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(targetClass);
|
||||||
|
|
||||||
getter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("get", 1));
|
getter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("get", 1));
|
||||||
setter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("put", 2));
|
setter = struct.methods.get(PainlessLookupUtility.buildPainlessMethodKey("put", 2));
|
||||||
|
|
||||||
if (getter != null && (getter.rtn == void.class || getter.arguments.size() != 1)) {
|
if (getter != null && (getter.rtn == void.class || getter.arguments.size() != 1)) {
|
||||||
throw createError(new IllegalArgumentException("Illegal map get shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal map get shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setter != null && setter.arguments.size() != 2) {
|
if (setter != null && setter.arguments.size() != 2) {
|
||||||
throw createError(new IllegalArgumentException("Illegal map set shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal map set shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getter != null && setter != null &&
|
if (getter != null && setter != null &&
|
||||||
|
@ -78,7 +81,7 @@ final class PSubMapShortcut extends AStoreable {
|
||||||
|
|
||||||
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
actual = setter != null ? setter.arguments.get(1) : getter.rtn;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new IllegalArgumentException("Illegal map shortcut for type [" + struct.name + "]."));
|
throw createError(new IllegalArgumentException("Illegal map shortcut for type [" + canonicalClassName + "]."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||||
|
import org.elasticsearch.painless.lookup.def;
|
||||||
import org.elasticsearch.painless.spi.Whitelist;
|
import org.elasticsearch.painless.spi.Whitelist;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -71,52 +72,54 @@ public class PainlessDocGenerator {
|
||||||
Files.newOutputStream(indexPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE),
|
Files.newOutputStream(indexPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE),
|
||||||
false, StandardCharsets.UTF_8.name())) {
|
false, StandardCharsets.UTF_8.name())) {
|
||||||
emitGeneratedWarning(indexStream);
|
emitGeneratedWarning(indexStream);
|
||||||
List<PainlessClass> structs = PAINLESS_LOOKUP.getStructs().stream().sorted(comparing(t -> t.name)).collect(toList());
|
List<Class<?>> classes = PAINLESS_LOOKUP.getStructs().stream().sorted(comparing(Class::getCanonicalName)).collect(toList());
|
||||||
for (PainlessClass struct : structs) {
|
for (Class<?> clazz : classes) {
|
||||||
if (struct.clazz.isPrimitive()) {
|
PainlessClass struct = PAINLESS_LOOKUP.getPainlessStructFromJavaClass(clazz);
|
||||||
|
String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(clazz);
|
||||||
|
|
||||||
|
if (clazz.isPrimitive()) {
|
||||||
// Primitives don't have methods to reference
|
// Primitives don't have methods to reference
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ("def".equals(struct.name)) {
|
if (clazz == def.class) {
|
||||||
// def is special but doesn't have any methods all of its own.
|
// def is special but doesn't have any methods all of its own.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
indexStream.print("include::");
|
indexStream.print("include::");
|
||||||
indexStream.print(struct.name);
|
indexStream.print(canonicalClassName);
|
||||||
indexStream.println(".asciidoc[]");
|
indexStream.println(".asciidoc[]");
|
||||||
|
|
||||||
Path typePath = apiRootPath.resolve(struct.name + ".asciidoc");
|
Path typePath = apiRootPath.resolve(canonicalClassName + ".asciidoc");
|
||||||
logger.info("Writing [{}.asciidoc]", struct.name);
|
logger.info("Writing [{}.asciidoc]", canonicalClassName);
|
||||||
try (PrintStream typeStream = new PrintStream(
|
try (PrintStream typeStream = new PrintStream(
|
||||||
Files.newOutputStream(typePath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE),
|
Files.newOutputStream(typePath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE),
|
||||||
false, StandardCharsets.UTF_8.name())) {
|
false, StandardCharsets.UTF_8.name())) {
|
||||||
emitGeneratedWarning(typeStream);
|
emitGeneratedWarning(typeStream);
|
||||||
typeStream.print("[[");
|
typeStream.print("[[");
|
||||||
emitAnchor(typeStream, struct.clazz);
|
emitAnchor(typeStream, clazz);
|
||||||
typeStream.print("]]++");
|
typeStream.print("]]++");
|
||||||
typeStream.print(struct.name);
|
typeStream.print(canonicalClassName);
|
||||||
typeStream.println("++::");
|
typeStream.println("++::");
|
||||||
|
|
||||||
Consumer<PainlessField> documentField = field -> PainlessDocGenerator.documentField(typeStream, field);
|
Consumer<PainlessField> documentField = field -> PainlessDocGenerator.documentField(typeStream, field);
|
||||||
Consumer<PainlessMethod> documentMethod = method -> PainlessDocGenerator.documentMethod(typeStream, method);
|
Consumer<PainlessMethod> documentMethod = method -> PainlessDocGenerator.documentMethod(typeStream, method);
|
||||||
struct.staticMembers.values().stream().sorted(FIELD_NAME).forEach(documentField);
|
struct.staticFields.values().stream().sorted(FIELD_NAME).forEach(documentField);
|
||||||
struct.members.values().stream().sorted(FIELD_NAME).forEach(documentField);
|
struct.fields.values().stream().sorted(FIELD_NAME).forEach(documentField);
|
||||||
struct.staticMethods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(documentMethod);
|
struct.staticMethods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(documentMethod);
|
||||||
struct.constructors.values().stream().sorted(NUMBER_OF_ARGS).forEach(documentMethod);
|
struct.constructors.values().stream().sorted(NUMBER_OF_ARGS).forEach(documentMethod);
|
||||||
Map<String, PainlessClass> inherited = new TreeMap<>();
|
Map<String, Class<?>> inherited = new TreeMap<>();
|
||||||
struct.methods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(method -> {
|
struct.methods.values().stream().sorted(METHOD_NAME.thenComparing(NUMBER_OF_ARGS)).forEach(method -> {
|
||||||
if (method.target == struct.clazz) {
|
if (method.target == clazz) {
|
||||||
documentMethod(typeStream, method);
|
documentMethod(typeStream, method);
|
||||||
} else {
|
} else {
|
||||||
PainlessClass painlessClass = PAINLESS_LOOKUP.getPainlessStructFromJavaClass(method.target);
|
inherited.put(canonicalClassName, method.target);
|
||||||
inherited.put(painlessClass.name, painlessClass);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (false == inherited.isEmpty()) {
|
if (false == inherited.isEmpty()) {
|
||||||
typeStream.print("* Inherits methods from ");
|
typeStream.print("* Inherits methods from ");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (PainlessClass inheritsFrom : inherited.values()) {
|
for (Class<?> inheritsFrom : inherited.values()) {
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,7 +245,7 @@ public class PainlessDocGenerator {
|
||||||
an internal link with the text.
|
an internal link with the text.
|
||||||
*/
|
*/
|
||||||
private static void emitType(PrintStream stream, Class<?> clazz) {
|
private static void emitType(PrintStream stream, Class<?> clazz) {
|
||||||
emitStruct(stream, PAINLESS_LOOKUP.getPainlessStructFromJavaClass(clazz));
|
emitStruct(stream, clazz);
|
||||||
while ((clazz = clazz.getComponentType()) != null) {
|
while ((clazz = clazz.getComponentType()) != null) {
|
||||||
stream.print("[]");
|
stream.print("[]");
|
||||||
}
|
}
|
||||||
|
@ -252,15 +255,17 @@ public class PainlessDocGenerator {
|
||||||
* Emit a {@link PainlessClass}. If the {@linkplain PainlessClass} is primitive or def this just emits the name of the struct.
|
* Emit a {@link PainlessClass}. If the {@linkplain PainlessClass} is primitive or def this just emits the name of the struct.
|
||||||
* Otherwise this emits an internal link with the name.
|
* Otherwise this emits an internal link with the name.
|
||||||
*/
|
*/
|
||||||
private static void emitStruct(PrintStream stream, PainlessClass struct) {
|
private static void emitStruct(PrintStream stream, Class<?> clazz) {
|
||||||
if (false == struct.clazz.isPrimitive() && false == struct.name.equals("def")) {
|
String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(clazz);
|
||||||
|
|
||||||
|
if (false == clazz.isPrimitive() && clazz != def.class) {
|
||||||
stream.print("<<");
|
stream.print("<<");
|
||||||
emitAnchor(stream, struct.clazz);
|
emitAnchor(stream, clazz);
|
||||||
stream.print(',');
|
stream.print(',');
|
||||||
stream.print(struct.name);
|
stream.print(canonicalClassName);
|
||||||
stream.print(">>");
|
stream.print(">>");
|
||||||
} else {
|
} else {
|
||||||
stream.print(struct.name);
|
stream.print(canonicalClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,7 @@ public class NodeToStringTests extends ESTestCase {
|
||||||
public void testPSubField() {
|
public void testPSubField() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
PainlessClass s = painlessLookup.getPainlessStructFromJavaClass(Boolean.class);
|
PainlessClass s = painlessLookup.getPainlessStructFromJavaClass(Boolean.class);
|
||||||
PainlessField f = s.staticMembers.get("TRUE");
|
PainlessField f = s.staticFields.get("TRUE");
|
||||||
PSubField node = new PSubField(l, f);
|
PSubField node = new PSubField(l, f);
|
||||||
node.prefix = new EStatic(l, "Boolean");
|
node.prefix = new EStatic(l, "Boolean");
|
||||||
assertEquals("(PSubField (EStatic Boolean) TRUE)", node.toString());
|
assertEquals("(PSubField (EStatic Boolean) TRUE)", node.toString());
|
||||||
|
@ -469,32 +469,28 @@ public class NodeToStringTests extends ESTestCase {
|
||||||
|
|
||||||
public void testPSubListShortcut() {
|
public void testPSubListShortcut() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
PainlessClass s = painlessLookup.getPainlessStructFromJavaClass(List.class);
|
PSubListShortcut node = new PSubListShortcut(l, List.class, new EConstant(l, 1));
|
||||||
PSubListShortcut node = new PSubListShortcut(l, s, new EConstant(l, 1));
|
|
||||||
node.prefix = new EVariable(l, "a");
|
node.prefix = new EVariable(l, "a");
|
||||||
assertEquals("(PSubListShortcut (EVariable a) (EConstant Integer 1))", node.toString());
|
assertEquals("(PSubListShortcut (EVariable a) (EConstant Integer 1))", node.toString());
|
||||||
assertEquals("(PSubNullSafeCallInvoke (PSubListShortcut (EVariable a) (EConstant Integer 1)))",
|
assertEquals("(PSubNullSafeCallInvoke (PSubListShortcut (EVariable a) (EConstant Integer 1)))",
|
||||||
new PSubNullSafeCallInvoke(l, node).toString());
|
new PSubNullSafeCallInvoke(l, node).toString());
|
||||||
|
|
||||||
l = new Location(getTestName(), 0);
|
l = new Location(getTestName(), 0);
|
||||||
s = painlessLookup.getPainlessStructFromJavaClass(List.class);
|
node = new PSubListShortcut(l, List.class, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
||||||
node = new PSubListShortcut(l, s, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
|
||||||
node.prefix = new EVariable(l, "a");
|
node.prefix = new EVariable(l, "a");
|
||||||
assertEquals("(PSubListShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
assertEquals("(PSubListShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPSubMapShortcut() {
|
public void testPSubMapShortcut() {
|
||||||
Location l = new Location(getTestName(), 0);
|
Location l = new Location(getTestName(), 0);
|
||||||
PainlessClass s = painlessLookup.getPainlessStructFromJavaClass(Map.class);
|
PSubMapShortcut node = new PSubMapShortcut(l, Map.class, new EConstant(l, "cat"));
|
||||||
PSubMapShortcut node = new PSubMapShortcut(l, s, new EConstant(l, "cat"));
|
|
||||||
node.prefix = new EVariable(l, "a");
|
node.prefix = new EVariable(l, "a");
|
||||||
assertEquals("(PSubMapShortcut (EVariable a) (EConstant String 'cat'))", node.toString());
|
assertEquals("(PSubMapShortcut (EVariable a) (EConstant String 'cat'))", node.toString());
|
||||||
assertEquals("(PSubNullSafeCallInvoke (PSubMapShortcut (EVariable a) (EConstant String 'cat')))",
|
assertEquals("(PSubNullSafeCallInvoke (PSubMapShortcut (EVariable a) (EConstant String 'cat')))",
|
||||||
new PSubNullSafeCallInvoke(l, node).toString());
|
new PSubNullSafeCallInvoke(l, node).toString());
|
||||||
|
|
||||||
l = new Location(getTestName(), 1);
|
l = new Location(getTestName(), 1);
|
||||||
s = painlessLookup.getPainlessStructFromJavaClass(Map.class);
|
node = new PSubMapShortcut(l, Map.class, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
||||||
node = new PSubMapShortcut(l, s, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
|
||||||
node.prefix = new EVariable(l, "a");
|
node.prefix = new EVariable(l, "a");
|
||||||
assertEquals("(PSubMapShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
assertEquals("(PSubMapShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue