Skip to content

Commit 95c078a

Browse files
committed
Make "extract method" work on multi-line function calls
1 parent f39cf67 commit 95c078a

File tree

7 files changed

+82
-1
lines changed

7 files changed

+82
-1
lines changed

python/python-psi-impl/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java

+9
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ public void visitElement(final @NotNull PsiElement element) {
7575
if (parent == null) {
7676
return null;
7777
}
78+
79+
// Allow function call where arguments are on multiple lines
80+
if (parent instanceof PyArgumentList) {
81+
PyCallExpression callExpression = PsiTreeUtil.getParentOfType(parent, PyCallExpression.class);
82+
if (callExpression != null) {
83+
return callExpression;
84+
}
85+
}
86+
7887
// If it is PyIfPart for example, parent if statement, we should deny
7988
if (!(parent instanceof PyExpression)){
8089
return null;

python/python-psi-impl/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java

+13
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
import com.intellij.refactoring.RefactoringBundle;
1515
import com.intellij.refactoring.util.CommonRefactoringUtil;
1616
import com.jetbrains.python.PyPsiBundle;
17+
import com.jetbrains.python.PyTokenTypes;
1718
import com.jetbrains.python.codeInsight.codeFragment.PyCodeFragment;
1819
import com.jetbrains.python.codeInsight.codeFragment.PyCodeFragmentUtil;
1920
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
2021
import com.jetbrains.python.psi.PyClass;
2122
import com.jetbrains.python.psi.PyElement;
23+
import com.jetbrains.python.psi.PyElementType;
2224
import com.jetbrains.python.psi.impl.PyPsiUtils;
2325
import com.jetbrains.python.refactoring.PyRefactoringUtil;
2426
import org.jetbrains.annotations.NotNull;
@@ -143,6 +145,17 @@ private static boolean rangeBelongsToSameClassBody(@NotNull PsiElement element1,
143145
element2 == PyPsiUtils.getPrevSignificantLeaf(PsiTreeUtil.getDeepestLast(statement2), !(element2 instanceof PsiComment))) {
144146
return Couple.of(statement1, statement2);
145147
}
148+
149+
// multi-line function call
150+
boolean isLeftParen = "(".equals(element2.getText());
151+
PsiElement prevSignificantLeaf = PyPsiUtils.getPrevSignificantLeaf(
152+
PsiTreeUtil.getDeepestLast(statement2),
153+
!(statement2 instanceof PsiComment)
154+
);
155+
boolean isRightParen = prevSignificantLeaf != null && ")".equals(prevSignificantLeaf.getText());
156+
if (isLeftParen && isRightParen) {
157+
return Couple.of(statement1, statement2);
158+
}
146159
return null;
147160
}
148161
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def long_function_name(**kwargs): ...
2+
3+
def example_function():
4+
result = extracted()
5+
processed = result.upper()
6+
return processed
7+
8+
9+
def extracted():
10+
return long_function_name(
11+
first_argument="value1",
12+
second_argument="value2",
13+
third_argument="value3"
14+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def long_function_name(**kwargs): ...
2+
3+
def example_function():
4+
result = long_function_name(
5+
first_argument<caret>="value1",
6+
second_argument="value2",
7+
third_argument="value3"
8+
)
9+
processed = result.upper()
10+
return processed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
def long_function_name(**kwargs): ...
2+
3+
def example_function():
4+
result = extracted()
5+
processed = result.upper()
6+
return processed
7+
8+
9+
def extracted():
10+
result = long_function_name(
11+
first_argument="value1",
12+
second_argument="value2",
13+
third_argument="value3"
14+
)
15+
return result
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def long_function_name(**kwargs): ...
2+
3+
def example_function():
4+
result = long_function_<caret>name(
5+
first_argument="value1",
6+
second_argument="value2",
7+
third_argument="value3"
8+
)
9+
processed = result.upper()
10+
return processed

python/testSrc/com/jetbrains/python/refactoring/PyExtractMethodTest.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ public void testMethodInnerFuncCombined() {
6868
doTest("extracted");
6969
}
7070

71+
// PY-53711
72+
public void testStartInArgumentListOfMultiLineFunctionCall() {
73+
doTest("extracted");
74+
}
75+
76+
// PY-53711
77+
public void testStartOnMultiLineFunctionCall() {
78+
doTest("extracted");
79+
}
80+
7181
public void testParameter() {
7282
doTest("bar");
7383
}
@@ -315,4 +325,4 @@ public void testCommentsPrecedingSourceStatement() {
315325
public void testInterruptedOuterLoop() {
316326
doFail("foo", "Cannot perform refactoring when execution flow is interrupted");
317327
}
318-
}
328+
}

0 commit comments

Comments
 (0)