Skip to content

Commit 3f65e31

Browse files
authored
SONARJAVA-4741 FP on S6857 for special default values in property placeholders (#4766)
1 parent a7b0c31 commit 3f65e31

2 files changed

Lines changed: 62 additions & 38 deletions

File tree

java-checks-test-sources/default/src/main/java/checks/spring/SpelExpressionCheckSample.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,55 +60,64 @@ public class SpelExpressionCheckSample {
6060
private String region4;
6161

6262
@Value("${user.region:defaultRegion}") // Compliant
63-
private String multi1;
63+
private String default1;
6464

6565
@Value("${user.region::defaultRegion}") // Noncompliant {{Correct this malformed property placeholder.}}
66-
private String multi2;
66+
private String default2;
6767

6868
@Value("${:user.region:defaultRegion}") // Noncompliant {{Correct this malformed property placeholder.}}
69-
private String multi3;
69+
private String default3;
7070

71-
@Value("${user.region:defaultRegion:}") // Noncompliant {{Correct this malformed property placeholder.}}
72-
private String multi4;
71+
@Value("${user.region:defaultRegion:}") // Noncompliant
72+
private String default4;
7373

7474
@Value("${ user.region : defaultRegion }") // Compliant
75-
private String multi5;
75+
private String default5;
7676

7777
@Value("${user.region:#{null}}") // Compliant
78-
private String multi6;
78+
private String default6;
7979

8080
@Value("${user.region:#{ null }}") // Compliant
81-
private String multi7;
81+
private String default7;
8282

8383
@Value("${user.region:#{ null + 3 }}") // Compliant
84-
private String multi8;
84+
private String default8;
8585

8686
@Value("${user.region:#{ null + * 3 }}") // Noncompliant [[sc=25;ec=41]] {{Correct this malformed SpEL expression.}}
87-
private String multi9;
87+
private String default9;
8888

8989
@Value("${user.region:#{'D'+'E'}}") // Compliant
90-
private String multi10;
90+
private String default10;
9191

92-
@Value("${user.region:#{null}:#{null}:foo.bar}") // Compliant
93-
private String multi11;
92+
@Value("${user.region:#{null}:#{null}:foo.bar}") // Noncompliant
93+
private String default11;
9494

95-
@Value("${user.region:#{null}:#{4**4}:foo.bar}") // Noncompliant [[sc=33;ec=40]] {{Correct this malformed SpEL expression.}}
96-
private String multi12;
95+
@Value("${user.region:#{null}:#{4**4}:foo.bar}") // Noncompliant [[sc=11;ec=49]] {{Correct this malformed property placeholder.}}
96+
private String default12;
9797

98-
@Value("${user.region:#{null}:#{4*4}:foo.bar}") // Compliant
99-
private String multi13;
98+
@Value("${user.region:#{4**4}:#{null}:foo.bar}") // Noncompliant [[sc=25;ec=32]] {{Correct this malformed SpEL expression.}}
99+
private String default13;
100100

101-
@Value("${user.region:#{null}:#{4*4}:foo..bar}") // Noncompliant
102-
private String multi14;
103-
104-
@Value("${user.region:#{4**4}:#{4**4}:foo.bar}") // Noncompliant
105-
private String multi15;
101+
@Value("${user.2region:default-region}") // Compliant
102+
private String default14;
106103

107104
@Value("${:defaultRegion}") // Noncompliant
108-
private String multi16;
105+
private String default15;
109106

110-
@Value("${user.2region:default-region}") // Compliant
111-
private String multi17;
107+
@Value("${user.region:}") // Compliant
108+
private String emptyDefaultValue;
109+
110+
@Value("${foo.bar:0 0 * 8 b c}") // Compliant
111+
private String defaultValueStringContents;
112+
113+
@Value("${server.error.path:${error.path}}") // Compliant
114+
private String nestedPropertyValue1;
115+
116+
@Value("${server.error.path:${error.path} }") // Compliant
117+
private String checkTrimEMptyEnd;
118+
119+
@Value("${server.error.path:${error.path:defaultErrorValue}}") // Compliant
120+
private String nestedPropertyValue2;
112121

113122
@Value("#{'${listOfValues}' split(',')}") // Noncompliant [[sc=11;ec=42]] {{Correct this malformed SpEL expression.}}
114123
private List<String> valuesListNc;

java-checks/src/main/java/org/sonar/java/checks/spring/SpelExpressionCheck.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,22 +238,14 @@ private static void parseValidPropertyPlaceholder(String placeholder, int startC
238238
}
239239

240240
private static boolean isValidPropertyPlaceholder(String placeholder, int startColumn) throws SyntaxError {
241-
var startIndex = 0;
242-
var endIndex = placeholder.indexOf(':');
243-
244-
while (endIndex != -1) {
245-
var segment = placeholder.substring(startIndex, endIndex);
246-
if (!isValidPropertyPlaceholderSegment(segment, startColumn + startIndex)) {
247-
return false;
248-
}
249-
startIndex = endIndex + 1;
250-
endIndex = placeholder.indexOf(':', startIndex);
241+
var segments = placeholder.split(":",2);
242+
if (!isValidPropertyPlaceholderFirstSegment(segments[0], startColumn)) {
243+
return false;
251244
}
252-
var segment = placeholder.substring(startIndex);
253-
return isValidPropertyPlaceholderSegment(segment, startColumn + startIndex);
245+
return segments.length < 2 || (isValidPropertyPlaceholderDefaultSegment(segments[1], startColumn + segments[0].length() + 1));
254246
}
255247

256-
private static boolean isValidPropertyPlaceholderSegment(String segment, int startColumn) throws SyntaxError {
248+
private static boolean isValidPropertyPlaceholderFirstSegment(String segment, int startColumn) throws SyntaxError {
257249
var stripped = segment.stripLeading();
258250
startColumn += segment.length() - stripped.length();
259251
stripped = stripped.stripTrailing();
@@ -266,6 +258,29 @@ private static boolean isValidPropertyPlaceholderSegment(String segment, int sta
266258
}
267259
}
268260

261+
private static boolean isValidPropertyPlaceholderDefaultSegment(String segment, int startColumn) throws SyntaxError {
262+
var stripped = segment.stripLeading();
263+
startColumn += segment.length() - stripped.length();
264+
stripped = stripped.stripTrailing();
265+
266+
var contentsParser = getContentsParser(stripped);
267+
if (contentsParser != null) {
268+
var endIndex = parseDelimitersAndContents(stripped, 1, startColumn + 2, contentsParser);
269+
return endIndex == segment.stripTrailing().length();
270+
}
271+
return segment.indexOf(':') < 0;
272+
}
273+
274+
private static ObjIntConsumer<String> getContentsParser(String contents) {
275+
if (contents.startsWith("${")) {
276+
return SpelExpressionCheck::parseValidPropertyPlaceholder;
277+
}
278+
if (contents.startsWith("#{")) {
279+
return SpelExpressionCheck::parseValidSpelExpression;
280+
}
281+
return null;
282+
}
283+
269284
private static void parseValidSpelExpression(String expressionString, int startColumn) throws SyntaxError {
270285
if (!isValidSpelExpression(expressionString)) {
271286
// +3 because of delimiter `${` and `}`

0 commit comments

Comments
 (0)