void (@NotNull final Project project, @NotNull final Editor editor, @NotNull final PyTargetExpression local, @Nullable PyReferenceExpression refExpr) { if (!CommonRefactoringUtil.checkReadOnlyStatus(project, local)) return; final HighlightManager highlightManager = HighlightManager.getInstance(project); final String localName = local.getName(); final ScopeOwner containerBlock = getContext(local); LOG.assertTrue(containerBlock != null); final Pair<PyStatement, Boolean> defPair = getAssignmentToInline(containerBlock, refExpr, local, project); final PyStatement def = defPair.first; if (def == null || getValue(def) == null) { final String key = defPair.second ? "variable.has.no.dominating.definition" : "variable.has.no.initializer"; final String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, localName)); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HELP_ID); return; } if (def instanceof PyAssignmentStatement && ((PyAssignmentStatement)def).getTargets().length > 1) { highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{def}, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); final String message = RefactoringBundle.getCannotRefactorMessage(PyPsiBundle.message("refactoring.inline.local.multiassignment", localName)); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HELP_ID); return; } final PsiElement[] refsToInline = PyDefUseUtil.getPostRefs(containerBlock, local, getObject(def)); if (refsToInline.length == 0) { final String message = RefactoringBundle.message("variable.is.never.used", localName); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HELP_ID); return; } if (!ApplicationManager.getApplication().isUnitTestMode()) { highlightManager.addOccurrenceHighlights(editor, refsToInline, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); final int occurrencesCount = refsToInline.length; final String occurrencesString = RefactoringBundle.message("occurrences.string", occurrencesCount); final String question = RefactoringBundle.message("inline.local.variable.prompt", localName) + " " + occurrencesString; boolean result = RefactoringUiService.getInstance().showRefactoringMessageDialog(getRefactoringName(), question, HELP_ID, "OptionPane.questionIcon", true, project); if (!result) { WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting")); return; } } final PsiFile workingFile = local.getContainingFile(); for (PsiElement ref : refsToInline) { final PsiFile otherFile = ref.getContainingFile(); if (!otherFile.equals(workingFile)) { final String message = RefactoringBundle.message("variable.is.referenced.in.multiple.files", localName); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HELP_ID); return; } } for (final PsiElement ref : refsToInline) { final List<PsiElement> elems = new ArrayList<>(); final List<Instruction> latestDefs = PyDefUseUtil.getLatestDefs(containerBlock, local.getName(), ref, false, false); for (Instruction i : latestDefs) { elems.add(i.getElement()); } final PsiElement[] defs = elems.toArray(PsiElement.EMPTY_ARRAY); boolean isSameDefinition = true; for (PsiElement otherDef : defs) { isSameDefinition &= isSameDefinition(def, otherDef); } if (!isSameDefinition) { highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{ref}, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); final String message = RefactoringBundle.getCannotRefactorMessage( RefactoringBundle.message("variable.is.accessed.for.writing.and.used.with.inlined", localName)); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HELP_ID); WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting")); return; } } CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { try { final RefactoringEventData afterData = new RefactoringEventData(); afterData.addElement(local); project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringStarted(getRefactoringId(), afterData); final List<PsiElement> exprs = new ArrayList<>(); final PyExpression value = prepareValue(def, localName, project); final PsiElement lastChild = def.getLastChild(); if (lastChild != null && lastChild.getNode().getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) { final PsiElement parent = def.getParent(); if (parent != null) parent.addBefore(lastChild, def); } // Determine possibility to inline all refs // Return if at least one ref is impossible to inline var simpleReplacements = new HashMap<PsiElement, PsiElement>(); var fStringFragmentsReplacements = new HashMap<PyFStringFragment, PyStringElement>(); for (var refToInline: refsToInline) { if (!checkPossibleInlineElement(refToInline, value, project, editor, simpleReplacements, fStringFragmentsReplacements)) { return; } } final LanguageLevel level = LanguageLevel.forElement(value); for (var entry : simpleReplacements.entrySet()) { PsiElement replElement = entry.getKey(); PsiElement replValue = entry.getValue(); if (PyReplaceExpressionUtil.isNeedParenthesis((PyExpression)replElement, (PyExpression)replValue)) { replValue = PyElementGenerator.getInstance(project).createExpressionFromText(level, "(" + replValue.getText() + ")"); } exprs.add(replElement.replace(replValue)); } makeFStringFragmentsReplacements(fStringFragmentsReplacements); final PsiElement next = def.getNextSibling(); if (next instanceof PsiWhiteSpace) { PyPsiUtils.removeElements(next); } PyPsiUtils.removeElements(def); final List<TextRange> ranges = ContainerUtil.mapNotNull(exprs, element -> { final PyStatement parentalStatement = PsiTreeUtil.getParentOfType(element, PyStatement.class, false); return parentalStatement != null ? parentalStatement.getTextRange() : null; }); PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); CodeStyleManager.getInstance(project).reformatText(workingFile, ranges); if (!ApplicationManager.getApplication().isUnitTestMode()) { highlightManager.addOccurrenceHighlights(editor, exprs.toArray(PsiElement.EMPTY_ARRAY), EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); WindowManager.getInstance().getStatusBar(project) .setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting")); } } finally { final RefactoringEventData afterData = new RefactoringEventData(); afterData.addElement(local); project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringDone(getRefactoringId(), afterData); } }), RefactoringBundle.message("inline.command", localName), null); }