Search in sources :

Example 46 with RefactoringEventData

use of com.intellij.refactoring.listeners.RefactoringEventData in project intellij-community by JetBrains.

the class EncapsulateFieldsProcessor method getBeforeData.

@Nullable
@Override
protected RefactoringEventData getBeforeData() {
    RefactoringEventData data = new RefactoringEventData();
    final List<PsiElement> fields = new ArrayList<>();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
        fields.add(fieldDescriptor.getField());
    }
    data.addElements(fields);
    return data;
}
Also used : RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) Nullable(org.jetbrains.annotations.Nullable)

Example 47 with RefactoringEventData

use of com.intellij.refactoring.listeners.RefactoringEventData in project intellij-community by JetBrains.

the class PyExtractMethodUtil method extractFromStatements.

public static void extractFromStatements(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PyCodeFragment fragment, @NotNull final PsiElement statement1, @NotNull final PsiElement statement2) {
    if (!fragment.getOutputVariables().isEmpty() && fragment.isReturnInstructionInside()) {
        CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.local.variable.modifications.and.returns"), RefactoringBundle.message("error.title"), "refactoring.extractMethod");
        return;
    }
    final PyFunction function = PsiTreeUtil.getParentOfType(statement1, PyFunction.class);
    final PyUtil.MethodFlags flags = function == null ? null : PyUtil.MethodFlags.of(function);
    final boolean isClassMethod = flags != null && flags.isClassMethod();
    final boolean isStaticMethod = flags != null && flags.isStaticMethod();
    // collect statements
    final List<PsiElement> elementsRange = PyPsiUtils.collectElements(statement1, statement2);
    if (elementsRange.isEmpty()) {
        CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.empty.fragment"), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
        return;
    }
    final Pair<String, AbstractVariableData[]> data = getNameAndVariableData(project, fragment, statement1, isClassMethod, isStaticMethod);
    if (data.first == null || data.second == null) {
        return;
    }
    final String methodName = data.first;
    final AbstractVariableData[] variableData = data.second;
    final SimpleDuplicatesFinder finder = new SimpleDuplicatesFinder(statement1, statement2, fragment.getOutputVariables(), variableData);
    CommandProcessor.getInstance().executeCommand(project, () -> {
        final RefactoringEventData beforeData = new RefactoringEventData();
        beforeData.addElements(new PsiElement[] { statement1, statement2 });
        project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(getRefactoringId(), beforeData);
        final StringBuilder builder = new StringBuilder();
        final boolean isAsync = fragment.isAsync();
        if (isAsync) {
            builder.append("async ");
        }
        builder.append("def f():\n    ");
        final List<PsiElement> newMethodElements = new ArrayList<>(elementsRange);
        final boolean hasOutputVariables = !fragment.getOutputVariables().isEmpty();
        final PyElementGenerator generator = PyElementGenerator.getInstance(project);
        final LanguageLevel languageLevel = LanguageLevel.forElement(statement1);
        if (hasOutputVariables) {
            // Generate return modified variables statements
            final String outputVariables = StringUtil.join(fragment.getOutputVariables(), ", ");
            final String newMethodText = builder + "return " + outputVariables;
            builder.append(outputVariables);
            final PyFunction function1 = generator.createFromText(languageLevel, PyFunction.class, newMethodText);
            final PsiElement returnStatement = function1.getStatementList().getStatements()[0];
            newMethodElements.add(returnStatement);
        }
        // Generate method
        final PyFunction generatedMethod = generateMethodFromElements(project, methodName, variableData, newMethodElements, flags, isAsync);
        final PyFunction insertedMethod = WriteAction.compute(() -> insertGeneratedMethod(statement1, generatedMethod));
        // Process parameters
        final PsiElement firstElement = elementsRange.get(0);
        final boolean isMethod = PyPsiUtils.isMethodContext(firstElement);
        WriteAction.run(() -> {
            processParameters(project, insertedMethod, variableData, isMethod, isClassMethod, isStaticMethod);
            processGlobalWrites(insertedMethod, fragment);
            processNonlocalWrites(insertedMethod, fragment);
        });
        // Generate call element
        if (hasOutputVariables) {
            builder.append(" = ");
        } else if (fragment.isReturnInstructionInside()) {
            builder.append("return ");
        }
        if (isAsync) {
            builder.append("await ");
        } else if (fragment.isYieldInside()) {
            builder.append("yield from ");
        }
        if (isMethod) {
            appendSelf(firstElement, builder, isStaticMethod);
        }
        builder.append(methodName).append("(");
        builder.append(createCallArgsString(variableData)).append(")");
        final PyFunction function1 = generator.createFromText(languageLevel, PyFunction.class, builder.toString());
        final PsiElement callElement = function1.getStatementList().getStatements()[0];
        // Both statements are used in finder, so should be valid at this moment
        PyPsiUtils.assertValid(statement1);
        PyPsiUtils.assertValid(statement2);
        final List<SimpleMatch> duplicates = collectDuplicates(finder, statement1, insertedMethod);
        // replace statements with call
        PsiElement insertedCallElement = WriteAction.compute(() -> replaceElements(elementsRange, callElement));
        insertedCallElement = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(insertedCallElement);
        if (insertedCallElement != null) {
            processDuplicates(duplicates, insertedCallElement, editor);
        }
        // Set editor
        setSelectionAndCaret(editor, insertedCallElement);
        final RefactoringEventData afterData = new RefactoringEventData();
        afterData.addElement(insertedMethod);
        project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(getRefactoringId(), afterData);
    }, PyBundle.message("refactoring.extract.method"), null);
}
Also used : AbstractVariableData(com.intellij.refactoring.util.AbstractVariableData) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData)

