RecordExhaustivenessResult (@NotNull PsiType currentRecordType, @NotNull List<? extends PsiType> leftRecordTypes, @NotNull List<? extends List<PsiPattern>> deconstructions) { if (leftRecordTypes.isEmpty() || ContainerUtil.exists(deconstructions, t -> t.size() == 0)) { //there is no deconstruction, a case with an empty set of labels is considered before, don't repeat errors return RecordExhaustivenessResult.createExhaustiveResult(); } PsiType typeToCheck = leftRecordTypes.get(0); //A case with unresolved type checks before, don't repeat errors if (typeToCheck == null) return RecordExhaustivenessResult.createExhaustiveResult(); MultiMap<PsiType, List<PsiPattern>> groupedByType = ContainerUtil.groupBy(deconstructions, deconstructionComponents -> JavaPsiPatternUtil.getPatternType( deconstructionComponents.get(0))); List<GroupExhaustiveness> groupsExhaustiveness = getGroupsExhaustiveness(currentRecordType, leftRecordTypes, groupedByType); if (groupsExhaustiveness.isEmpty()) return RecordExhaustivenessResult.createNotBeAdded(); List<PsiPattern> checkedExhaustivePatterns = new ArrayList<>(); Map<PsiType, BranchesExhaustiveness> notExhaustive = new LinkedHashMap<>(); for (GroupExhaustiveness group : groupsExhaustiveness) { if (!group.branchesExhaustiveness().result().isExhaustive()) { PsiType notExhaustiveType = group.psiType(); notExhaustive.put(notExhaustiveType, group.branchesExhaustiveness()); continue; } Collection<List<PsiPattern>> lists = groupedByType.get(group.psiType()); if (lists.isEmpty()) continue; List<PsiPattern> next = lists.iterator().next(); if (next == null || next.isEmpty()) continue; checkedExhaustivePatterns.add(next.get(0)); } if (ContainerUtil.exists(checkedExhaustivePatterns, pattern -> JavaPsiPatternUtil.isUnconditionalForType(pattern, typeToCheck, true))) { return RecordExhaustivenessResult.createExhaustiveResult(); // exhaustive even without not-exhaustive-subgroup } Set<PsiClass> missedClasses = findMissedClassesForSealed(typeToCheck, checkedExhaustivePatterns); if (missedClasses.isEmpty() && !checkedExhaustivePatterns.isEmpty()) { return RecordExhaustivenessResult.createExhaustiveResult(); //exhaustive even without not-exhaustive-subgroup } //if one of them is unconditional, return any of them List<BranchesExhaustiveness> coveredPatterns = ContainerUtil.filter(notExhaustive.values(), group -> group.branches().stream() .filter(t -> !t.isEmpty()) .map(patterns -> patterns.get(0)) .anyMatch(pattern -> JavaPsiPatternUtil.isUnconditionalForType(pattern, typeToCheck, true))); if (!coveredPatterns.isEmpty()) { RecordExhaustivenessResult nextResult = coveredPatterns.get(0).result(); nextResult.addNextType(currentRecordType, typeToCheck); return nextResult; } return mergeMissedClasses(currentRecordType, leftRecordTypes, notExhaustive, missedClasses); }