diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java index e9dcdb1ef409d..3437bd2cd7585 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java @@ -207,9 +207,10 @@ private static void addFactoryMethod(Map> additionalClasses, Cl * @return The ScriptRoot used to compile */ ScriptRoot compile(Loader loader, String name, String source, CompilerSettings settings) { + String scriptName = Location.computeSourceName(name); ScriptClassInfo scriptClassInfo = new ScriptClassInfo(painlessLookup, scriptClass); - SClass root = Walker.buildPainlessTree(scriptClassInfo, name, source, settings, painlessLookup, null); - ScriptRoot scriptRoot = new ScriptRoot(painlessLookup, settings, scriptClassInfo, root); + SClass root = Walker.buildPainlessTree(scriptClassInfo, scriptName, source, settings, painlessLookup); + ScriptRoot scriptRoot = new ScriptRoot(painlessLookup, settings, scriptClassInfo, scriptName, source); ClassNode classNode = root.writeClass(scriptRoot); DefBootstrapInjectionPhase.phase(classNode); ScriptInjectionPhase.phase(scriptRoot, classNode); @@ -236,10 +237,12 @@ ScriptRoot compile(Loader loader, String name, String source, CompilerSettings s * @return The bytes for compilation. */ byte[] compile(String name, String source, CompilerSettings settings, Printer debugStream) { + String scriptName = Location.computeSourceName(name); ScriptClassInfo scriptClassInfo = new ScriptClassInfo(painlessLookup, scriptClass); - SClass root = Walker.buildPainlessTree(scriptClassInfo, name, source, settings, painlessLookup, debugStream); - ScriptRoot scriptRoot = new ScriptRoot(painlessLookup, settings, scriptClassInfo, root); + SClass root = Walker.buildPainlessTree(scriptClassInfo, scriptName, source, settings, painlessLookup); + ScriptRoot scriptRoot = new ScriptRoot(painlessLookup, settings, scriptClassInfo, scriptName, source); ClassNode classNode = root.writeClass(scriptRoot); + classNode.setDebugStream(debugStream); DefBootstrapInjectionPhase.phase(classNode); ScriptInjectionPhase.phase(scriptRoot, classNode); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java index 9950f2283d030..6cab52f86f181 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java @@ -159,7 +159,6 @@ import org.elasticsearch.painless.node.SThrow; import org.elasticsearch.painless.node.STry; import org.elasticsearch.painless.node.SWhile; -import org.objectweb.asm.util.Printer; import java.util.ArrayList; import java.util.List; @@ -170,26 +169,21 @@ public final class Walker extends PainlessParserBaseVisitor { public static SClass buildPainlessTree(ScriptClassInfo mainMethod, String sourceName, - String sourceText, CompilerSettings settings, PainlessLookup painlessLookup, - Printer debugStream) { - return new Walker(mainMethod, sourceName, sourceText, settings, painlessLookup, debugStream).source; + String sourceText, CompilerSettings settings, PainlessLookup painlessLookup) { + return new Walker(mainMethod, sourceName, sourceText, settings, painlessLookup).source; } private final ScriptClassInfo scriptClassInfo; private final SClass source; private final CompilerSettings settings; - private final Printer debugStream; private final String sourceName; - private final String sourceText; private final PainlessLookup painlessLookup; private Walker(ScriptClassInfo scriptClassInfo, String sourceName, String sourceText, - CompilerSettings settings, PainlessLookup painlessLookup, Printer debugStream) { + CompilerSettings settings, PainlessLookup painlessLookup) { this.scriptClassInfo = scriptClassInfo; - this.debugStream = debugStream; this.settings = settings; - this.sourceName = Location.computeSourceName(sourceName); - this.sourceText = sourceText; + this.sourceName = sourceName; this.painlessLookup = painlessLookup; this.source = (SClass)visit(buildAntlrTree(sourceText)); } @@ -279,7 +273,7 @@ public ANode visitSource(SourceContext ctx) { location(ctx), statements), true, false, false, true); functions.add(execute); - return new SClass(scriptClassInfo, sourceName, sourceText, debugStream, location(ctx), functions); + return new SClass(location(ctx), functions); } @Override diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/ClassNode.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/ClassNode.java index 39530e87471c8..60d508c78841a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/ClassNode.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/ClassNode.java @@ -69,36 +69,9 @@ public BlockNode getClinitBlockNode() { /* ---- end tree structure, begin node data ---- */ - private ScriptClassInfo scriptClassInfo; - private String name; - private String sourceText; private Printer debugStream; private ScriptRoot scriptRoot; - public void setScriptClassInfo(ScriptClassInfo scriptClassInfo) { - this.scriptClassInfo = scriptClassInfo; - } - - public ScriptClassInfo getScriptClassInfo() { - return scriptClassInfo; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setSourceText(String sourceText) { - this.sourceText = sourceText; - } - - public String getSourceText() { - return sourceText; - } - public void setDebugStream(Printer debugStream) { this.debugStream = debugStream; } @@ -125,7 +98,8 @@ public ClassNode() { } public byte[] write() { - BitSet statements = new BitSet(sourceText.length()); + ScriptClassInfo scriptClassInfo = scriptRoot.getScriptClassInfo(); + BitSet statements = new BitSet(scriptRoot.getScriptSource().length()); scriptRoot.addStaticConstant("$STATEMENTS", statements); // Create the ClassWriter. @@ -139,7 +113,7 @@ public byte[] write() { ClassWriter classWriter = new ClassWriter(scriptRoot.getCompilerSettings(), statements, debugStream, scriptClassInfo.getBaseClass(), classFrames, classAccess, className, classInterfaces); ClassVisitor classVisitor = classWriter.getClassVisitor(); - classVisitor.visitSource(Location.computeSourceName(name), null); + classVisitor.visitSource(Location.computeSourceName(scriptRoot.getScriptName()), null); org.objectweb.asm.commons.Method init; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java index 4790e222e99d7..8b076025403ac 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java @@ -21,17 +21,8 @@ import org.elasticsearch.painless.Location; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; import java.util.Objects; -import static java.lang.Math.max; -import static java.util.Collections.emptyList; - /** * The superclass for all nodes. */ @@ -40,7 +31,7 @@ public abstract class ANode { /** * The identifier of the script and character offset used for debugging and errors. */ - final Location location; + protected final Location location; /** * Standard constructor with location used for error tracking. @@ -55,81 +46,4 @@ public abstract class ANode { RuntimeException createError(RuntimeException exception) { return location.createError(exception); } - - /** - * Subclasses should implement this with a method like {@link #singleLineToString(Object...)} or - * {@link #multilineToString(Collection, Collection)}. - */ - public abstract String toString(); - - // Below are utilities for building the toString - - /** - * Build {@link #toString()} for a node without inserting line breaks between the sub-nodes. - */ - protected String singleLineToString(Object... subs) { - return singleLineToString(Arrays.asList(subs)); - } - - /** - * Build {@link #toString()} for a node without inserting line breaks between the sub-nodes. - */ - protected String singleLineToString(Collection subs) { - return joinWithName(getClass().getSimpleName(), subs, emptyList()); - } - - /** - * Build {@link #toString()} for a node that optionally ends in {@code (Args some arguments here)}. Usually function calls. - */ - protected String singleLineToStringWithOptionalArgs(Collection arguments, Object... restOfSubs) { - List subs = new ArrayList<>(); - Collections.addAll(subs, restOfSubs); - if (false == arguments.isEmpty()) { - subs.add(joinWithName("Args", arguments, emptyList())); - } - return singleLineToString(subs); - } - - /** - * Build {@link #toString()} for a node that should have new lines after some of its sub-nodes. - */ - protected String multilineToString(Collection sameLine, Collection ownLine) { - return joinWithName(getClass().getSimpleName(), sameLine, ownLine); - } - - /** - * Zip two (potentially uneven) lists together into for {@link #toString()}. - */ - protected List pairwiseToString(Collection lefts, Collection rights) { - List pairs = new ArrayList<>(max(lefts.size(), rights.size())); - Iterator left = lefts.iterator(); - Iterator right = rights.iterator(); - while (left.hasNext() || right.hasNext()) { - pairs.add(joinWithName("Pair", - Arrays.asList(left.hasNext() ? left.next() : "", right.hasNext() ? right.next() : ""), - emptyList())); - } - return pairs; - } - - /** - * Build a {@link #toString()} for some expressions. Usually best to use {@link #singleLineToString(Object...)} or - * {@link #multilineToString(Collection, Collection)} instead because they include the name of the node by default. - */ - protected String joinWithName(String name, Collection sameLine, - Collection ownLine) { - StringBuilder b = new StringBuilder(); - b.append('(').append(name); - for (Object sub : sameLine) { - b.append(' ').append(sub); - } - if (ownLine.size() == 1 && sameLine.isEmpty()) { - b.append(' ').append(ownLine.iterator().next()); - } else { - for (Object sub : ownLine) { - b.append("\n ").append(Objects.toString(sub).replace("\n", "\n ")); - } - } - return b.append(')').toString(); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java index c1917944f260e..6214a6100389a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java @@ -73,9 +73,4 @@ public DResolvedType resolveType(PainlessLookup painlessLookup) { public Class getType() { return type; } - - @Override - public String toString() { - return "(DResolvedType [" + PainlessLookupUtility.typeToCanonicalTypeName(type) + "])"; - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java index 8e21507fdaa05..3c727d771eff3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java @@ -52,10 +52,5 @@ public DResolvedType resolveType(PainlessLookup painlessLookup) { return new DResolvedType(location, type); } - - @Override - public String toString() { - return "(DUnresolvedType [" + typeName + "])"; - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java index 970d31935831b..6c03f09950723 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java @@ -36,8 +36,6 @@ import org.elasticsearch.painless.lookup.def; import org.elasticsearch.painless.symbol.ScriptRoot; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** @@ -251,24 +249,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - List subs = new ArrayList<>(); - subs.add(lhs); - if (rhs != null) { - // Make sure "=" is in the symbol so this is easy to read at a glance - subs.add(operation == null ? "=" : operation.symbol + "="); - subs.add(rhs); - return singleLineToString(subs); - } - subs.add(operation.symbol); - if (pre) { - subs.add("pre"); - } - if (post) { - subs.add("post"); - } - return singleLineToString(subs); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java index 9f6fc56f97ff2..807b0e2f2ce02 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java @@ -151,9 +151,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(left, operation.symbol, right); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java index e9dac2123c6cd..f8fa06b84cd26 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java @@ -74,9 +74,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(left, operation.symbol, right); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java index b1362e99cb2a5..984ebbbdbfe39 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java @@ -57,9 +57,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(constant); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java index c86966df03f60..a9ed9c15976dd 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java @@ -22,8 +22,8 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.Scope; import org.elasticsearch.painless.ir.ClassNode; -import org.elasticsearch.painless.ir.MemberCallNode; import org.elasticsearch.painless.ir.FieldNode; +import org.elasticsearch.painless.ir.MemberCallNode; import org.elasticsearch.painless.lookup.PainlessClassBinding; import org.elasticsearch.painless.lookup.PainlessInstanceBinding; import org.elasticsearch.painless.lookup.PainlessMethod; @@ -188,9 +188,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, name); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java index e5f3b11910d18..0d071b054ab09 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java @@ -100,9 +100,4 @@ public String getPointer() { public List> getCaptures() { return Collections.singletonList(captured.getType()); } - - @Override - public String toString() { - return singleLineToString(variable, call); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java index 359546e805a40..77e68e8d281e3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java @@ -107,9 +107,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(left, operation.symbol, right); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java index 2b4440787347b..f562d31e89024 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java @@ -99,9 +99,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(condition, left, right); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java index 317a9dae3bd3d..e7f57acb581dd 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java @@ -77,13 +77,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - String c = constant.toString(); - if (constant instanceof String) { - c = "'" + c + "'"; - } - return singleLineToString(constant.getClass().getSimpleName(), c); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java index 35388db216cb5..b953ae2dad512 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java @@ -79,9 +79,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(value); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java index 6ccb1a3f397b8..eadcacca4d48a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java @@ -106,9 +106,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(lhs, rhs); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java index 532e9607fb7a6..9da3b7b153bf3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java @@ -61,9 +61,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(type, child); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java index a9cb7876fe11a..19ab946f91cd9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java @@ -85,9 +85,4 @@ public String getPointer() { public List> getCaptures() { return Collections.emptyList(); } - - @Override - public String toString() { - return singleLineToString(type, call); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java index 9bf0a00e610ca..d4bab41eb0121 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java @@ -91,9 +91,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(expression, type); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java index 41ffd62df044f..aa2a63f101219 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java @@ -240,9 +240,4 @@ public List> getCaptures() { } return types; } - - @Override - public String toString() { - return multilineToString(pairwiseToString(paramTypeStrs, paramNameStrs), statements); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java index c60a9d1bea78b..19a129eb4f6de 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java @@ -97,9 +97,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(values); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java index fbe500c027dab..759c913570aea 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java @@ -116,9 +116,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(pairwiseToString(keys, values)); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java index a4ce05d57cf98..9c115ab6b65a0 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java @@ -88,9 +88,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, type, initialize ? "init" : "dims"); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java index 16dc2ee729827..a24800568ec14 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java @@ -22,12 +22,15 @@ import org.elasticsearch.painless.FunctionRef; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.Scope; +import org.elasticsearch.painless.ir.BlockNode; import org.elasticsearch.painless.ir.ClassNode; import org.elasticsearch.painless.ir.FunctionNode; import org.elasticsearch.painless.ir.NewArrayFuncRefNode; +import org.elasticsearch.painless.ir.NewArrayNode; +import org.elasticsearch.painless.ir.ReturnNode; +import org.elasticsearch.painless.ir.VariableNode; import org.elasticsearch.painless.symbol.ScriptRoot; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -52,28 +55,64 @@ public ENewArrayFunctionRef(Location location, String type) { Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input input) { Output output = new Output(); - SReturn code = new SReturn(location, new ENewArray(location, type, Arrays.asList(new EVariable(location, "size")), false)); - SFunction function = new SFunction( - location, type, scriptRoot.getNextSyntheticName("newarray"), - Collections.singletonList("int"), Collections.singletonList("size"), - new SBlock(location, Collections.singletonList(code)), true, true, true, false); - function.generateSignature(scriptRoot.getPainlessLookup()); - FunctionNode functionNode = function.writeFunction(classNode, scriptRoot); - scriptRoot.getFunctionTable().addFunction(function.name, function.returnType, function.typeParameters, true, true); + if (input.read == false) { + throw createError(new IllegalArgumentException("A newly created array must be read from.")); + } + + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); + + if (clazz == null) { + throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); + } + + String name = scriptRoot.getNextSyntheticName("newarray"); + scriptRoot.getFunctionTable().addFunction(name, clazz, Collections.singletonList(int.class), true, true); FunctionRef ref; if (input.expected == null) { ref = null; output.actual = String.class; - defPointer = "Sthis." + function.name + ",0"; + defPointer = "Sthis." + name + ",0"; } else { defPointer = null; ref = FunctionRef.create(scriptRoot.getPainlessLookup(), scriptRoot.getFunctionTable(), - location, input.expected, "this", function.name, 0); + location, input.expected, "this", name, 0); output.actual = input.expected; } + VariableNode variableNode = new VariableNode(); + variableNode.setLocation(location); + variableNode.setExpressionType(int.class); + variableNode.setName("size"); + + NewArrayNode newArrayNode = new NewArrayNode(); + newArrayNode.setLocation(location); + newArrayNode.setExpressionType(clazz); + newArrayNode.setInitialize(false); + + newArrayNode.addArgumentNode(variableNode); + + ReturnNode returnNode = new ReturnNode(); + returnNode.setLocation(location); + returnNode.setExpressionNode(newArrayNode); + + BlockNode blockNode = new BlockNode(); + blockNode.setAllEscape(true); + blockNode.setStatementCount(1); + blockNode.addStatementNode(returnNode); + + FunctionNode functionNode = new FunctionNode(); + functionNode.setMaxLoopCounter(0); + functionNode.setName(name); + functionNode.setReturnType(clazz); + functionNode.addTypeParameter(int.class); + functionNode.addParameterName("size"); + functionNode.setStatic(true); + functionNode.setVarArgs(false); + functionNode.setSynthetic(true); + functionNode.setBlockNode(blockNode); + classNode.addFunctionNode(functionNode); NewArrayFuncRefNode newArrayFuncRefNode = new NewArrayFuncRefNode(); @@ -96,9 +135,4 @@ public String getPointer() { public List> getCaptures() { return Collections.emptyList(); } - - @Override - public String toString() { - return singleLineToString(type + "[]", "new"); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java index 1659910986173..2b09da6c75dd1 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java @@ -108,9 +108,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, type); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java index 1b61a05a68501..402f551e8ca42 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java @@ -63,9 +63,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java index 1e548252f1a74..4f4cc12a1ad13 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java @@ -121,12 +121,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - if (radix != 10) { - return singleLineToString(value, radix); - } - return singleLineToString(value); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java index 23e92f018c371..2b2b76033210a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java @@ -180,23 +180,4 @@ private int flagForChar(char c) { throw new IllegalArgumentException("Unknown flag [" + c + "]"); } } - - @Override - public String toString() { - StringBuilder f = new StringBuilder(); - if ((flags & Pattern.CANON_EQ) != 0) f.append('c'); - if ((flags & Pattern.CASE_INSENSITIVE) != 0) f.append('i'); - if ((flags & Pattern.LITERAL) != 0) f.append('l'); - if ((flags & Pattern.MULTILINE) != 0) f.append('m'); - if ((flags & Pattern.DOTALL) != 0) f.append('s'); - if ((flags & Pattern.UNICODE_CHARACTER_CLASS) != 0) f.append('U'); - if ((flags & Pattern.UNICODE_CASE) != 0) f.append('u'); - if ((flags & Pattern.COMMENTS) != 0) f.append('x'); - - String p = "/" + pattern + "/"; - if (f.length() == 0) { - return singleLineToString(p); - } - return singleLineToString(p, f); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java index b45ba741ae1a3..fc599175f7831 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java @@ -59,9 +59,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(type); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java index 77b9fb857bc08..a211cce681d5d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java @@ -59,9 +59,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString("'" + constant.toString() + "'"); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java index cafcda3b7dd2a..b9b056811dfdb 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java @@ -100,9 +100,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(operation.symbol, child); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java index 0c345dfa46735..f311830a3c073 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java @@ -79,9 +79,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(name); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java index 664a9e1c0048a..459cff55dc97a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java @@ -109,9 +109,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return isDefOptimized; } - - @Override - public String toString() { - return singleLineToString(prefix, index); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java index 036c04f3878b5..641a77b37fe4a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java @@ -102,9 +102,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, prefix, name); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java index 9751786e1515b..3ca3899d53b2b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java @@ -153,12 +153,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return isDefOptimized; } - - @Override - public String toString() { - if (nullSafe) { - return singleLineToString("nullSafe", prefix, value); - } - return singleLineToString(prefix, value); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java index aaefa0717d3ba..157e9aa0a8e0e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java @@ -70,9 +70,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java index 2a285d49acbe2..245a82b75c23e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java @@ -69,9 +69,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix, index); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java index 721e76cd3e500..145a541840b7b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java @@ -83,9 +83,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, prefix, method.javaMethod.getName()); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java index 00f09a493c0e9..24ee1ba5b60c2 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java @@ -70,9 +70,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return true; } - - @Override - public String toString() { - return singleLineToString(prefix, index); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java index 8339d161f2a84..b0b3f5cc0cde5 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java @@ -108,9 +108,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToStringWithOptionalArgs(arguments, prefix, name); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java index 1cb8b2a0119e3..dadd31c495327 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java @@ -64,9 +64,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return true; } - - @Override - public String toString() { - return singleLineToString(prefix, value); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java index 26d2858f54afb..140a3c181a903 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java @@ -69,9 +69,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix, field.javaField.getName()); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java index d23039453b3f8..e027ae67076a4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java @@ -98,9 +98,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix, index); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java index 4105bcec8b261..c9a5853dc0df1 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java @@ -97,9 +97,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix, index); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java index bc9a259a2e96c..284257e3d4822 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java @@ -63,9 +63,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(guarded); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java index 22d4c91945273..3977a5c077d69 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java @@ -70,9 +70,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(guarded); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java index a55a5556bafca..a6ff5c0ba26ad 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java @@ -85,9 +85,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, AStoreab boolean isDefOptimized() { return false; } - - @Override - public String toString() { - return singleLineToString(prefix, value); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java index f662976c2e4b3..95298999ca05f 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java @@ -29,8 +29,6 @@ import java.util.Collections; import java.util.List; -import static java.util.Collections.emptyList; - /** * Represents a set of statements as a branch of control-flow. */ @@ -94,9 +92,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return multilineToString(emptyList(), statements); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java index 55d22a2097a9f..627c11757d0eb 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java @@ -54,9 +54,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java index 06dc1a06514fd..6922581e974a6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java @@ -88,9 +88,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(baseException, declaration, block); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java index 1c03994d55d06..ef41a1ab521f9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java @@ -20,55 +20,33 @@ package org.elasticsearch.painless.node; import org.elasticsearch.painless.Location; -import org.elasticsearch.painless.ScriptClassInfo; import org.elasticsearch.painless.ir.ClassNode; -import org.elasticsearch.painless.symbol.FunctionTable; import org.elasticsearch.painless.symbol.ScriptRoot; -import org.objectweb.asm.util.Printer; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import static java.util.Collections.emptyList; - /** * The root of all Painless trees. Contains a series of statements. */ public class SClass extends ANode { - protected final ScriptClassInfo scriptClassInfo; - protected final String name; - protected final String sourceText; - protected final Printer debugStream; protected final List functions = new ArrayList<>(); - public SClass(ScriptClassInfo scriptClassInfo, String name, String sourceText, Printer debugStream, - Location location, List functions) { + public SClass(Location location, List functions) { super(location); - this.scriptClassInfo = Objects.requireNonNull(scriptClassInfo); - this.name = Objects.requireNonNull(name); - this.sourceText = Objects.requireNonNull(sourceText); - this.debugStream = debugStream; this.functions.addAll(Objects.requireNonNull(functions)); } - public ClassNode writeClass(ScriptRoot scriptRoot) { - scriptRoot.addStaticConstant("$NAME", name); - scriptRoot.addStaticConstant("$SOURCE", sourceText); - + public void buildClassScope(ScriptRoot scriptRoot) { for (SFunction function : functions) { - function.generateSignature(scriptRoot.getPainlessLookup()); - - String key = FunctionTable.buildLocalFunctionKey(function.name, function.typeParameters.size()); - - if (scriptRoot.getFunctionTable().getFunction(key) != null) { - throw createError(new IllegalArgumentException("Illegal duplicate functions [" + key + "].")); - } - - scriptRoot.getFunctionTable().addFunction( - function.name, function.returnType, function.typeParameters, function.isInternal, function.isStatic); + function.buildClassScope(scriptRoot); } + } + + public ClassNode writeClass(ScriptRoot scriptRoot) { + buildClassScope(scriptRoot); ClassNode classNode = new ClassNode(); @@ -77,19 +55,8 @@ public ClassNode writeClass(ScriptRoot scriptRoot) { } classNode.setLocation(location); - classNode.setScriptClassInfo(scriptClassInfo); classNode.setScriptRoot(scriptRoot); - classNode.setDebugStream(debugStream); - classNode.setName(name); - classNode.setSourceText(sourceText); return classNode; } - - @Override - public String toString() { - List subs = new ArrayList<>(functions.size()); - subs.addAll(functions); - return multilineToString(emptyList(), subs); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java index 830455274f9e3..3e9a7e21a9db7 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java @@ -57,9 +57,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java index 4bbfcf6d1d505..8aad9dfe58a81 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java @@ -30,8 +30,6 @@ import java.util.Collections; import java.util.List; -import static java.util.Collections.emptyList; - /** * Represents a series of declarations. */ @@ -69,9 +67,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return multilineToString(emptyList(), declarations); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java index 22b71eb931a79..17f158be9c2dc 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java @@ -74,12 +74,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - if (expression == null) { - return singleLineToString(type, name); - } - return singleLineToString(type, name, expression); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java index f5f4b0636a370..58e392a533216 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java @@ -93,9 +93,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(condition, block); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java index ac8741cc551ec..618ae918dbac8 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java @@ -107,9 +107,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(type, name, expression, block); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java index ace1be4b96736..7244b1f7865b4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java @@ -85,9 +85,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(expression); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java index ce43e9a434f1a..a029dd33e7ae4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java @@ -26,10 +26,6 @@ import org.elasticsearch.painless.ir.ForLoopNode; import org.elasticsearch.painless.symbol.ScriptRoot; -import java.util.Arrays; - -import static java.util.Collections.emptyList; - /** * Represents a for loop. */ @@ -155,9 +151,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return multilineToString(emptyList(), Arrays.asList(initializer, condition, afterthought, block)); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java index fad71982b4772..2014a0c8d1879 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java @@ -32,15 +32,14 @@ import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.node.AStatement.Input; import org.elasticsearch.painless.node.AStatement.Output; +import org.elasticsearch.painless.symbol.FunctionTable; import org.elasticsearch.painless.symbol.ScriptRoot; -import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; -import static java.util.Collections.emptyList; import static org.elasticsearch.painless.Scope.newFunctionScope; /** @@ -63,12 +62,6 @@ public class SFunction extends ANode { */ protected final boolean isAutoReturnEnabled; - protected Class returnType; - protected List> typeParameters; - protected MethodType methodType; - - protected org.objectweb.asm.commons.Method method; - public SFunction(Location location, String rtnType, String name, List paramTypes, List paramNames, SBlock block, boolean isInternal, boolean isStatic, boolean synthetic, boolean isAutoReturnEnabled) { @@ -85,44 +78,53 @@ public SFunction(Location location, String rtnType, String name, this.isAutoReturnEnabled = isAutoReturnEnabled; } - // TODO: do this in class on add to remove need for mutable state - void generateSignature(PainlessLookup painlessLookup) { - returnType = painlessLookup.canonicalTypeNameToType(rtnTypeStr); + void buildClassScope(ScriptRoot scriptRoot) { + if (paramTypeStrs.size() != paramNameStrs.size()) { + throw createError(new IllegalStateException( + "parameter types size [" + paramTypeStrs.size() + "] is not equal to " + + "parameter names size [" + paramNameStrs.size() + "]")); + } - if (returnType == null) { - throw createError(new IllegalArgumentException("Illegal return type [" + rtnTypeStr + "] for function [" + name + "].")); + PainlessLookup painlessLookup = scriptRoot.getPainlessLookup(); + FunctionTable functionTable = scriptRoot.getFunctionTable(); + + String functionKey = FunctionTable.buildLocalFunctionKey(name, paramTypeStrs.size()); + + if (functionTable.getFunction(functionKey) != null) { + throw createError(new IllegalArgumentException("illegal duplicate functions [" + functionKey + "].")); } - if (paramTypeStrs.size() != paramNameStrs.size()) { - throw createError(new IllegalStateException("Illegal tree structure.")); + Class returnType = painlessLookup.canonicalTypeNameToType(rtnTypeStr); + + if (returnType == null) { + throw createError(new IllegalArgumentException( + "return type [" + rtnTypeStr + "] not found for function [" + functionKey + "]")); } - Class[] paramClasses = new Class[this.paramTypeStrs.size()]; - List> paramTypes = new ArrayList<>(); + List> typeParameters = new ArrayList<>(); - for (int param = 0; param < this.paramTypeStrs.size(); ++param) { - Class paramType = painlessLookup.canonicalTypeNameToType(this.paramTypeStrs.get(param)); + for (String typeParameter : paramTypeStrs) { + Class paramType = painlessLookup.canonicalTypeNameToType(typeParameter); if (paramType == null) { throw createError(new IllegalArgumentException( - "Illegal parameter type [" + this.paramTypeStrs.get(param) + "] for function [" + name + "].")); + "parameter type [" + typeParameter + "] not found for function [" + functionKey + "]")); } - paramClasses[param] = PainlessLookupUtility.typeToJavaType(paramType); - paramTypes.add(paramType); + typeParameters.add(paramType); } - typeParameters = paramTypes; - methodType = MethodType.methodType(PainlessLookupUtility.typeToJavaType(returnType), paramClasses); - method = new org.objectweb.asm.commons.Method(name, MethodType.methodType( - PainlessLookupUtility.typeToJavaType(returnType), paramClasses).toMethodDescriptorString()); + functionTable.addFunction(name, returnType, typeParameters, isInternal, isStatic); } FunctionNode writeFunction(ClassNode classNode, ScriptRoot scriptRoot) { - FunctionScope functionScope = newFunctionScope(returnType); + FunctionTable.LocalFunction localFunction = scriptRoot.getFunctionTable().getFunction(name, paramTypeStrs.size()); + Class returnType = localFunction.getReturnType(); + List> typeParameters = localFunction.getTypeParameters(); + FunctionScope functionScope = newFunctionScope(localFunction.getReturnType()); - for (int index = 0; index < typeParameters.size(); ++index) { - Class typeParameter = typeParameters.get(index); + for (int index = 0; index < localFunction.getTypeParameters().size(); ++index) { + Class typeParameter = localFunction.getTypeParameters().get(index); String parameterName = paramNameStrs.get(index); functionScope.defineVariable(location, typeParameter, parameterName, false); } @@ -216,15 +218,4 @@ FunctionNode writeFunction(ClassNode classNode, ScriptRoot scriptRoot) { return functionNode; } - - @Override - public String toString() { - List description = new ArrayList<>(); - description.add(rtnTypeStr); - description.add(name); - if (false == (paramTypeStrs.isEmpty() && paramNameStrs.isEmpty())) { - description.add(joinWithName("Args", pairwiseToString(paramTypeStrs, paramNameStrs), emptyList())); - } - return multilineToString(description, block.statements); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java index 44b6e0d6105c4..e8ee41cff51c3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java @@ -80,9 +80,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(condition, ifblock); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java index 6ae366ad8428a..8d23f6705da2b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java @@ -26,11 +26,8 @@ import org.elasticsearch.painless.ir.IfElseNode; import org.elasticsearch.painless.symbol.ScriptRoot; -import java.util.Arrays; import java.util.Objects; -import static java.util.Collections.singleton; - /** * Represents an if/else block. */ @@ -104,9 +101,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return multilineToString(singleton(condition), Arrays.asList(ifblock, elseblock)); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java index 6ab6c6590e350..20aa2ef94fe26 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java @@ -73,9 +73,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return expression == null ? singleLineToString() : singleLineToString(expression); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java index fef81dfed6968..3db8213f8afbc 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java @@ -77,10 +77,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - //return singleLineToString(variable.getCanonicalTypeName(), variable.getName(), expression, block); - return null; - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java index 83561431db1b1..14e17f7338464 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java @@ -92,10 +92,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - //return singleLineToString(variable.getCanonicalTypeName(), variable.getName(), expression, block); - return null; - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java index 3fff9615b12d9..9ac4ea8320e23 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java @@ -62,9 +62,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(expression); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java index b9fd59f6b3fc1..0d9a6138fec2b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java @@ -31,8 +31,6 @@ import java.util.Collections; import java.util.List; -import static java.util.Collections.singleton; - /** * Represents the try block as part of a try-catch block. */ @@ -107,9 +105,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return multilineToString(singleton(block), catches); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java index 9fa3139b87eed..1cce884ecb29e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java @@ -100,9 +100,4 @@ Output analyze(ClassNode classNode, ScriptRoot scriptRoot, Scope scope, Input in return output; } - - @Override - public String toString() { - return singleLineToString(condition, block); - } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/symbol/ScriptRoot.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/symbol/ScriptRoot.java index 71f67d534b9ec..02a4720fc9a79 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/symbol/ScriptRoot.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/symbol/ScriptRoot.java @@ -22,7 +22,6 @@ import org.elasticsearch.painless.CompilerSettings; import org.elasticsearch.painless.ScriptClassInfo; import org.elasticsearch.painless.lookup.PainlessLookup; -import org.elasticsearch.painless.node.SClass; import java.util.Collections; import java.util.HashMap; @@ -38,8 +37,8 @@ public class ScriptRoot { protected final PainlessLookup painlessLookup; protected final CompilerSettings compilerSettings; protected final ScriptClassInfo scriptClassInfo; - - protected final SClass classNode; + protected final String scriptName; + protected final String scriptSource; protected final FunctionTable functionTable = new FunctionTable(); protected int syntheticCounter = 0; @@ -48,12 +47,16 @@ public class ScriptRoot { protected Set usedVariables = Collections.emptySet(); protected Map staticConstants = new HashMap<>(); - public ScriptRoot(PainlessLookup painlessLookup, CompilerSettings compilerSettings, ScriptClassInfo scriptClassInfo, SClass classRoot) { + public ScriptRoot(PainlessLookup painlessLookup, CompilerSettings compilerSettings, + ScriptClassInfo scriptClassInfo, String scriptName, String scriptSource) { this.painlessLookup = Objects.requireNonNull(painlessLookup); this.compilerSettings = Objects.requireNonNull(compilerSettings); this.scriptClassInfo = Objects.requireNonNull(scriptClassInfo); - this.classNode = Objects.requireNonNull(classRoot); + this.scriptName = Objects.requireNonNull(scriptName); + this.scriptSource = Objects.requireNonNull(scriptName); + staticConstants.put("$NAME", scriptName); + staticConstants.put("$SOURCE", scriptSource); staticConstants.put("$DEFINITION", painlessLookup); staticConstants.put("$FUNCTIONS", functionTable); } @@ -70,8 +73,12 @@ public ScriptClassInfo getScriptClassInfo() { return scriptClassInfo; } - public SClass getClassNode() { - return classNode; + public String getScriptName() { + return scriptName; + } + + public String getScriptSource() { + return scriptSource; } public FunctionTable getFunctionTable() { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java index 3fa4c4f94a55f..d3e478a56d5c7 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java @@ -70,7 +70,7 @@ public void testDuplicates() { Exception expected = expectScriptThrows(IllegalArgumentException.class, () -> { exec("void test(int x) {x = 2;} void test(def y) {y = 3;} test()"); }); - assertThat(expected.getMessage(), containsString("Illegal duplicate functions")); + assertThat(expected.getMessage(), containsString("illegal duplicate functions")); } public void testBadCastFromMethod() { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 65c9f911f1f2f..1f79b18749d55 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -96,7 +96,7 @@ public Object exec(String script, Map vars, Map c pickySettings.setPicky(true); pickySettings.setRegexesEnabled(CompilerSettings.REGEX_ENABLED.get(scriptEngineSettings())); Walker.buildPainlessTree(scriptClassInfo, getTestName(), script, pickySettings, - scriptEngine.getContextsToLookups().get(PainlessTestScript.CONTEXT), null); + scriptEngine.getContextsToLookups().get(PainlessTestScript.CONTEXT)); } // test actual script execution PainlessTestScript.Factory factory = scriptEngine.compile(null, script, PainlessTestScript.CONTEXT, compileParams); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java deleted file mode 100644 index 70e754a4168f5..0000000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java +++ /dev/null @@ -1,889 +0,0 @@ -/* - * 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.node; - -import org.apache.lucene.util.LuceneTestCase.AwaitsFix; -import org.elasticsearch.painless.CompilerSettings; -import org.elasticsearch.painless.FeatureTestObject; -import org.elasticsearch.painless.Location; -import org.elasticsearch.painless.Operation; -import org.elasticsearch.painless.ScriptClassInfo; -import org.elasticsearch.painless.action.PainlessExecuteAction; -import org.elasticsearch.painless.antlr.Walker; -import org.elasticsearch.painless.lookup.PainlessClass; -import org.elasticsearch.painless.lookup.PainlessField; -import org.elasticsearch.painless.lookup.PainlessLookup; -import org.elasticsearch.painless.lookup.PainlessLookupBuilder; -import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.lookup.PainlessMethod; -import org.elasticsearch.painless.spi.Whitelist; -import org.elasticsearch.painless.spi.WhitelistLoader; -import org.elasticsearch.test.ESTestCase; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; - -// TODO: fix these tests to match new node structure - -/** - * Tests {@link Object#toString} implementations on all extensions of {@link ANode}. - */ -@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/51842") -public class NodeToStringTests extends ESTestCase { - - public void testEAssignment() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SExpression (EAssignment (EVariable i) = (ENumeric 2)))\n" - + " (SReturn (EVariable i)))", - "def i;\n" - + "i = 2;\n" - + "return i"); - for (String operator : new String[] {"+", "-", "*", "/", "%", "&", "^", "|", "<<", ">>", ">>>"}) { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i (ENumeric 1)))\n" - + " (SExpression (EAssignment (EVariable i) " + operator + "= (ENumeric 2)))\n" - + " (SReturn (EVariable i)))", - "def i = 1;\n" - + "i " + operator + "= 2;\n" - + "return i"); - } - // Compound - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SReturn (EAssignment (EVariable i) = (ENumeric 2))))", - "def i;\n" - + "return i = 2"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SReturn (EAssignment (EVariable i) ++ post)))", - "def i;\n" - + "return i++"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SReturn (EAssignment (EVariable i) ++ pre)))", - "def i;\n" - + "return ++i"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SReturn (EAssignment (EVariable i) -- post)))", - "def i;\n" - + "return i--"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" - + " (SReturn (EAssignment (EVariable i) -- pre)))", - "def i;\n" - + "return --i"); - } - - public void testEBinary() { - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) * (ENumeric 1))))", "return 1 * 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) / (ENumeric 1))))", "return 1 / 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) % (ENumeric 1))))", "return 1 % 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) + (ENumeric 1))))", "return 1 + 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) - (ENumeric 1))))", "return 1 - 1"); - assertToString( "(SClass (SReturn (EBinary (EString 'asb') =~ (ERegex /cat/))))", "return 'asb' =~ /cat/"); - assertToString("(SClass (SReturn (EBinary (EString 'asb') ==~ (ERegex /cat/))))", "return 'asb' ==~ /cat/"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) << (ENumeric 1))))", "return 1 << 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) >> (ENumeric 1))))", "return 1 >> 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) >>> (ENumeric 1))))", "return 1 >>> 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) & (ENumeric 1))))", "return 1 & 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) ^ (ENumeric 1))))", "return 1 ^ 1"); - assertToString( "(SClass (SReturn (EBinary (ENumeric 1) | (ENumeric 1))))", "return 1 | 1"); - } - - public void testEBool() { - assertToString("(SClass (SReturn (EBool (EBoolean true) && (EBoolean false))))", "return true && false"); - assertToString("(SClass (SReturn (EBool (EBoolean true) || (EBoolean false))))", "return true || false"); - } - - public void testEBoolean() { - assertToString("(SClass (SReturn (EBoolean true)))", "return true"); - assertToString("(SClass (SReturn (EBoolean false)))", "return false"); - } - - public void testECallLocal() { - assertToString( - "(SClass\n" - + " (SFunction def a\n" - + " (SReturn (EBoolean true)))\n" - + " (SReturn (ECallLocal a)))", - "def a() {\n" - + " return true\n" - + "}\n" - + "return a()"); - assertToString( - "(SClass\n" - + " (SFunction def a (Args (Pair int i) (Pair int j))\n" - + " (SReturn (EBoolean true)))\n" - + " (SReturn (ECallLocal a (Args (ENumeric 1) (ENumeric 2)))))", - "def a(int i, int j) {\n" - + " return true\n" - + "}\n" - + "return a(1, 2)"); - } - - public void testECapturingFunctionRef() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [Integer]) x " - + "(PCallInvoke (EStatic Integer) valueOf (Args (ENumeric 5)))))\n" - + " (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args (ECapturingFunctionRef x toString)))))", - "Integer x = Integer.valueOf(5);\n" - + "return Optional.empty().orElseGet(x::toString)"); - } - - public void testEComp() { - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) < (ENumeric 10))))", "return params.a < 10"); - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) <= (ENumeric 10))))", "return params.a <= 10"); - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) > (ENumeric 10))))", "return params.a > 10"); - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) >= (ENumeric 10))))", "return params.a >= 10"); - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) == (ENumeric 10))))", "return params.a == 10"); - assertToString("(SClass (SReturn (EComp (PField (EVariable params) a) === (ENumeric 10))))", "return params.a === 10"); - assertToString( "(SClass (SReturn (EComp (PField (EVariable params) a) != (ENumeric 10))))", "return params.a != 10"); - assertToString("(SClass (SReturn (EComp (PField (EVariable params) a) !== (ENumeric 10))))", "return params.a !== 10"); - } - - public void testEConditional() { - assertToString("(SClass (SReturn (EConditional (PField (EVariable params) a) (ENumeric 1) (ENumeric 6))))", - "return params.a ? 1 : 6"); - } - - public void testEConstant() { - assertEquals("(EConstant String '121')", new EConstant(new Location(getTestName(), 0), "121").toString()); - assertEquals("(EConstant String '92 ')", new EConstant(new Location(getTestName(), 0), "92 ").toString()); - assertEquals("(EConstant Integer 1237)", new EConstant(new Location(getTestName(), 1), 1237).toString()); - assertEquals("(EConstant Boolean true)", new EConstant(new Location(getTestName(), 2), true).toString()); - } - - public void testEDecimal() { - assertToString("(SClass (SReturn (EDecimal 1.0)))", "return 1.0"); - assertToString("(SClass (SReturn (EDecimal 14.121d)))", "return 14.121d"); - assertToString("(SClass (SReturn (EDecimal 2234.1f)))", "return 2234.1f"); - assertToString("(SClass (SReturn (EDecimal 14.121D)))", "return 14.121D"); - assertToString("(SClass (SReturn (EDecimal 1234.1F)))", "return 1234.1F"); - } - - public void testEElvis() { - assertToString("(SClass (SReturn (EElvis (PField (EVariable params) a) (ENumeric 1))))", "return params.a ?: 1"); - } - - public void testEExplicit() { - assertToString("(SClass (SReturn (EExplicit byte (PField (EVariable params) a))))", "return (byte)(params.a)"); - } - - public void testEFunctionRef() { - assertToString( - "(SClass (SReturn " - + "(PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args (EFunctionRef Optional empty)))))", - "return Optional.empty().orElseGet(Optional::empty)"); - } - - public void testEInstanceOf() { - assertToString("(SClass (SReturn (EInstanceof (ENewObj Object) Object)))", "return new Object() instanceof Object"); - assertToString("(SClass (SReturn (EInstanceof (ENumeric 12) double)))", "return 12 instanceof double"); - } - - public void testELambda() { - assertToString( - "(SClass (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args " - + "(ELambda (SReturn (ENumeric 1)))))))", - "return Optional.empty().orElseGet(() -> {\n" - + " return 1\n" - + "})"); - assertToString( - "(SClass (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args " - + "(ELambda (SReturn (ENumeric 1)))))))", - "return Optional.empty().orElseGet(() -> 1)"); - assertToString( - "(SClass (SReturn (PCallInvoke (PCallInvoke (PCallInvoke (EListInit (ENumeric 1) (ENumeric 2) (ENumeric 3)) stream) " - + "mapToInt (Args (ELambda (Pair def x)\n" - + " (SReturn (EBinary (EVariable x) + (ENumeric 1)))))) sum)))", - "return [1, 2, 3].stream().mapToInt((def x) -> {\n" - + " return x + 1\n" - + "}).sum()"); - assertToString( - "(SClass (SReturn (PCallInvoke (PCallInvoke (PCallInvoke (EListInit (ENumeric 1) (ENumeric 2) (ENumeric 3)) stream) " - + "mapToInt (Args (ELambda (Pair null x)\n" - + " (SReturn (EBinary (EVariable x) + (ENumeric 1)))))) sum)))", - "return [1, 2, 3].stream().mapToInt(x -> x + 1).sum()"); - assertToString( - "(SClass (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair def a) (Pair def b)\n" - + " (SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length))))))))", - "return ['a', 'b'].sort((def a, def b) -> {\n" - + " return a.length() - b.length()\n" - + "})"); - assertToString( - "(SClass (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair null a) (Pair null b)\n" - + " (SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length))))))))", - "return ['a', 'b'].sort((a, b) -> a.length() - b.length())"); - assertToString( - "(SClass (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair def a) (Pair def b)\n" - + " (SIf (EComp (EVariable a) < (EVariable b)) (SBlock " - + "(SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length)))))\n" - + " (SReturn (ENumeric 1)))))))", - "return ['a', 'b'].sort((def a, def b) -> {\n" - + " if (a < b) {\n" - + " return a.length() - b.length()\n" - + " }\n" - + " return 1\n" - + "})"); - } - - public void testEListInit() { - assertToString("(SClass (SReturn (EListInit (ENumeric 1) (ENumeric 2) (EString 'cat') (EString 'dog') (ENewObj Object))))", - "return [1, 2, 'cat', 'dog', new Object()]"); - assertToString("(SClass (SReturn (EListInit)))", "return []"); - } - - public void testEMapInit() { - assertToString("(SClass (SReturn (EMapInit " - + "(Pair (EString 'a') (ENumeric 1)) " - + "(Pair (EString 'b') (ENumeric 3)) " - + "(Pair (ENumeric 12) (ENewObj Object)))))", - "return ['a': 1, 'b': 3, 12: new Object()]"); - assertToString("(SClass (SReturn (EMapInit)))", "return [:]"); - } - - public void testENewArray() { - assertToString("(SClass (SReturn (ENewArray int[] dims (Args (ENumeric 10)))))", "return new int[10]"); - assertToString("(SClass (SReturn (ENewArray int[][][] dims (Args (ENumeric 10) (ENumeric 4) (ENumeric 5)))))", - "return new int[10][4][5]"); - assertToString("(SClass (SReturn (ENewArray int[] init (Args (ENumeric 1) (ENumeric 2) (ENumeric 3)))))", - "return new int[] {1, 2, 3}"); - assertToString("(SClass (SReturn (ENewArray def[] init (Args (ENumeric 1) (ENumeric 2) (EString 'bird')))))", - "return new def[] {1, 2, 'bird'}"); - } - - public void testENewObj() { - assertToString("(SClass (SReturn (ENewObj Object)))", "return new Object()"); - assertToString("(SClass (SReturn (ENewObj DateTimeException (Args (EString 'test')))))", "return new DateTimeException('test')"); - } - - public void testENull() { - assertToString("(SClass (SReturn (ENull)))", "return null"); - } - - public void testENumeric() { - assertToString("(SClass (SReturn (ENumeric 1)))", "return 1"); - assertToString("(SClass (SReturn (ENumeric 114121d)))", "return 114121d"); - assertToString("(SClass (SReturn (ENumeric 114134f)))", "return 114134f"); - assertToString("(SClass (SReturn (ENumeric 114121D)))", "return 114121D"); - assertToString("(SClass (SReturn (ENumeric 111234F)))", "return 111234F"); - assertToString("(SClass (SReturn (ENumeric 774121l)))", "return 774121l"); - assertToString("(SClass (SReturn (ENumeric 881234L)))", "return 881234L"); - - assertToString("(SClass (SReturn (ENumeric 1 16)))", "return 0x1"); - assertToString("(SClass (SReturn (ENumeric 774121l 16)))", "return 0x774121l"); - assertToString("(SClass (SReturn (ENumeric 881234L 16)))", "return 0x881234L"); - - assertToString("(SClass (SReturn (ENumeric 1 8)))", "return 01"); - assertToString("(SClass (SReturn (ENumeric 774121l 8)))", "return 0774121l"); - assertToString("(SClass (SReturn (ENumeric 441234L 8)))", "return 0441234L"); - } - - public void testERegex() { - assertToString("(SClass (SReturn (ERegex /foo/)))", "return /foo/"); - assertToString("(SClass (SReturn (ERegex /foo/ cix)))", "return /foo/cix"); - assertToString("(SClass (SReturn (ERegex /foo/ cix)))", "return /foo/xci"); - } - - public void testEStatic() { - assertToString("(SClass (SReturn (PCallInvoke (EStatic Optional) empty)))", "return Optional.empty()"); - } - - public void testEString() { - assertToString("(SClass (SReturn (EString 'foo')))", "return 'foo'"); - assertToString("(SClass (SReturn (EString ' oo')))", "return ' oo'"); - assertToString("(SClass (SReturn (EString 'fo ')))", "return 'fo '"); - assertToString("(SClass (SReturn (EString ' o ')))", "return ' o '"); - } - - public void testEUnary() { - assertToString("(SClass (SReturn (EUnary ! (EBoolean true))))", "return !true"); - assertToString("(SClass (SReturn (EUnary ~ (ENumeric 1))))", "return ~1"); - assertToString("(SClass (SReturn (EUnary + (ENumeric 1))))", "return +1"); - assertToString("(SClass (SReturn (EUnary - (ENumeric 1))))", "return -(1)"); - } - - public void testEVariable() { - assertToString("(SClass (SReturn (EVariable params)))", "return params"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a (ENumeric 1)))\n" - + " (SReturn (EVariable a)))", - "def a = 1;\n" - + "return a"); - } - - public void testPBrace() { - assertToString("(SClass (SReturn (PBrace (PField (EVariable params) a) (ENumeric 10))))", "return params.a[10]"); - assertToString("(SClass (SReturn (PBrace (EVariable params) (EString 'a'))))", "return params['a']"); - } - - public void testPCallInvoke() { - assertToString("(SClass (SReturn (PCallInvoke (EStatic Optional) empty)))", "return Optional.empty()"); - assertToString("(SClass (SReturn (PCallInvoke (EStatic Optional) of (Args (ENumeric 1)))))", "return Optional.of(1)"); - assertToString("(SClass (SReturn (PCallInvoke (EStatic Objects) equals (Args (ENumeric 1) (ENumeric 2)))))", - "return Objects.equals(1, 2)"); - assertToString("(SClass (SReturn (PCallInvoke (EVariable params) equals (Args (ENumeric 1)))))", "return params.equals(1)"); - } - - public void testPField() { - assertToString("(SClass (SReturn (PField (EVariable params) a)))", "return params.a"); - assertToString("(SClass (SReturn (PField nullSafe (EVariable params) a)))", "return params?.a"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int[]]) a (ENewArray int[] dims (Args (ENumeric 10)))))\n" - + " (SReturn (PField (EVariable a) length)))", - "int[] a = new int[10];\n" - + "return a.length"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [org.elasticsearch.painless.FeatureTestObject]) a" - + " (ENewObj org.elasticsearch.painless.FeatureTestObject)))\n" - + " (SExpression (EAssignment (PField (EVariable a) x) = (ENumeric 10)))\n" - + " (SReturn (PField (EVariable a) x)))", - "org.elasticsearch.painless.FeatureTestObject a = new org.elasticsearch.painless.FeatureTestObject();\n" - + "a.x = 10;\n" - + "return a.x"); - } - - public void testPSubArrayLength() { - Location l = new Location(getTestName(), 0); - PSubArrayLength node = new PSubArrayLength(l, "int", "a"); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubArrayLength (EVariable a))", node.toString()); - assertEquals("(PSubNullSafeField (PSubArrayLength (EVariable a)))", new PSubNullSafeField(l, node).toString()); - } - - public void testPSubBrace() { - Location l = new Location(getTestName(), 0); - PSubBrace node = new PSubBrace(l, int.class, new ENumeric(l, "1", 10)); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubBrace (EVariable a) (ENumeric 1))", node.toString()); - } - - public void testPSubCallInvoke() { - Location l = new Location(getTestName(), 0); - PainlessClass c = painlessLookup.lookupPainlessClass(Integer.class); - PainlessMethod m = c.methods.get(PainlessLookupUtility.buildPainlessMethodKey("toString", 0)); - PSubCallInvoke node = new PSubCallInvoke(l, m, null, emptyList()); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubCallInvoke (EVariable a) toString)", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubCallInvoke (EVariable a) toString))", new PSubNullSafeCallInvoke(l, node).toString()); - - l = new Location(getTestName(), 1); - m = c.methods.get(PainlessLookupUtility.buildPainlessMethodKey("equals", 1)); - node = new PSubCallInvoke(l, m, null, singletonList(new EVariable(l, "b"))); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubCallInvoke (EVariable a) equals (Args (EVariable b)))", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubCallInvoke (EVariable a) equals (Args (EVariable b))))", - new PSubNullSafeCallInvoke(l, node).toString()); - } - - public void testPSubDefArray() { - Location l = new Location(getTestName(), 0); - PSubDefArray node = new PSubDefArray(l, new EConstant(l, 1)); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubDefArray (EVariable a) (EConstant Integer 1))", node.toString()); - } - - public void testPSubDefCall() { - Location l = new Location(getTestName(), 0); - PSubDefCall node = new PSubDefCall(l, "toString", emptyList()); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubDefCall (EVariable a) toString)", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) toString))", new PSubNullSafeCallInvoke(l, node).toString()); - - l = new Location(getTestName(), 0); - node = new PSubDefCall(l, "equals", singletonList(new EVariable(l, "b"))); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubDefCall (EVariable a) equals (Args (EVariable b)))", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) equals (Args (EVariable b))))", - new PSubNullSafeCallInvoke(l, node).toString()); - - l = new Location(getTestName(), 0); - node = new PSubDefCall(l, "superWeird", Arrays.asList(new EVariable(l, "b"), new EVariable(l, "c"), new EVariable(l, "d"))); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubDefCall (EVariable a) superWeird (Args (EVariable b) (EVariable c) (EVariable d)))", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) superWeird (Args (EVariable b) (EVariable c) (EVariable d))))", - new PSubNullSafeCallInvoke(l, node).toString()); - } - - public void testPSubDefField() { - Location l = new Location(getTestName(), 0); - PSubDefField node = new PSubDefField(l, "ok"); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubDefField (EVariable a) ok)", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubDefField (EVariable a) ok))", new PSubNullSafeCallInvoke(l, node).toString()); - } - - public void testPSubField() { - Location l = new Location(getTestName(), 0); - PainlessClass s = painlessLookup.lookupPainlessClass(Boolean.class); - PainlessField f = s.staticFields.get("TRUE"); - PSubField node = new PSubField(l, f); - node.prefix = new EStatic(l, "Boolean"); - assertEquals("(PSubField (EStatic Boolean) TRUE)", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubField (EStatic Boolean) TRUE))", new PSubNullSafeCallInvoke(l, node).toString()); - } - - public void testPSubListShortcut() { - Location l = new Location(getTestName(), 0); - PSubListShortcut node = new PSubListShortcut(l, List.class, new EConstant(l, 1)); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubListShortcut (EVariable a) (EConstant Integer 1))", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubListShortcut (EVariable a) (EConstant Integer 1)))", - new PSubNullSafeCallInvoke(l, node).toString()); - - l = new Location(getTestName(), 0); - node = new PSubListShortcut(l, List.class, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4))); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubListShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString()); - } - - public void testPSubMapShortcut() { - Location l = new Location(getTestName(), 0); - PSubMapShortcut node = new PSubMapShortcut(l, Map.class, new EConstant(l, "cat")); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubMapShortcut (EVariable a) (EConstant String 'cat'))", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubMapShortcut (EVariable a) (EConstant String 'cat')))", - new PSubNullSafeCallInvoke(l, node).toString()); - - l = new Location(getTestName(), 1); - node = new PSubMapShortcut(l, Map.class, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4))); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubMapShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString()); - } - - public void testPSubShortcut() { - Location l = new Location(getTestName(), 0); - PainlessClass s = painlessLookup.lookupPainlessClass(FeatureTestObject.class); - PainlessMethod getter = s.methods.get(PainlessLookupUtility.buildPainlessMethodKey("getX", 0)); - PainlessMethod setter = s.methods.get(PainlessLookupUtility.buildPainlessMethodKey("setX", 1)); - PSubShortcut node = new PSubShortcut(l, "x", FeatureTestObject.class.getName(), getter, setter); - node.prefix = new EVariable(l, "a"); - assertEquals("(PSubShortcut (EVariable a) x)", node.toString()); - assertEquals("(PSubNullSafeCallInvoke (PSubShortcut (EVariable a) x))", - new PSubNullSafeCallInvoke(l, node).toString()); - } - - public void testSBreak() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" - + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" - + " (SExpression (EAssignment (EVariable itr) ++ post))\n" - + " (SIf (EComp (EVariable itr) > (ENumeric 10000)) (SBlock (SBreak)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" - + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" - + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" - + " (SReturn (EVariable b)))", - "int itr = 2;\n" - + "int a = 1;\n" - + "int b = 1;\n" - + "do {\n" - + " itr++;\n" - + " if (itr > 10000) {\n" - + " break\n" - + " }\n" - + " int tmp = a;\n" - + " a = b;\n" - + " b = tmp + b\n" - + "} while (b < 1000);\n" - + "return b"); - } - - public void testSContinue() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" - + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" - + " (SExpression (EAssignment (EVariable itr) ++ post))\n" - + " (SIf (EComp (EVariable itr) < (ENumeric 10000)) (SBlock (SContinue)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" - + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" - + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" - + " (SReturn (EVariable b)))", - "int itr = 2;\n" - + "int a = 1;\n" - + "int b = 1;\n" - + "do {\n" - + " itr++;\n" - + " if (itr < 10000) {\n" - + " continue\n" - + " }\n" - + " int tmp = a;\n" - + " a = b;\n" - + " b = tmp + b\n" - + "} while (b < 1000);\n" - + "return b"); - } - - public void testSDeclBlock() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a))\n" - + " (SExpression (EAssignment (EVariable a) = (ENumeric 10)))\n" - + " (SReturn (EVariable a)))", - "def a;\n" - + "a = 10;\n" - + "return a"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a (ENumeric 10)))\n" - + " (SReturn (EVariable a)))", - "def a = 10;\n" - + "return a"); - assertToString( - "(SClass\n" - + " (SDeclBlock\n" - + " (SDeclaration (DUnresolvedType [def]) a)\n" - + " (SDeclaration (DUnresolvedType [def]) b)\n" - + " (SDeclaration (DUnresolvedType [def]) c))\n" - + " (SReturn (EVariable a)))", - "def a, b, c;\n" - + "return a"); - assertToString( - "(SClass\n" - + " (SDeclBlock\n" - + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" - + " (SDeclaration (DUnresolvedType [def]) b (ENumeric 20))\n" - + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" - + " (SReturn (EVariable a)))", - "def a = 10, b = 20, c = 100;\n" - + "return a"); - assertToString( - "(SClass\n" - + " (SDeclBlock\n" - + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" - + " (SDeclaration (DUnresolvedType [def]) b)\n" - + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" - + " (SReturn (EVariable a)))", - "def a = 10, b, c = 100;\n" - + "return a"); - assertToString( - "(SClass\n" - + " (SIf (PField (EVariable params) a) (SBlock\n" - + " (SDeclBlock\n" - + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" - + " (SDeclaration (DUnresolvedType [def]) b)\n" - + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" - + " (SReturn (EVariable a))))\n" - + " (SReturn (EBoolean false)))", - "if (params.a) {" - + " def a = 10, b, c = 100;\n" - + " return a\n" - + "}\n" - + "return false"); - } - - public void testSDo() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" - + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" - + " (SExpression (EAssignment (EVariable itr) ++ post))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" - + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" - + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" - + " (SReturn (EVariable b)))", - "int itr = 2;\n" - + "int a = 1;\n" - + "int b = 1;\n" - + "do {\n" - + " itr++;\n" - + " int tmp = a;\n" - + " a = b;\n" - + " b = tmp + b\n" - + "} while (b < 1000);\n" - + "return b"); - } - - public void testSEach() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) l (ENumeric 0)))\n" - + " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock " - + "(SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s) length)))))\n" - + " (SReturn (EVariable l)))", - "int l = 0;\n" - + "for (String s : ['cat', 'dog', 'chicken']) {\n" - + " l += s.length()\n" - + "}\n" - + "return l"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) l (ENumeric 0)))\n" - + " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [String]) s2 (EBinary (EString 'dire ') + (EVariable s))))\n" - + " (SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s2) length)))))\n" - + " (SReturn (EVariable l)))", - "int l = 0;\n" - + "for (String s : ['cat', 'dog', 'chicken']) {\n" - + " String s2 = 'dire ' + s;\n" - + " l += s2.length()\n" - + "}\n" - + "return l"); - } - - public void testSFor() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) sum (ENumeric 0)))\n" - + " (SFor\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" - + " (EComp (EVariable i) < (ENumeric 1000))\n" - + " (EAssignment (EVariable i) ++ post)\n" - + " (SBlock (SExpression (EAssignment (EVariable sum) += (EVariable i)))))\n" - + " (SReturn (EVariable sum)))", - "int sum = 0;\n" - + "for (int i = 0; i < 1000; i++) {\n" - + " sum += i\n" - + "}\n" - + "return sum"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) sum (ENumeric 0)))\n" - + " (SFor\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" - + " (EComp (EVariable i) < (ENumeric 1000))\n" - + " (EAssignment (EVariable i) ++ post)\n" - + " (SBlock (SFor\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) j (ENumeric 0)))\n" - + " (EComp (EVariable j) < (ENumeric 1000))\n" - + " (EAssignment (EVariable j) ++ post)\n" - + " (SBlock (SExpression (EAssignment (EVariable sum) += (EBinary (EVariable i) * (EVariable j))))))))\n" - + " (SReturn (EVariable sum)))", - "int sum = 0;\n" - + "for (int i = 0; i < 1000; i++) {\n" - + " for (int j = 0; j < 1000; j++) {\n" - + " sum += i * j\n" - + " }\n" - + "}\n" - + "return sum"); - } - - public void testSIf() { - assertToString( - "(SClass (SIf (PField (EVariable param) a) (SBlock (SReturn (EBoolean true)))))", - "if (param.a) {\n" - + " return true\n" - +"}"); - assertToString( - "(SClass (SIf (PField (EVariable param) a) (SBlock\n" - + " (SIf (PField (EVariable param) b) (SBlock (SReturn (EBoolean true))))\n" - + " (SReturn (EBoolean false)))))", - "if (param.a) {\n" - + " if (param.b) {\n" - + " return true\n" - + " }\n" - + " return false\n" - +"}"); - } - - public void testSIfElse() { - assertToString( - "(SClass (SIfElse (PField (EVariable param) a)\n" - + " (SBlock (SReturn (EBoolean true)))\n" - + " (SBlock (SReturn (EBoolean false)))))", - "if (param.a) {\n" - + " return true\n" - + "} else {\n" - + " return false\n" - + "}"); - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" - + " (SIfElse (PField (EVariable param) a)\n" - + " (SBlock (SIfElse (PField (EVariable param) b)\n" - + " (SBlock (SReturn (EBoolean true)))\n" - + " (SBlock (SReturn (EString 'cat')))))\n" - + " (SBlock (SReturn (EBoolean false)))))", - "int i = 0;\n" - + "if (param.a) {\n" - + " if (param.b) {\n" - + " return true\n" - + " } else {\n" - + " return 'cat'\n" - + " }\n" - + "} else {" - + " return false\n" - + "}"); - } - - public void testSThrow() { - assertToString("(SClass (SThrow (ENewObj RuntimeException)))", "throw new RuntimeException()"); - } - - public void testSWhile() { - assertToString( - "(SClass\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" - + " (SWhile (EComp (EVariable i) < (ENumeric 10)) (SBlock (SExpression (EAssignment (EVariable i) ++ post))))\n" - + " (SReturn (EVariable i)))", - "int i = 0;\n" - + "while (i < 10) {\n" - + " i++\n" - + "}\n" - + "return i"); - } - - public void testSFunction() { - assertToString( - "(SClass\n" - + " (SFunction def a\n" - + " (SReturn (EBoolean true)))\n" - + " (SReturn (EBoolean true)))", - "def a() {\n" - + " return true\n" - + "}\n" - + "return true"); - assertToString( - "(SClass\n" - + " (SFunction def a (Args (Pair int i) (Pair int j))\n" - + " (SReturn (EBoolean true)))\n" - + " (SReturn (EBoolean true)))", - "def a(int i, int j) {\n" - + " return true\n" - + "}\n" - + "return true"); - assertToString( - "(SClass\n" - + " (SFunction def a (Args (Pair int i) (Pair int j))\n" - + " (SIf (EComp (EVariable i) < (EVariable j)) (SBlock (SReturn (EBoolean true))))\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) k (EBinary (EVariable i) + (EVariable j))))\n" - + " (SReturn (EVariable k)))\n" - + " (SReturn (EBoolean true)))", - "def a(int i, int j) {\n" - + " if (i < j) {\n" - + " return true\n" - + " }\n" - + " int k = i + j;\n" - + " return k\n" - + "}\n" - + "return true"); - assertToString( - "(SClass\n" - + " (SFunction def a\n" - + " (SReturn (EBoolean true)))\n" - + " (SFunction def b\n" - + " (SReturn (EBoolean false)))\n" - + " (SReturn (EBoolean true)))", - "def a() {\n" - + " return true\n" - + "}\n" - + "def b() {\n" - + " return false\n" - + "}\n" - + "return true"); - } - - public void testSTryAndSCatch() { - assertToString( - "(SClass (STry (SBlock (SReturn (ENumeric 1)))\n" - + " (SCatch (DResolvedType [java.lang.Exception]) (SDeclaration (DUnresolvedType [Exception]) e) " + - "(SBlock (SReturn (ENumeric 2))))))", - "try {\n" - + " return 1\n" - + "} catch (Exception e) {\n" - + " return 2\n" - + "}"); - assertToString( - "(SClass (STry (SBlock\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 1)))\n" - + " (SReturn (ENumeric 1)))\n" - + " (SCatch (DResolvedType [java.lang.Exception]) (SDeclaration (DUnresolvedType [Exception]) e) " + - "(SBlock (SReturn (ENumeric 2))))))", - "try {\n" - + " int i = 1;" - + " return 1\n" - + "} catch (Exception e) {\n" - + " return 2\n" - + "}"); - assertToString( - "(SClass (STry (SBlock (SReturn (ENumeric 1)))\n" - + " (SCatch (DResolvedType [java.lang.Exception]) (SDeclaration (DUnresolvedType [Exception]) e) (SBlock\n" - + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 1)))\n" - + " (SReturn (ENumeric 2))))))", - "try {\n" - + " return 1\n" - + "} catch (Exception e) {" - + " int i = 1;\n" - + " return 2\n" - + "}"); - assertToString( - "(SClass (STry (SBlock (SReturn (ENumeric 1)))\n" - + " (SCatch (DResolvedType [java.lang.Exception]) (SDeclaration (DUnresolvedType [NullPointerException]) e) " + - "(SBlock (SReturn (ENumeric 2))))\n" - + " (SCatch (DResolvedType [java.lang.Exception]) (SDeclaration (DUnresolvedType [Exception]) e) " + - "(SBlock (SReturn (ENumeric 3))))))", - "try {\n" - + " return 1\n" - + "} catch (NullPointerException e) {\n" - + " return 2\n" - + "} catch (Exception e) {\n" - + " return 3\n" - + "}"); - } - - private final PainlessLookup painlessLookup; - - public NodeToStringTests() { - List whitelists = new ArrayList<>(Whitelist.BASE_WHITELISTS); - whitelists.add(WhitelistLoader.loadFromResourceFiles(Whitelist.class, "org.elasticsearch.painless.test")); - painlessLookup = PainlessLookupBuilder.buildFromWhitelists(whitelists); - } - - private void assertToString(String expected, String code) { - assertEquals(expected, walk(code).toString()); - } - - private SClass walk(String code) { - ScriptClassInfo scriptClassInfo = new ScriptClassInfo(painlessLookup, PainlessExecuteAction.PainlessTestScript.class); - CompilerSettings compilerSettings = new CompilerSettings(); - compilerSettings.setRegexesEnabled(true); - try { - return Walker.buildPainlessTree( - scriptClassInfo, getTestName(), code, compilerSettings, painlessLookup, null); - } catch (Exception e) { - throw new AssertionError("Failed to compile: " + code, e); - } - } -}