Example 48 with RefactoringEventData

use of com.intellij.refactoring.listeners.RefactoringEventData in project intellij-community by JetBrains.

the class PyInlineLocalHandler method invoke.

private static void invoke(@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 TextAttributes writeAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES);
    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, REFACTORING_NAME, HELP_ID);
        return;
    }
    if (def instanceof PyAssignmentStatement && ((PyAssignmentStatement) def).getTargets().length > 1) {
        highlightManager.addOccurrenceHighlights(editor, new PsiElement[] { def }, writeAttributes, true, null);
        final String message = RefactoringBundle.getCannotRefactorMessage(PyBundle.message("refactoring.inline.local.multiassignment", localName));
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, 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, REFACTORING_NAME, HELP_ID);
        return;
    }
    final TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
    if (!ApplicationManager.getApplication().isUnitTestMode()) {
        highlightManager.addOccurrenceHighlights(editor, refsToInline, 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;
        final RefactoringMessageDialog dialog = new RefactoringMessageDialog(REFACTORING_NAME, question, HELP_ID, "OptionPane.questionIcon", true, project);
        if (!dialog.showAndGet()) {
            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, REFACTORING_NAME, 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(new PsiElement[elems.size()]);
        boolean isSameDefinition = true;
        for (PsiElement otherDef : defs) {
            isSameDefinition &= isSameDefinition(def, otherDef);
        }
        if (!isSameDefinition) {
            highlightManager.addOccurrenceHighlights(editor, defs, writeAttributes, true, null);
            highlightManager.addOccurrenceHighlights(editor, new PsiElement[] { ref }, 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, REFACTORING_NAME, 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 PsiElement[] exprs = new PsiElement[refsToInline.length];
            final PyExpression value = prepareValue(def, localName, project);
            final PyExpression withParenthesis = PyElementGenerator.getInstance(project).createExpressionFromText("(" + value.getText() + ")");
            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);
            }
            for (int i = 0, refsToInlineLength = refsToInline.length; i < refsToInlineLength; i++) {
                final PsiElement element = refsToInline[i];
                if (PyReplaceExpressionUtil.isNeedParenthesis((PyExpression) element, value)) {
                    exprs[i] = element.replace(withParenthesis);
                } else {
                    exprs[i] = element.replace(value);
                }
            }
            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, 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);
}
Also used : Language(com.intellij.lang.Language) EditorColorsManager(com.intellij.openapi.editor.colors.EditorColorsManager) RefactoringBundle(com.intellij.refactoring.RefactoringBundle) PythonLanguage(com.jetbrains.python.PythonLanguage) RefactoringEventListener(com.intellij.refactoring.listeners.RefactoringEventListener) ContainerUtil(com.intellij.util.containers.ContainerUtil) PyPsiUtils(com.jetbrains.python.psi.impl.PyPsiUtils) ArrayList(java.util.ArrayList) Query(com.intellij.util.Query) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) Project(com.intellij.openapi.project.Project) com.jetbrains.python.psi(com.jetbrains.python.psi) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) Logger(com.intellij.openapi.diagnostic.Logger) Instruction(com.intellij.codeInsight.controlflow.Instruction) PyDefUseUtil(com.jetbrains.python.refactoring.PyDefUseUtil) Extensions(com.intellij.openapi.extensions.Extensions) ReferencesSearch(com.intellij.psi.search.searches.ReferencesSearch) PyBundle(com.jetbrains.python.PyBundle) InlineActionHandler(com.intellij.lang.refactoring.InlineActionHandler) PyReplaceExpressionUtil(com.jetbrains.python.refactoring.PyReplaceExpressionUtil) WindowManager(com.intellij.openapi.wm.WindowManager) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) PyTokenTypes(com.jetbrains.python.PyTokenTypes) TextRange(com.intellij.openapi.util.TextRange) RefactoringMessageDialog(com.intellij.refactoring.util.RefactoringMessageDialog) Editor(com.intellij.openapi.editor.Editor) CommandProcessor(com.intellij.openapi.command.CommandProcessor) CommonRefactoringUtil(com.intellij.refactoring.util.CommonRefactoringUtil) Nullable(org.jetbrains.annotations.Nullable) CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager) List(java.util.List) EditorColors(com.intellij.openapi.editor.colors.EditorColors) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) Function(com.intellij.util.Function) Pair(com.intellij.openapi.util.Pair) TargetElementUtil(com.intellij.codeInsight.TargetElementUtil) ApplicationManager(com.intellij.openapi.application.ApplicationManager) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) com.intellij.psi(com.intellij.psi) NotNull(org.jetbrains.annotations.NotNull) RefactoringMessageDialog(com.intellij.refactoring.util.RefactoringMessageDialog) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) ArrayList(java.util.ArrayList) Instruction(com.intellij.codeInsight.controlflow.Instruction) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) ArrayList(java.util.ArrayList) List(java.util.List)

