AutoCloseableResourceInspection: warning on Files.lines,...: IDEA-182784

This commit is contained in:
Roman Ivanov
2018-01-26 16:19:51 +07:00
parent b6a99ddaeb
commit 8f4781ecb2
4 changed files with 58 additions and 3 deletions
@@ -1757,6 +1757,7 @@ logger.class.name=Logger class name
ignore.exceptions.declared.on.library.override.option=Ignore exceptions declared on methods overriding a &library method
allow.resource.to.be.opened.inside.a.try.block=Allow resource to be opened inside a 'try' block
any.method.may.close.resource.argument=Any method may close resource argument
show.warning.for.stream.holding.resource=Show warning for java.util.Stream holding resource
log.method.name=Logging method name
log.condition.text=Log condition text
ignore.if.annotated.by=Ignore if annotated by
@@ -42,6 +42,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.intellij.util.ObjectUtils.tryCast;
/**
* @author Bas Leijdekkers
*/
@@ -54,6 +56,8 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
@SuppressWarnings("PublicField")
public boolean ignoreFromMethodCall = false;
public boolean showWarningForStreamHoldingResource = true;
final List<String> ignoredTypes = new ArrayList<>(DEFAULT_IGNORED_TYPES);
protected final MethodMatcher myMethodMatcher;
@@ -67,6 +71,8 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
.finishDefault();
}
CallMatcher STREAM_HOLDING_RESOURCE = CallMatcher.staticCall("java.nio.file.Files", "lines", "walk", "list", "find");
@Nls
@NotNull
@Override
@@ -148,7 +154,12 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
@Override
protected boolean isResourceCreation(PsiExpression expression) {
return TypeUtils.expressionHasTypeOrSubtype(expression, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE) &&
!TypeUtils.expressionHasTypeOrSubtype(expression, ignoredTypes);
(isStreamHoldingResource(expression)
|| !TypeUtils.expressionHasTypeOrSubtype(expression, ignoredTypes));
}
private boolean isStreamHoldingResource(PsiExpression expression) {
return showWarningForStreamHoldingResource && STREAM_HOLDING_RESOURCE.matches(tryCast(expression, PsiMethodCallExpression.class));
}
@Override
@@ -178,7 +189,7 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
if (ignoreFromMethodCall || myMethodMatcher.matches(expression) || isSafelyClosedResource(expression)) {
return;
}
registerMethodCallError(expression, expression.getType(), Boolean.TRUE);
registerMethodCallError(expression, expression.getType(), !isStreamHoldingResource(expression));
}
@Override
@@ -64,6 +64,7 @@ public class AutoCloseableResourceInspection extends AutoCloseableResourceInspec
checkBox.addChangeListener(e -> table2.setEnabled(!ignoreFromMethodCall));
panel.add(checkBox);
panel.add(new CheckBox(InspectionGadgetsBundle.message("any.method.may.close.resource.argument"), this, "anyMethodMayClose"));
panel.add(new CheckBox(InspectionGadgetsBundle.message("show.warning.for.stream.holding.resource"), this, "showWarningForStreamHoldingResource"));
return panel;
}
}
@@ -16,7 +16,9 @@
package com.siyeh.ig.resources;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.testFramework.LightProjectDescriptor;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
@@ -74,6 +76,7 @@ public class AutoCloseableResourceInspectionTest extends LightInspectionTestCase
}
public void testARM() {
mockSql();
doTest("import java.sql.*;\n" +
"class X {\n" +
" void m(Driver driver) throws SQLException {\n" +
@@ -81,12 +84,29 @@ public class AutoCloseableResourceInspectionTest extends LightInspectionTestCase
" PreparedStatement statement = connection.prepareStatement(\"SELECT *\");\n" +
" ResultSet resultSet = statement.executeQuery()) {\n" +
" while (resultSet.next()) { resultSet.getMetaData(); }\n" +
" }\n" +
" } catch(Exception e) {}\n" +
" }\n" +
"}");
}
private void mockSql() {
addEnvironmentClass("package java.sql;\n" +
"public interface Driver { Connection connect(String s, Object o) throws SQLException;}");
addEnvironmentClass("package java.sql;\n" +
"public interface Connection extends AutoCloseable { PreparedStatement prepareStatement(String s);}");
addEnvironmentClass("package java.sql;\n" +
"public interface PreparedStatement extends AutoCloseable { ResultSet executeQuery();}");
addEnvironmentClass("package java.sql;\n" +
"public class SQLException extends Exception {}");
addEnvironmentClass("package java.sql;\n" +
"public interface ResultSet extends AutoCloseable {\n" +
" boolean next();\n" +
" void getMetaData();\n" +
"}");
}
public void testSimple() {
mockSql();
doTest("import java.sql.*;" +
"class X {" +
" void m(Driver driver) throws SQLException {" +
@@ -163,6 +183,28 @@ public class AutoCloseableResourceInspectionTest extends LightInspectionTestCase
"}");
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
public void testFilesMethod() {
addEnvironmentClass("package java.nio.file;\n" +
"import java.util.stream.Stream;\n" +
"public final class Files {\n" +
" public static Stream<String> lines(Path path) {return Stream.empty();}\n" +
"}");
doTest("import java.io.*;\n" +
"import java.nio.file.Files;\n" +
"import java.util.stream.Stream;\n" +
"class X {\n" +
" private static void example(int a) {\n" +
" Stream<String> s = Files.<warning descr=\"'Stream<String>' used without 'try'-with-resources statement\">lines</warning>(null);\n" +
" }\n" +
"}");
}
public void testClosedResource() {
doTest("import java.io.*;\n" +
"\n" +