mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Allow to specify which methods returning AutoCloseable will be ignored when called (IDEA-CR-7624)
This commit is contained in:
+2
-1
@@ -2030,7 +2030,8 @@ package.info.without.package.quickfix=add ''package {0};''
|
||||
package.info.without.package.family.quickfix=add package statement
|
||||
auto.closeable.resource.display.name=AutoCloseable used without 'try'-with-resources
|
||||
auto.closeable.resource.problem.descriptor=''{0}'' used without ''try''-with-resources statement #loc
|
||||
auto.closeable.resource.returned.option=Ignore AutoCloseable instances returned from method calls
|
||||
auto.closeable.resource.quickfix=Ignore 'AutoCloseable' returned by this method
|
||||
auto.closeable.resource.returned.option=Ignore AutoCloseable instances returned from all method calls
|
||||
problematic.varargs.method.display.name=Non-varargs method overrides varargs method
|
||||
problematic.varargs.method.override.problem.descriptor=Non-varargs method <code>#ref()</code> overrides varargs method #loc
|
||||
negatively.named.boolean.variable.problem.descriptor=Boolean variable <code>#ref</code> is negatively named #loc
|
||||
|
||||
+39
-1
@@ -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.
|
||||
@@ -60,6 +60,44 @@ public class MethodMatcher {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void add(@NotNull PsiMethodCallExpression expression) {
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method != null) {
|
||||
add(method);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(@NotNull PsiMethod method) {
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
final String fqName = aClass.getQualifiedName();
|
||||
final int index = myClassNames.indexOf(fqName);
|
||||
final String methodName = method.getName();
|
||||
if (index < 0) {
|
||||
myClassNames.add(fqName);
|
||||
myMethodNamePatterns.add(methodName);
|
||||
}
|
||||
else {
|
||||
final String pattern = myMethodNamePatterns.get(index);
|
||||
if (pattern.isEmpty()) {
|
||||
myMethodNamePatterns.set(index, methodName);
|
||||
return;
|
||||
}
|
||||
else if (".*".equals(pattern)) {
|
||||
return;
|
||||
}
|
||||
final String[] names = pattern.split("\\|");
|
||||
for (String name : names) {
|
||||
if (methodName.equals(name)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
myMethodNamePatterns.set(index, pattern + '|' + methodName);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getOptionName() {
|
||||
return myOptionName;
|
||||
|
||||
+59
-14
@@ -15,18 +15,23 @@
|
||||
*/
|
||||
package com.siyeh.ig.resources;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.MethodMatcher;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -43,6 +48,16 @@ public class AutoCloseableResourceInspectionBase extends ResourceInspection {
|
||||
public boolean ignoreFromMethodCall = false;
|
||||
|
||||
final List<String> ignoredTypes = new ArrayList<String>(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) {
|
||||
|
||||
+30
-8
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports <b>AutoCloseable</b> instances which are not used in a <b>try</b>-with-resources statement, also known as
|
||||
Reports <b>AutoCloseable</b> instances which are not used in a try-with-resources statement, also known as
|
||||
<i>Automatic Resource Management</i>.
|
||||
This means that the open resource before/in <b>try</b>, close in <b>finally</b> style which was used before
|
||||
<b>try</b>-with-resources was available is also reported.
|
||||
try-with-resources was available is also reported.
|
||||
This inspection is meant to replace all <i>opened but not safely closed</i> inspections when developing in Java 7 and higher.
|
||||
<p>
|
||||
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.
|
||||
<p>
|
||||
Use the second table below to specify which methods returning AutoCloseable will be ignored when called.
|
||||
<p>
|
||||
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.
|
||||
<p>
|
||||
|
||||
Reference in New Issue
Block a user