Example 49 with RefactoringEventData

use of com.intellij.refactoring.listeners.RefactoringEventData in project intellij-community by JetBrains.

the class IntroduceHandler method performReplace.

private PsiElement performReplace(@NotNull final PsiElement declaration, final IntroduceOperation operation) {
    final PyExpression expression = operation.getInitializer();
    final Project project = operation.getProject();
    return new WriteCommandAction<PsiElement>(project, expression.getContainingFile()) {

        protected void run(@NotNull final Result<PsiElement> result) throws Throwable {
            try {
                final RefactoringEventData afterData = new RefactoringEventData();
                afterData.addElement(declaration);
                project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(getRefactoringId(), afterData);
                result.setResult(addDeclaration(operation, declaration));
                PyExpression newExpression = createExpression(project, operation.getName(), declaration);
                if (operation.isReplaceAll()) {
                    List<PsiElement> newOccurrences = new ArrayList<>();
                    for (PsiElement occurrence : operation.getOccurrences()) {
                        final PsiElement replaced = replaceExpression(occurrence, newExpression, operation);
                        if (replaced != null) {
                            newOccurrences.add(replaced);
                        }
                    }
                    operation.setOccurrences(newOccurrences);
                } else {
                    final PsiElement replaced = replaceExpression(expression, newExpression, operation);
                    operation.setOccurrences(Collections.singletonList(replaced));
                }
                postRefactoring(operation.getElement());
            } finally {
                final RefactoringEventData afterData = new RefactoringEventData();
                afterData.addElement(declaration);
                project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(getRefactoringId(), afterData);
            }
        }
    }.execute().getResultObject();
}
Also used : WriteCommandAction(com.intellij.openapi.command.WriteCommandAction) Project(com.intellij.openapi.project.Project) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) NotNull(org.jetbrains.annotations.NotNull) Result(com.intellij.openapi.application.Result)

Example 50 with RefactoringEventData

use of com.intellij.refactoring.listeners.RefactoringEventData in project intellij-community by JetBrains.

the class PyMembersRefactoringBaseProcessor method getAfterData.

@Nullable
@Override
protected RefactoringEventData getAfterData(@NotNull UsageInfo[] usages) {
    final RefactoringEventData data = new RefactoringEventData();
    data.addElements(myTo);
    return data;
}
Also used : RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

RefactoringEventData (com.intellij.refactoring.listeners.RefactoringEventData)51 Nullable (org.jetbrains.annotations.Nullable)36 NotNull (org.jetbrains.annotations.NotNull)6 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)5 Project (com.intellij.openapi.project.Project)5 UsageInfo (com.intellij.usageView.UsageInfo)5 ArrayList (java.util.ArrayList)5 Result (com.intellij.openapi.application.Result)4 Logger (com.intellij.openapi.diagnostic.Logger)4 com.intellij.psi (com.intellij.psi)4 RefactoringEventListener (com.intellij.refactoring.listeners.RefactoringEventListener)4 MultiMap (com.intellij.util.containers.MultiMap)4 HighlightManager (com.intellij.codeInsight.highlighting.HighlightManager)3 ApplicationManager (com.intellij.openapi.application.ApplicationManager)3 CommandProcessor (com.intellij.openapi.command.CommandProcessor)3 EditorColors (com.intellij.openapi.editor.colors.EditorColors)3 EditorColorsManager (com.intellij.openapi.editor.colors.EditorColorsManager)3 TextAttributes (com.intellij.openapi.editor.markup.TextAttributes)3 WindowManager (com.intellij.openapi.wm.WindowManager)3 ReferencesSearch (com.intellij.psi.search.searches.ReferencesSearch)3