PY-8174 Suggests better names for new parameters in the quickfix

using NameSuggestionUtil#generateNames() and text of the main reference
expression in argument as a template. Only if no meaningful names were
found this way, it falls back to names generated from expression types.
This commit is contained in:
Mikhail Golubev
2017-06-05 21:22:39 +03:00
parent cf0c247416
commit 33f424edc7
4 changed files with 23 additions and 15 deletions
@@ -187,15 +187,21 @@ public class PyChangeSignatureQuickFix extends LocalQuickFixOnPsiElement {
@NotNull PyFunction function,
@NotNull Set<String> usedParameterNames,
@NotNull TypeEvalContext context) {
PyType type = context.getType(argumentValue);
if (type instanceof PyUnionType) {
type = ContainerUtil.find(((PyUnionType)type).getMembers(), Conditions.instanceOf(PyClassType.class));
final Collection<String> suggestions = new LinkedHashSet<>();
final PyCallExpression callExpr = as(argumentValue, PyCallExpression.class);
final PyElement referenceElem = as(callExpr != null ? callExpr.getCallee() : argumentValue, PyReferenceExpression.class);
if (referenceElem != null) {
suggestions.addAll(NameSuggesterUtil.generateNames(referenceElem.getText()));
}
final String typeName = type != null && type.getName() != null ? type.getName() : "object";
final Collection<String> suggestions = NameSuggesterUtil.generateNamesByType(typeName);
final String shortestName = ContainerUtil.getFirstItem(suggestions);
assert shortestName != null;
if (suggestions.isEmpty()) {
PyType type = context.getType(argumentValue);
if (type instanceof PyUnionType) {
type = ContainerUtil.find(((PyUnionType)type).getMembers(), Conditions.instanceOf(PyClassType.class));
}
final String typeName = type != null && type.getName() != null ? type.getName() : "object";
suggestions.addAll(NameSuggesterUtil.generateNamesByType(typeName));
}
final String shortestName = Collections.min(suggestions, Comparator.comparingInt(String::length));
String result = shortestName;
int counter = 1;
@@ -2,5 +2,4 @@ def func(i1):
i2 = 'Spam'
x = 42 or 'str'
func<warning descr="Unexpected argument(s)">(<caret>1, <warning descr="Unexpected argument">2</warning>, <warning descr="Unexpected argument">x</warning>)</warning>
func<warning descr="Unexpected argument(s)">(<caret>1, <warning descr="Unexpected argument">2</warning>, <warning descr="Unexpected argument">42 or 'str'</warning>, <warning descr="Unexpected argument">get_num()</warning>)</warning>
@@ -1,6 +1,5 @@
def func(i1, i, i3):
def func(i1, i, i3, num):
i2 = 'Spam'
x = 42 or 'str'
func(1, 2, x)
func(1, 2, 42 or 'str', get_num())
@@ -17,8 +17,10 @@ package com.jetbrains.python;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.TestDataFile;
import com.intellij.testFramework.TestDataPath;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
import com.jetbrains.python.fixtures.PyTestCase;
@@ -661,7 +663,7 @@ public class PyQuickFixTest extends PyTestCase {
// PY-8174
public void testChangeSignatureNewParametersNames() {
doInspectionTest(PyArgumentListInspection.class, "<html>Change signature of func(i1, <b>i</b>, <b>i3</b>)</html>", true, true);
doInspectionTest(PyArgumentListInspection.class, "<html>Change signature of func(i1, <b>i</b>, <b>i3</b>, <b>num</b>)</html>", true, true);
}
// PY-8174
@@ -712,7 +714,9 @@ public class PyQuickFixTest extends PyTestCase {
final List<IntentionAction> intentionActions = myFixture.filterAvailableIntentions(quickFixName);
if (available) {
if (intentionActions.isEmpty()) {
throw new AssertionError("Quickfix \"" + quickFixName + "\" is not available");
final List<String> intentionNames = ContainerUtil.map(myFixture.getAvailableIntentions(), IntentionAction::getText);
throw new AssertionError("Quickfix starting with \"" + quickFixName + "\" is not available. " +
"Available intentions:\n" + StringUtil.join(intentionNames, "\n"));
}
if (intentionActions.size() > 1) {
throw new AssertionError("There are more than one quickfix with the name \"" + quickFixName + "\"");