[lombok] IDEA-363645 Captured exceptions not identified, if @SneakyThrows used in conjunction with try-with-resources

GitOrigin-RevId: 8ddbb8f1d9a174dc265c57dc7ced6d209d7e18f2
This commit is contained in:
Michail Plushnikov
2024-12-30 21:58:33 +00:00
committed by intellij-monorepo-bot
parent 82e1aa419b
commit b0a027a032
3 changed files with 69 additions and 13 deletions
@@ -3,6 +3,7 @@ package de.plushnikov.intellij.plugin.handler;
import com.intellij.codeInsight.CustomExceptionHandler;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.JavaPsiConstructorUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -18,8 +19,6 @@ import java.util.List;
public final class SneakyThrowsExceptionHandler extends CustomExceptionHandler {
private static final String JAVA_LANG_THROWABLE = "java.lang.Throwable";
@Override
public boolean isHandled(@Nullable PsiElement element, @NotNull PsiClassType exceptionType, PsiElement topElement) {
if (isHandledByParent(element, exceptionType)) {
@@ -41,15 +40,18 @@ public final class SneakyThrowsExceptionHandler extends CustomExceptionHandler {
private static boolean isHandledByParent(@Nullable PsiElement element, @NotNull PsiClassType exceptionType) {
PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class, PsiTryStatement.class, PsiMethod.class);
if(parent == null) {
if (parent == null) {
return false;
} else if (parent instanceof PsiMethod) {
}
else if (parent instanceof PsiMethod) {
// we out of the scope of the method, so the exception wasn't handled inside the method
return false;
} else if (parent instanceof PsiLambdaExpression) {
}
else if (parent instanceof PsiLambdaExpression) {
// lambda it's another scope, @SneakyThrows annotation can't neglect exceptions in lambda only on method, constructor
return true;
} else if (parent instanceof PsiTryStatement && isHandledByTryCatch(exceptionType, (PsiTryStatement) parent)) {
}
else if (parent instanceof PsiTryStatement psiTryStatement && isHandledByTryCatch(exceptionType, psiTryStatement)) {
// that exception MAY be already handled by regular try-catch statement
return true;
}
@@ -88,28 +90,34 @@ public final class SneakyThrowsExceptionHandler extends CustomExceptionHandler {
PsiAnnotationUtil.getAnnotationValues(psiAnnotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class, throwable);
//Default SneakyThrows handles all exceptions
return sneakedExceptionTypes.isEmpty()
|| sneakedExceptionTypes.iterator().next().equalsToText(JAVA_LANG_THROWABLE)
|| sneakedExceptionTypes.iterator().next().equalsToText(CommonClassNames.JAVA_LANG_THROWABLE)
|| isExceptionHandled(exceptionClassType, sneakedExceptionTypes);
}
private static boolean isExceptionHandled(@NotNull PsiClassType exceptionClassType, @NotNull Collection<PsiType> sneakedExceptionTypes) {
for (PsiType sneakedExceptionType : sneakedExceptionTypes) {
if (sneakedExceptionType.equalsToText(JAVA_LANG_THROWABLE) || sneakedExceptionType.equals(exceptionClassType)) {
if (sneakedExceptionType.equalsToText(CommonClassNames.JAVA_LANG_THROWABLE) || sneakedExceptionType.equals(exceptionClassType)) {
return true;
}
}
final PsiClass unhandledExceptionClass = exceptionClassType.resolve();
if (null != unhandledExceptionClass) {
for (PsiType sneakedExceptionType : sneakedExceptionTypes) {
if (sneakedExceptionType instanceof PsiClassType) {
final PsiClass sneakedExceptionClass = ((PsiClassType)sneakedExceptionType).resolve();
if (null != sneakedExceptionClass && unhandledExceptionClass.isInheritor(sneakedExceptionClass, true)) {
if (sneakedExceptionType instanceof PsiClassType psiClassType) {
if (InheritanceUtil.isInheritorOrSelf(unhandledExceptionClass, psiClassType.resolve(), true)) {
return true;
}
}
else if (sneakedExceptionType instanceof PsiDisjunctionType disjunctionType) {
for (PsiType disjunctionTypePart : disjunctionType.getDisjunctions()) {
if (disjunctionTypePart instanceof PsiClassType disjunctionClassType) {
if (InheritanceUtil.isInheritorOrSelf(unhandledExceptionClass, disjunctionClassType.resolve(), true)) {
return true;
}
}
}
}
}
}
return false;
@@ -34,4 +34,8 @@ public class SneakyThrowsHighlightTest extends AbstractLombokHighlightsTest {
public void testSneakyThrowsTryInsideLambda() {
doTest();
}
public void testSneakyThrowsTryWithResources() {
doTest();
}
}
@@ -0,0 +1,44 @@
import lombok.SneakyThrows;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
public class SneakyThrowsTryWithResources {
private static class SomeException extends Exception {
}
private Connection getConnection() throws IOException, SQLException, SomeException {
return null;
}
@SneakyThrows
public void methodOneNotCatched() {
try (Connection connection = getConnection()) {
// no errors
} catch (IOException | SQLException e) {
}
}
@SneakyThrows
public void methodAllCatched() {
try (Connection connection = getConnection()) {
// no errors
} catch (IOException | SQLException | SomeException e) {
}
}
public void methodWithUnhandledException() {
try (Connection connection = <error descr="Unhandled exception: SneakyThrowsTryWithResources.SomeException">getConnection</error>()) {
} catch (IOException | SQLException e) {
}
}
}