mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-20917 'Replace with str.format method call' messes up with set call
In call expression we should try to add arguments only for dict calls, "collection" and other calls we should get "as is"
This commit is contained in:
+25
-16
@@ -37,6 +37,7 @@ import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -286,22 +287,15 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction
|
||||
else if (rhs instanceof PyCallExpression) { // potential dict(foo=1) -> format(foo=1)
|
||||
final PyCallExpression callExpression = (PyCallExpression)rhs;
|
||||
final PyExpression callee = callExpression.getCallee();
|
||||
if (callee instanceof PyReferenceExpression) {
|
||||
PsiElement maybeDict = ((PyReferenceExpression)callee).getReference().resolve();
|
||||
if (maybeDict instanceof PyFunction) {
|
||||
PyFunction dictInit = (PyFunction)maybeDict;
|
||||
if (PyNames.INIT.equals(dictInit.getName())) {
|
||||
final PyClassType dictType = PyBuiltinCache.getInstance(file).getDictType();
|
||||
if (dictType != null && dictType.getPyClass() == dictInit.getContainingClass()) {
|
||||
target.append(sure(sure(callExpression.getArgumentList()).getNode()).getChars());
|
||||
}
|
||||
}
|
||||
else { // just a call, reuse
|
||||
target.append("(");
|
||||
if (converted.getSecond()) target.append("**"); // map-by-name formatting was detected
|
||||
target.append(paramText).append(")");
|
||||
}
|
||||
}
|
||||
final PyClassType dictType = PyBuiltinCache.getInstance(file).getDictType();
|
||||
final PyClassType classType = PyUtil.as(rhsType, PyClassType.class);
|
||||
if (classType != null && callee != null && isDictCall(callee, classType, dictType)) {
|
||||
target.append(sure(sure(callExpression.getArgumentList()).getNode()).getChars());
|
||||
}
|
||||
else { // just a call, reuse
|
||||
target.append("(");
|
||||
if (converted.getSecond()) target.append("**"); // map-by-name formatting was detected
|
||||
target.append(paramText).append(")");
|
||||
}
|
||||
}
|
||||
else if (rhsType instanceof PyCollectionType && "dict".equals(rhsType.getName())) {
|
||||
@@ -313,6 +307,21 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction
|
||||
final PyExpression parenthesized = elementGenerator.createExpressionFromText(LanguageLevel.forElement(element), target.toString());
|
||||
element.replace(sure(((PyParenthesizedExpression)parenthesized).getContainedExpression()));
|
||||
}
|
||||
|
||||
private static boolean isDictCall(@NotNull PyExpression callee, @NotNull PyClassType classType, @Nullable PyClassType dictType) {
|
||||
if (dictType != null && classType.getPyClass() == dictType.getPyClass()) {
|
||||
if (callee instanceof PyReferenceExpression) {
|
||||
PsiElement maybeDict = ((PyReferenceExpression)callee).getReference().resolve();
|
||||
final PyFunction dictInit = PyUtil.as(maybeDict, PyFunction.class);
|
||||
if (dictInit != null) {
|
||||
if (PyNames.INIT.equals(dictInit.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getSeparator(PyStringLiteralExpression leftExpression) {
|
||||
String separator = ""; // detect nontrivial whitespace around the "%"
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
def f():
|
||||
pass
|
||||
|
||||
"%s" <caret>% f()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
"{}".format(f())
|
||||
@@ -0,0 +1 @@
|
||||
"%s" <caret>% set({1, 2})
|
||||
+1
@@ -0,0 +1 @@
|
||||
"{}".format(set({1, 2}))
|
||||
+10
@@ -88,4 +88,14 @@ public class PyConvertFormatOperatorToMethodIntentionTest extends PyIntentionTes
|
||||
public void testSet() {
|
||||
doTest(PyBundle.message("INTN.replace.with.method"), LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
// PY-20917
|
||||
public void testSetCall() {
|
||||
doTest(PyBundle.message("INTN.replace.with.method"), LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
// PY-20917
|
||||
public void testCallWithNoneReturnType() {
|
||||
doTest(PyBundle.message("INTN.replace.with.method"), LanguageLevel.PYTHON26);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user