Rework compilation of OpNE/OpEQ SpEL operators
For SPR-14863 we need to adjust the code generation for OpNE
to use !x.equals(y) rather than x!=y. There are also further
cases in the equalityCheck() code in Operator that were not
being handled in the compilation case (when comparators are
used for example). This latter issue also affects OpEQ.
Rather than add yet more bytecode generation, both OpNE and
OpEQ generateCode() methods have been simplified. The
generated code now delegates to equalityCheck() in Operator
which is exactly what the interpreted case does.
This ensures that the compiled code continues to behave just
like the interpreted case. It ensures changes to the interpreted
case are automatically picked up for the compiled case. It
makes the bytecode generation simpler.
The benefit of compilation of SpEL expressions is to avoid
slow reflective calls - that doesn't apply for a basic
(in)equality test so there is no need to go crazy in bytecode
gen.
Issue: SPR-14863
(cherry picked from commit 9000acd
)
This commit is contained in:
parent
77e00f1926
commit
38cd1ecff4
|
@ -28,15 +28,28 @@ import org.springframework.asm.Opcodes;
|
|||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Manages the class being generated by the compilation process. It records
|
||||
* intermediate compilation state as the bytecode is generated. It also includes
|
||||
* various bytecode generation helper functions.
|
||||
* Manages the class being generated by the compilation process.
|
||||
*
|
||||
* <p>Records intermediate compilation state as the bytecode is generated.
|
||||
* Also includes various bytecode generation helper functions.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class CodeFlow implements Opcodes {
|
||||
|
||||
/**
|
||||
* Name of the class being generated. Typically used when generating code
|
||||
* that accesses freshly generated fields on the generated type.
|
||||
*/
|
||||
private final String className;
|
||||
|
||||
/**
|
||||
* The current class being generated.
|
||||
*/
|
||||
private final ClassWriter classWriter;
|
||||
|
||||
/**
|
||||
* Record the type of what is on top of the bytecode stack (i.e. the type of the
|
||||
* output from the previous expression component). New scopes are used to evaluate
|
||||
|
@ -45,17 +58,12 @@ public class CodeFlow implements Opcodes {
|
|||
*/
|
||||
private final Stack<ArrayList<String>> compilationScopes;
|
||||
|
||||
/**
|
||||
* The current class being generated
|
||||
*/
|
||||
private ClassWriter cw;
|
||||
|
||||
/**
|
||||
* As SpEL ast nodes are called to generate code for the main evaluation method
|
||||
* they can register to add a field to this class. Any registered FieldAdders
|
||||
* will be called after the main evaluation function has finished being generated.
|
||||
*/
|
||||
private List<FieldAdder> fieldAdders = null;
|
||||
private List<FieldAdder> fieldAdders;
|
||||
|
||||
/**
|
||||
* As SpEL ast nodes are called to generate code for the main evaluation method
|
||||
|
@ -63,13 +71,7 @@ public class CodeFlow implements Opcodes {
|
|||
* registered ClinitAdders will be called after the main evaluation function
|
||||
* has finished being generated.
|
||||
*/
|
||||
private List<ClinitAdder> clinitAdders = null;
|
||||
|
||||
/**
|
||||
* Name of the class being generated. Typically used when generating code
|
||||
* that accesses freshly generated fields on the generated type.
|
||||
*/
|
||||
private String clazzName;
|
||||
private List<ClinitAdder> clinitAdders;
|
||||
|
||||
/**
|
||||
* When code generation requires holding a value in a class level field, this
|
||||
|
@ -83,13 +85,20 @@ public class CodeFlow implements Opcodes {
|
|||
*/
|
||||
private int nextFreeVariableId = 1;
|
||||
|
||||
public CodeFlow(String clazzName, ClassWriter cw) {
|
||||
|
||||
/**
|
||||
* Construct a new {@code CodeFlow} for the given class.
|
||||
* @param className the name of the class
|
||||
* @param classWriter the corresponding ASM {@code ClassWriter}
|
||||
*/
|
||||
public CodeFlow(String className, ClassWriter classWriter) {
|
||||
this.className = className;
|
||||
this.classWriter = classWriter;
|
||||
this.compilationScopes = new Stack<ArrayList<String>>();
|
||||
this.compilationScopes.add(new ArrayList<String>());
|
||||
this.cw = cw;
|
||||
this.clazzName = clazzName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Push the byte code to load the target (i.e. what was passed as the first argument
|
||||
* to CompiledExpression.getValue(target, context))
|
||||
|
@ -99,6 +108,16 @@ public class CodeFlow implements Opcodes {
|
|||
mv.visitVarInsn(ALOAD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the bytecode to load the EvaluationContext (the second parameter passed to
|
||||
* the compiled expression method).
|
||||
* @param mv the visitor into which the load instruction should be inserted
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public void loadEvaluationContext(MethodVisitor mv) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the descriptor for the most recently evaluated expression element.
|
||||
* @param descriptor type descriptor for most recently evaluated element
|
||||
|
@ -155,13 +174,13 @@ public class CodeFlow implements Opcodes {
|
|||
public void finish() {
|
||||
if (this.fieldAdders != null) {
|
||||
for (FieldAdder fieldAdder : this.fieldAdders) {
|
||||
fieldAdder.generateField(cw,this);
|
||||
fieldAdder.generateField(this.classWriter, this);
|
||||
}
|
||||
}
|
||||
if (this.clinitAdders != null) {
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
MethodVisitor mv = this.classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
this.nextFreeVariableId = 0; // To 0 because there is no 'this' in a clinit
|
||||
this.nextFreeVariableId = 0; // to 0 because there is no 'this' in a clinit
|
||||
for (ClinitAdder clinitAdder : this.clinitAdders) {
|
||||
clinitAdder.generateCode(mv, this);
|
||||
}
|
||||
|
@ -204,18 +223,18 @@ public class CodeFlow implements Opcodes {
|
|||
}
|
||||
|
||||
public String getClassName() {
|
||||
return this.clazzName;
|
||||
return this.className;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getClassname() {
|
||||
return this.clazzName;
|
||||
return this.className;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert any necessary cast and value call to convert from a boxed type to a
|
||||
* primitive value
|
||||
* primitive value.
|
||||
* @param mv the method visitor into which instructions should be inserted
|
||||
* @param ch the primitive type desired as output
|
||||
* @param stackDescriptor the descriptor of the type on top of the stack
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,8 +16,8 @@
|
|||
|
||||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import org.springframework.asm.Label;
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.CodeFlow;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
@ -43,7 +43,8 @@ public class OpEQ extends Operator {
|
|||
Object right = getRightOperand().getValueInternal(state).getValue();
|
||||
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
|
||||
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
|
||||
return BooleanTypedValue.forValue(equalityCheck(state, left, right));
|
||||
return BooleanTypedValue.forValue(
|
||||
equalityCheck(state.getEvaluationContext(), left, right));
|
||||
}
|
||||
|
||||
// This check is different to the one in the other numeric operators (OpLt/etc)
|
||||
|
@ -58,90 +59,36 @@ public class OpEQ extends Operator {
|
|||
|
||||
String leftDesc = left.exitTypeDescriptor;
|
||||
String rightDesc = right.exitTypeDescriptor;
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc,
|
||||
rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
return (!dc.areNumbers || dc.areCompatible);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void generateCode(MethodVisitor mv, CodeFlow cf) {
|
||||
cf.loadEvaluationContext(mv);
|
||||
String leftDesc = getLeftOperand().exitTypeDescriptor;
|
||||
String rightDesc = getRightOperand().exitTypeDescriptor;
|
||||
Label elseTarget = new Label();
|
||||
Label endOfIf = new Label();
|
||||
boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
|
||||
boolean rightPrim = CodeFlow.isPrimitive(rightDesc);
|
||||
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
|
||||
if (dc.areNumbers && dc.areCompatible) {
|
||||
char targetType = dc.compatibleType;
|
||||
cf.enterCompilationScope();
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
if (!leftPrim) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
cf.exitCompilationScope();
|
||||
if (leftPrim) {
|
||||
CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
|
||||
}
|
||||
cf.enterCompilationScope();
|
||||
getRightOperand().generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
if (!rightPrim) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
|
||||
}
|
||||
// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
|
||||
if (targetType == 'D') {
|
||||
mv.visitInsn(DCMPL);
|
||||
mv.visitJumpInsn(IFNE, elseTarget);
|
||||
}
|
||||
else if (targetType == 'F') {
|
||||
mv.visitInsn(FCMPL);
|
||||
mv.visitJumpInsn(IFNE, elseTarget);
|
||||
}
|
||||
else if (targetType == 'J') {
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitJumpInsn(IFNE, elseTarget);
|
||||
}
|
||||
else if (targetType == 'I' || targetType == 'Z') {
|
||||
mv.visitJumpInsn(IF_ICMPNE, elseTarget);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected descriptor " + leftDesc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
if (leftPrim) {
|
||||
CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
|
||||
}
|
||||
getRightOperand().generateCode(mv, cf);
|
||||
if (rightPrim) {
|
||||
CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
|
||||
}
|
||||
Label leftNotNull = new Label();
|
||||
mv.visitInsn(DUP_X1); // dup right on the top of the stack
|
||||
mv.visitJumpInsn(IFNONNULL, leftNotNull);
|
||||
// Right is null!
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitInsn(POP); // remove it
|
||||
Label rightNotNull = new Label();
|
||||
mv.visitJumpInsn(IFNONNULL, rightNotNull);
|
||||
// Left is null too
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
mv.visitLabel(rightNotNull);
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
mv.visitLabel(leftNotNull);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false);
|
||||
mv.visitLabel(endOfIf);
|
||||
cf.pushDescriptor("Z");
|
||||
return;
|
||||
}
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
mv.visitLabel(elseTarget);
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitLabel(endOfIf);
|
||||
|
||||
String operatorClassName = Operator.class.getName().replace('.', '/');
|
||||
String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
|
||||
mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
|
||||
"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||
cf.pushDescriptor("Z");
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.expression.spel.ast;
|
|||
|
||||
import org.springframework.asm.Label;
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.CodeFlow;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
@ -43,7 +44,8 @@ public class OpNE extends Operator {
|
|||
Object right = getRightOperand().getValueInternal(state).getValue();
|
||||
this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
|
||||
this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
|
||||
return BooleanTypedValue.forValue(!equalityCheck(state, left, right));
|
||||
return BooleanTypedValue.forValue(
|
||||
!equalityCheck(state.getEvaluationContext(), left, right));
|
||||
}
|
||||
|
||||
// This check is different to the one in the other numeric operators (OpLt/etc)
|
||||
|
@ -58,65 +60,47 @@ public class OpNE extends Operator {
|
|||
|
||||
String leftDesc = left.exitTypeDescriptor;
|
||||
String rightDesc = right.exitTypeDescriptor;
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc,
|
||||
rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
return (!dc.areNumbers || dc.areCompatible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateCode(MethodVisitor mv, CodeFlow cf) {
|
||||
cf.loadEvaluationContext(mv);
|
||||
String leftDesc = getLeftOperand().exitTypeDescriptor;
|
||||
String rightDesc = getRightOperand().exitTypeDescriptor;
|
||||
Label elseTarget = new Label();
|
||||
Label endOfIf = new Label();
|
||||
boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
|
||||
boolean rightPrim = CodeFlow.isPrimitive(rightDesc);
|
||||
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
|
||||
if (dc.areNumbers && dc.areCompatible) {
|
||||
char targetType = dc.compatibleType;
|
||||
cf.enterCompilationScope();
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
if (!leftPrim) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
cf.exitCompilationScope();
|
||||
if (leftPrim) {
|
||||
CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
|
||||
}
|
||||
cf.enterCompilationScope();
|
||||
getRightOperand().generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
if (!rightPrim) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
|
||||
}
|
||||
// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
|
||||
if (targetType == 'D') {
|
||||
mv.visitInsn(DCMPL);
|
||||
mv.visitJumpInsn(IFEQ, elseTarget);
|
||||
}
|
||||
else if (targetType == 'F') {
|
||||
mv.visitInsn(FCMPL);
|
||||
mv.visitJumpInsn(IFEQ, elseTarget);
|
||||
}
|
||||
else if (targetType == 'J') {
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitJumpInsn(IFEQ, elseTarget);
|
||||
}
|
||||
else if (targetType == 'I' || targetType == 'Z') {
|
||||
mv.visitJumpInsn(IF_ICMPEQ, elseTarget);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected descriptor " + leftDesc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
getRightOperand().generateCode(mv, cf);
|
||||
mv.visitJumpInsn(IF_ACMPEQ, elseTarget);
|
||||
if (rightPrim) {
|
||||
CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
|
||||
}
|
||||
|
||||
String operatorClassName = Operator.class.getName().replace('.', '/');
|
||||
String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
|
||||
mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
|
||||
"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||
|
||||
// Invert the boolean
|
||||
Label notZero = new Label();
|
||||
Label end = new Label();
|
||||
mv.visitJumpInsn(IFNE, notZero);
|
||||
mv.visitInsn(ICONST_1);
|
||||
mv.visitJumpInsn(GOTO,endOfIf);
|
||||
mv.visitLabel(elseTarget);
|
||||
mv.visitJumpInsn(GOTO, end);
|
||||
mv.visitLabel(notZero);
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitLabel(endOfIf);
|
||||
mv.visitLabel(end);
|
||||
|
||||
cf.pushDescriptor("Z");
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ import java.math.BigInteger;
|
|||
|
||||
import org.springframework.asm.Label;
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.CodeFlow;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.NumberUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
@ -114,7 +114,9 @@ public abstract class Operator extends SpelNodeImpl {
|
|||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
|
||||
|
||||
cf.enterCompilationScope();
|
||||
getLeftOperand().generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
if (unboxLeft) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
}
|
||||
|
@ -157,7 +159,17 @@ public abstract class Operator extends SpelNodeImpl {
|
|||
cf.pushDescriptor("Z");
|
||||
}
|
||||
|
||||
protected boolean equalityCheck(ExpressionState state, Object left, Object right) {
|
||||
|
||||
/**
|
||||
* Perform an equality check for the given operand values.
|
||||
* <p>This method is not just used for reflective comparisons in subclasses
|
||||
* but also from compiled expression code, which is why it needs to be
|
||||
* declared as {@code public static} here.
|
||||
* @param context the current evaluation context
|
||||
* @param left the left-hand operand value
|
||||
* @param right the right-hand operand value
|
||||
*/
|
||||
public static boolean equalityCheck(EvaluationContext context, Object left, Object right) {
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number leftNumber = (Number) left;
|
||||
Number rightNumber = (Number) right;
|
||||
|
@ -207,7 +219,7 @@ public abstract class Operator extends SpelNodeImpl {
|
|||
if (left instanceof Comparable && right instanceof Comparable) {
|
||||
Class<?> ancestor = ClassUtils.determineCommonAncestor(left.getClass(), right.getClass());
|
||||
if (ancestor != null && Comparable.class.isAssignableFrom(ancestor)) {
|
||||
return (state.getTypeComparator().compare(left, right) == 0);
|
||||
return (context.getTypeComparator().compare(left, right) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,16 +44,14 @@ import org.springframework.expression.spel.testdata.PersonInOtherPackage;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Checks the behaviour of the SpelCompiler. This should cover compilation all compiled node types.
|
||||
* Checks the behaviour of the SpelCompiler.
|
||||
* This should cover compilation all compiled node types.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 4.1
|
||||
*/
|
||||
public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
|
||||
private Expression expression;
|
||||
private SpelNodeImpl ast;
|
||||
|
||||
/*
|
||||
* Further TODOs for compilation:
|
||||
*
|
||||
|
@ -118,6 +116,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
* Selection
|
||||
*/
|
||||
|
||||
|
||||
private Expression expression;
|
||||
|
||||
private SpelNodeImpl ast;
|
||||
|
||||
|
||||
@Test
|
||||
public void typeReference() throws Exception {
|
||||
expression = parse("T(String)");
|
||||
|
@ -198,7 +202,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertCanCompile(expression);
|
||||
assertEquals(false, expression.getValue());
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
List<String> list = new ArrayList<>();
|
||||
expression = parse("#root instanceof T(java.util.List)");
|
||||
assertEquals(true, expression.getValue(list));
|
||||
assertCanCompile(expression);
|
||||
|
@ -761,8 +765,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
expression = parser.parseExpression("#doFormat('hey %s', 'there')");
|
||||
context = new StandardEvaluationContext();
|
||||
context.registerFunction("doFormat",
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class,
|
||||
Object[].class));
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
|
||||
((SpelExpression) expression).setEvaluationContext(context);
|
||||
|
||||
assertEquals("hey there", expression.getValue(String.class));
|
||||
|
@ -773,8 +776,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
expression = parser.parseExpression("#doFormat([0], 'there')");
|
||||
context = new StandardEvaluationContext(new Object[] {"hey %s"});
|
||||
context.registerFunction("doFormat",
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class,
|
||||
Object[].class));
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
|
||||
((SpelExpression) expression).setEvaluationContext(context);
|
||||
|
||||
assertEquals("hey there", expression.getValue(String.class));
|
||||
|
@ -785,8 +787,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
expression = parser.parseExpression("#doFormat([0], #arg)");
|
||||
context = new StandardEvaluationContext(new Object[] {"hey %s"});
|
||||
context.registerFunction("doFormat",
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class,
|
||||
Object[].class));
|
||||
DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
|
||||
context.setVariable("arg", "there");
|
||||
((SpelExpression) expression).setEvaluationContext(context);
|
||||
|
||||
|
@ -799,7 +800,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
@Test
|
||||
public void functionReference() throws Exception {
|
||||
EvaluationContext ctx = new StandardEvaluationContext();
|
||||
Method m = this.getClass().getDeclaredMethod("concat",String.class,String.class);
|
||||
Method m = getClass().getDeclaredMethod("concat", String.class, String.class);
|
||||
ctx.setVariable("concat",m);
|
||||
|
||||
expression = parser.parseExpression("#concat('a','b')");
|
||||
|
@ -1066,7 +1067,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
@Test
|
||||
public void functionReferenceVarargs() throws Exception {
|
||||
EvaluationContext ctx = new StandardEvaluationContext();
|
||||
Method m = this.getClass().getDeclaredMethod("join", String[].class);
|
||||
Method m = getClass().getDeclaredMethod("join", String[].class);
|
||||
ctx.setVariable("join", m);
|
||||
expression = parser.parseExpression("#join('a','b','c')");
|
||||
assertEquals("abc", expression.getValue(ctx));
|
||||
|
@ -1335,8 +1336,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
public void opEq() throws Exception {
|
||||
String tvar = "35";
|
||||
expression = parse("#root == 35");
|
||||
Boolean bb = (Boolean)expression.getValue(tvar);
|
||||
System.out.println(bb);
|
||||
assertFalse((Boolean) expression.getValue(tvar));
|
||||
assertCanCompile(expression);
|
||||
assertFalse((Boolean) expression.getValue(tvar));
|
||||
|
@ -1623,6 +1622,82 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertTrue((Boolean) expression.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void opNe_SPR14863() throws Exception {
|
||||
SpelParserConfiguration configuration =
|
||||
new SpelParserConfiguration(SpelCompilerMode.MIXED, ClassLoader.getSystemClassLoader());
|
||||
SpelExpressionParser parser = new SpelExpressionParser(configuration);
|
||||
Expression expression = parser.parseExpression("data['my-key'] != 'my-value'");
|
||||
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("my-key", new String("my-value"));
|
||||
StandardEvaluationContext context = new StandardEvaluationContext(new MyContext(data));
|
||||
assertFalse(expression.getValue(context, Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
((SpelExpression) expression).compileExpression();
|
||||
assertFalse(expression.getValue(context, Boolean.class));
|
||||
|
||||
List<String> ls = new ArrayList<String>();
|
||||
ls.add(new String("foo"));
|
||||
context = new StandardEvaluationContext(ls);
|
||||
expression = parse("get(0) != 'foo'");
|
||||
assertFalse(expression.getValue(context, Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(context, Boolean.class));
|
||||
|
||||
ls.remove(0);
|
||||
ls.add("goo");
|
||||
assertTrue(expression.getValue(context, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void opEq_SPR14863() throws Exception {
|
||||
// Exercise the comparator invocation code that runs in
|
||||
// equalityCheck() (called from interpreted and compiled code)
|
||||
expression = parser.parseExpression("#aa==#bb");
|
||||
StandardEvaluationContext sec = new StandardEvaluationContext();
|
||||
Apple aa = new Apple(1);
|
||||
Apple bb = new Apple(2);
|
||||
sec.setVariable("aa",aa);
|
||||
sec.setVariable("bb",bb);
|
||||
boolean b = expression.getValue(sec, Boolean.class);
|
||||
// Verify what the expression caused aa to be compared to
|
||||
assertEquals(bb,aa.gotComparedTo);
|
||||
assertFalse(b);
|
||||
bb.setValue(1);
|
||||
b = expression.getValue(sec, Boolean.class);
|
||||
assertEquals(bb,aa.gotComparedTo);
|
||||
assertTrue(b);
|
||||
|
||||
assertCanCompile(expression);
|
||||
|
||||
// Similar test with compiled expression
|
||||
aa = new Apple(99);
|
||||
bb = new Apple(100);
|
||||
sec.setVariable("aa",aa);
|
||||
sec.setVariable("bb",bb);
|
||||
b = expression.getValue(sec, Boolean.class);
|
||||
assertFalse(b);
|
||||
assertEquals(bb,aa.gotComparedTo);
|
||||
bb.setValue(99);
|
||||
b = expression.getValue(sec, Boolean.class);
|
||||
assertTrue(b);
|
||||
assertEquals(bb,aa.gotComparedTo);
|
||||
|
||||
|
||||
List<String> ls = new ArrayList<String>();
|
||||
ls.add(new String("foo"));
|
||||
StandardEvaluationContext context = new StandardEvaluationContext(ls);
|
||||
expression = parse("get(0) == 'foo'");
|
||||
assertTrue(expression.getValue(context, Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(context, Boolean.class));
|
||||
|
||||
ls.remove(0);
|
||||
ls.add("goo");
|
||||
assertFalse(expression.getValue(context, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void opPlus() throws Exception {
|
||||
expression = parse("2+2");
|
||||
|
@ -2616,7 +2691,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
checkCalc(p,"payload.valueI*payload.valueBB20",2400);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void opModulus_mixedNumberTypes() throws Exception {
|
||||
PayloadX p = new PayloadX();
|
||||
|
@ -2923,11 +2997,11 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals(0, expression.getValue());
|
||||
|
||||
expression = parse("payload%2==0");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(5),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(5), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(5),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(5), Boolean.TYPE));
|
||||
|
||||
expression = parse("8%3");
|
||||
assertEquals(2, expression.getValue());
|
||||
|
@ -3104,7 +3178,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
public void constructorReference_SPR12326() {
|
||||
String type = this.getClass().getName();
|
||||
String type = getClass().getName();
|
||||
String prefix = "new " + type + ".Obj";
|
||||
|
||||
expression = parser.parseExpression(prefix + "([0])");
|
||||
|
@ -3183,7 +3257,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
// Variant of above more like what was in the bug report:
|
||||
SpelExpressionParser parser = new SpelExpressionParser(
|
||||
new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
|
||||
this.getClass().getClassLoader()));
|
||||
getClass().getClassLoader()));
|
||||
|
||||
SpelExpression ex = parser.parseRaw("#it?.age.equals([0])");
|
||||
context = new StandardEvaluationContext(new Object[] { person.getAge() });
|
||||
|
@ -3783,7 +3857,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertTrue(see.getCause() instanceof ClassCastException);
|
||||
}
|
||||
|
||||
|
||||
// method with changing target
|
||||
expression = parser.parseExpression("#root.charAt(0)");
|
||||
assertEquals('a', expression.getValue("abc"));
|
||||
|
@ -3897,11 +3970,11 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
public void mixingItUp_indexerOpEqTernary() throws Exception {
|
||||
Map<String, String> m = new HashMap<String,String>();
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("andy","778");
|
||||
|
||||
expression = parse("['andy']==null?1:2");
|
||||
System.out.println(expression.getValue(m));
|
||||
assertEquals(2, expression.getValue(m));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(2, expression.getValue(m));
|
||||
m.remove("andy");
|
||||
|
@ -4028,7 +4101,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("C", getAst().getExitDescriptor());
|
||||
|
||||
// Collections
|
||||
List<String> strings = new ArrayList<String>();
|
||||
List<String> strings = new ArrayList<>();
|
||||
strings.add("aaa");
|
||||
strings.add("bbb");
|
||||
strings.add("ccc");
|
||||
|
@ -4038,7 +4111,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("bbb", expression.getValue(strings));
|
||||
assertEquals("Ljava/lang/Object", getAst().getExitDescriptor());
|
||||
|
||||
List<Integer> ints = new ArrayList<Integer>();
|
||||
List<Integer> ints = new ArrayList<>();
|
||||
ints.add(123);
|
||||
ints.add(456);
|
||||
ints.add(789);
|
||||
|
@ -4049,7 +4122,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("Ljava/lang/Object", getAst().getExitDescriptor());
|
||||
|
||||
// Maps
|
||||
Map<String,Integer> map1 = new HashMap<String,Integer>();
|
||||
Map<String, Integer> map1 = new HashMap<>();
|
||||
map1.put("aaa", 111);
|
||||
map1.put("bbb", 222);
|
||||
map1.put("ccc", 333);
|
||||
|
@ -4082,7 +4155,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
// list of arrays
|
||||
|
||||
List<String[]> listOfStringArrays = new ArrayList<String[]>();
|
||||
List<String[]> listOfStringArrays = new ArrayList<>();
|
||||
listOfStringArrays.add(new String[] {"a","b","c"});
|
||||
listOfStringArrays.add(new String[] {"d","e","f"});
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
@ -4097,7 +4170,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("d", stringify(expression.getValue(listOfStringArrays)));
|
||||
assertEquals("Ljava/lang/String", getAst().getExitDescriptor());
|
||||
|
||||
List<Integer[]> listOfIntegerArrays = new ArrayList<Integer[]>();
|
||||
List<Integer[]> listOfIntegerArrays = new ArrayList<>();
|
||||
listOfIntegerArrays.add(new Integer[] {1,2,3});
|
||||
listOfIntegerArrays.add(new Integer[] {4,5,6});
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
@ -4114,11 +4187,11 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
// array of lists
|
||||
List<String>[] stringArrayOfLists = new ArrayList[2];
|
||||
stringArrayOfLists[0] = new ArrayList<String>();
|
||||
stringArrayOfLists[0] = new ArrayList<>();
|
||||
stringArrayOfLists[0].add("a");
|
||||
stringArrayOfLists[0].add("b");
|
||||
stringArrayOfLists[0].add("c");
|
||||
stringArrayOfLists[1] = new ArrayList<String>();
|
||||
stringArrayOfLists[1] = new ArrayList<>();
|
||||
stringArrayOfLists[1].add("d");
|
||||
stringArrayOfLists[1].add("e");
|
||||
stringArrayOfLists[1].add("f");
|
||||
|
@ -4163,13 +4236,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("I", getAst().getExitDescriptor());
|
||||
|
||||
// list of lists of reference types
|
||||
List<List<String>> listOfListOfStrings = new ArrayList<List<String>>();
|
||||
List<String> list = new ArrayList<String>();
|
||||
List<List<String>> listOfListOfStrings = new ArrayList<>();
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("a");
|
||||
list.add("b");
|
||||
list.add("c");
|
||||
listOfListOfStrings.add(list);
|
||||
list = new ArrayList<String>();
|
||||
list = new ArrayList<>();
|
||||
list.add("d");
|
||||
list.add("e");
|
||||
list.add("f");
|
||||
|
@ -4189,8 +4262,8 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("Ljava/lang/Object", getAst().getExitDescriptor());
|
||||
|
||||
// Map of lists
|
||||
Map<String,List<String>> mapToLists = new HashMap<String,List<String>>();
|
||||
list = new ArrayList<String>();
|
||||
Map<String,List<String>> mapToLists = new HashMap<>();
|
||||
list = new ArrayList<>();
|
||||
list.add("a");
|
||||
list.add("b");
|
||||
list.add("c");
|
||||
|
@ -4209,7 +4282,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertEquals("Ljava/lang/Object", getAst().getExitDescriptor());
|
||||
|
||||
// Map to array
|
||||
Map<String,int[]> mapToIntArray = new HashMap<String,int[]>();
|
||||
Map<String,int[]> mapToIntArray = new HashMap<>();
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
ctx.addPropertyAccessor(new CompilableMapAccessor());
|
||||
mapToIntArray.put("foo",new int[] {1,2,3});
|
||||
|
@ -4244,7 +4317,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
// Map array
|
||||
Map<String, String>[] mapArray = new Map[1];
|
||||
mapArray[0] = new HashMap<String,String>();
|
||||
mapArray[0] = new HashMap<>();
|
||||
mapArray[0].put("key", "value1");
|
||||
expression = parser.parseExpression("[0]");
|
||||
assertEquals("{key=value1}", stringify(expression.getValue(mapArray)));
|
||||
|
@ -4318,11 +4391,11 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
// v = expression.getValue(ctx,holder);
|
||||
// }
|
||||
// System.out.println((System.currentTimeMillis() - stime));
|
||||
//
|
||||
|
||||
assertCanCompile(expression);
|
||||
v = expression.getValue(ctx,holder);
|
||||
assertEquals("abc", v);
|
||||
//
|
||||
|
||||
// // time it compiled
|
||||
// stime = System.currentTimeMillis();
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
|
@ -4334,202 +4407,202 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
@Test
|
||||
public void compilerWithGenerics_12040() {
|
||||
expression = parser.parseExpression("payload!=2");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(2),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(2), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("2!=payload");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(2),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(2), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("payload!=6L");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Long>(4L),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(4L), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Long>(6L),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(6L), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("payload==2");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(2),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(2), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("2==payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(2),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(2), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("payload==6L");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Long>(4L),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(4L), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Long>(6L),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(6L), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("2==payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<Integer>(4),Boolean.class));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<Integer>(2),Boolean.class));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper<>(2), Boolean.class));
|
||||
|
||||
expression = parser.parseExpression("payload/2");
|
||||
assertEquals(2,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(2, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3,expression.getValue(new GenericMessageTestHelper<Integer>(6)));
|
||||
assertEquals(3, expression.getValue(new GenericMessageTestHelper<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100/payload");
|
||||
assertEquals(25,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(25, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(10,expression.getValue(new GenericMessageTestHelper<Integer>(10)));
|
||||
assertEquals(10, expression.getValue(new GenericMessageTestHelper<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload+2");
|
||||
assertEquals(6,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(6, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(8,expression.getValue(new GenericMessageTestHelper<Integer>(6)));
|
||||
assertEquals(8, expression.getValue(new GenericMessageTestHelper<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100+payload");
|
||||
assertEquals(104,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(104, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(110,expression.getValue(new GenericMessageTestHelper<Integer>(10)));
|
||||
assertEquals(110, expression.getValue(new GenericMessageTestHelper<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload-2");
|
||||
assertEquals(2,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(2, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(4,expression.getValue(new GenericMessageTestHelper<Integer>(6)));
|
||||
assertEquals(4, expression.getValue(new GenericMessageTestHelper<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100-payload");
|
||||
assertEquals(96,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(96, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(90,expression.getValue(new GenericMessageTestHelper<Integer>(10)));
|
||||
assertEquals(90, expression.getValue(new GenericMessageTestHelper<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload*2");
|
||||
assertEquals(8,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(8, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(12,expression.getValue(new GenericMessageTestHelper<Integer>(6)));
|
||||
assertEquals(12, expression.getValue(new GenericMessageTestHelper<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100*payload");
|
||||
assertEquals(400,expression.getValue(new GenericMessageTestHelper<Integer>(4)));
|
||||
assertEquals(400, expression.getValue(new GenericMessageTestHelper<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(1000,expression.getValue(new GenericMessageTestHelper<Integer>(10)));
|
||||
assertEquals(1000, expression.getValue(new GenericMessageTestHelper<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload/2L");
|
||||
assertEquals(2L,expression.getValue(new GenericMessageTestHelper<Long>(4L)));
|
||||
assertEquals(2L, expression.getValue(new GenericMessageTestHelper<>(4L)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3L,expression.getValue(new GenericMessageTestHelper<Long>(6L)));
|
||||
assertEquals(3L, expression.getValue(new GenericMessageTestHelper<>(6L)));
|
||||
|
||||
expression = parser.parseExpression("100L/payload");
|
||||
assertEquals(25L,expression.getValue(new GenericMessageTestHelper<Long>(4L)));
|
||||
assertEquals(25L, expression.getValue(new GenericMessageTestHelper<>(4L)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(10L,expression.getValue(new GenericMessageTestHelper<Long>(10L)));
|
||||
assertEquals(10L, expression.getValue(new GenericMessageTestHelper<>(10L)));
|
||||
|
||||
expression = parser.parseExpression("payload/2f");
|
||||
assertEquals(2f,expression.getValue(new GenericMessageTestHelper<Float>(4f)));
|
||||
assertEquals(2f, expression.getValue(new GenericMessageTestHelper<>(4f)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3f,expression.getValue(new GenericMessageTestHelper<Float>(6f)));
|
||||
assertEquals(3f, expression.getValue(new GenericMessageTestHelper<>(6f)));
|
||||
|
||||
expression = parser.parseExpression("100f/payload");
|
||||
assertEquals(25f,expression.getValue(new GenericMessageTestHelper<Float>(4f)));
|
||||
assertEquals(25f, expression.getValue(new GenericMessageTestHelper<>(4f)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(10f,expression.getValue(new GenericMessageTestHelper<Float>(10f)));
|
||||
assertEquals(10f, expression.getValue(new GenericMessageTestHelper<>(10f)));
|
||||
|
||||
expression = parser.parseExpression("payload/2d");
|
||||
assertEquals(2d,expression.getValue(new GenericMessageTestHelper<Double>(4d)));
|
||||
assertEquals(2d, expression.getValue(new GenericMessageTestHelper<>(4d)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3d,expression.getValue(new GenericMessageTestHelper<Double>(6d)));
|
||||
assertEquals(3d, expression.getValue(new GenericMessageTestHelper<>(6d)));
|
||||
|
||||
expression = parser.parseExpression("100d/payload");
|
||||
assertEquals(25d,expression.getValue(new GenericMessageTestHelper<Double>(4d)));
|
||||
assertEquals(25d, expression.getValue(new GenericMessageTestHelper<>(4d)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(10d,expression.getValue(new GenericMessageTestHelper<Double>(10d)));
|
||||
assertEquals(10d, expression.getValue(new GenericMessageTestHelper<>(10d)));
|
||||
}
|
||||
|
||||
// The new helper class here uses an upper bound on the generic
|
||||
@Test
|
||||
public void compilerWithGenerics_12040_2() {
|
||||
expression = parser.parseExpression("payload/2");
|
||||
assertEquals(2,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(2, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3,expression.getValue(new GenericMessageTestHelper2<Integer>(6)));
|
||||
assertEquals(3, expression.getValue(new GenericMessageTestHelper2<>(6)));
|
||||
|
||||
expression = parser.parseExpression("9/payload");
|
||||
assertEquals(1,expression.getValue(new GenericMessageTestHelper2<Integer>(9)));
|
||||
assertEquals(1, expression.getValue(new GenericMessageTestHelper2<>(9)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(3,expression.getValue(new GenericMessageTestHelper2<Integer>(3)));
|
||||
assertEquals(3, expression.getValue(new GenericMessageTestHelper2<>(3)));
|
||||
|
||||
expression = parser.parseExpression("payload+2");
|
||||
assertEquals(6,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(6, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(8,expression.getValue(new GenericMessageTestHelper2<Integer>(6)));
|
||||
assertEquals(8, expression.getValue(new GenericMessageTestHelper2<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100+payload");
|
||||
assertEquals(104,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(104, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(110,expression.getValue(new GenericMessageTestHelper2<Integer>(10)));
|
||||
assertEquals(110, expression.getValue(new GenericMessageTestHelper2<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload-2");
|
||||
assertEquals(2,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(2, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(4,expression.getValue(new GenericMessageTestHelper2<Integer>(6)));
|
||||
assertEquals(4, expression.getValue(new GenericMessageTestHelper2<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100-payload");
|
||||
assertEquals(96,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(96, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(90,expression.getValue(new GenericMessageTestHelper2<Integer>(10)));
|
||||
assertEquals(90, expression.getValue(new GenericMessageTestHelper2<>(10)));
|
||||
|
||||
expression = parser.parseExpression("payload*2");
|
||||
assertEquals(8,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(8, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(12,expression.getValue(new GenericMessageTestHelper2<Integer>(6)));
|
||||
assertEquals(12, expression.getValue(new GenericMessageTestHelper2<>(6)));
|
||||
|
||||
expression = parser.parseExpression("100*payload");
|
||||
assertEquals(400,expression.getValue(new GenericMessageTestHelper2<Integer>(4)));
|
||||
assertEquals(400, expression.getValue(new GenericMessageTestHelper2<>(4)));
|
||||
assertCanCompile(expression);
|
||||
assertEquals(1000,expression.getValue(new GenericMessageTestHelper2<Integer>(10)));
|
||||
assertEquals(1000, expression.getValue(new GenericMessageTestHelper2<>(10)));
|
||||
}
|
||||
|
||||
// The other numeric operators
|
||||
@Test
|
||||
public void compilerWithGenerics_12040_3() {
|
||||
expression = parser.parseExpression("payload >= 2");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(4),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(4), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("2 >= payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(5),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(5), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("payload > 2");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(4),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(4), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("2 > payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(5),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(5), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("payload <=2");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(6),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(6), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("2 <= payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(6),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(6), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("payload < 2");
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(6),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(6), Boolean.TYPE));
|
||||
|
||||
expression = parser.parseExpression("2 < payload");
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<Integer>(1),Boolean.TYPE));
|
||||
assertFalse(expression.getValue(new GenericMessageTestHelper2<>(1), Boolean.TYPE));
|
||||
assertCanCompile(expression);
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<Integer>(6),Boolean.TYPE));
|
||||
assertTrue(expression.getValue(new GenericMessageTestHelper2<>(6), Boolean.TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indexerMapAccessor_12045() throws Exception {
|
||||
SpelParserConfiguration spc = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,this.getClass().getClassLoader());
|
||||
SpelParserConfiguration spc = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,getClass().getClassLoader());
|
||||
SpelExpressionParser sep = new SpelExpressionParser(spc);
|
||||
expression=sep.parseExpression("headers[command]");
|
||||
MyMessage root = new MyMessage();
|
||||
|
@ -4615,8 +4688,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
|
||||
|
||||
// helper classes
|
||||
|
||||
public interface Message<T> {
|
||||
|
||||
MessageHeaders getHeaders();
|
||||
|
@ -4627,6 +4698,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
int[] getIa();
|
||||
}
|
||||
|
||||
|
||||
public static class MyMessage implements Message<String> {
|
||||
|
||||
public MessageHeaders getHeaders() {
|
||||
|
@ -4655,10 +4727,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class MessageHeaders extends HashMap<String, Object> {
|
||||
}
|
||||
|
||||
|
||||
public static class GenericMessageTestHelper<T> {
|
||||
|
||||
private T payload;
|
||||
|
@ -4672,6 +4746,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// This test helper has a bound on the type variable
|
||||
public static class GenericMessageTestHelper2<T extends Number> {
|
||||
|
||||
|
@ -4686,6 +4761,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static class MyAccessor implements CompilablePropertyAccessor {
|
||||
|
||||
private Method method;
|
||||
|
@ -4743,6 +4819,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static class CompilableMapAccessor implements CompilablePropertyAccessor {
|
||||
|
||||
@Override
|
||||
|
@ -4799,6 +4876,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown from {@code read} in order to reset a cached
|
||||
* PropertyAccessor, allowing other accessors to have a try.
|
||||
|
@ -4820,8 +4898,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
|
||||
|
||||
// test classes
|
||||
|
||||
public static class Greeter {
|
||||
|
||||
public String getWorld() {
|
||||
|
@ -4833,16 +4909,19 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FooObject {
|
||||
|
||||
public Object getObject() { return "hello"; }
|
||||
}
|
||||
|
||||
|
||||
public static class FooString {
|
||||
|
||||
public String getObject() { return "hello"; }
|
||||
}
|
||||
|
||||
|
||||
public static class Payload {
|
||||
|
||||
Two[] DR = new Two[] {new Two()};
|
||||
|
@ -4854,6 +4933,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Payload2 {
|
||||
|
||||
String var1 = "abc";
|
||||
|
@ -4870,11 +4950,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Payload2Holder {
|
||||
|
||||
public Payload2 payload2 = new Payload2();
|
||||
}
|
||||
|
||||
|
||||
public class Person {
|
||||
|
||||
private int age;
|
||||
|
@ -4892,6 +4974,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public class Person3 {
|
||||
|
||||
private int age;
|
||||
|
@ -4909,6 +4992,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Two {
|
||||
|
||||
Three three = new Three();
|
||||
|
@ -4921,6 +5005,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Three {
|
||||
|
||||
double four = 0.04d;
|
||||
|
@ -4930,6 +5015,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public class PayloadX {
|
||||
|
||||
public int valueI = 120;
|
||||
|
@ -4962,12 +5048,15 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
public Short valueSB = (short)120;
|
||||
public Short valueSB18 = (short)18;
|
||||
public Short valueSB20 = (short)20;
|
||||
|
||||
public PayloadX payload;
|
||||
|
||||
public PayloadX() {
|
||||
payload = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass1 {
|
||||
|
||||
public int index1 = 1;
|
||||
|
@ -4975,6 +5064,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
public String word = "abcd";
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass4 {
|
||||
|
||||
public boolean a,b;
|
||||
|
@ -4984,6 +5074,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
public boolean getB() { return b; }
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass10 {
|
||||
|
||||
public String s = null;
|
||||
|
@ -5025,6 +5116,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass5 {
|
||||
|
||||
public int i = 0;
|
||||
|
@ -5238,6 +5330,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass6 {
|
||||
|
||||
public String orange = "value1";
|
||||
|
@ -5254,6 +5347,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass7 {
|
||||
|
||||
public static String property;
|
||||
|
@ -5269,9 +5363,9 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
StringTokenizer st = new StringTokenizer(s);
|
||||
property = st.nextToken();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass8 {
|
||||
|
||||
public int i;
|
||||
|
@ -5287,7 +5381,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
|
||||
public TestClass8() {
|
||||
|
||||
}
|
||||
|
||||
public TestClass8(Integer i) {
|
||||
|
@ -5300,6 +5393,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Obj {
|
||||
|
||||
private final String param1;
|
||||
|
@ -5309,6 +5403,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Obj2 {
|
||||
|
||||
public final String output;
|
||||
|
@ -5322,6 +5417,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Obj3 {
|
||||
|
||||
public final String output;
|
||||
|
@ -5347,6 +5443,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Obj4 {
|
||||
|
||||
public final String output;
|
||||
|
@ -5360,11 +5457,14 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestClass9 {
|
||||
|
||||
public TestClass9(int i) {}
|
||||
public TestClass9(int i) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// These test classes simulate a pattern of public/private classes seen in Spring Security
|
||||
|
||||
|
@ -5381,10 +5481,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper
|
||||
static class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper {
|
||||
}
|
||||
|
||||
|
||||
public static class HttpServletRequestWrapper {
|
||||
|
||||
public String getServletPath() {
|
||||
|
@ -5392,6 +5494,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Here the declaring class is not public
|
||||
static class SomeCompareMethod {
|
||||
|
||||
|
@ -5406,6 +5509,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SomeCompareMethod2 {
|
||||
|
||||
public static int negate(int i1) {
|
||||
|
@ -5478,6 +5582,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DelegatingStringFormat {
|
||||
|
||||
public static String format(String s, Object... args) {
|
||||
|
@ -5485,8 +5590,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class StaticsHelper {
|
||||
|
||||
static StaticsHelper sh = new StaticsHelper();
|
||||
public static StaticsHelper fielda = sh;
|
||||
public static String fieldb = "fb";
|
||||
|
||||
public static StaticsHelper methoda() {
|
||||
return sh;
|
||||
}
|
||||
|
@ -5502,12 +5612,53 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
return "pb";
|
||||
}
|
||||
|
||||
|
||||
public static StaticsHelper fielda = sh;
|
||||
public static String fieldb = "fb";
|
||||
|
||||
public String toString() {
|
||||
return "sh";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Apple implements Comparable<Apple> {
|
||||
|
||||
public Object gotComparedTo = null;
|
||||
public int i;
|
||||
|
||||
public Apple(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public void setValue(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Apple that) {
|
||||
this.gotComparedTo = that;
|
||||
if (this.i < that.i) {
|
||||
return -1;
|
||||
}
|
||||
else if (this.i > that.i) {
|
||||
return +1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For opNe_SPR14863
|
||||
public static class MyContext {
|
||||
|
||||
private final Map<String, String> data;
|
||||
|
||||
public MyContext(Map<String, String> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Map<String, String> getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue