PY-6637 Inline method qualifier as is if it consists solely of reference expressions
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Mon, 5 Oct 2015 11:46:01 +0000 (14:46 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Mon, 5 Oct 2015 11:46:01 +0000 (14:46 +0300)
Assume that such expressions has no side effects and are not computationally intensive.

python/src/com/jetbrains/python/refactoring/makeFunctionTopLevel/PyMakeMethodTopLevelProcessor.java
python/testData/refactoring/convertTopLevel/methodMultipleAttributesConstructorQualifier.after.py [moved from python/testData/refactoring/convertTopLevel/methodMultipleAttributesRead.after.py with 100% similarity]
python/testData/refactoring/convertTopLevel/methodMultipleAttributesConstructorQualifier.py [moved from python/testData/refactoring/convertTopLevel/methodMultipleAttributesRead.py with 100% similarity]
python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.after.py [new file with mode: 0644]
python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/refactoring/PyMakeFunctionTopLevelTest.java

index e0035b45d253794f1320c87ca1ef5ebe893eec66..c0374ac7c0151ba188347823609c3cdb29e8fff0 100644 (file)
@@ -56,7 +56,7 @@ public class PyMakeMethodTopLevelProcessor extends PyBaseMakeFunctionTopLevelPro
   }
 
   @Override
-  protected void updateExistingFunctionUsages(@NotNull final Collection<String> newParamNames, @NotNull UsageInfo[] usages) {
+  protected void updateExistingFunctionUsages(@NotNull Collection<String> newParamNames, @NotNull UsageInfo[] usages) {
     final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(myProject);
 
     for (UsageInfo usage : usages) {
@@ -69,7 +69,15 @@ public class PyMakeMethodTopLevelProcessor extends PyBaseMakeFunctionTopLevelPro
         final PyExpression qualifier = ((PyReferenceExpression)usageElem).getQualifier();
         final PyCallExpression callExpr = as(usageElem.getParent(), PyCallExpression.class);
         if (qualifier != null && callExpr != null && callExpr.getArgumentList() != null) {
-          if (newParamNames.size() == 1) {
+          if (isPureReferenceExpression(qualifier)) {
+            addArguments(callExpr.getArgumentList(), ContainerUtil.map(newParamNames, new Function<String, String>() {
+              @Override
+              public String fun(String attribute) {
+                return qualifier.getText() + "." + attribute;
+              }
+            }));
+          }
+          else if (newParamNames.size() == 1) {
             addArguments(callExpr.getArgumentList(), Collections.singleton(qualifier.getText() + "." + ContainerUtil.getFirstItem(newParamNames)));
           }
           else if (!newParamNames.isEmpty()) {
@@ -80,6 +88,7 @@ public class PyMakeMethodTopLevelProcessor extends PyBaseMakeFunctionTopLevelPro
             final PyAssignmentStatement assignment = elementGenerator.createFromText(LanguageLevel.forElement(callExpr),
                                                                                      PyAssignmentStatement.class,
                                                                                      assignmentText);
+            //noinspection ConstantConditions
             anchor.getParent().addBefore(assignment, anchor);
             addArguments(callExpr.getArgumentList(), ContainerUtil.map(newParamNames, new Function<String, String>() {
               @Override
@@ -106,6 +115,14 @@ public class PyMakeMethodTopLevelProcessor extends PyBaseMakeFunctionTopLevelPro
     }
   }
 
+  private static boolean isPureReferenceExpression(@NotNull PyExpression expr) {
+    if (!(expr instanceof PyReferenceExpression)) {
+      return false;
+    }
+    final PyExpression qualifier = ((PyReferenceExpression)expr).getQualifier();
+    return qualifier == null || isPureReferenceExpression(qualifier);
+  }
+
   @NotNull
   @Override
   protected PyFunction createNewFunction(@NotNull Collection<String> newParams) {
diff --git a/python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.after.py b/python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.after.py
new file mode 100644 (file)
index 0000000..d1bf980
--- /dev/null
@@ -0,0 +1,12 @@
+class C:
+    def __init__(self):
+        self.foo = 42
+        self.bar = 'spam'
+
+
+def method(foo, bar, x):
+    print(foo, bar)
+
+
+inst = C()
+method(inst.foo, inst.bar, 1)
\ No newline at end of file
diff --git a/python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.py b/python/testData/refactoring/convertTopLevel/methodMultipleAttributesReadReferenceQualifier.py
new file mode 100644 (file)
index 0000000..bd66ea0
--- /dev/null
@@ -0,0 +1,11 @@
+class C:
+    def __init__(self):
+        self.foo = 42
+        self.bar = 'spam'
+
+    def me<caret>thod(self, x):
+        print(self.foo, self.bar)
+
+
+inst = C()
+inst.method(1)
\ No newline at end of file
index 9b2ed96dab420de43b999b95c3222eee45e42f5f..5bd3a67db1a798b0a1ba9773c144db975ddcb500 100644 (file)
@@ -173,7 +173,11 @@ public class PyMakeFunctionTopLevelTest extends PyTestCase {
     doTestSuccess();
   }
 
-  public void testMethodMultipleAttributesRead() {
+  public void testMethodMultipleAttributesReadReferenceQualifier() {
+    doTestSuccess();
+  }
+
+  public void testMethodMultipleAttributesConstructorQualifier() {
     doTestSuccess();
   }