Use isReferenceTo(keywordContainer) instead of name matching (PY-26285)

This commit is contained in:
Semyon Proshev
2017-11-29 21:37:36 +03:00
parent 2650bf2d41
commit 787e678baa
6 changed files with 51 additions and 20 deletions

View File

@@ -180,11 +180,10 @@ public class ConvertVariadicParamIntention extends PyBaseIntentionAction {
@NotNull
private static <T> List<T> findKeywordContainerUsages(@NotNull PyFunction function,
@NotNull BiPredicate<PsiElement, String> usagePredicate) {
@NotNull BiPredicate<PsiElement, PyParameter> usagePredicate) {
final PyParameter keywordContainer = getKeywordContainer(function.getParameterList());
final String keywordContainerName = keywordContainer == null ? null : keywordContainer.getName();
if (keywordContainerName != null) {
if (keywordContainer != null) {
final List<T> result = new ArrayList<>();
final Stack<PsiElement> stack = new Stack<>();
@@ -194,7 +193,7 @@ public class ConvertVariadicParamIntention extends PyBaseIntentionAction {
while (!stack.isEmpty()) {
final PsiElement element = stack.pop();
if (usagePredicate.test(element, keywordContainerName)) {
if (usagePredicate.test(element, keywordContainer)) {
//noinspection unchecked
result.add((T)element);
}
@@ -212,25 +211,31 @@ public class ConvertVariadicParamIntention extends PyBaseIntentionAction {
return Collections.emptyList();
}
private static boolean isKeywordContainerSubscription(@Nullable PsiElement element, @NotNull String keywordContainerName) {
return element instanceof PySubscriptionExpression &&
keywordContainerName.equals(((PySubscriptionExpression)element).getOperand().getText());
private static boolean isKeywordContainerSubscription(@Nullable PsiElement element, @NotNull PyParameter keywordContainer) {
if (element instanceof PySubscriptionExpression) {
final PyExpression operand = ((PySubscriptionExpression)element).getOperand();
if (operand instanceof PyReferenceExpression) {
return ((PyReferenceExpression)operand).getReference().isReferenceTo(keywordContainer);
}
}
private static boolean isKeywordContainerCall(@Nullable PsiElement element, @NotNull String keywordContainerName) {
return Optional
.ofNullable(PyUtil.as(element, PyCallExpression.class))
.map(PyCallExpression::getCallee)
.map(callee -> PyUtil.as(callee, PyQualifiedExpression.class))
.filter(
callee -> {
final PyExpression qualifier = callee.getQualifier();
return qualifier != null &&
qualifier.getText().equals(keywordContainerName) &&
ArrayUtil.contains(callee.getReferencedName(), "get", "pop", PyNames.GETITEM);
return false;
}
)
.isPresent();
private static boolean isKeywordContainerCall(@Nullable PsiElement element, @NotNull PyParameter keywordContainer) {
if (element instanceof PyCallExpression) {
final PyExpression callee = ((PyCallExpression)element).getCallee();
if (callee instanceof PyQualifiedExpression) {
final PyQualifiedExpression qualifiedCallee = (PyQualifiedExpression)callee;
final PyExpression qualifier = qualifiedCallee.getQualifier();
if (qualifier instanceof PyReferenceExpression) {
return ((PyReferenceExpression)qualifier).getReference().isReferenceTo(keywordContainer) &&
ArrayUtil.contains(qualifiedCallee.getReferencedName(), "get", "pop", PyNames.GETITEM);
}
}
}
return false;
}
private static void insertParameter(@NotNull PyParameterList parameterList,

View File

@@ -0,0 +1,4 @@
def outer(<caret>**kwargs):
def nested():
print(kwargs['foo'])
return kwargs.get('bar')

View File

@@ -0,0 +1,4 @@
def outer(foo, bar=None, **kwargs):
def nested():
print(foo)
return bar

View File

@@ -0,0 +1,4 @@
def outer(<caret>**kwargs):
def nested(**kwargs):
print(kwargs['foo'])
return kwargs.get('bar')

View File

@@ -0,0 +1,4 @@
def outer(bar=None, **kwargs):
def nested(**kwargs):
print(kwargs['foo'])
return bar

View File

@@ -244,6 +244,16 @@ public class PyIntentionTest extends PyTestCase {
doTest(PyBundle.message("INTN.convert.variadic.param"));
}
// PY-26285
public void testConvertVariadicParamOverriddenInNested() {
doTest(PyBundle.message("INTN.convert.variadic.param"));
}
// PY-26285
public void testConvertVariadicParamNotOverriddenInNested() {
doTest(PyBundle.message("INTN.convert.variadic.param"));
}
public void testConvertTripleQuotedString() { //PY-2697
doTest(PyBundle.message("INTN.triple.quoted.string"));
}