check possible inference for method references before simplification (IDEA-171976)

This commit is contained in:
Anna.Kozlova
2017-04-26 20:33:51 +02:00
parent 6c7d18819a
commit d82105d5ec
3 changed files with 47 additions and 8 deletions

View File

@@ -135,13 +135,13 @@ public class RedundantTypeArgsInspection extends GenericsInspectionToolBase {
if (qualifierTypeElement != null) {
final PsiType psiType = qualifierTypeElement.getType();
if (psiType instanceof PsiClassType && !(((PsiClassType)psiType).isRaw())) {
PsiClass aClass = ((PsiClassType)psiType).resolve();
if (aClass == null) return;
final JavaResolveResult result = expression.advancedResolve(false);
final PsiElement element = result.getElement();
if (element instanceof PsiTypeParameterListOwner) {
final PsiMethodReferenceExpression copy = createMethodReference(expression, qualifierTypeElement);
final JavaResolveResult simplifiedResolve = copy.advancedResolve(false);
final PsiElement candidate = simplifiedResolve.getElement();
if (candidate == element) {
PsiMethod method = element instanceof PsiMethod ? (PsiMethod)element : null;
if (PsiDiamondTypeUtil.areTypeArgumentsRedundant(((PsiClassType)psiType).getParameters(), expression, false, method, aClass.getTypeParameters())) {
final PsiJavaCodeReferenceElement referenceElement = qualifierTypeElement.getInnermostComponentReferenceElement();
LOG.assertTrue(referenceElement != null, qualifierTypeElement);
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();

View File

@@ -149,7 +149,7 @@ public class PsiDiamondTypeUtil {
}
public static boolean areTypeArgumentsRedundant(PsiType[] typeArguments,
PsiCallExpression expression,
PsiExpression expression,
boolean constructorRef,
@Nullable PsiMethod method,
PsiTypeParameter[] typeParameters) {
@@ -168,7 +168,7 @@ public class PsiDiamondTypeUtil {
copy = initializer.getInitializers()[0].replace(expression);
}
else {
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpressionList argumentList = expression instanceof PsiCallExpression ? ((PsiCallExpression)expression).getArgumentList() : null;
final int offset = (argumentList != null ? argumentList : expression).getTextRange().getStartOffset();
final PsiCall call = LambdaUtil.treeWalkUp(expression);
if (call != null) {
@@ -193,6 +193,13 @@ public class PsiDiamondTypeUtil {
}
}
}
if (expression instanceof PsiMethodReferenceExpression) {
PsiMethodReferenceExpression methodRefCopy = PsiTreeUtil.getParentOfType(copy, PsiMethodReferenceExpression.class, false);
if (methodRefCopy != null && !isInferenceEquivalent(typeArguments, typeParameters, method, methodRefCopy)) {
return false;
}
return true;
}
final PsiCallExpression exprCopy = PsiTreeUtil.getParentOfType(copy, PsiCallExpression.class, false);
if (exprCopy != null) {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(exprCopy.getProject()).getElementFactory();
@@ -216,6 +223,29 @@ public class PsiDiamondTypeUtil {
return true;
}
private static boolean isInferenceEquivalent(PsiType[] typeArguments,
PsiTypeParameter[] typeParameters,
PsiMethod method,
PsiMethodReferenceExpression methodRefCopy) {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodRefCopy.getProject()).getElementFactory();
PsiTypeElement qualifierType = methodRefCopy.getQualifierType();
LOG.assertTrue(qualifierType != null);
qualifierType.replace(elementFactory.createTypeElement(((PsiClassType)qualifierType.getType()).rawType()));
JavaResolveResult result = methodRefCopy.advancedResolve(false);
if (method != null && result.getElement() != method) return false;
final PsiSubstitutor psiSubstitutor = result.getSubstitutor();
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
final PsiType inferredType = psiSubstitutor.getSubstitutionMap().get(typeParameter);
if (!typeArguments[i].equals(inferredType)) {
return false;
}
}
return checkParentApplicability(methodRefCopy);
}
private static boolean isInferenceEquivalent(PsiType[] typeArguments,
PsiElementFactory elementFactory,
PsiCallExpression exprCopy,
@@ -282,9 +312,9 @@ public class PsiDiamondTypeUtil {
return checkParentApplicability(exprCopy);
}
private static boolean checkParentApplicability(PsiCallExpression exprCopy) {
private static boolean checkParentApplicability(PsiExpression exprCopy) {
while (exprCopy != null){
JavaResolveResult resolveResult = exprCopy.resolveMethodGenerics();
JavaResolveResult resolveResult = exprCopy instanceof PsiCallExpression ? ((PsiCallExpression)exprCopy).resolveMethodGenerics() : null;
if (exprCopy instanceof PsiNewExpression) {
PsiDiamondType diamondType = PsiDiamondType.getDiamondType((PsiNewExpression)exprCopy);
if (diamondType != null) {

View File

@@ -0,0 +1,9 @@
// "Remove explicit type arguments" "false"
import java.util.Map.Entry;
import java.util.stream.Collectors;
class Foo {
{
Collectors.toMap(Entry<Integer, <caret>Integer>::getKey, null);
}
}