Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Painless to Allow Augmentation from Any Class #25360

Merged
merged 2 commits into from
Jun 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,14 @@ public String toString() {
public static class Method {
public final String name;
public final Struct owner;
public final boolean augmentation;
public final Class<?> augmentation;
public final Type rtn;
public final List<Type> arguments;
public final org.objectweb.asm.commons.Method method;
public final int modifiers;
public final MethodHandle handle;

public Method(String name, Struct owner, boolean augmentation, Type rtn, List<Type> arguments,
public Method(String name, Struct owner, Class<?> augmentation, Type rtn, List<Type> arguments,
org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle) {
this.name = name;
this.augmentation = augmentation;
Expand All @@ -232,10 +232,10 @@ public MethodType getMethodType() {
// otherwise compute it
final Class<?> params[];
final Class<?> returnValue;
if (augmentation) {
if (augmentation != null) {
// static method disguised as virtual/interface method
params = new Class<?>[1 + arguments.size()];
params[0] = Augmentation.class;
params[0] = augmentation;
for (int i = 0; i < arguments.size(); i++) {
params[i + 1] = arguments.get(i).clazz;
}
Expand Down Expand Up @@ -268,9 +268,9 @@ public MethodType getMethodType() {

public void write(MethodWriter writer) {
final org.objectweb.asm.Type type;
if (augmentation) {
if (augmentation != null) {
assert java.lang.reflect.Modifier.isStatic(modifiers);
type = WriterConstants.AUGMENTATION_TYPE;
type = org.objectweb.asm.Type.getType(augmentation);
} else {
type = owner.type;
}
Expand Down Expand Up @@ -731,7 +731,7 @@ private void addConstructorInternal(final String struct, final String name, fina
" with arguments " + Arrays.toString(classes) + ".");
}

final Method constructor = new Method(name, owner, false, returnType, Arrays.asList(args), asm, reflect.getModifiers(), handle);
final Method constructor = new Method(name, owner, null, returnType, Arrays.asList(args), asm, reflect.getModifiers(), handle);

owner.constructors.put(methodKey, constructor);
}
Expand Down Expand Up @@ -775,10 +775,14 @@ private void addSignature(String className, String signature) {
}
addConstructorInternal(className, "<init>", args);
} else {
if (methodName.indexOf("*") >= 0) {
addMethodInternal(className, methodName.substring(0, methodName.length() - 1), true, rtn, args);
int index = methodName.lastIndexOf(".");

if (index >= 0) {
String augmentation = methodName.substring(0, index);
methodName = methodName.substring(index + 1);
addMethodInternal(className, methodName, augmentation, rtn, args);
} else {
addMethodInternal(className, methodName, false, rtn, args);
addMethodInternal(className, methodName, null, rtn, args);
}
}
} else {
Expand All @@ -787,8 +791,7 @@ private void addSignature(String className, String signature) {
}
}

private void addMethodInternal(String struct, String name, boolean augmentation,
Type rtn, Type[] args) {
private void addMethodInternal(String struct, String name, String augmentation, Type rtn, Type[] args) {
final Struct owner = structsMap.get(struct);

if (owner == null) {
Expand Down Expand Up @@ -817,14 +820,20 @@ private void addMethodInternal(String struct, String name, boolean augmentation,
final Class<?> implClass;
final Class<?>[] params;

if (augmentation == false) {
if (augmentation == null) {
implClass = owner.clazz;
params = new Class<?>[args.length];
for (int count = 0; count < args.length; ++count) {
params[count] = args[count].clazz;
}
} else {
implClass = Augmentation.class;
try {
implClass = Class.forName(augmentation);
} catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException("Augmentation class [" + augmentation + "]" +
" not found for struct [" + struct + "] using method name [" + name + "].", cnfe);
}

params = new Class<?>[args.length + 1];
params[0] = owner.clazz;
for (int count = 0; count < args.length; ++count) {
Expand Down Expand Up @@ -862,9 +871,10 @@ private void addMethodInternal(String struct, String name, boolean augmentation,
}

final int modifiers = reflect.getModifiers();
final Method method = new Method(name, owner, augmentation, rtn, Arrays.asList(args), asm, modifiers, handle);
final Method method =
new Method(name, owner, augmentation == null ? null : implClass, rtn, Arrays.asList(args), asm, modifiers, handle);

if (augmentation == false && java.lang.reflect.Modifier.isStatic(modifiers)) {
if (augmentation == null && java.lang.reflect.Modifier.isStatic(modifiers)) {
owner.staticMethods.put(methodKey, method);
} else {
owner.methods.put(methodKey, method);
Expand Down Expand Up @@ -966,8 +976,8 @@ private void copyStruct(String struct, List<String> children) {
// TODO: we *have* to remove all these public members and use getter methods to encapsulate!
final Class<?> impl;
final Class<?> arguments[];
if (method.augmentation) {
impl = Augmentation.class;
if (method.augmentation != null) {
impl = method.augmentation;
arguments = new Class<?>[method.arguments.size() + 1];
arguments[0] = method.owner.clazz;
for (int i = 0; i < method.arguments.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.painless;

public class FeatureTestAugmentation {
public static int getTotal(FeatureTest ft) {
return ft.getX() + ft.getY();
}

public static int addToTotal(FeatureTest ft, int add) {
return getTotal(ft) + add;
}

private FeatureTestAugmentation() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ public FunctionRef(Type expected, Method interfaceMethod, Method delegateMethod,
// the Painless$Script class can be inferred if owner is null
if (delegateMethod.owner == null) {
delegateClassName = CLASS_NAME;
} else if (delegateMethod.augmentation) {
delegateClassName = Augmentation.class.getName();
} else if (delegateMethod.augmentation != null) {
delegateClassName = delegateMethod.augmentation.getName();
} else {
delegateClassName = delegateMethod.owner.clazz.getName();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void generateSignature(Definition definition) {

org.objectweb.asm.commons.Method method =
new org.objectweb.asm.commons.Method(name, MethodType.methodType(rtnType.clazz, paramClasses).toMethodDescriptorString());
this.method = new Method(name, null, false, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null);
this.method = new Method(name, null, null, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class CharSequence -> java.lang.CharSequence {
IntStream chars()
IntStream codePoints()
int length()
String replaceAll*(Pattern,Function)
String replaceFirst*(Pattern,Function)
String org.elasticsearch.painless.api.Augmentation.replaceAll(Pattern,Function)
String org.elasticsearch.painless.api.Augmentation.replaceFirst(Pattern,Function)
CharSequence subSequence(int,int)
String toString()
}
Expand All @@ -53,17 +53,17 @@ class Iterable -> java.lang.Iterable {
Iterator iterator()
Spliterator spliterator()
# some adaptations of groovy methods
boolean any*(Predicate)
Collection asCollection*()
List asList*()
def each*(Consumer)
def eachWithIndex*(ObjIntConsumer)
boolean every*(Predicate)
List findResults*(Function)
Map groupBy*(Function)
String join*(String)
double sum*()
double sum*(ToDoubleFunction)
boolean org.elasticsearch.painless.api.Augmentation.any(Predicate)
Collection org.elasticsearch.painless.api.Augmentation.asCollection()
List org.elasticsearch.painless.api.Augmentation.asList()
def org.elasticsearch.painless.api.Augmentation.each(Consumer)
def org.elasticsearch.painless.api.Augmentation.eachWithIndex(ObjIntConsumer)
boolean org.elasticsearch.painless.api.Augmentation.every(Predicate)
List org.elasticsearch.painless.api.Augmentation.findResults(Function)
Map org.elasticsearch.painless.api.Augmentation.groupBy(Function)
String org.elasticsearch.painless.api.Augmentation.join(String)
double org.elasticsearch.painless.api.Augmentation.sum()
double org.elasticsearch.painless.api.Augmentation.sum(ToDoubleFunction)
}

# Readable: i/o
Expand Down Expand Up @@ -756,8 +756,8 @@ class String -> java.lang.String extends CharSequence,Comparable,Object {
boolean contentEquals(CharSequence)
String copyValueOf(char[])
String copyValueOf(char[],int,int)
String decodeBase64*()
String encodeBase64*()
String org.elasticsearch.painless.api.Augmentation.decodeBase64()
String org.elasticsearch.painless.api.Augmentation.encodeBase64()
boolean endsWith(String)
boolean equalsIgnoreCase(String)
String format(Locale,String,def[])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Matcher -> java.util.regex.Matcher extends Object {
boolean find(int)
String group()
String group(int)
String namedGroup*(String)
String org.elasticsearch.painless.api.Augmentation.namedGroup(String)
int groupCount()
boolean hasAnchoringBounds()
boolean hasTransparentBounds()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ class Collection -> java.util.Collection extends Iterable {
def[] toArray(def[])

# some adaptations of groovy methods
List collect*(Function)
def collect*(Collection,Function)
def find*(Predicate)
List findAll*(Predicate)
def findResult*(Function)
def findResult*(def,Function)
List split*(Predicate)
List org.elasticsearch.painless.api.Augmentation.collect(Function)
def org.elasticsearch.painless.api.Augmentation.collect(Collection,Function)
def org.elasticsearch.painless.api.Augmentation.find(Predicate)
List org.elasticsearch.painless.api.Augmentation.findAll(Predicate)
def org.elasticsearch.painless.api.Augmentation.findResult(Function)
def org.elasticsearch.painless.api.Augmentation.findResult(def,Function)
List org.elasticsearch.painless.api.Augmentation.split(Predicate)
}

class Comparator -> java.util.Comparator {
Expand Down Expand Up @@ -123,7 +123,7 @@ class List -> java.util.List extends Collection,Iterable {
def remove(int)
void replaceAll(UnaryOperator)
def set(int,def)
int getLength*()
int org.elasticsearch.painless.api.Augmentation.getLength()
void sort(Comparator)
List subList(int,int)
}
Expand Down Expand Up @@ -163,17 +163,17 @@ class Map -> java.util.Map {
Collection values()

# some adaptations of groovy methods
List collect*(BiFunction)
def collect*(Collection,BiFunction)
int count*(BiPredicate)
def each*(BiConsumer)
boolean every*(BiPredicate)
Map.Entry find*(BiPredicate)
Map findAll*(BiPredicate)
def findResult*(BiFunction)
def findResult*(def,BiFunction)
List findResults*(BiFunction)
Map groupBy*(BiFunction)
List org.elasticsearch.painless.api.Augmentation.collect(BiFunction)
def org.elasticsearch.painless.api.Augmentation.collect(Collection,BiFunction)
int org.elasticsearch.painless.api.Augmentation.count(BiPredicate)
def org.elasticsearch.painless.api.Augmentation.each(BiConsumer)
boolean org.elasticsearch.painless.api.Augmentation.every(BiPredicate)
Map.Entry org.elasticsearch.painless.api.Augmentation.find(BiPredicate)
Map org.elasticsearch.painless.api.Augmentation.findAll(BiPredicate)
def org.elasticsearch.painless.api.Augmentation.findResult(BiFunction)
def org.elasticsearch.painless.api.Augmentation.findResult(def,BiFunction)
List org.elasticsearch.painless.api.Augmentation.findResults(BiFunction)
Map org.elasticsearch.painless.api.Augmentation.groupBy(BiFunction)
}

class Map.Entry -> java.util.Map$Entry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ class org.elasticsearch.painless.FeatureTest -> org.elasticsearch.painless.Featu
boolean overloadedStatic(boolean)
Object twoFunctionsOfX(Function,Function)
void listInput(List)
int org.elasticsearch.painless.FeatureTestAugmentation.getTotal()
int org.elasticsearch.painless.FeatureTestAugmentation.addToTotal(int)
}

class org.elasticsearch.search.lookup.FieldLookup -> org.elasticsearch.search.lookup.FieldLookup extends Object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,15 @@ public void testMap_GroupBy() {
exec("Map m = new TreeMap(); m.a = -1; m.b = 1; " +
"return m.groupBy((key,value) -> value < 0 ? 'negative' : 'positive')"));
}

public void testFeatureTest() {
assertEquals(5, exec("org.elasticsearch.painless.FeatureTest ft = new org.elasticsearch.painless.FeatureTest();" +
" ft.setX(3); ft.setY(2); return ft.getTotal()"));
assertEquals(5, exec("def ft = new org.elasticsearch.painless.FeatureTest();" +
" ft.setX(3); ft.setY(2); return ft.getTotal()"));
assertEquals(8, exec("org.elasticsearch.painless.FeatureTest ft = new org.elasticsearch.painless.FeatureTest();" +
" ft.setX(3); ft.setY(2); return ft.addToTotal(3)"));
assertEquals(8, exec("def ft = new org.elasticsearch.painless.FeatureTest();" +
" ft.setX(3); ft.setY(2); return ft.addToTotal(3)"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private static void documentMethod(PrintStream stream, Method method) {
emitAnchor(stream, method);
stream.print("]]");

if (false == method.augmentation && Modifier.isStatic(method.modifiers)) {
if (null == method.augmentation && Modifier.isStatic(method.modifiers)) {
stream.print("static ");
}

Expand Down Expand Up @@ -268,12 +268,12 @@ private static void emitJavadocLink(PrintStream stream, String root, Method meth
stream.print("link:{");
stream.print(root);
stream.print("-javadoc}/");
stream.print((method.augmentation ? Augmentation.class : method.owner.clazz).getName().replace('.', '/'));
stream.print((method.augmentation != null ? method.augmentation : method.owner.clazz).getName().replace('.', '/'));
stream.print(".html#");
stream.print(methodName(method));
stream.print("%2D");
boolean first = true;
if (method.augmentation) {
if (method.augmentation != null) {
first = false;
stream.print(method.owner.clazz.getName());
}
Expand Down Expand Up @@ -309,7 +309,7 @@ private static void emitJavadocLink(PrintStream stream, String root, Field field
* Pick the javadoc root for a {@link Method}.
*/
private static String javadocRoot(Method method) {
if (method.augmentation) {
if (method.augmentation != null) {
return "painless";
}
return javadocRoot(method.owner);
Expand Down