@Override
      public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
        if (STREAM_OF_SINGLE.test(call)) {
          handleSingleElementStream(call);
        }
        PsiReferenceExpression methodExpression = call.getMethodExpression();
        String name = methodExpression.getReferenceName();
        if (name == null || !INTERESTING_NAMES.contains(name)) return;
        PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
        if (qualifier == null) return;
        PsiMethod method = call.resolveMethod();
        if (method == null) return;
        PsiClass aClass = method.getContainingClass();
        if (aClass == null) return;
        String className = aClass.getQualifiedName();
        if (className == null) return;
        boolean optional = OptionalUtil.isJdkOptionalClassName(className);
        boolean stream = InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM);
        if (!optional && !stream) return;
        PsiExpression[] args = call.getArgumentList().getExpressions();
        if (name.equals("flatMap") && args.length == 1 && isIdentityMapping(args[0], false)) {
          PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call);
          if (STREAM_MAP.test(qualifierCall) && qualifierCall.getMethodExpression().getTypeParameters().length == 0 &&
              !isIdentityMapping(qualifierCall.getArgumentList().getExpressions()[0], false)) {
            String message = JavaBundle.message("inspection.redundant.stream.optional.call.message", name) +
                             ": " + JavaBundle.message("inspection.redundant.stream.optional.call.explanation.map.flatMap");
            holder.registerProblem(call, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getRange(call),
                                   new RemoveCallFix(name, "map"));
          }
        }
        if (!EquivalenceChecker.getCanonicalPsiEquivalence().typesAreEquivalent(qualifier.getType(), call.getType())) return;
        switch (name) {
          case "filter" -> {
            if (args.length == 1 && isTruePredicate(args[0])) {
              register(call, JavaBundle.message("inspection.redundant.stream.optional.call.explanation.filter"));
            }
          }
          case "map" -> {
            boolean allowBoxUnbox =
              USELESS_BOXING_IN_STREAM_MAP || optional || StreamApiUtil.getStreamElementType(call.getType()) instanceof PsiPrimitiveType;
            if (args.length == 1 && isIdentityMapping(args[0], allowBoxUnbox)) {
              register(call, null);
            }
          }
          case "flatMap" -> {
            if (args.length == 1) {
              if (optional) {
                if (FunctionalExpressionUtils
                      .isFunctionalReferenceTo(args[0], CommonClassNames.JAVA_UTIL_OPTIONAL, null, "of", new PsiType[1]) ||
                    FunctionalExpressionUtils
                      .isFunctionalReferenceTo(args[0], CommonClassNames.JAVA_UTIL_OPTIONAL, null, "ofNullable", new PsiType[1])) {
                  register(call, null);
                }
              }
              else {
                if (FunctionalExpressionUtils
                  .isFunctionalReferenceTo(args[0], CommonClassNames.JAVA_UTIL_STREAM_STREAM, null, "of", new PsiType[1])) {
                  register(call, null);
                }
              }
            }
          }
          case "sorted" -> {
            if (args.length <= 1) {
              PsiMethodCallExpression furtherCall = findCallThatSpoilsSorting(call);
              if (furtherCall != null) {
                String furtherCallName = furtherCall.getMethodExpression().getReferenceName();
                String terminalReplacement = CALLS_MAKING_SORT_USELESS_PARALLEL.get(furtherCallName);
                if (terminalReplacement != null && !isParallelStream(call)) return;
                if (("max".equals(furtherCallName) || "min".equals(furtherCallName)) &&
                    !sortingCancelsPreviousSorting(call, furtherCall)) {
                  return;
                }
                LocalQuickFix additionalFix = null;
                if ("toSet".equals(furtherCallName) || "toCollection".equals(furtherCallName)) {
                  additionalFix = new CollectToOrderedSetFix();
                }
                else if (terminalReplacement != null) {
                  additionalFix = new ReplaceTerminalCallFix(terminalReplacement);
                }
                String message = "sorted".equals(furtherCallName)
                                 ? JavaBundle.message("inspection.redundant.stream.optional.call.explanation.sorted.twice")
                                 : terminalReplacement != null
                                   ? JavaBundle.message("inspection.redundant.stream.optional.call.explanation.sorted.parallel",
                                                        furtherCallName)
                                   : JavaBundle.message("inspection.redundant.stream.optional.call.explanation.sorted", furtherCallName);
                register(call, message, LocalQuickFix.notNullElements(additionalFix));
              }
            }
          }
          case "distinct" -> {
            if (args.length == 0) {
              PsiMethodCallExpression furtherCall =
                findSubsequentCall(call, Predicate.isEqual("distinct"), CALLS_KEEPING_ELEMENTS_DISTINCT::contains);
              if (furtherCall != null && furtherCall.getArgumentList().isEmpty()) {
                register(furtherCall, JavaBundle.message("inspection.redundant.stream.optional.call.explanation.distinct"));
              }
              Predicate<PsiMethodCallExpression> setCollector =
                COLLECTOR_TO_SET.or(RedundantStreamOptionalCallInspection::isToCollectionSet);
              if (findSubsequentCall(call, c -> false, setCollector,
                                     Set.of("unordered", "parallel", "sequential", "sorted")::contains) != null) {
                register(call, JavaBundle.message("inspection.redundant.stream.optional.call.explanation.distinct.set"));
              }
            }
          }
          case "unordered" -> {
            if (args.length == 0) {
              PsiMethodCallExpression furtherCall =
                findSubsequentCall(call, Predicate.isEqual("unordered"), n -> !n.equals("sorted"));
              if (furtherCall != null && furtherCall.getArgumentList().isEmpty()) {
                register(furtherCall, JavaBundle.message("inspection.redundant.stream.optional.call.explanation.unordered"));
              }
            }
          }
          case "sequential", "parallel" -> {
            if (args.length == 0) {
              PsiMethodCallExpression furtherCall = findSubsequentCall(call, CALLS_AFFECTING_PARALLELIZATION::contains, n -> true);
              if (furtherCall != null && furtherCall.getArgumentList().isEmpty()) {
                register(call, JavaBundle.message("inspection.redundant.stream.optional.call.explanation.parallel",
                                                  furtherCall.getMethodExpression().getReferenceName()));
              }
              else {
                PsiMethodCallExpression previousCall = MethodCallUtils.getQualifierMethodCall(call);
                while (true) {
                  if (previousCall == null) break;
                  String prevName = previousCall.getMethodExpression().getReferenceName();
                  if (prevName == null) break;
                  if (CALLS_AFFECTING_PARALLELIZATION.contains(prevName)) break; // already reported on previous call
                  if (COLLECTION_STREAM_SOURCE.test(previousCall)) {
                    boolean previousParallel = prevName.equals("parallelStream");
                    boolean curParallel = name.equals("parallel");
                    if (previousParallel == curParallel) {
                      register(call,
                               JavaBundle.message(curParallel ? "inspection.redundant.stream.optional.call.explanation.parallel.source" :
                                                  "inspection.redundant.stream.optional.call.explanation.sequential.source"));
                      break;
                    }
                  }
                  if (StreamApiUtil.getStreamElementType(previousCall.getType()) == null) break;
                  previousCall = MethodCallUtils.getQualifierMethodCall(previousCall);
                }
              }
            }
          }
        }
      }
@Override
      public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call)