IG: handle try resource lists correctly in "Overly broad 'catch' block" inspection

This commit is contained in:
Bas Leijdekkers
2015-05-15 16:38:34 +02:00
parent 1a429ba900
commit 39c8627084
3 changed files with 38 additions and 46 deletions
@@ -81,6 +81,7 @@ public class TooBroadCatchInspectionBase extends BaseInspection {
return;
}
final Set<PsiType> thrownTypes = ExceptionUtils.calculateExceptionsThrown(tryBlock);
ExceptionUtils.calculateExceptionsThrown(statement.getResourceList(), thrownTypes);
final Set<PsiType> caughtTypes = new HashSet<PsiType>(thrownTypes.size());
final PsiCatchSection[] catchSections = statement.getCatchSections();
for (final PsiCatchSection catchSection : catchSections) {
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.Set;
public class ExceptionUtils {
@@ -39,12 +39,19 @@ public class ExceptionUtils {
@NotNull
public static Set<PsiType> calculateExceptionsThrown(@Nullable PsiElement element) {
return calculateExceptionsThrown(element, new HashSet<PsiType>());
return calculateExceptionsThrown(element, new LinkedHashSet<PsiType>(5));
}
@NotNull
public static Set<PsiType> calculateExceptionsThrown(@Nullable PsiElement element, @NotNull Set<PsiType> out) {
if (element == null) return out;
if (element instanceof PsiResourceList) {
final PsiResourceList resourceList = (PsiResourceList)element;
for (PsiResourceVariable variable : resourceList.getResourceVariables()) {
final PsiMethod method = PsiUtil.getResourceCloserMethod(variable);
collectExceptionsThrown(method, out);
}
}
final ExceptionsThrownVisitor visitor = new ExceptionsThrownVisitor(out);
element.accept(visitor);
return out;
@@ -199,6 +206,19 @@ public class ExceptionUtils {
return false;
}
private static void collectExceptionsThrown(@Nullable PsiMethod method, @NotNull Set<PsiType> out) {
if (method == null) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
for (PsiJavaCodeReferenceElement referenceElement : method.getThrowsList().getReferenceElements()) {
final PsiClass exceptionClass = (PsiClass)referenceElement.resolve();
if (exceptionClass != null) {
out.add(factory.createType(exceptionClass));
}
}
}
private static class ExceptionsThrownVisitor extends JavaRecursiveElementVisitor {
private final Set<PsiType> m_exceptionsThrown;
@@ -234,53 +254,21 @@ public class ExceptionUtils {
@Override
public void visitTryStatement(@NotNull PsiTryStatement statement) {
final Set<PsiType> exceptionsHandled = getExceptionTypesHandled(statement);
final PsiResourceList resourceList = statement.getResourceList();
if (resourceList != null) {
final List<PsiResourceVariable> resourceVariables = resourceList.getResourceVariables();
for (PsiResourceVariable resourceVariable : resourceVariables) {
final Set<PsiType> resourceExceptions = calculateExceptionsThrown(resourceVariable);
collectExceptionsThrown(PsiUtil.getResourceCloserMethod(resourceVariable), resourceExceptions);
for (PsiType resourceException : resourceExceptions) {
if (!isExceptionHandled(exceptionsHandled, resourceException)) {
m_exceptionsThrown.add(resourceException);
}
}
}
}
final PsiCodeBlock tryBlock = statement.getTryBlock();
if (tryBlock != null) {
final Set<PsiType> tryExceptions = calculateExceptionsThrown(tryBlock);
for (PsiType tryException : tryExceptions) {
if (!isExceptionHandled(exceptionsHandled, tryException)) {
m_exceptionsThrown.add(tryException);
}
}
}
final PsiCodeBlock finallyBlock = statement.getFinallyBlock();
if (finallyBlock != null) {
final Set<PsiType> finallyExceptions = calculateExceptionsThrown(finallyBlock);
m_exceptionsThrown.addAll(finallyExceptions);
}
final PsiCodeBlock[] catchBlocks = statement.getCatchBlocks();
for (PsiCodeBlock catchBlock : catchBlocks) {
final Set<PsiType> catchExceptions = calculateExceptionsThrown(catchBlock);
m_exceptionsThrown.addAll(catchExceptions);
}
}
private static void collectExceptionsThrown(@Nullable PsiMethod method, @NotNull Set<PsiType> out) {
if (method == null) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
final PsiJavaCodeReferenceElement[] referenceElements = method.getThrowsList().getReferenceElements();
for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
final PsiClass exceptionClass = (PsiClass)referenceElement.resolve();
if (exceptionClass != null) {
out.add(factory.createType(exceptionClass));
for (PsiType resourceException : calculateExceptionsThrown(statement.getResourceList())) {
if (!isExceptionHandled(exceptionsHandled, resourceException)) {
m_exceptionsThrown.add(resourceException);
}
}
for (PsiType tryException : calculateExceptionsThrown(statement.getTryBlock())) {
if (!isExceptionHandled(exceptionsHandled, tryException)) {
m_exceptionsThrown.add(tryException);
}
}
calculateExceptionsThrown(statement.getFinallyBlock(), m_exceptionsThrown);
for (PsiCodeBlock catchBlock : statement.getCatchBlocks()) {
calculateExceptionsThrown(catchBlock, m_exceptionsThrown);
}
}
private static boolean isExceptionHandled(Iterable<PsiType> exceptionsHandled, PsiType thrownType) {
@@ -61,6 +61,9 @@ public class TooBroadCatchBlock{
try {
try (java.io.FileInputStream in = new java.io.FileInputStream("asdf")) {}
} catch (<warning descr="'catch' of 'IOException' is too broad, masking exception 'FileNotFoundException'">IOException</warning> e) {}
try (java.io.InputStream in = new java.io.FileInputStream("")) {
} catch (<warning descr="'catch' of 'Exception' is too broad, masking exceptions 'IOException' and 'FileNotFoundException'">Exception</warning> e) {}
}
boolean m() {