From 7b20aefecf3564d740f0c1be1184bf2bc319f030 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 6 Jun 2023 12:35:55 +0200 Subject: [PATCH] Improve error message for unsupported character in SpEL expression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this commit, when an unsupported character such as "ü" was encountered in a SpEL expression, the error message was: Cannot handle (252) 'ü' With this commit, the error message is now similar to: Unsupported character 'ü' (252) encountered at position 5 in expression. See gh-30580 Closes gh-30602 --- .../expression/spel/standard/Tokenizer.java | 6 +- .../expression/spel/ParsingTests.java | 55 ++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java b/spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java index 2726fa53fb..461aaf9519 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 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. @@ -265,7 +265,9 @@ class Tokenizer { raiseParseException(this.pos, SpelMessage.UNEXPECTED_ESCAPE_CHAR); break; default: - throw new IllegalStateException("Cannot handle (" + (int) ch + ") '" + ch + "'"); + throw new IllegalStateException( + "Unsupported character '%s' (%d) encountered at position %d in expression." + .formatted(ch, (int) ch, (this.pos + 1))); } } } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java index 652dcdc002..03e6b72dab 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -24,6 +24,7 @@ import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** * Parse some expressions and check we get the AST we expect. @@ -42,6 +43,58 @@ class ParsingTests { @Nested class Miscellaneous { + @Test + void supportedCharactersInIdentifiers() { + parseCheck("#var='value'"); + parseCheck("#Varz='value'"); + parseCheck("#VarZ='value'"); + parseCheck("#_var='value'"); + parseCheck("#$var='value'"); + parseCheck("#_$_='value'"); + + parseCheck("age"); + parseCheck("getAge()"); + parseCheck("get$age()"); + parseCheck("age"); + parseCheck("Age"); + parseCheck("__age"); + parseCheck("get__age()"); + + parseCheck("person.age"); + parseCheck("person.getAge()"); + parseCheck("person.get$age()"); + parseCheck("person$1.age"); + parseCheck("person_1.Age"); + parseCheck("person_1.__age"); + parseCheck("Person_1.get__age()"); + } + + @Test + void unsupportedCharactersInIdentifiers() { + // Invalid syntax + assertThatIllegalStateException() + .isThrownBy(() -> parser.parseRaw("apple~banana")) + .withMessage("Unsupported character '~' (126) encountered at position 6 in expression."); + + // German characters + assertThatIllegalStateException() + .isThrownBy(() -> parser.parseRaw("begrüssung")) + .withMessage("Unsupported character 'ü' (252) encountered at position 5 in expression."); + assertThatIllegalStateException() + .isThrownBy(() -> parser.parseRaw("Spaß")) + .withMessage("Unsupported character 'ß' (223) encountered at position 4 in expression."); + + // Spanish characters + assertThatIllegalStateException() + .isThrownBy(() -> parser.parseRaw("buenos_sueños")) + .withMessage("Unsupported character 'ñ' (241) encountered at position 11 in expression."); + + // Chinese characters + assertThatIllegalStateException() + .isThrownBy(() -> parser.parseRaw("have乐趣()")) + .withMessage("Unsupported character '乐' (20048) encountered at position 5 in expression."); + } + @Test void literalNull() { parseCheck("null");