@Override
  protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
    final List<String> callTexts = new ArrayList<>();
    PsiMethodCallExpression call = ObjectUtils.tryCast(element, PsiMethodCallExpression.class);
    if (call == null) return;
    CodeBlockSurrounder surrounder = CodeBlockSurrounder.forExpression(call);
    if (surrounder == null) return;
    CodeBlockSurrounder.SurroundResult result = surrounder.surround();
    call = (PsiMethodCallExpression)result.getExpression();
    final PsiStatement appendStatement = result.getAnchor();
    PsiExpression toReplace = call;
    PsiExpression root = MethodCallChainPredicate.getCallChainRoot(call);
    if (root == null) return;
    PsiType callType = call.getType();
    if (callType == null) return;
    CommentTracker tracker = new CommentTracker();
    while (call != null && call != root) {
      callTexts.add(call.getMethodExpression().getReferenceName() + tracker.text(call.getArgumentList()));
      call = MethodCallUtils.getQualifierMethodCall(call);
    }
    final PsiType rootType = root.getType();
    if (rootType == null) return;
    final PsiElement parent = PsiUtil.skipParenthesizedExprUp(toReplace.getParent());
    
    // By default we introduce new variable and assign it to builder 
    String targetText = new VariableNameGenerator(root, VariableKind.LOCAL_VARIABLE).byExpression(root).generate(true);
    boolean introduceVariable = true;
    boolean keepLastStatement = true;
    final String variableText = rootType.getCanonicalText() + ' ' + targetText + '=' + root.getText() + ';';
    @NonNls String firstStatement = (JavaCodeStyleSettings.getInstance(toReplace.getContainingFile()).GENERATE_FINAL_LOCALS ? "final " : "") 
                                    + variableText;
    // In some cases we can omit new variable reusing the existing one instead
    if (isSimpleReference(root)) {
      targetText = root.getText();
      firstStatement = null;
      introduceVariable = false;
    }
    else if (parent instanceof PsiAssignmentExpression assignment && parent.getParent() instanceof PsiExpressionStatement &&
             assignment.getOperationTokenType().equals(JavaTokenType.EQ)) {
      final PsiExpression lhs = PsiUtil.skipParenthesizedExprDown(assignment.getLExpression());
      if (lhs instanceof PsiReferenceExpression expression) {
        final PsiElement target = expression.resolve();
        if (target instanceof PsiVariable variable) {
          final PsiType variableType = variable.getType();
          if (variableType.equals(rootType)) {
            targetText = tracker.text(lhs);
            firstStatement = targetText + '=' + root.getText() + ';';
            keepLastStatement = introduceVariable = false;
          }
        }
      }
    }
    else if (parent instanceof PsiLocalVariable variable) {
      final PsiType variableType = variable.getType();
      if (variableType.equals(rootType)) {
        targetText = variable.getName();
        PsiLocalVariable varCopy = (PsiLocalVariable)variable.copy();
        varCopy.setInitializer(root);
        firstStatement = varCopy.getText();
        keepLastStatement = introduceVariable = false;
      }
    }
    if (parent instanceof PsiExpressionStatement) {
      keepLastStatement = false;
    }
    if (keepLastStatement && !callType.equals(rootType)) {
      callTexts.remove(0);
      toReplace = Objects.requireNonNull(((PsiMethodCallExpression)toReplace).getMethodExpression().getQualifierExpression());
    }
    String replacementBlock = generateReplacementBlock(callTexts, targetText, firstStatement);
    PsiVariable variable = appendStatements(appendStatement, tracker, introduceVariable, replacementBlock, updater);
    if (keepLastStatement) {
      updater.moveCaretTo(tracker.replaceAndRestoreComments(toReplace, targetText));
    } else {
      tracker.deleteAndRestoreComments(appendStatement);
    }
    if (variable != null) {
      updater.rename(variable, new VariableNameGenerator(variable, VariableKind.LOCAL_VARIABLE)
        .byExpression(variable.getInitializer()).byType(variable.getType()).generateAll(true));
    }
  }
@Override
  protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater)