Skip to content

Commit 2384474

Browse files
committed
Support compilation of map indexing with primitive in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to compile an expression that indexed into a Map using a primitive literal (boolean, int, long, float, or double). This commit adds support for compilation of such expressions by ensuring that primitive literals are boxed into their corresponding wrapper types in the compiled bytecode. Closes gh-32903 (cherry picked from commit aed1d5f)
1 parent 0f04052 commit 2384474

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

Diff for: spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,7 @@ else if (this.indexedType == IndexedType.MAP) {
285285
mv.visitLdcInsn(mapKeyName);
286286
}
287287
else {
288-
cf.enterCompilationScope();
289-
index.generateCode(mv, cf);
290-
cf.exitCompilationScope();
288+
generateIndexCode(mv, cf, index, Object.class);
291289
}
292290
mv.visitMethodInsn(
293291
INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);

Diff for: spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java

+46
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,52 @@ void indexIntoListUsingIntegerWrapper() {
552552
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
553553
}
554554

555+
@Test // gh-32903
556+
void indexIntoMapUsingPrimitiveLiteral() {
557+
Map<Object, String> map = new HashMap<>();
558+
map.put(false, "0"); // BooleanLiteral
559+
map.put(1, "ABC"); // IntLiteral
560+
map.put(2L, "XYZ"); // LongLiteral
561+
map.put(9.99F, "~10"); // FloatLiteral
562+
map.put(3.14159, "PI"); // RealLiteral
563+
context.setVariable("map", map);
564+
565+
// BooleanLiteral
566+
expression = parser.parseExpression("#map[false]");
567+
assertThat(expression.getValue(context)).isEqualTo("0");
568+
assertCanCompile(expression);
569+
assertThat(expression.getValue(context)).isEqualTo("0");
570+
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
571+
572+
// IntLiteral
573+
expression = parser.parseExpression("#map[1]");
574+
assertThat(expression.getValue(context)).isEqualTo("ABC");
575+
assertCanCompile(expression);
576+
assertThat(expression.getValue(context)).isEqualTo("ABC");
577+
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
578+
579+
// LongLiteral
580+
expression = parser.parseExpression("#map[2L]");
581+
assertThat(expression.getValue(context)).isEqualTo("XYZ");
582+
assertCanCompile(expression);
583+
assertThat(expression.getValue(context)).isEqualTo("XYZ");
584+
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
585+
586+
// FloatLiteral
587+
expression = parser.parseExpression("#map[9.99F]");
588+
assertThat(expression.getValue(context)).isEqualTo("~10");
589+
assertCanCompile(expression);
590+
assertThat(expression.getValue(context)).isEqualTo("~10");
591+
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
592+
593+
// RealLiteral
594+
expression = parser.parseExpression("#map[3.14159]");
595+
assertThat(expression.getValue(context)).isEqualTo("PI");
596+
assertCanCompile(expression);
597+
assertThat(expression.getValue(context)).isEqualTo("PI");
598+
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
599+
}
600+
555601
private String stringify(Object object) {
556602
Stream<? extends Object> stream;
557603
if (object instanceof Collection) {

0 commit comments

Comments
 (0)