`UnnecessaryStringBuilder` misses the split declaration/assignment form
- Dominant language
- Java
- Stars
- 7.2k
- Forks
- 820
- Avg merge
- 5h 9m
- Merged PRs (30d)
- 50
Description
### Error Prone version
Error Prone 2.49.0 (javac plugin) — javac 21.0.8, source/target 21.
### Check name
[UnnecessaryStringBuilder](https://errorprone.info/bugpattern/UnnecessaryStringBuilder)
### Description
`UnnecessaryStringBuilder` flags a `StringBuilder` local that is created and not meaningfully used (replaceable by plain string handling). The matcher keys on the combined declarator-with-initializer node `StringBuilder x = new StringBuilder(...)`. Splitting it into a separate declaration and assignment — `StringBuilder x; x = new StringBuilder(...);` — is a semantics-preserving refactor (the variable is still initialized once before any use), yet the rule stops firing entirely.
### Reproducer
```java
// BEFORE — 2 findings (on the two StringBuilder locals)
class S {
public void f() {
StringBuffer foo = new java.lang.StringBuffer('x');
StringBuilder foo2 = new StringBuilder('x'); // flagged
StringBuffer foo3 = new StringBuffer("x");
StringBuilder foo4 = new StringBuilder("x"); // flagged
}
}
```
```java
// AFTER — equivalent rewrite, 0 findings
class S {
public void f() {
StringBuffer foo;
foo = new java.lang.StringBuffer('x');
StringBuilder foo2;
foo2 = new StringBuilder('x');
StringBuffer foo3;
foo3 = new StringBuffer("x");
StringBuilder foo4;
foo4 = new StringBuilder("x");
}
}
```
### Expected behavior
`UnnecessaryStringBuilder` should report the same findings on BEFORE and AFTER, since `T x = init;` and `T x; x = init;` are observationally equivalent.
### Actual behavior
- BEFORE: 2 findings (`Prefer string concatenation over explicitly using StringBuilder#append ...`).
- AFTER: 0 findings.
The matcher only recognizes the declarator-with-initializer form and does not follow the variable when the initializer is a separate assignment statement.
Contributor guide
Assessment
This issue has not been assessed yet.