void (@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiTryStatement.class); final PsiCodeBlock tryBlock = tryStatement == null ? null : tryStatement.getTryBlock(); if (tryBlock == null) return; final JavaCompletionSession session = new JavaCompletionSession(result); List<PsiClass> preferred = new ArrayList<>(); for (final PsiClassType type : ExceptionUtil.getThrownExceptions(tryBlock.getStatements())) { PsiClass typeClass = type.resolve(); if (typeClass != null) { result.addElement(PrioritizedLookupElement.withPriority(createCatchTypeVariant(tryBlock, type), 100)); session.registerClass(typeClass); preferred.add(typeClass); } } final Collection<PsiClassType> expectedClassTypes = Collections.singletonList(JavaPsiFacade.getElementFactory( tryBlock.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE)); JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), type -> { final PsiClass psiClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null; if (psiClass == null || psiClass instanceof PsiTypeParameter) return; if (!session.alreadyProcessed(psiClass)) { LookupElement element = createCatchTypeVariant(tryBlock, (PsiClassType)type); final int maxNumberOfHopsToConsider = 25; // Tune priorities for classes in catch: // 100 = class that exactly matches the thrown type // 26..50 = superclasses of the thrown type (higher priority = less inheritance hops) // 1..25 = subclasses of the thrown type (higher priority = less inheritance hops) int priority = StreamEx.of(preferred) .mapToInt(aClass -> { int hops = Math.min(maxNumberOfHopsToConsider, getNumberOfHops(psiClass, aClass)); if (hops >= 0) { return 1 + maxNumberOfHopsToConsider * 2 - hops; } hops = Math.min(maxNumberOfHopsToConsider, getNumberOfHops(aClass, psiClass)); if (hops >= 0) { return 1 + maxNumberOfHopsToConsider - hops; } return 0; }) .max().orElse(0); if (priority > 0) { element = PrioritizedLookupElement.withPriority(element, priority); } result.addElement(element); } }); }