mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-16581 Quickfix "Implement abstract methods" implements abstract properties as properties. Fix possible memory leak caused by holding PsiElement
This commit is contained in:
@@ -191,8 +191,11 @@ public class PyOverrideImplementUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass, PyFunction baseFunction, boolean implement) {
|
||||
private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass,
|
||||
PyFunction baseFunction,
|
||||
boolean implement) {
|
||||
final boolean overridingNew = PyNames.NEW.equals(baseFunction.getName());
|
||||
assert baseFunction.getName() != null;
|
||||
PyFunctionBuilder pyFunctionBuilder = new PyFunctionBuilder(baseFunction.getName(), baseFunction);
|
||||
final PyDecoratorList decorators = baseFunction.getDecoratorList();
|
||||
boolean baseMethodIsStatic = false;
|
||||
@@ -204,6 +207,10 @@ public class PyOverrideImplementUtil {
|
||||
baseMethodIsStatic = true;
|
||||
pyFunctionBuilder.decorate(PyNames.STATICMETHOD);
|
||||
}
|
||||
else if (decorators.findDecorator(PyNames.PROPERTY) != null ||
|
||||
decorators.findDecorator(PyNames.ABSTRACTPROPERTY) != null) {
|
||||
pyFunctionBuilder.decorate(PyNames.PROPERTY);
|
||||
}
|
||||
}
|
||||
PyAnnotation anno = baseFunction.getAnnotation();
|
||||
if (anno != null) {
|
||||
|
||||
+31
-13
@@ -15,15 +15,17 @@
|
||||
*/
|
||||
package com.jetbrains.python.inspections.quickfix;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.codeInsight.override.PyMethodMember;
|
||||
import com.jetbrains.python.codeInsight.override.PyOverrideImplementUtil;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
@@ -31,23 +33,24 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* User: ktisha
|
||||
*/
|
||||
public class PyImplementMethodsQuickFix implements LocalQuickFix {
|
||||
public class PyImplementMethodsQuickFix extends LocalQuickFixOnPsiElement {
|
||||
|
||||
private final PyClass myClass;
|
||||
private final Set<PyFunction> myToImplement;
|
||||
|
||||
public PyImplementMethodsQuickFix(PyClass aClass, Set<PyFunction> toBeImplemented) {
|
||||
myClass = aClass;
|
||||
myToImplement = toBeImplemented;
|
||||
public PyImplementMethodsQuickFix(PyClass aClass, Set<PyFunction> toImplement) {
|
||||
super(aClass);
|
||||
myToImplement = toImplement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
@Override
|
||||
public String getText() {
|
||||
return PyBundle.message("QFIX.NAME.implement.methods");
|
||||
}
|
||||
|
||||
@@ -57,10 +60,26 @@ public class PyImplementMethodsQuickFix implements LocalQuickFix {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
final Editor editor = getEditor(project, descriptor.getPsiElement().getContainingFile());
|
||||
if (editor != null)
|
||||
PyOverrideImplementUtil.chooseAndOverrideOrImplementMethods(project, editor, myClass, myToImplement, "Select Methods to Implement", true);
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
|
||||
final Editor editor = getEditor(project, file);
|
||||
|
||||
if (editor != null && startElement instanceof PyClass) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
ArrayList<PyMethodMember> list = new ArrayList<PyMethodMember>();
|
||||
for (PyFunction function: myToImplement) {
|
||||
list.add(new PyMethodMember(function));
|
||||
}
|
||||
PyOverrideImplementUtil.overrideMethods(editor, (PyClass)startElement, list, true);
|
||||
|
||||
}
|
||||
else {
|
||||
PyOverrideImplementUtil
|
||||
.chooseAndOverrideOrImplementMethods(project, editor,
|
||||
(PyClass)startElement, myToImplement,
|
||||
"Select Methods to Implement", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -76,5 +95,4 @@ public class PyImplementMethodsQuickFix implements LocalQuickFix {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractproperty
|
||||
|
||||
|
||||
class Base(ABC):
|
||||
@abstractproperty
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
|
||||
class <weak_warning descr="Class Sub must implement all abstract methods">S<caret>ub</weak_warning>(Base):
|
||||
pass
|
||||
@@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractproperty
|
||||
|
||||
|
||||
class Base(ABC):
|
||||
@abstract
|
||||
@property
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
|
||||
class <weak_warning descr="Class Sub must implement all abstract methods">S<caret>ub</weak_warning>(Base):
|
||||
pass
|
||||
@@ -0,0 +1,14 @@
|
||||
from abc import ABC, abstractproperty
|
||||
|
||||
|
||||
class Base(ABC):
|
||||
@abstractproperty
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
|
||||
class Sub(Base):
|
||||
@property
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from abc import ABC, abstractproperty
|
||||
|
||||
|
||||
class Base(ABC):
|
||||
@abstractproperty
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
|
||||
class Sub(Base):
|
||||
@property
|
||||
def some_method(self):
|
||||
pass
|
||||
|
||||
@@ -619,6 +619,16 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
}
|
||||
|
||||
public void testImplementAbstractProperty() {
|
||||
doInspectionTest("ImplementAbstractProperty.py", PyAbstractClassInspection.class, PyBundle.message("QFIX.NAME.implement.methods"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
public void testImplementAbstractProperty1() {
|
||||
doInspectionTest("ImplementAbstractProperty.py", PyAbstractClassInspection.class, PyBundle.message("QFIX.NAME.implement.methods"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNls
|
||||
protected String getTestDataPath() {
|
||||
@@ -669,7 +679,7 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
}
|
||||
if (applyFix) {
|
||||
myFixture.launchAction(intentionActions.get(0));
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"), true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user