diff --git a/java-checks-test-sources/default/src/main/java/checks/PrintfMisuseCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/PrintfMisuseCheckSample.java index 08adab0ff67..203a5db3d28 100644 --- a/java-checks-test-sources/default/src/main/java/checks/PrintfMisuseCheckSample.java +++ b/java-checks-test-sources/default/src/main/java/checks/PrintfMisuseCheckSample.java @@ -454,3 +454,13 @@ void foo(org.slf4j.Logger log, org.slf4j.Marker marker) { log.debug("message"); } } + +class SonarJava5098 { + void foo() { + String.format("\\newpage %n"); // Compliant + String.format("\\\newpage %n"); // Noncompliant {{%n should be used in place of \n to produce the platform-specific line separator.}} + String.format("\newpage %n"); // Noncompliant + String.format("aaa\\naaa\\\\naaa\\\\\na%naaa\\\\\\n"); // Noncompliant + String.format("aaa\\naaa\\\\naaa\\\\na%naaa\\\\\\n"); // Compliant + } +} diff --git a/java-checks/src/main/java/org/sonar/java/checks/PrintfMisuseCheck.java b/java-checks/src/main/java/org/sonar/java/checks/PrintfMisuseCheck.java index 83a2b8e292d..dfeb7ed32d6 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/PrintfMisuseCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/PrintfMisuseCheck.java @@ -391,9 +391,22 @@ private void checkBoolean(MethodInvocationTree mit, String param, Type argType) } private void checkLineFeed(String formatString, MethodInvocationTree mit) { - if (formatString.contains("\\n")) { - reportIssue(mit, "%n should be used in place of \\n to produce the platform-specific line separator."); + var index = formatString.indexOf("\\n"); + while (index != -1) { + if (isOddNumberOfEscapeChars(formatString, index)) { + reportIssue(mit, "%n should be used in place of \\n to produce the platform-specific line separator."); + return; + } + index = formatString.indexOf("\\n", index+2); + } + } + + private static boolean isOddNumberOfEscapeChars(String formatString, int lastIndex) { + var index = lastIndex-1; + while (index >= 0 && formatString.charAt(index) == '\\') { + index--; } + return (lastIndex - index) % 2 != 0; } private static boolean usesMessageFormat(String formatString, List params) {