Skip to content

Commit 358e567

Browse files
SONARJAVA-5444 Handle case of Reader.of for try-with-resources (#5231)
1 parent 3e1736b commit 358e567

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

java-checks-test-sources/default/src/main/java/checks/TryWithResourcesCheckSample.java

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,37 @@
33
import java.io.BufferedReader;
44
import java.io.FileReader;
55
import java.io.IOException;
6+
import java.io.Reader;
67

78
class TryWithResourcesCheckSample {
9+
String readerFactoryNonCompliant(String sequence) throws IOException {
10+
char[] buf = new char[1024];
11+
Reader reader = null;
12+
try { // Noncompliant {{Change this "try" to a try-with-resources.}}
13+
// ^^^
14+
reader = Reader.of(sequence);
15+
// ^^^^^^^^^^^^^^^^^^^<
16+
reader.read(buf, 0, buf.length);
17+
} catch (IOException e) {
18+
throw new RuntimeException(e);
19+
} finally {
20+
if (reader != null) {
21+
reader.close();
22+
}
23+
}
24+
return String.valueOf(buf);
25+
}
26+
27+
String readerFactoryCompliant(String sequence) {
28+
char[] buf = new char[1024];
29+
try (Reader reader = Reader.of(sequence)) { // Compliant
30+
reader.read(buf, 0, buf.length);
31+
} catch (IOException e) {
32+
throw new RuntimeException(e);
33+
}
34+
return String.valueOf(buf);
35+
}
36+
837
String foo(String fileName) {
938
FileReader fr = null;
1039
BufferedReader br = null;
@@ -32,7 +61,7 @@ String foo(String fileName) {
3261
}
3362
try { // compliant, no finally block so let's rely on unclosed resource rule
3463
fr = new FileReader(fileName);
35-
} catch (Exception e){
64+
} catch (Exception e) {
3665

3766
}
3867
try (
@@ -52,7 +81,7 @@ void newJustBeforeTryStatement() {
5281
try { // Noncompliant {{Change this "try" to a try-with-resources.}}
5382
// ^^^
5483
a1.doSomething();
55-
} finally {
84+
} finally {
5685
a1.close();
5786
a2.close();
5887
}
@@ -67,7 +96,7 @@ void newJustBeforeAndAfterTryStatement() {
6796
a1 = new Auto();
6897
// ^^^^^^^^^^<
6998
a1.doSomething();
70-
} finally {
99+
} finally {
71100
a1.close();
72101
a2.close();
73102
}
@@ -78,30 +107,33 @@ void methodBetweenNewAndTry() {
78107
a.doSomething();
79108
try {
80109
a.doSomething();
81-
} finally {
110+
} finally {
82111
a.close();
83112
}
84113
}
85114

86-
class B {}
115+
class B {
116+
}
87117

88118
void unknownNewBetweenNewAndTry() {
89119
Auto a = new Auto();
90120
B b = new B();
91121
try {
92122
a.doSomething();
93-
} finally {
123+
} finally {
94124
a.close();
95125
}
96126
}
97127

98-
Auto passThrough(Auto a) { return a; }
128+
Auto passThrough(Auto a) {
129+
return a;
130+
}
99131

100132
void newInsideMethodInvocation() {
101133
Auto a = passThrough(new Auto()); // Compliant, we do not know what happens in the method
102134
try {
103135
a.doSomething();
104-
} finally {
136+
} finally {
105137
a.close();
106138
}
107139
}
@@ -110,7 +142,7 @@ void newJustBeforeTryWithResource() {
110142
Auto a1 = new Auto();
111143
try (Auto a2 = new Auto()) {
112144
a1.doSomething();
113-
} finally {
145+
} finally {
114146
a1.close();
115147
}
116148
}
@@ -128,7 +160,7 @@ void enclosedTryWithFinallyStatements() {
128160
} finally {
129161
a2.close();
130162
}
131-
} finally {
163+
} finally {
132164
a1.close();
133165
}
134166
}
@@ -144,8 +176,9 @@ void enclosedTryStatements() {
144176
try {
145177
a2.doSomething();
146178
a2.close();
147-
} catch (Exception e) {}
148-
} finally {
179+
} catch (Exception e) {
180+
}
181+
} finally {
149182
a1.close();
150183
}
151184
}
@@ -161,10 +194,12 @@ void method_with_while_continue(boolean a) {
161194
}
162195

163196
static class Auto implements AutoCloseable {
164-
public void doSomething() {}
197+
public void doSomething() {
198+
}
165199

166200
@Override
167-
public void close() {}
201+
public void close() {
202+
}
168203
}
169204

170205
}

java-checks/src/main/java/org/sonar/java/checks/TryWithResourcesCheck.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public class TryWithResourcesCheck extends IssuableSubscriptionVisitor implement
4242
MethodMatchers.create().ofTypes("java.net.http.HttpClient").names("newHttpClient").addWithoutParametersMatcher().build()
4343
);
4444

45+
private static final MethodMatchers AUTOCLOSEABLE_FACTORY_MATCHER =
46+
MethodMatchers.create().ofSubTypes("java.io.Reader")
47+
.names("of")
48+
.addParametersMatcher("java.lang.CharSequence").build();
49+
4550
private final Deque<TryStatementTree> withinTry = new LinkedList<>();
4651
private final Deque<List<Tree>> toReport = new LinkedList<>();
4752

@@ -78,7 +83,8 @@ public void visitNode(Tree tree) {
7883

7984
private static boolean isNewAutocloseableOrBuilder(Tree tree, JavaFileScannerContext context) {
8085
return (tree instanceof NewClassTree newClass && newClass.symbolType().isSubtypeOf("java.lang.AutoCloseable")) ||
81-
(context.getJavaVersion().isJava21Compatible() && tree instanceof MethodInvocationTree mit && AUTOCLOSEABLE_BUILDER_MATCHER.matches(mit));
86+
(context.getJavaVersion().isJava21Compatible() && tree instanceof MethodInvocationTree mit && AUTOCLOSEABLE_BUILDER_MATCHER.matches(mit))||
87+
(tree instanceof MethodInvocationTree mit2 && AUTOCLOSEABLE_FACTORY_MATCHER.matches(mit2));
8288
}
8389

8490
private static boolean isFollowedByTryWithFinally(Tree tree) {

0 commit comments

Comments
 (0)