package de.plushnikov.intellij.plugin.handler; import com.intellij.codeInsight.CustomExceptionHandler; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiCodeBlock; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.PsiType; import com.intellij.psi.util.PsiTreeUtil; import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil; import lombok.SneakyThrows; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; public 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 (!(topElement instanceof PsiCodeBlock)) { final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class); return psiMethod != null && isExceptionHandled(psiMethod, exceptionType); } return false; } private boolean isExceptionHandled(@NotNull PsiModifierListOwner psiModifierListOwner, PsiClassType exceptionClassType) { final PsiAnnotation psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiModifierListOwner, SneakyThrows.class); if (psiAnnotation == null) { return false; } final Collection<PsiType> sneakedExceptionTypes = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class); //Default SneakyThrows handles all exceptions return sneakedExceptionTypes.isEmpty() || sneakedExceptionTypes.iterator().next().equalsToText(JAVA_LANG_THROWABLE) || isExceptionHandled(exceptionClassType, sneakedExceptionTypes); } private boolean isExceptionHandled(@NotNull PsiClassType exceptionClassType, @NotNull Collection<PsiType> sneakedExceptionTypes) { for (PsiType sneakedExceptionType : sneakedExceptionTypes) { if (sneakedExceptionType.equalsToText(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)) { return true; } } } } return false; } }