(DEFAULT_IGNORED_TYPES);
+ protected final MethodMatcher myMethodMatcher;
+
+ public AutoCloseableResourceInspectionBase() {
+ myMethodMatcher = new MethodMatcher()
+ .add("java.util.Formatter", "format")
+ .add("java.io.Writer", "append")
+ .add("com.google.common.base.Preconditions", "checkNotNull")
+ .add("org.hibernate.Session", "close")
+ .finishDefault();
+ }
@Nls
@NotNull
@@ -65,6 +80,43 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
return InspectionGadgetsBundle.message("auto.closeable.resource.problem.descriptor", text);
}
+ @Nullable
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final boolean buildQuickfix = ((Boolean)infos[1]).booleanValue();
+ if (!buildQuickfix) {
+ return null;
+ }
+ return new AutoCloseableResourceFix();
+ }
+
+ private class AutoCloseableResourceFix extends InspectionGadgetsFix {
+
+ @Nls
+ @NotNull
+ @Override
+ public String getName() {
+ return InspectionGadgetsBundle.message("auto.closeable.resource.quickfix");
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
+ if (methodCallExpression == null) {
+ return;
+ }
+ myMethodMatcher.add(methodCallExpression);
+ }
+ }
+
@Override
public void readSettings(@NotNull Element node) throws InvalidDataException {
super.readSettings(node);
@@ -78,6 +130,7 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
}
}
}
+ myMethodMatcher.readSettings(node);
}
@Override
@@ -88,6 +141,7 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
final String ignoredTypesString = formatString(ignoredTypes);
node.addContent(new Element("option").setAttribute("name", "ignoredTypes").setAttribute("value", ignoredTypesString));
}
+ myMethodMatcher.writeSettings(node);
}
@Override
@@ -114,25 +168,16 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
if (!isNotSafelyClosedResource(expression)) {
return;
}
- registerNewExpressionError(expression, expression.getType());
+ registerNewExpressionError(expression, expression.getType(), Boolean.FALSE);
}
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
- if (ignoreFromMethodCall) {
+ if (ignoreFromMethodCall || myMethodMatcher.matches(expression) || !isNotSafelyClosedResource(expression)) {
return;
}
- if (MethodCallUtils.isCallToMethod(expression, "java.util.Formatter", null, "format", null) ||
- MethodCallUtils.isCallToMethod(expression, "java.io.Writer", null, "append", null) ||
- MethodCallUtils.isCallToMethod(expression, "com.google.common.base.Preconditions", null, "checkNotNull", null) ||
- MethodCallUtils.isCallToMethod(expression, "org.hibernate.Session", null, "close")) {
- return;
- }
- if (!isNotSafelyClosedResource(expression)) {
- return;
- }
- registerMethodCallError(expression, expression.getType());
+ registerMethodCallError(expression, expression.getType(), Boolean.TRUE);
}
@Override
@@ -150,7 +195,7 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
return;
}
}
- registerError(expression, type);
+ registerError(expression, type, Boolean.FALSE);
}
private boolean isNotSafelyClosedResource(PsiExpression expression) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/AutoCloseableResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/AutoCloseableResourceInspection.java
index d66e2f25dece..64117ddfe710 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/AutoCloseableResourceInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/AutoCloseableResourceInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,31 +17,53 @@ package com.siyeh.ig.resources;
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
-import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.components.panels.VerticalLayout;
+import com.intellij.util.ui.CheckBox;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.ui.UiUtils;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
+import java.util.Arrays;
/**
* @author Bas Leijdekkers
*/
public class AutoCloseableResourceInspection extends AutoCloseableResourceInspectionBase {
+ @NotNull
@Override
public JComponent createOptionsPanel() {
- final JComponent panel = new JPanel(new BorderLayout());
+ final JComponent panel = new JPanel(new VerticalLayout(2));
final ListTable table =
new ListTable(new ListWrappingTableModel(ignoredTypes, InspectionGadgetsBundle.message("ignored.autocloseable.types.column.label")));
final JPanel tablePanel =
UiUtils.createAddRemoveTreeClassChooserPanel(table, InspectionGadgetsBundle.message("choose.autocloseable.type.to.ignore.title"),
"java.lang.AutoCloseable");
- final MultipleCheckboxOptionsPanel checkboxPanel = new MultipleCheckboxOptionsPanel(this);
- checkboxPanel.addCheckbox(InspectionGadgetsBundle.message("auto.closeable.resource.returned.option"), "ignoreFromMethodCall");
- checkboxPanel.addCheckbox(InspectionGadgetsBundle.message("any.method.may.close.resource.argument"), "anyMethodMayClose");
- panel.add(tablePanel, BorderLayout.CENTER);
- panel.add(checkboxPanel, BorderLayout.SOUTH);
+ final ListTable table2 = new ListTable(
+ new ListWrappingTableModel(Arrays.asList(myMethodMatcher.getClassNames(), myMethodMatcher.getMethodNamePatterns()),
+ InspectionGadgetsBundle.message("result.of.method.call.ignored.class.column.title"),
+ InspectionGadgetsBundle.message("method.name.regex"))) {
+ @Override
+ public void setEnabled(boolean enabled) {
+ // hack to display correctly on initial opening of
+ // inspection settings (otherwise it is always enabled)
+ super.setEnabled(enabled && !ignoreFromMethodCall);
+ }
+ };
+ final JPanel tablePanel2 = UiUtils.createAddRemoveTreeClassChooserPanel(table2, "Choose class");
+ final JPanel wrapperPanel = new JPanel(new BorderLayout());
+ wrapperPanel.setBorder(IdeBorderFactory.createTitledBorder("Ignore AutoCloseable instances returned from these methods", false));
+ wrapperPanel.add(tablePanel2);
+ panel.add(tablePanel);
+ panel.add(wrapperPanel);
+ final CheckBox checkBox =
+ new CheckBox(InspectionGadgetsBundle.message("auto.closeable.resource.returned.option"), this, "ignoreFromMethodCall");
+ checkBox.addChangeListener(e -> table2.setEnabled(!ignoreFromMethodCall));
+ panel.add(checkBox);
+ panel.add(new CheckBox(InspectionGadgetsBundle.message("any.method.may.close.resource.argument"), this, "anyMethodMayClose"));
return panel;
}
}
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AutoCloseableResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AutoCloseableResource.html
index 57010958fa0b..9a58ab92b4cd 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AutoCloseableResource.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AutoCloseableResource.html
@@ -1,14 +1,16 @@
-Reports AutoCloseable instances which are not used in a try-with-resources statement, also known as
+Reports AutoCloseable instances which are not used in a try-with-resources statement, also known as
Automatic Resource Management.
This means that the open resource before/in try, close in finally style which was used before
-try-with-resources was available is also reported.
+try-with-resources was available is also reported.
This inspection is meant to replace all opened but not safely closed inspections when developing in Java 7 and higher.
-Use the table below to specify which AutoCloseable subclasses should be ignored by this inspection.
+Use the first table below to specify which AutoCloseable subclasses should be ignored by this inspection.
Specify AutoCloseable subclasses here which do not need to be closed.
+Use the second table below to specify which methods returning AutoCloseable will be ignored when called.
+
Use the first checkbox below to ignore an AutoCloseable if it the result of a method call.
When enabled, the results of factory methods will also be ignored.