Skip to content

Commit ea63196

Browse files
SONARJAVA-5598 S3063: Fix additional FPs on charAt, methodRef, and arrays (#5202)
1 parent d213389 commit ea63196

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

java-checks-test-sources/default/src/main/java/checks/unused/UnusedStringBuilderCheckSample.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ public char[] usedGetChars() {
5050
return chars;
5151
}
5252

53+
public char usedChatAt() {
54+
StringBuilder buf = new StringBuilder();
55+
buf.append("Hello ");
56+
buf.append("World!");
57+
char c = buf.charAt(8);
58+
return c;
59+
}
60+
61+
public void usedInArray() {
62+
StringBuilder buf = new StringBuilder();
63+
buf.append("Hello");
64+
buf.append("World!");
65+
System.out.println("%s: %s".formatted(new Object[]{"Message", buf}));
66+
}
67+
68+
public void usedInMethodReference() {
69+
StringBuilder buf = new StringBuilder();
70+
buf.append("Hello");
71+
buf.append("World!");
72+
myLog(buf::toString);
73+
}
74+
75+
private void myLog(Supplier<String> messageSupplier) {
76+
System.out.println(messageSupplier.get());
77+
}
78+
5379
public void unused() {
5480
StringBuilder sb = new StringBuilder(); // Noncompliant {{Consume or remove this unused StringBuilder}}
5581
// ^^
@@ -124,6 +150,13 @@ private String unusedConstructorWithArgument() {
124150
return "Hello!";
125151
}
126152

153+
private String unusedConstructorAndAppend() {
154+
// FN due to chained method, which we do not support.
155+
StringBuilder sb = new StringBuilder().append("Hello");
156+
sb.append("!");
157+
return "Hello!";
158+
}
159+
127160
public void usedStringBufferTerminalMethod() {
128161
StringBuffer stringBuffer = new StringBuffer();
129162
stringBuffer.append("Hello");

java-checks/src/main/java/org/sonar/java/checks/unused/UnusedStringBuilderCheck.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import javax.annotation.Nullable;
2323
import org.sonar.check.Rule;
2424
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
25+
import org.sonar.java.ast.parser.InitializerListTreeImpl;
2526
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
2627
import org.sonar.plugins.java.api.semantic.Symbol;
2728
import org.sonar.plugins.java.api.semantic.Type;
2829
import org.sonar.plugins.java.api.tree.AssignmentExpressionTree;
2930
import org.sonar.plugins.java.api.tree.BinaryExpressionTree;
3031
import org.sonar.plugins.java.api.tree.ExpressionTree;
3132
import org.sonar.plugins.java.api.tree.MemberSelectExpressionTree;
33+
import org.sonar.plugins.java.api.tree.MethodReferenceTree;
3234
import org.sonar.plugins.java.api.tree.NewClassTree;
3335
import org.sonar.plugins.java.api.tree.ReturnStatementTree;
3436
import org.sonar.plugins.java.api.tree.Tree;
@@ -39,7 +41,7 @@
3941
*/
4042
@Rule(key = "S3063")
4143
public class UnusedStringBuilderCheck extends IssuableSubscriptionVisitor {
42-
private static final Set<String> TERMINAL_METHODS = Set.of("getChars", "substring", "toString");
44+
private static final Set<String> TERMINAL_METHODS = Set.of("charAt", "getChars", "substring", "toString");
4345

4446
@Override
4547
public List<Tree.Kind> nodesToVisit() {
@@ -110,7 +112,9 @@ private static boolean isConsumed(Tree tree) {
110112
.filter(UnusedStringBuilderCheck::isConsumed)
111113
.isPresent();
112114
}
113-
} else if (parent instanceof ReturnStatementTree || parent instanceof ArgumentListTreeImpl || parent instanceof BinaryExpressionTree) {
115+
} else if (parent instanceof ReturnStatementTree || parent instanceof ArgumentListTreeImpl
116+
|| parent instanceof BinaryExpressionTree || parent instanceof MethodReferenceTree
117+
|| parent instanceof InitializerListTreeImpl) {
114118
return true;
115119
}
116120
return false;

0 commit comments

Comments
 (0)