mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 21:11:28 +07:00
PY-21398 Wrap batch updates of existing usages in quickfixes with PotemkinProgress
It also fixes EA-425763 about using incorrect parent and anchor elements to insert a function generated from a method of a nested class. GitOrigin-RevId: f9b9da303396eb78c2c12b2750065dbdc0ba70ed
This commit is contained in:
committed by
intellij-monorepo-bot
parent
71a7d544c6
commit
3b6dea06a3
@@ -69,6 +69,8 @@ refactoring.inline.function.nonlocal=Cannot inline functions with nonlocal varia
|
||||
refactoring.inline.function.nested=Cannot inline functions with another function declaration
|
||||
refactoring.inline.function.interrupts.flow=Cannot inline functions that interrupt control flow
|
||||
|
||||
refactoring.progress.title.updating.existing.usages=Updating existing usages...
|
||||
|
||||
### Annotators ###
|
||||
ANN.deleting.none=Deleting None
|
||||
ANN.assign.to.none=Assignment to None
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.jetbrains.python.inspections.quickfix;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -20,7 +21,9 @@ import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferenc
|
||||
import com.jetbrains.python.inspections.unresolvedReference.SimplePyUnresolvedReferencesInspection;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,27 +45,36 @@ public class PyMakeFunctionFromMethodQuickFix implements LocalQuickFix {
|
||||
final PyClass containingClass = problemFunction.getContainingClass();
|
||||
if (containingClass == null) return;
|
||||
|
||||
final List<UsageInfo> usages = PyPsiIndexUtil.findUsages(problemFunction, false);
|
||||
final PyParameter[] parameters = problemFunction.getParameterList().getParameters();
|
||||
final List<PyReferenceExpression> usages = StreamEx.of(PyPsiIndexUtil.findUsages(problemFunction, false))
|
||||
.map(UsageInfo::getElement)
|
||||
.select(PyReferenceExpression.class)
|
||||
.toList();
|
||||
|
||||
ApplicationManagerEx.getApplicationEx().runWriteActionWithCancellableProgressInDispatchThread(
|
||||
PyPsiBundle.message("refactoring.progress.title.updating.existing.usages"), problemFunction.getProject(), null, (indicator -> {
|
||||
PyFunction function = transformDefinition(problemFunction);
|
||||
for (int i = 0; i < usages.size(); i++) {
|
||||
indicator.checkCanceled();
|
||||
indicator.setFraction((i + 1.0) / usages.size());
|
||||
PyReferenceExpression usage = usages.get(i);
|
||||
PsiFile usageFile = usage.getContainingFile();
|
||||
updateUsage(function, usage, usageFile, !usageFile.equals(containingClass.getContainingFile()));
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PyFunction transformDefinition(@NotNull PyFunction method) {
|
||||
PyParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameters.length > 0) {
|
||||
parameters[0].delete();
|
||||
}
|
||||
|
||||
PsiElement copy = problemFunction.copy();
|
||||
problemFunction.delete();
|
||||
final PsiElement parent = containingClass.getParent();
|
||||
PyClass aClass = PsiTreeUtil.getTopmostParentOfType(containingClass, PyClass.class);
|
||||
if (aClass == null)
|
||||
aClass = containingClass;
|
||||
copy = parent.addBefore(copy, aClass);
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
final PsiElement usageElement = usage.getElement();
|
||||
if (usageElement instanceof PyReferenceExpression) {
|
||||
final PsiFile usageFile = usageElement.getContainingFile();
|
||||
updateUsage(copy, (PyReferenceExpression)usageElement, usageFile, !usageFile.equals(parent));
|
||||
}
|
||||
}
|
||||
PyClass topmostClass = PsiTreeUtil.getTopmostParentOfType(method, PyClass.class);
|
||||
assert topmostClass != null;
|
||||
PsiElement copy = method.copy();
|
||||
method.delete();
|
||||
return (PyFunction)topmostClass.getParent().addBefore(copy, topmostClass);
|
||||
}
|
||||
|
||||
private static void updateUsage(@NotNull final PsiElement finalElement, @NotNull final PyReferenceExpression element,
|
||||
@@ -144,4 +156,14 @@ public class PyMakeFunctionFromMethodQuickFix implements LocalQuickFix {
|
||||
arguments[0].delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
|
||||
return currentFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.jetbrains.python.inspections.quickfix;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
@@ -12,7 +14,9 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.codeInsight.PyPsiIndexUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,21 +35,30 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class);
|
||||
if (problemFunction == null) return;
|
||||
final List<UsageInfo> usages = PyPsiIndexUtil.findUsages(problemFunction, false);
|
||||
|
||||
final PyParameter[] parameters = problemFunction.getParameterList().getParameters();
|
||||
List<PyReferenceExpression> usages = StreamEx.of(PyPsiIndexUtil.findUsages(problemFunction, false))
|
||||
.map(UsageInfo::getElement)
|
||||
.select(PyReferenceExpression.class)
|
||||
.toList();
|
||||
|
||||
ApplicationManagerEx.getApplicationEx().runWriteActionWithCancellableProgressInDispatchThread(
|
||||
PyPsiBundle.message("refactoring.progress.title.updating.existing.usages"), problemFunction.getProject(), null, (indicator -> {
|
||||
updateDefinition(problemFunction);
|
||||
for (int i = 0; i < usages.size(); i++) {
|
||||
indicator.checkCanceled();
|
||||
indicator.setFraction((i + 1.0) / usages.size());
|
||||
updateUsage(usages.get(i));
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private static void updateDefinition(@NotNull PyFunction function) {
|
||||
final PyParameter[] parameters = function.getParameterList().getParameters();
|
||||
if (parameters.length > 0) {
|
||||
parameters[0].delete();
|
||||
}
|
||||
|
||||
PyUtil.addDecorator(problemFunction, "@" + PyNames.STATICMETHOD);
|
||||
|
||||
for (UsageInfo usage : usages) {
|
||||
final PsiElement usageElement = usage.getElement();
|
||||
if (usageElement instanceof PyReferenceExpression) {
|
||||
updateUsage((PyReferenceExpression)usageElement);
|
||||
}
|
||||
}
|
||||
PyUtil.addDecorator(function, "@" + PyNames.STATICMETHOD);
|
||||
}
|
||||
|
||||
private static void updateUsage(@NotNull final PyReferenceExpression element) {
|
||||
@@ -69,4 +82,14 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix {
|
||||
arguments[0].delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
|
||||
return currentFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class Outer:
|
||||
class Inner:
|
||||
def met<caret>hod(self):
|
||||
return 42
|
||||
@@ -0,0 +1,7 @@
|
||||
def method():
|
||||
return 42
|
||||
|
||||
|
||||
class Outer:
|
||||
class Inner:
|
||||
pass
|
||||
@@ -80,4 +80,9 @@ public class PyMakeFunctionFromMethodQuickFixTest extends PyQuickFixTestCase {
|
||||
public void testRemoveQualifiers() {
|
||||
doQuickFixTest(PyMethodMayBeStaticInspection.class, PyPsiBundle.message("QFIX.NAME.make.function"));
|
||||
}
|
||||
|
||||
// EA-425763
|
||||
public void testInnerClassMethod() {
|
||||
doQuickFixTest(PyMethodMayBeStaticInspection.class, PyPsiBundle.message("QFIX.NAME.make.function"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user