boolean (ChainOperation op1, ChainOperation op2) { if (op1 instanceof ChainOperation.TypeCast || op2 instanceof ChainOperation.TypeCast) return false; PsiMethod[] methods1 = ((ChainOperation.MethodCall)op1).getCandidates(); PsiMethod[] methods2 = ((ChainOperation.MethodCall)op2).getCandidates(); PsiMethod repr1 = methods1[0]; PsiMethod repr2 = methods2[0]; if (repr1.hasModifierProperty(PsiModifier.STATIC) || repr2.hasModifierProperty(PsiModifier.STATIC)) return false; if (!repr1.getName().equals(repr2.getName()) || repr1.getParameterList().getParametersCount() != repr2.getParameterList().getParametersCount()) { return false; } Set<PsiMethod> methodSet1 = ContainerUtil.newHashSet(methods1); Set<PsiMethod> methodSet2 = ContainerUtil.newHashSet(methods2); if (ContainerUtil.intersects(methodSet1, methodSet2)) return true; Set<PsiMethod> deepestSupers1 = methodSet1.stream().flatMap(m -> Arrays.stream(m.findDeepestSuperMethods())).collect(Collectors.toSet()); return methodSet2.stream().flatMap(m -> Arrays.stream(m.findDeepestSuperMethods())).anyMatch(deepestSupers1::contains); }