diff --git a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SideEffectChecker.java b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SideEffectChecker.java index 6c9d8576b113..9c6178903221 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SideEffectChecker.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SideEffectChecker.java @@ -360,8 +360,7 @@ public final class SideEffectChecker { // all Throwable descendants from java.lang are side effects free if (CommonClassNames.DEFAULT_PACKAGE.equals(packageName) || "java.io".equals(packageName)) { - PsiClass throwableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass(CommonClassNames.JAVA_LANG_THROWABLE, aClass.getResolveScope()); - if (throwableClass != null && com.intellij.psi.util.InheritanceUtil.isInheritorOrSelf(aClass, throwableClass, true)) { + if (PsiClassUtil.isThrowable(aClass)) { return ThreeState.NO; } } diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java index 7a634e1a5528..06d26b44259c 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java @@ -1,6 +1,7 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.psi.util; +import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiAnonymousClass; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiModifier; @@ -8,6 +9,8 @@ import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; public final class PsiClassUtil { private PsiClassUtil() { } @@ -34,4 +37,22 @@ public final class PsiClassUtil { return Comparator.comparing(c -> PsiUtilCore.getVirtualFile(c), Comparator.nullsFirst((file1, file2) -> scope.compare(file2, file1))); } + + /** + * Checks if the given class is a throwable. The behavior is unspecified if the class or any of its superclasses is malformed. + * + * @param psiClass class to test + * @return true if class is {@code java.lang.Throwable} or legally inherits from it. + */ + public static boolean isThrowable(@NotNull PsiClass psiClass) { + Set supers = new HashSet<>(); + while (true) { + if (CommonClassNames.JAVA_LANG_THROWABLE.equals(psiClass.getQualifiedName())) return true; + if (psiClass.isInterface()) return false; + if (psiClass.getTypeParameters().length > 0) return false; // Valid throwables are never generic + PsiClass next = psiClass.getSuperClass(); + if (next == null || !supers.add(next)) return false; + psiClass = next; + } + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/ElementPresentationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/ElementPresentationUtil.java index 0c073a8a130a..6cef6fcec66e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/ElementPresentationUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/ElementPresentationUtil.java @@ -20,7 +20,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import javax.swing.Icon; +import javax.swing.*; public final class ElementPresentationUtil { private ElementPresentationUtil() { @@ -116,11 +116,7 @@ public final class ElementPresentationUtil { } if (!DumbService.getInstance(aClass.getProject()).isDumb()) { - final PsiManager manager = aClass.getManager(); - final PsiClass javaLangTrowable = - JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_THROWABLE, aClass.getResolveScope()); - final boolean isException = javaLangTrowable != null && InheritanceUtil.isInheritorOrSelf(aClass, javaLangTrowable, true); - if (isException) { + if (PsiClassUtil.isThrowable(aClass)) { return CLASS_KIND_EXCEPTION; }