RedundantExplicitCloseInspection created: IDEA-176630

This commit is contained in:
Roman Ivanov
2018-01-30 10:39:29 +07:00
parent 58444f64fa
commit d5d06483fe
7 changed files with 153 additions and 1 deletions
@@ -532,6 +532,12 @@
groupKey="group.names.code.style.issues" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.OptionalIsPresentInspection"
displayName="Replace Optional.isPresent() checks with functional-style expressions"/>
<localInspection groupPath="Java" language="JAVA" shortName="RedundantExplicitClose"
groupBundle="messages.InspectionsBundle"
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING"
bundle="messages.InspectionsBundle"
key="inspection.redundant.explicit.close"
implementationClass="com.intellij.codeInspection.RedundantExplicitCloseInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="RedundantLambdaParameterType"
groupBundle="messages.InspectionsBundle"
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="INFORMATION"
@@ -0,0 +1,72 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.psiutils.CommentTracker;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import static com.intellij.util.ObjectUtils.tryCast;
public class RedundantExplicitCloseInspection extends AbstractBaseJavaLocalInspectionTool {
CallMatcher CLOSE = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, "close").parameterCount(0);
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override
public void visitTryStatement(PsiTryStatement statement) {
PsiResourceList resourceList = statement.getResourceList();
if (resourceList == null) return;
PsiCodeBlock tryBlock = statement.getTryBlock();
if (tryBlock == null) return;
PsiStatement[] statements = tryBlock.getStatements();
if(statements.length == 0) return;
PsiStatement last = statements[statements.length - 1];
PsiExpressionStatement expressionStatement = tryCast(last, PsiExpressionStatement.class);
if(expressionStatement == null) return;
PsiMethodCallExpression call = tryCast(expressionStatement.getExpression(), PsiMethodCallExpression.class);
if (!CLOSE.test(call)) return;
PsiReferenceExpression reference = tryCast(call.getMethodExpression().getQualifierExpression(), PsiReferenceExpression.class);
if(reference == null) return;
PsiVariable variable = tryCast(reference.resolve(), PsiVariable.class);
if(variable == null) return;
boolean isReferenceToResourceVariable = StreamEx.of(resourceList.iterator())
.anyMatch(element -> {
if (element instanceof PsiResourceVariable && variable == element) {
return true;
}
else {
PsiReferenceExpression ref = tryCast(element, PsiReferenceExpression.class);
if (ref == null) return false;
return ref.resolve() == variable;
}
});
if(!isReferenceToResourceVariable) return;
holder.registerProblem(last, InspectionsBundle.message("inspection.redundant.explicit.close"),
ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DeleteRedundantCloseFix());
}
};
}
private static class DeleteRedundantCloseFix implements LocalQuickFix {
@Nls
@NotNull
@Override
public String getFamilyName() {
return InspectionsBundle.message("inspection.redundant.explicit.close.fix.name");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
new CommentTracker().deleteAndRestoreComments(element);
}
}
}
@@ -0,0 +1,7 @@
<html>
<body>
Inspection reports unnecessary close of resource in the end of try-with-resources block
<!-- tooltip end -->
<small>New in 2018.1</small>
</body>
</html>
@@ -0,0 +1,16 @@
// "Remove redundant close" "true"
class MyAutoCloseable implements AutoCloseable {
@Override
void close() {
}
}
class RemoveTry {
public static void main(String[] args) {
try(MyAutoCloseable ac = new MyAutoCloseable()) {
System.out.println("asdasd");
}
}
}
@@ -0,0 +1,17 @@
// "Remove redundant close" "true"
class MyAutoCloseable implements AutoCloseable {
@Override
void close() {
}
}
class RemoveTry {
public static void main(String[] args) {
try(MyAutoCloseable ac = new MyAutoCloseable()) {
System.out.println("asdasd");
ac.close<caret>();
}
}
}
@@ -0,0 +1,31 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.OptionalIsPresentInspection;
import com.intellij.codeInspection.RedundantExplicitCloseInspection;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class RedundantExplicitCloseInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{
new RedundantExplicitCloseInspection()
};
}
public void test() { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/redundantExplicitClose";
}
}
@@ -943,4 +943,7 @@ inspection.endless.stream.description=Non-short-circuit operation consumes the i
inspection.redundant.comparator.comparing.display.name=Redundant Comparator.comparing
inspection.capturing.cleaner=Runnable passed to Cleaner.register() captures ''{0}'' reference
inspection.capturing.cleaner.description=Cleaner captures object reference
inspection.capturing.cleaner.description=Cleaner captures object reference
inspection.redundant.explicit.close=Redundant close
inspection.redundant.explicit.close.fix.name=Remove redundant close