diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertMethodToPropertyIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertMethodToPropertyIntention.java index ca9d78869fb1..ea5c73471315 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertMethodToPropertyIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertMethodToPropertyIntention.java @@ -15,17 +15,22 @@ */ package com.jetbrains.python.codeInsight.intentions; +import com.intellij.codeInsight.FileModificationService; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.usageView.UsageInfo; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.psi.*; import com.jetbrains.python.refactoring.PyRefactoringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -76,6 +81,11 @@ public class PyConvertMethodToPropertyIntention extends PyBaseIntentionAction { return available[0]; } + @Override + public boolean startInWriteAction() { + return false; + } + public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { final PsiElement element = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset()); PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class); @@ -84,6 +94,8 @@ public class PyConvertMethodToPropertyIntention extends PyBaseIntentionAction { if (containingClass == null) return; final List usages = PyRefactoringUtil.findUsages(problemFunction, false); + if (!prepareForWrite(file, usages)) return; + final PyDecoratorList problemDecoratorList = problemFunction.getDecoratorList(); List decoTexts = new ArrayList<>(); decoTexts.add("@property"); @@ -94,8 +106,22 @@ public class PyConvertMethodToPropertyIntention extends PyBaseIntentionAction { } } - PyElementGenerator generator = PyElementGenerator.getInstance(project); - final PyDecoratorList decoratorList = generator.createDecoratorList(decoTexts.toArray(new String[decoTexts.size()])); + WriteAction.run(() -> { + ensureDecoratorList(problemFunction, problemDecoratorList, decoTexts); + deleteUsages(usages); + }); + } + + private static boolean prepareForWrite(PsiFile file, List usages) { + List toWrite = ContainerUtil.newArrayList(file); + toWrite.addAll(ContainerUtil.mapNotNull(usages, UsageInfo::getElement)); + if (!FileModificationService.getInstance().preparePsiElementsForWrite(toWrite)) return false; + return true; + } + + private static void ensureDecoratorList(PyFunction problemFunction, @Nullable PyDecoratorList problemDecoratorList, List decoTexts) { + PyElementGenerator generator = PyElementGenerator.getInstance(problemFunction.getProject()); + PyDecoratorList decoratorList = generator.createDecoratorList(ArrayUtil.toStringArray(decoTexts)); if (problemDecoratorList != null) { problemDecoratorList.replace(decoratorList); @@ -103,7 +129,9 @@ public class PyConvertMethodToPropertyIntention extends PyBaseIntentionAction { else { problemFunction.addBefore(decoratorList, problemFunction.getFirstChild()); } + } + private static void deleteUsages(List usages) { for (UsageInfo usage : usages) { final PsiElement usageElement = usage.getElement(); if (usageElement instanceof PyReferenceExpression) {