Java: Don't cast the argument to generic type because we already know that the actual type is assignable to it (IDEA-171284)

This commit is contained in:
Pavel Dolgov
2018-06-29 13:27:21 +03:00
parent 8afdaeaca3
commit 9dce85a4fe
7 changed files with 82 additions and 15 deletions
@@ -15,10 +15,7 @@
*/
package com.intellij.refactoring.util;
import com.intellij.psi.LambdaUtil;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.SmartTypePointerManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,10 +47,11 @@ public class VariableData extends AbstractVariableData {
if (var == null) {
return this;
}
PsiType type = JavaPsiFacade.getElementFactory(var.getProject()).createTypeFromText(this.type.getCanonicalText(), var);
VariableData data = new VariableData(var, type);
data.name = name;
data.originalName = originalName;
data.passAsParameter = passAsParameter;
data.name = this.name;
data.originalName = this.originalName;
data.passAsParameter = this.passAsParameter;
return data;
}
}
@@ -1339,14 +1339,11 @@ public class ExtractMethodProcessor implements MatchProvider {
final List<PsiElement> parameterValue = match.getParameterValues(data.variable);
if (parameterValue != null) {
for (PsiElement val : parameterValue) {
if (val instanceof PsiExpression) {
final PsiType exprType = ((PsiExpression)val).getType();
if (exprType != null && !TypeConversionUtil.isAssignable(data.type, exprType)) {
final PsiTypeCastExpression cast = (PsiTypeCastExpression)elementFactory.createExpressionFromText("(A)a", val);
cast.getCastType().replace(elementFactory.createTypeElement(data.type));
cast.getOperand().replace(val.copy());
val = cast;
}
if (val instanceof PsiExpression && isCastRequired(data, (PsiExpression)val)) {
final PsiTypeCastExpression cast = (PsiTypeCastExpression)elementFactory.createExpressionFromText("(A)a", val);
cast.getCastType().replace(elementFactory.createTypeElement(data.type));
cast.getOperand().replace(val.copy());
val = cast;
}
methodCallExpression.getArgumentList().add(val);
}
@@ -1362,6 +1359,15 @@ public class ExtractMethodProcessor implements MatchProvider {
return replacedMatch;
}
private static boolean isCastRequired(@NotNull VariableData data, @NotNull PsiExpression val) {
final PsiType exprType = val.getType();
if (exprType == null || TypeConversionUtil.isAssignable(data.type, exprType)) {
return false;
}
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(data.type);
return !(psiClass instanceof PsiTypeParameter);
}
@NotNull
private static List<String> findReusedVariables(@NotNull Match match,
@NotNull InputVariables inputVariables,
@@ -0,0 +1,10 @@
class C {
<K> void f(K k) {
<selection>System.out.println(k);</selection>
}
void g() {
Object o = "";
System.out.println(o);
}
}
@@ -0,0 +1,13 @@
class C {
<K> void method() {
class Local {
void foo(K k) {
<selection>System.out.println(k);</selection>
}
void bar() {
Object o = new Object();
System.out.println(o);
}
}
}
}
@@ -0,0 +1,18 @@
class C {
<K> void method() {
class Local {
void foo(K k) {
newMethod(k);
}
private void newMethod(K k) {
System.out.println(k);
}
void bar() {
Object o = new Object();
newMethod(o);
}
}
}
}
@@ -0,0 +1,14 @@
class C {
<K> void f(K k) {
newMethod(k);
}
private <K> void newMethod(K k) {
System.out.println(k);
}
void g() {
Object o = "";
newMethod(o);
}
}
@@ -1274,6 +1274,14 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doDuplicatesTest();
}
public void testAvoidGenericArgumentCast() throws Exception {
doDuplicatesTest();
}
public void testAvoidGenericArgumentCastLocalClass() throws Exception {
doDuplicatesTest();
}
public void testBeforeCommentAfterSelectedFragment() throws Exception {
doTest();
}