void (@NotNull PsiElement element, @NotNull ActionContext context, @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 && ((PsiAssignmentExpression)parent).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) { final PsiLocalVariable variable = (PsiLocalVariable)parent; 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.moveTo(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)); } }