diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java index ba97dd348b3e..8f0305e38543 100644 --- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java @@ -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) { diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java index d1d3c8b0bb38..282bca97dbb5 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java @@ -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 myToImplement; - public PyImplementMethodsQuickFix(PyClass aClass, Set toBeImplemented) { - myClass = aClass; - myToImplement = toBeImplemented; + public PyImplementMethodsQuickFix(PyClass aClass, Set 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 list = new ArrayList(); + 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; } - } diff --git a/python/testData/inspections/ImplementAbstractProperty.py b/python/testData/inspections/ImplementAbstractProperty.py new file mode 100644 index 000000000000..014c41917424 --- /dev/null +++ b/python/testData/inspections/ImplementAbstractProperty.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractproperty + + +class Base(ABC): + @abstractproperty + def some_method(self): + pass + + +class Sub(Base): + pass \ No newline at end of file diff --git a/python/testData/inspections/ImplementAbstractProperty1.py b/python/testData/inspections/ImplementAbstractProperty1.py new file mode 100644 index 000000000000..f73b41109416 --- /dev/null +++ b/python/testData/inspections/ImplementAbstractProperty1.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractproperty + + +class Base(ABC): + @abstract + @property + def some_method(self): + pass + + +class Sub(Base): + pass \ No newline at end of file diff --git a/python/testData/inspections/ImplementAbstractProperty1_after.py b/python/testData/inspections/ImplementAbstractProperty1_after.py new file mode 100644 index 000000000000..7429bc48f86a --- /dev/null +++ b/python/testData/inspections/ImplementAbstractProperty1_after.py @@ -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 + diff --git a/python/testData/inspections/ImplementAbstractProperty_after.py b/python/testData/inspections/ImplementAbstractProperty_after.py new file mode 100644 index 000000000000..7429bc48f86a --- /dev/null +++ b/python/testData/inspections/ImplementAbstractProperty_after.py @@ -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 + diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index 9220b567c094..dded82dd8930 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -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 {