@Nullable
    @Override
    public StringReplacement extractContext(@NotNull Project project, @NotNull PsiMethodCallExpression call) {
      PsiExpression falseArg = getOrElseArgument(call, myType);
      if (falseArg == null) return null;
      PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call);
      if (!OPTIONAL_MAP.test(qualifierCall)) return null;
      PsiLambdaExpression lambda = getLambda(qualifierCall.getArgumentList().getExpressions()[0]);
      if (lambda == null) return null;
      PsiExpression trueArg = LambdaUtil.extractSingleExpressionFromBody(lambda.getBody());
      if (trueArg == null) return null;
      PsiParameter[] parameters = lambda.getParameterList().getParameters();
      if (parameters.length != 1) return null;
      PsiExpression qualifier = qualifierCall.getMethodExpression().getQualifierExpression();
      if (qualifier == null) return null;
      String opt = qualifier.getText();
      PsiParameter parameter = parameters[0];
      boolean useOrElseGet = myType == OrElseType.OrElseGet;
      String proposed = OptionalRefactoringUtil.generateOptionalUnwrap(opt, parameter, trueArg, falseArg, call.getType(), useOrElseGet);
      String canonicalOrElse;
      if (useOrElseGet && !ExpressionUtils.isSafelyRecomputableExpression(falseArg)) {
        canonicalOrElse = ".orElseGet(() -> " + falseArg.getText() + ")";
      }
      else {
        canonicalOrElse = ".orElse(" + falseArg.getText() + ")";
      }
      String canonical = opt + ".map(" + LambdaUtil.createLambda(parameter, trueArg) + ")" + canonicalOrElse;
      if (proposed.length() < canonical.length()) {
        String displayCode;
        if (proposed.equals(opt)) {
          displayCode = "";
        }
        else if (opt.length() > 10) {
          // should be a parseable expression
          opt = "(($))";
          String template =
            OptionalRefactoringUtil.generateOptionalUnwrap(opt, parameter, trueArg, falseArg, call.getType(), useOrElseGet);
          displayCode =
            PsiExpressionTrimRenderer
              .render(JavaPsiFacade.getElementFactory(parameter.getProject()).createExpressionFromText(template, call));
          displayCode = displayCode.replaceFirst(Pattern.quote(opt), "..");
        }
        else {
          displayCode =
            PsiExpressionTrimRenderer
              .render(JavaPsiFacade.getElementFactory(parameter.getProject()).createExpressionFromText(proposed, call));
        }
        String message = displayCode.isEmpty()
                         ? JavaBundle.message("simplify.optional.chain.inspection.remove.redundant.steps.from.optional.chain")
                         : JavaBundle.message("simplify.optional.chain.inspection.to.x", displayCode);
        String description = JavaBundle.message("simplify.optional.chain.inspection.map.or.else.description");
        return new StringReplacement(proposed, message, description);
      }
      return null;
    }
@Nullable
    @Override
    public StringReplacement extractContext(@NotNull Project project, @NotNull PsiMethodCallExpression call)