redundant cast: special processing for functional expressions as enum args (IDEA-154354)

This commit is contained in:
Anna.Kozlova
2016-04-15 16:04:38 +02:00
parent b701c29875
commit 09f46115cf
7 changed files with 50 additions and 21 deletions

View File

@@ -297,4 +297,16 @@ public class PsiTypesUtil {
}
});
}
public static PsiType getParameterType(PsiParameter[] parameters, int i, boolean varargs) {
final PsiParameter parameter = parameters[i < parameters.length ? i : parameters.length - 1];
PsiType parameterType = parameter.getType();
if (parameterType instanceof PsiEllipsisType && varargs) {
parameterType = ((PsiEllipsisType)parameterType).getComponentType();
}
if (!parameterType.isValid()) {
PsiUtil.ensureValidType(parameterType, "Invalid type of parameter " + parameter + " of " + parameter.getClass());
}
return parameterType;
}
}

View File

@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
@@ -333,8 +334,10 @@ public class RedundantCastUtil {
PsiExpressionList argumentList = expression.getArgumentList();
if (argumentList == null) return;
PsiExpression[] args = argumentList.getExpressions();
PsiMethod oldMethod = expression.resolveMethod();
if (oldMethod == null) return;
final JavaResolveResult oldResult = expression.resolveMethodGenerics();
final PsiElement element = oldResult.getElement();
if (!(element instanceof PsiMethod)) return;
PsiMethod oldMethod = (PsiMethod)element;
PsiParameter[] parameters = oldMethod.getParameterList().getParameters();
try {
@@ -387,9 +390,20 @@ public class RedundantCastUtil {
oldAnonymousClass != null && newAnonymousClass != null && Comparing.equal(oldAnonymousClass.getBaseClassType(), newAnonymousClass.getBaseClassType()) ||
Comparing.equal(PsiUtil.recaptureWildcards(((PsiCallExpression)newCall).getType(), expression), ((PsiCallExpression)expression).getType())) &&
newResult.isValidResult()) {
if (!(newArgs[i] instanceof PsiFunctionalExpression) || castType != null && castType.equals(((PsiFunctionalExpression)newArgs[i]).getFunctionalInterfaceType())) {
if (!(newArgs[i] instanceof PsiFunctionalExpression)) {
addToResults(cast);
}
else {
final boolean varargs = newResult instanceof MethodCandidateInfo && ((MethodCandidateInfo)newResult).isVarargs();
final PsiType parameterType = PsiTypesUtil.getParameterType(parameters, i, varargs);
final PsiType newArgType = newResult.getSubstitutor().substitute(parameterType);
//todo replace with castType.equals(FunctionalInterfaceParameterizationUtil.getGroundType(newArgType, lambda))
if (Comparing.equal(oldResult.getSubstitutor().substitute(parameterType), newArgType) &&
Comparing.equal(TypeConversionUtil.erasure(castType), TypeConversionUtil.erasure(newArgType))) {
addToResults(cast);
}
}
}
}
else if (arg instanceof PsiLambdaExpression) {

View File

@@ -279,18 +279,7 @@ public class InferenceSession {
private static PsiType getParameterType(PsiParameter[] parameters, int i, @Nullable PsiSubstitutor substitutor, boolean varargs) {
if (substitutor == null) return null;
final PsiParameter parameter = parameters[i < parameters.length ? i : parameters.length - 1];
final PsiType type = parameter.getType();
if (!type.isValid()) {
PsiUtil.ensureValidType(type, "Invalid type of parameter " + parameter + " of " + parameter.getClass());
}
PsiType parameterType = substitutor.substitute(type);
if (parameterType instanceof PsiEllipsisType && varargs) {
parameterType = ((PsiEllipsisType)parameterType).getComponentType();
}
return parameterType;
return substitutor.substitute(PsiTypesUtil.getParameterType(parameters, i, varargs));
}
@NotNull

View File

@@ -0,0 +1,12 @@
import java.util.function.Supplier;
enum E {
A( (<warning descr="Casting 'E::f' to 'Supplier<Object>' is redundant">Supplier<Object></warning>)E::f),
B( (Supplier<String>)E::f),
;
<T> E(Supplier<T> s){}
static <K> K f() {
return null;
}
}

View File

@@ -3,11 +3,11 @@
<problem>
<file>Test.java</file>
<line>5</line>
<description>Casting &lt;code&gt;getComponent(&quot;bar&quot;)&lt;/code&gt; to &lt;code&gt;Bar&lt;/code&gt; is redundant</description>
<description>Casting &lt;code&gt;getComponent()&lt;/code&gt; to &lt;code&gt;Bar&lt;/code&gt; is redundant</description>
</problem>
<problem>
<file>Test.java</file>
<line>6</line>
<description>Casting &lt;code&gt;getComponent(&quot;bar&quot;)&lt;/code&gt; to &lt;code&gt;Bar&lt;/code&gt; is redundant</description>
<description>Casting &lt;code&gt;getComponent()&lt;/code&gt; to &lt;code&gt;Bar&lt;/code&gt; is redundant</description>
</problem>
</problems>

View File

@@ -1,16 +1,16 @@
class Test {
{
f((Bar) getComponent("bar"));
f1((Bar) getComponent("bar"));
Bar b = (Bar) getComponent("bar");
f((Bar) getComponent());
f1((Bar) getComponent());
Bar b = (Bar) getComponent();
}
private <J extends Bar> void f(J j) {}
private <J> void f1(J j) {}
private <T> T getComponent(String name) {
private <T> T getComponent() {
return null;
}

View File

@@ -69,6 +69,8 @@ public class LambdaRedundantCastTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testEnumConstantWithFunctionalExpressionArg() throws Exception { doTest(); }
private void doTest() {
doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, false);
}