PY-8174 Always use actual arguments as default values for new parameters

even if names referenced in them are not available at the places of
some usages and the definition. It's user responsibility to review them
and ensure that refactoring won't cause any errors. This approach
follows the one used for Java.
This commit is contained in:
Mikhail Golubev
2017-06-05 21:20:45 +03:00
parent fc59d948bf
commit ef60722aea
5 changed files with 25 additions and 25 deletions
@@ -76,20 +76,14 @@ public class PyChangeSignatureQuickFix extends LocalQuickFixOnPsiElement {
final Set<String> usedParamNames = new HashSet<>();
for (PyExpression arg : mapping.getUnmappedArguments()) {
if (arg instanceof PyKeywordArgument) {
final String defaultValueText;
final PyExpression value = ((PyKeywordArgument)arg).getValueExpression();
if (value != null && PyRefactoringUtil.isSimpleExpression(value) && !value.textContains('\n')) {
defaultValueText = value.getText();
}
else {
defaultValueText = ApplicationManager.getApplication().isUnitTestMode() ? "None" : "";
}
final String valueText = value != null ? value.getText() : "";
newParameters.add(Pair.create(parameters.length - 1,
new PyParameterInfo(-1, ((PyKeywordArgument)arg).getKeyword(), defaultValueText, true)));
new PyParameterInfo(-1, ((PyKeywordArgument)arg).getKeyword(), valueText, true)));
}
else {
final String paramName = generateParameterName(arg, function, usedParamNames, context);
newParameters.add(Pair.create(positionalParamAnchor, new PyParameterInfo(-1, paramName, "", false)));
newParameters.add(Pair.create(positionalParamAnchor, new PyParameterInfo(-1, paramName, arg.getText(), false)));
usedParamNames.add(paramName);
}
}
@@ -109,12 +103,15 @@ public class PyChangeSignatureQuickFix extends LocalQuickFixOnPsiElement {
}
return new PyChangeSignatureQuickFix(function, extraParams, null);
}
private final List<Pair<Integer, PyParameterInfo>> myExtraParameters;
private final SmartPsiElementPointer<PyCallExpression> myOriginalCallExpression;
/**
* @param extraParameters new parameters anchored by indexes of the existing parameters they should be inserted <em>after</em>
* (-1 in case they should precede the first parameter)
*/
public PyChangeSignatureQuickFix(@NotNull PyFunction function,
@NotNull List<Pair<Integer, PyParameterInfo>> extraParameters,
@Nullable PyCallExpression expression) {
@@ -17,7 +17,6 @@ package com.jetbrains.python.refactoring;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.find.findUsages.FindUsagesHandler;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
@@ -29,7 +28,6 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.findUsages.PyFindUsagesHandlerFactory;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.refactoring.introduce.IntroduceValidator;
@@ -399,16 +397,4 @@ public class PyRefactoringUtil {
public static boolean isValidNewName(@NotNull String name, @NotNull PsiElement scopeAnchor) {
return !(IntroduceValidator.isDefinedInScope(name, scopeAnchor) || PyNames.isReserved(name));
}
public static boolean isSimpleExpression(@NotNull PyExpression value) {
if (value instanceof PyLiteralExpression) {
final ASTNode node = value.getNode();
// Check that string literal doesn't contain multiple glued nodes
return node.getChildren(null).length == 1 && PyTokenTypes.SCALAR_LITERALS.contains(node.getFirstChildNode().getElementType());
}
else if (value instanceof PyReferenceExpression) {
return PyUtil.isPy2ReservedWord((PyReferenceExpression)value);
}
return false;
}
}
@@ -0,0 +1,6 @@
def func():
pass
func<warning descr="Unexpected argument(s)">(<caret><warning descr="Unexpected argument">42</warning>, <warning descr="Unexpected argument">foo='spam'</warning>)</warning>
func()
@@ -0,0 +1,6 @@
def func(i, foo='spam'):
pass
func(42, foo='spam')
func(42)
@@ -657,6 +657,11 @@ public class PyQuickFixTest extends PyTestCase {
doInspectionTest(PyArgumentListInspection.class, "<html>Change signature of", true, true);
}
// PY-8174
public void testAddParameterDefaultValues() {
doInspectionTest(PyArgumentListInspection.class, "<html>Change signature of", true, true);
}
@Override
@NonNls
protected String getTestDataPath() {