Fix SpEL generated code for default method invocation
Closes gh-25706
(cherry picked from commit c368ce8223)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -351,8 +351,9 @@ public class MethodReference extends SpelNodeImpl {
|
||||
}
|
||||
|
||||
generateCodeForArguments(mv, cf, method, this.children);
|
||||
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : INVOKEVIRTUAL), classDesc, method.getName(),
|
||||
CodeFlow.createSignatureDescriptor(method), method.getDeclaringClass().isInterface());
|
||||
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : (method.isDefault() ? INVOKEINTERFACE : INVOKEVIRTUAL)),
|
||||
classDesc, method.getName(), CodeFlow.createSignatureDescriptor(method),
|
||||
method.getDeclaringClass().isInterface());
|
||||
cf.pushDescriptor(this.exitTypeDescriptor);
|
||||
|
||||
if (this.originalPrimitiveExitTypeDescriptor != null) {
|
||||
|
||||
@@ -5183,7 +5183,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertIsCompiled(Expression expression) {
|
||||
public static void assertIsCompiled(Expression expression) {
|
||||
try {
|
||||
Field field = SpelExpression.class.getDeclaredField("compiledAst");
|
||||
field.setAccessible(true);
|
||||
|
||||
@@ -22,20 +22,23 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.SpelCompilationCoverageTests;
|
||||
import org.springframework.expression.spel.SpelCompilerMode;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for the {@link SpelCompiler}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Andy Clement
|
||||
* @since 5.1.14
|
||||
*/
|
||||
public class SpelCompilerTests {
|
||||
|
||||
@Test // gh-24357
|
||||
@Test // gh-24357
|
||||
public void expressionCompilesWhenMethodComesFromPublicInterface() {
|
||||
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
|
||||
SpelExpressionParser parser = new SpelExpressionParser(config);
|
||||
@@ -47,6 +50,31 @@ public class SpelCompilerTests {
|
||||
IntStream.rangeClosed(1, 5).forEach(i -> assertEquals(42, expression.getValue(component)));
|
||||
}
|
||||
|
||||
@Test // gh-25706
|
||||
public void defaultMethodInvocation() {
|
||||
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
|
||||
SpelExpressionParser parser = new SpelExpressionParser(config);
|
||||
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
Item item = new Item();
|
||||
context.setRootObject(item);
|
||||
|
||||
Expression expression = parser.parseExpression("#root.isEditable2()");
|
||||
assertFalse(SpelCompiler.compile(expression));
|
||||
assertEquals(false, expression.getValue(context));
|
||||
assertTrue(SpelCompiler.compile(expression));
|
||||
SpelCompilationCoverageTests.assertIsCompiled(expression);
|
||||
assertEquals(false, expression.getValue(context));
|
||||
|
||||
context.setVariable("user", new User());
|
||||
expression = parser.parseExpression("#root.isEditable(#user)");
|
||||
assertFalse(SpelCompiler.compile(expression));
|
||||
assertEquals(true, expression.getValue(context));
|
||||
assertTrue(SpelCompiler.compile(expression));
|
||||
SpelCompilationCoverageTests.assertIsCompiled(expression);
|
||||
assertEquals(true, expression.getValue(context));
|
||||
}
|
||||
|
||||
|
||||
static class OrderedComponent implements Ordered {
|
||||
|
||||
@@ -56,4 +84,40 @@ public class SpelCompilerTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class User {
|
||||
|
||||
boolean isAdmin() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Item implements Editable {
|
||||
|
||||
// some fields
|
||||
private String someField = "";
|
||||
|
||||
// some getters and setters
|
||||
|
||||
@Override
|
||||
public boolean hasSomeProperty() {
|
||||
return someField != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface Editable {
|
||||
|
||||
default boolean isEditable(User user) {
|
||||
return user.isAdmin() && hasSomeProperty();
|
||||
}
|
||||
|
||||
default boolean isEditable2() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasSomeProperty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user