Skip to content

Commit a844987

Browse files
committed
Add avoidable-StringBuilder-toString.ql
1 parent 064bd39 commit a844987

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Finds code which calls `StringBuilder.toString()` and then calls a method on
3+
* the resulting `String` which could have directly been called on the `StringBuilder`
4+
* instead, avoiding the intermediate `String` object.
5+
*
6+
* For example:
7+
* ```java
8+
* StringBuilder builder = ...;
9+
* int i = builder.toString().indexOf("substr");
10+
* // can be simplified:
11+
* int i = builder.indexOf("substr");
12+
* ```
13+
*
14+
* @kind problem
15+
*/
16+
17+
// Slightly related to `avoidable-String-operation-before-StringBuilder-append.ql`
18+
19+
import java
20+
21+
predicate haveSameSignature(Method m1, Method m2) {
22+
m1.getReturnType() = m2.getReturnType() and
23+
m1.getSignature() = m2.getSignature()
24+
}
25+
26+
from
27+
StringBuildingType stringBuildingType, MethodAccess toStringCall, MethodAccess callOnString,
28+
Method calledMethod
29+
where
30+
stringBuildingType = toStringCall.getReceiverType() and
31+
toStringCall.getMethod().hasStringSignature("toString()") and
32+
callOnString.getQualifier() = toStringCall and
33+
calledMethod = callOnString.getMethod() and
34+
// There is a StringBuilder method with the same signature
35+
exists(Method stringBuilderMethod |
36+
// Declared by StringBuilder or internal superclass
37+
stringBuilderMethod.getDeclaringType() = stringBuildingType.getASourceSupertype*() and
38+
haveSameSignature(calledMethod, stringBuilderMethod)
39+
) and
40+
// But ignore if method is declared by Object, e.g. equals(Object)
41+
not exists(Method objectMethod |
42+
objectMethod.getDeclaringType() instanceof TypeObject and
43+
haveSameSignature(objectMethod, calledMethod)
44+
)
45+
select toStringCall,
46+
"Instead of first creating String, should directly call `" + stringBuildingType.getName() + "." +
47+
calledMethod.getName() + "`"

0 commit comments

Comments
 (0)