fixed PY-10848 Implement abstract method: do not insert super call for abstract metho...
authorEkaterina Tuzova <Ekaterina.Tuzova@jetbrains.com>
Mon, 14 Oct 2013 10:45:45 +0000 (12:45 +0200)
committerEkaterina Tuzova <Ekaterina.Tuzova@jetbrains.com>
Mon, 14 Oct 2013 10:45:45 +0000 (12:45 +0200)
python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java
python/testData/override/implement.py [new file with mode: 0644]
python/testData/override/implement_after.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/PyOverrideTest.java

index 66a5fb58b931dfc9af4da1bb9f41b9bb4b5cdd67..b6157edc53ed14f6ca69642dbf345445c48a91d2 100644 (file)
@@ -76,14 +76,14 @@ public class PyOverrideImplementUtil {
     ApplicationManager.getApplication().assertReadAccessAllowed();
 
     final Collection<PyFunction> superFunctions = getAllSuperFunctions(pyClass);
-    chooseAndOverrideOrImplementMethods(project, editor, pyClass, superFunctions, "Select Methods to Override");
+    chooseAndOverrideOrImplementMethods(project, editor, pyClass, superFunctions, "Select Methods to Override", false);
   }
 
   public static void chooseAndOverrideOrImplementMethods(@NotNull final Project project,
                                                          @NotNull final Editor editor,
                                                          @NotNull final PyClass pyClass,
                                                          @NotNull final Collection<PyFunction> superFunctions,
-                                                         String title) {
+                                                         @NotNull final String title, final boolean implement) {
     List<PyMethodMember> elements = new ArrayList<PyMethodMember>();
     for (PyFunction function : superFunctions) {
       final String name = function.getName();
@@ -119,23 +119,24 @@ public class PyOverrideImplementUtil {
       return;
     }
     List<PyMethodMember> membersToOverride = chooser.getSelectedElements();
-    overrideMethods(editor, pyClass, membersToOverride);
+    overrideMethods(editor, pyClass, membersToOverride, implement);
   }
 
-  public static void overrideMethods(final Editor editor, final PyClass pyClass, final List<PyMethodMember> membersToOverride) {
+  public static void overrideMethods(final Editor editor, final PyClass pyClass, final List<PyMethodMember> membersToOverride,
+                                     final boolean implement) {
     if (membersToOverride == null) {
       return;
     }
     new WriteCommandAction(pyClass.getProject(), pyClass.getContainingFile()) {
       protected void run(final Result result) throws Throwable {
-        write(pyClass, membersToOverride, editor);
+        write(pyClass, membersToOverride, editor, implement);
       }
     }.execute();
   }
 
   private static void write(@NotNull final PyClass pyClass,
                             @NotNull final List<PyMethodMember> newMembers,
-                            @NotNull final Editor editor) {
+                            @NotNull final Editor editor, boolean implement) {
     final PyStatementList statementList = pyClass.getStatementList();
     final int offset = editor.getCaretModel().getOffset();
     PsiElement anchor = null;
@@ -148,7 +149,7 @@ public class PyOverrideImplementUtil {
     PyFunction element = null;
     for (PyMethodMember newMember : newMembers) {
       PyFunction baseFunction = (PyFunction) newMember.getPsiElement();
-      final PyFunctionBuilder builder = buildOverriddenFunction(pyClass, baseFunction);
+      final PyFunctionBuilder builder = buildOverriddenFunction(pyClass, baseFunction, implement);
       PyFunction function = builder.addFunctionAfter(statementList, anchor, LanguageLevel.forElement(statementList));
       element = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(function);
     }
@@ -165,7 +166,7 @@ public class PyOverrideImplementUtil {
     }
   }
 
-  private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass, PyFunction baseFunction) {
+  private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass, PyFunction baseFunction, boolean implement) {
     PyFunctionBuilder pyFunctionBuilder = new PyFunctionBuilder(baseFunction.getName());
     final PyDecoratorList decorators = baseFunction.getDecoratorList();
     if (decorators != null && decorators.findDecorator(PyNames.CLASSMETHOD) != null) {
@@ -204,7 +205,7 @@ public class PyOverrideImplementUtil {
       }
     }
 
-    if (PyNames.FAKE_OLD_BASE.equals(baseClass.getName())) {
+    if (PyNames.FAKE_OLD_BASE.equals(baseClass.getName()) || implement) {
       statementBody.append(PyNames.PASS);
     }
     else {
index b267e179813fbd185430b131176d3c2a8bc29499..67f32d44c61d60f9c42a596292a4c7e57cb938d9 100644 (file)
@@ -45,7 +45,7 @@ public class PyImplementMethodsQuickFix implements LocalQuickFix {
   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");
+      PyOverrideImplementUtil.chooseAndOverrideOrImplementMethods(project, editor, myClass, myToImplement, "Select Methods to Implement", true);
   }
 
   @Nullable
diff --git a/python/testData/override/implement.py b/python/testData/override/implement.py
new file mode 100644 (file)
index 0000000..5eb6947
--- /dev/null
@@ -0,0 +1,11 @@
+from abc import abstractmethod
+class A1(object):
+    def __init__(self):
+      self.a = "Something"
+
+    @abstractmethod
+    def my_method(self):
+        print self.a
+
+class B(A1):
+    def __iter__(self): pass
diff --git a/python/testData/override/implement_after.py b/python/testData/override/implement_after.py
new file mode 100644 (file)
index 0000000..e762f12
--- /dev/null
@@ -0,0 +1,14 @@
+from abc import abstractmethod
+class A1(object):
+    def __init__(self):
+      self.a = "Something"
+
+    @abstractmethod
+    def my_method(self):
+        print self.a
+
+class B(A1):
+    def my_method(self):
+        <selection>pass</selection>
+
+    def __iter__(self): pass
index b3f797e8885954e5f1540a13f9360534bea145f8..471168e03c9fe1867e6d9a8b91d1a66c93d8595a 100644 (file)
@@ -20,7 +20,7 @@ public class PyOverrideTest extends PyTestCase {
     myFixture.configureByFile("override/" + getTestName(true) + ".py");
     PyFunction toOverride = getTopLevelClass(0).getMethods() [0];
     PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1),
-                                            Collections.singletonList(new PyMethodMember(toOverride)));
+                                            Collections.singletonList(new PyMethodMember(toOverride)), false);
     myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
   }
 
@@ -68,7 +68,7 @@ public class PyOverrideTest extends PyTestCase {
     PyFunction toOverride = getTopLevelClass(0).getMethods()[0];
     PyClass pyClass = getTopLevelClass(1).getNestedClasses()[0];
     PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), pyClass,
-                                            Collections.singletonList(new PyMethodMember(toOverride)));
+                                            Collections.singletonList(new PyMethodMember(toOverride)), false);
     myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
   }
 
@@ -79,7 +79,15 @@ public class PyOverrideTest extends PyTestCase {
     PyFunction initMethod = dateClass.findMethodByName(PyNames.INIT, false);
     assertNotNull(initMethod);
     PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(0),
-                                            Collections.singletonList(new PyMethodMember(initMethod)));
+                                            Collections.singletonList(new PyMethodMember(initMethod)), false);
+    myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
+  }
+
+  public void testImplement() {
+    myFixture.configureByFile("override/" + getTestName(true) + ".py");
+    PyFunction toImplement = getTopLevelClass(0).getMethods()[1];
+    PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1),
+                                            Collections.singletonList(new PyMethodMember(toImplement)), true);
     myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
   }
 
@@ -112,7 +120,7 @@ public class PyOverrideTest extends PyTestCase {
     myFixture.configureByFile("override/" + getTestName(true) + ".py");
     final PyClass cls = getTopLevelClass(0);
     final PyFunction method = cls.findMethodByName("__instancecheck__", true);
-    PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), cls, Collections.singletonList(new PyMethodMember(method)));
+    PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), cls, Collections.singletonList(new PyMethodMember(method)), false);
     myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
   }
 }