SLING-8217 - Numeric operations can lead to Java code that doesn't compile
diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/LongOpGen.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/LongOpGen.java
index a2b2502..7876b96 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/LongOpGen.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/LongOpGen.java
@@ -17,6 +17,7 @@
package org.apache.sling.scripting.sightly.java.compiler.impl.operator;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
import org.apache.sling.scripting.sightly.java.compiler.impl.Type;
/**
@@ -24,8 +25,8 @@
*/
public class LongOpGen extends NumericOpGen {
- public LongOpGen(String javaOperator) {
- super(javaOperator);
+ public LongOpGen(String javaOperator, BinaryOperator binaryOperator) {
+ super(javaOperator, binaryOperator);
}
@Override
diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/NumericOpGen.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/NumericOpGen.java
index be3dc7e..2d57d56 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/NumericOpGen.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/NumericOpGen.java
@@ -17,9 +17,11 @@
package org.apache.sling.scripting.sightly.java.compiler.impl.operator;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
import org.apache.sling.scripting.sightly.java.compiler.impl.ExpressionTranslator;
import org.apache.sling.scripting.sightly.java.compiler.impl.GenHelper;
import org.apache.sling.scripting.sightly.java.compiler.impl.JavaSource;
+import org.apache.sling.scripting.sightly.java.compiler.impl.SourceGenConstants;
import org.apache.sling.scripting.sightly.java.compiler.impl.Type;
/**
@@ -27,10 +29,15 @@
*/
public class NumericOpGen implements BinaryOpGen {
- private final String javaOperator;
+ private static final String OBJECT_NAME = BinaryOperator.class.getName();
+ private static final String METHOD_NAME = "eval";
- public NumericOpGen(String javaOperator) {
+ private final String javaOperator;
+ private final BinaryOperator binaryOperator;
+
+ public NumericOpGen(String javaOperator, BinaryOperator binaryOperator) {
this.javaOperator = javaOperator;
+ this.binaryOperator = binaryOperator;
}
@Override
@@ -41,9 +48,12 @@
@Override
public void generate(JavaSource source, ExpressionTranslator visitor, TypedNode left, TypedNode right) {
Type commonType = commonType(left.getType(), right.getType());
- GenHelper.typeCoercion(source, visitor, left, commonType);
- source.append(" ").append(javaOperator).append(" ");
- GenHelper.typeCoercion(source, visitor, right, commonType);
+ source.objectModel().startCall(SourceGenConstants.ROM_TO_NUMBER, true).startMethodCall(OBJECT_NAME + "." + binaryOperator.name(),
+ METHOD_NAME);
+ left.getNode().accept(visitor);
+ source.separateArgument();
+ right.getNode().accept(visitor);
+ source.endCall().endCall().startCall(commonType.getNativeClass() + "Value", true).endCall();
}
protected Type commonType(Type leftType, Type rightType) {
diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/Operators.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/Operators.java
index c445b29..a895e4d 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/Operators.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/operator/Operators.java
@@ -37,12 +37,12 @@
representationMap.put(BinaryOperator.AND, LogicalOpGen.AND);
representationMap.put(BinaryOperator.OR, LogicalOpGen.OR);
representationMap.put(BinaryOperator.CONCATENATE, ConcatenateOpGen.INSTANCE);
- representationMap.put(BinaryOperator.ADD, new NumericOpGen("+"));
- representationMap.put(BinaryOperator.SUB, new NumericOpGen("-"));
- representationMap.put(BinaryOperator.MUL, new NumericOpGen("*"));
- representationMap.put(BinaryOperator.I_DIV, new LongOpGen("/"));
- representationMap.put(BinaryOperator.REM, new LongOpGen("%"));
- representationMap.put(BinaryOperator.DIV, new NumericOpGen("/"));
+ representationMap.put(BinaryOperator.ADD, new NumericOpGen("+", BinaryOperator.ADD));
+ representationMap.put(BinaryOperator.SUB, new NumericOpGen("-", BinaryOperator.SUB));
+ representationMap.put(BinaryOperator.MUL, new NumericOpGen("*", BinaryOperator.MUL));
+ representationMap.put(BinaryOperator.I_DIV, new LongOpGen("/", BinaryOperator.I_DIV));
+ representationMap.put(BinaryOperator.REM, new LongOpGen("%", BinaryOperator.REM));
+ representationMap.put(BinaryOperator.DIV, new NumericOpGen("/", BinaryOperator.DIV));
representationMap.put(BinaryOperator.EQ, new EquivalenceOpGen(false));
representationMap.put(BinaryOperator.NEQ, new EquivalenceOpGen(true));
representationMap.put(BinaryOperator.LT, new ComparisonOpGen(BinaryOperator.LT));
diff --git a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java
index a1606c3..9437054 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java
@@ -108,7 +108,27 @@
CharSequenceJavaCompiler<RenderUnit> compiler = new CharSequenceJavaCompiler<>(classLoader, null);
compiler.compile(classInfo.getFullyQualifiedClassName(), source);
}
-
+
+ @Test
+ public void sling_8217() throws Exception {
+ CompilationUnit compilationUnit = TestUtils.readScriptFromClasspath("/SLING-8217.html");
+ JavaClassBackendCompiler backendCompiler = new JavaClassBackendCompiler();
+ SightlyCompiler sightlyCompiler = new SightlyCompiler();
+ sightlyCompiler.compile(compilationUnit, backendCompiler);
+ ClassInfo classInfo = buildClassInfo("sling_8217");
+ String source = backendCompiler.build(classInfo);
+ StringWriter writer = new StringWriter();
+ Bindings bindings = new SimpleBindings();
+ HashMap<String, Integer> properties = new HashMap<String, Integer>(){{
+ put("begin", 1);
+ }};
+ bindings.put("properties", properties);
+ RenderContext renderContext = buildRenderContext(bindings);
+ render(writer, classInfo, source, renderContext, new SimpleBindings());
+ String expectedOutput = IOUtils.toString(this.getClass().getResourceAsStream("/SLING-8217.output.html"), "UTF-8");
+ assertEquals(expectedOutput, writer.toString());
+ }
+
private static final String normalizeLineEndings(String input) {
return StringUtils.replaceAll(input, "\r\n", "\n");
}
diff --git a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/utils/CharSequenceJavaCompiler.java b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/utils/CharSequenceJavaCompiler.java
index 2ddc681..b4c752d 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/utils/CharSequenceJavaCompiler.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/utils/CharSequenceJavaCompiler.java
@@ -31,6 +31,8 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+
+import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
@@ -124,13 +126,20 @@
*/
public synchronized Class<T> compile(final String qualifiedClassName,
final CharSequence javaSource,
- final Class<?>... types) throws CharSequenceJavaCompilerException,
- ClassCastException {
+ final Class<?>... types) throws ClassCastException {
Map<String, CharSequence> classes = new HashMap<>(1);
classes.put(qualifiedClassName, javaSource);
- Map<String, Class<T>> compiled = compile(classes);
- Class<T> newClass = compiled.get(qualifiedClassName);
- return castable(newClass, types);
+ try {
+ Map<String, Class<T>> compiled = compile(classes);
+ Class<T> newClass = compiled.get(qualifiedClassName);
+ return castable(newClass, types);
+ } catch (CharSequenceJavaCompilerException e) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (Diagnostic diagnostic : e.getDiagnostics().getDiagnostics()) {
+ stringBuilder.append(diagnostic.toString()).append(System.lineSeparator());
+ }
+ throw new RuntimeException(stringBuilder.toString());
+ }
}
/**
diff --git a/src/test/resources/SLING-8217.html b/src/test/resources/SLING-8217.html
new file mode 100644
index 0000000..8762f89
--- /dev/null
+++ b/src/test/resources/SLING-8217.html
@@ -0,0 +1,21 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+<ul data-sly-list="${[1, 2, 3, 4, 5] @ begin = properties.begin}">
+ <li class="${itemList.index}">${item}</li>
+</ul>
diff --git a/src/test/resources/SLING-8217.output.html b/src/test/resources/SLING-8217.output.html
new file mode 100644
index 0000000..311378e
--- /dev/null
+++ b/src/test/resources/SLING-8217.output.html
@@ -0,0 +1,10 @@
+
+<ul>
+ <li class="1">2</li>
+
+ <li class="2">3</li>
+
+ <li class="3">4</li>
+
+ <li class="4">5</li>
+</ul>