mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IPP: allow flipping method call with implicit this qualifier (IDEA-207785)
This commit is contained in:
+23
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2018 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2019 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@ package com.siyeh.ipp.commutative;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ipp.base.MutablyNamedIntention;
|
||||
@@ -30,12 +29,10 @@ public class FlipCommutativeMethodCallIntention extends MutablyNamedIntention {
|
||||
@Override
|
||||
protected String getTextForElement(PsiElement element) {
|
||||
final PsiMethodCallExpression call = (PsiMethodCallExpression)element;
|
||||
final PsiReferenceExpression methodExpression =
|
||||
call.getMethodExpression();
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
@NonNls final String methodName = methodExpression.getReferenceName();
|
||||
assert methodName != null;
|
||||
if ("equals".equals(methodName) ||
|
||||
"equalsIgnoreCase".equals(methodName)) {
|
||||
if ("equals".equals(methodName) || "equalsIgnoreCase".equals(methodName)) {
|
||||
return IntentionPowerPackBundle.message(
|
||||
"flip.commutative.method.call.intention.name", methodName);
|
||||
}
|
||||
@@ -52,39 +49,27 @@ public class FlipCommutativeMethodCallIntention extends MutablyNamedIntention {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIntention(PsiElement element) {
|
||||
final PsiMethodCallExpression call = (PsiMethodCallExpression)element;
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
final PsiExpression target = methodExpression.getQualifierExpression();
|
||||
if (target == null) {
|
||||
public void processIntention(@NotNull PsiElement element) {
|
||||
final PsiMethodCallExpression expression = (PsiMethodCallExpression)element;
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
final PsiExpression argument = argumentList.getExpressions()[0];
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
final PsiExpression strippedQualifier = ParenthesesUtils.stripParentheses(qualifier);
|
||||
final PsiExpression strippedArgument = ParenthesesUtils.stripParentheses(argument);
|
||||
if (strippedArgument == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
final PsiExpression arg = argumentList.getExpressions()[0];
|
||||
final PsiExpression strippedTarget =
|
||||
ParenthesesUtils.stripParentheses(target);
|
||||
if (strippedTarget == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedArg =
|
||||
ParenthesesUtils.stripParentheses(arg);
|
||||
if (strippedArg == null) {
|
||||
return;
|
||||
}
|
||||
final String callString;
|
||||
if (ParenthesesUtils.getPrecedence(strippedArg) >
|
||||
ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
callString = '(' + strippedArg.getText() + ")." + methodName + '(' +
|
||||
strippedTarget.getText() + ')';
|
||||
}
|
||||
else {
|
||||
callString = strippedArg.getText() + '.' + methodName + '(' +
|
||||
strippedTarget.getText() + ')';
|
||||
}
|
||||
CommentTracker commentTracker = new CommentTracker();
|
||||
commentTracker.markUnchanged(strippedArg);
|
||||
commentTracker.markUnchanged(strippedTarget);
|
||||
PsiReplacementUtil.replaceExpression(call, callString, commentTracker);
|
||||
CommentTracker tracker = new CommentTracker();
|
||||
if (qualifier != null) tracker.grabComments(qualifier);
|
||||
if (strippedQualifier != null) tracker.markUnchanged(strippedQualifier);
|
||||
tracker.grabComments(argument);
|
||||
tracker.markUnchanged(strippedArgument);
|
||||
final PsiElement newArgument = strippedQualifier == null
|
||||
? JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText("this", expression)
|
||||
: strippedQualifier.copy();
|
||||
methodExpression.setQualifierExpression(strippedArgument);
|
||||
argument.replace(newArgument);
|
||||
tracker.insertCommentsBefore(expression);
|
||||
}
|
||||
}
|
||||
+37
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2005 Dave Griffith
|
||||
* Copyright 2003-2019 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,58 +30,58 @@ class FlipCommutativeMethodCallPredicate implements PsiElementPredicate {
|
||||
if (ErrorUtil.containsError(element)) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethodCallExpression expression =
|
||||
(PsiMethodCallExpression)element;
|
||||
final PsiMethodCallExpression expression = (PsiMethodCallExpression)element;
|
||||
// do it only when there is just one argument.
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args.length != 1) {
|
||||
final PsiExpression[] arguments = expression.getArgumentList().getExpressions();
|
||||
if (arguments.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiReferenceExpression methodExpression =
|
||||
expression.getMethodExpression();
|
||||
final PsiExpression qualifier =
|
||||
methodExpression.getQualifierExpression();
|
||||
// make sure that there is a caller and a caller
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
final PsiType callerType;
|
||||
if (qualifier == null) {
|
||||
return false;
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return false;
|
||||
}
|
||||
callerType = JavaPsiFacade.getElementFactory(aClass.getProject()).createType(aClass);
|
||||
}
|
||||
else {
|
||||
callerType = qualifier.getType();
|
||||
if (!(callerType instanceof PsiClassType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
// the logic is...
|
||||
// if the argument takes a method of the same name with the caller
|
||||
// as parameter then we can switch the argument and the caller.
|
||||
final PsiType callerType = qualifier.getType();
|
||||
final PsiType argumentType = args[0].getType();
|
||||
final PsiType argumentType = arguments[0].getType();
|
||||
if (!(argumentType instanceof PsiClassType)) {
|
||||
return false;
|
||||
}
|
||||
if (!(callerType instanceof PsiClassType)) {
|
||||
return false;
|
||||
if (callerType.equals(argumentType)) {
|
||||
return true;
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)argumentType).resolveGenerics();
|
||||
final PsiClass argumentClass = resolveResult.getElement();
|
||||
if (argumentClass == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethod[] methods =
|
||||
argumentClass.findMethodsByName(methodName, true);
|
||||
final PsiMethod[] methods = argumentClass.findMethodsByName(methodName, true);
|
||||
for (final PsiMethod testMethod : methods) {
|
||||
final String testMethodName = testMethod.getName();
|
||||
if (testMethodName.equals(methodName)) {
|
||||
final PsiParameterList parameterList =
|
||||
testMethod.getParameterList();
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters.length == 1) {
|
||||
final PsiParameter parameter = parameters[0];
|
||||
final PsiClass containingClass = testMethod.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiSubstitutor substitutor =
|
||||
TypeConversionUtil.getClassSubstitutor(containingClass, argumentClass, resolveResult.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
final PsiType type = substitutor.substitute(parameter.getType());
|
||||
if (type != null && type.isAssignableFrom(callerType)) {
|
||||
return true;
|
||||
}
|
||||
final PsiParameterList parameterList = testMethod.getParameterList();
|
||||
if (parameterList.getParametersCount() == 1) {
|
||||
final PsiParameter parameter = parameterList.getParameters()[0];
|
||||
final PsiClass containingClass = testMethod.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiSubstitutor substitutor =
|
||||
TypeConversionUtil.getClassSubstitutor(containingClass, argumentClass, resolveResult.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
final PsiType type = substitutor.substitute(parameter.getType());
|
||||
if (type != null && type.isAssignableFrom(callerType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class X {
|
||||
|
||||
void foo(X x) {
|
||||
<caret>foo((/*1*/(new X())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class X {
|
||||
|
||||
void foo(X x) {
|
||||
/*1*/new X().foo(this);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-3
@@ -2,9 +2,7 @@ class A<T> {
|
||||
void foo(A<T> a){}
|
||||
|
||||
void bar(B b, B b1) {
|
||||
/*in method call*/
|
||||
/*comment in arg*/
|
||||
b1.foo(b);//end line comment
|
||||
b1./*in method call*/foo(b/*comment in arg*/);//end line comment
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
public class FlipCommutativeMethodCallIntentionTest extends IPPTestCase {
|
||||
public void testSubstitution() { doTest(); }
|
||||
public void testNoQualifier() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
|
||||
Reference in New Issue
Block a user