lambda-> method ref: do not insert type args to reference type if they were inferred for lambda expression

This commit is contained in:
Anna Kozlova
2014-04-11 17:06:01 +02:00
parent 86e8dd82fd
commit a3348c56cb
6 changed files with 135 additions and 15 deletions
@@ -25,6 +25,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -268,21 +269,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
final String methodReferenceName = methodExpression.getReferenceName();
if (qualifierExpression != null) {
boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod);
final String qualifier;
if (isReceiverType) {
final PsiMethod nonAmbiguousMethod = ensureNonAmbiguousMethod(parameters, psiMethod);
LOG.assertTrue(nonAmbiguousMethod != null);
final PsiClass nonAmbiguousContainingClass = nonAmbiguousMethod.getContainingClass();
if (!containingClass.equals(nonAmbiguousContainingClass)) {
qualifier = getClassReferenceName(nonAmbiguousContainingClass);
} else {
final PsiType qualifierExpressionType = qualifierExpression.getType();
qualifier = qualifierExpressionType != null ? qualifierExpressionType.getCanonicalText() : getClassReferenceName(nonAmbiguousContainingClass);
}
}
else {
qualifier = qualifierExpression.getText();
}
final String qualifier = isReceiverType ? composeReceiverQualifierText(parameters, psiMethod, containingClass, qualifierExpression)
: qualifierExpression.getText();
methodRefText = qualifier + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodReferenceName;
}
else {
@@ -330,6 +318,28 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
return methodRefText;
}
private static String composeReceiverQualifierText(PsiParameter[] parameters,
PsiMethod psiMethod,
PsiClass containingClass,
@NotNull PsiExpression qualifierExpression) {
final PsiMethod nonAmbiguousMethod = ensureNonAmbiguousMethod(parameters, psiMethod);
LOG.assertTrue(nonAmbiguousMethod != null);
final PsiClass nonAmbiguousContainingClass = nonAmbiguousMethod.getContainingClass();
if (!containingClass.equals(nonAmbiguousContainingClass)) {
return getClassReferenceName(nonAmbiguousContainingClass);
}
if (nonAmbiguousContainingClass.isPhysical() && qualifierExpression instanceof PsiReferenceExpression) {
final PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve();
if (resolve instanceof PsiParameter && ArrayUtil.find(parameters, resolve) > -1 && ((PsiParameter)resolve).getTypeElement() == null) {
return getClassReferenceName(nonAmbiguousContainingClass);
}
}
final PsiType qualifierExpressionType = qualifierExpression.getType();
return qualifierExpressionType != null ? qualifierExpressionType.getCanonicalText() : getClassReferenceName(nonAmbiguousContainingClass);
}
private static String getClassReferenceName(PsiClass containingClass) {
final String qualifiedName = containingClass.getQualifiedName();
return qualifiedName != null ? qualifiedName : containingClass.getName();
@@ -0,0 +1,29 @@
// "Replace lambda with method reference" "true"
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
class Box<T>
{
public Box(T value)
{
this._value = value;
}
private final T _value;
public T getValue()
{
return this._value;
}
{
List<Box<String>> l1 = new ArrayList<>();
l1.add(new Box<>("Foo"));
l1.add(new Box<>("Bar"));
List<String> l3 = l1.stream()
.map(Box::getValue)
.collect(Collectors.toList());
}
}
@@ -0,0 +1,23 @@
// "Replace lambda with method reference" "true"
import java.util.function.Function;
class Box<T>
{
public Box(T value)
{
this._value = value;
}
private final T _value;
public T getValue()
{
return this._value;
}
{
foo(Box<String>::getValue);
}
<K> void foo(Function<Box<K>, K> f){}
}
@@ -0,0 +1,29 @@
// "Replace lambda with method reference" "true"
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
class Box<T>
{
public Box(T value)
{
this._value = value;
}
private final T _value;
public T getValue()
{
return this._value;
}
{
List<Box<String>> l1 = new ArrayList<>();
l1.add(new Box<>("Foo"));
l1.add(new Box<>("Bar"));
List<String> l3 = l1.stream()
.map((t) -> t.get<caret>Value())
.collect(Collectors.toList());
}
}
@@ -0,0 +1,23 @@
// "Replace lambda with method reference" "true"
import java.util.function.Function;
class Box<T>
{
public Box(T value)
{
this._value = value;
}
private final T _value;
public T getValue()
{
return this._value;
}
{
foo((Box<String> t) -> t.get<caret>Value());
}
<K> void foo(Function<Box<K>, K> f){}
}
@@ -17,6 +17,8 @@ package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,4 +38,8 @@ public class Lambda2MethodReferenceInspectionTest extends LightQuickFixParameter
return "/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference";
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk18();
}
}