extend trivial method reference to support lambdas, convertible to method references

This commit is contained in:
Anna.Kozlova
2017-08-07 15:53:11 +02:00
parent 2a21a01d70
commit fe61fc50e0
8 changed files with 69 additions and 15 deletions

View File

@@ -0,0 +1,7 @@
// "Replace with qualifier" "true"
class Test {
void f(Runnable runnable) {
Runnable r = runnable;
}
}

View File

@@ -0,0 +1,7 @@
// "Replace with qualifier" "true"
class Test {
void f(Runnable runnable) {
Runnable r = () -> runna<caret>ble.run();
}
}

View File

@@ -0,0 +1,8 @@
// "Replace with qualifier" "false"
import java.util.function.Predicate;
class Test {
void foo(Predicate<String> p){
Predicate<String> stringPredicate = t -> p.te<caret>st("");
}
}

View File

@@ -16,17 +16,17 @@
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.FunctionalExpressionCanBeFoldedInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.TrivialMethodReferenceInspection;
import org.jetbrains.annotations.NotNull;
public class TrivialMethodReferenceInspectionTest extends LightQuickFixParameterizedTestCase {
public class FunctionalExpressionCanBeFoldedInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{
new TrivialMethodReferenceInspection(),
new FunctionalExpressionCanBeFoldedInspection(),
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,9 @@ import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class TrivialMethodReferenceInspection extends BaseJavaBatchLocalInspectionTool {
import java.util.function.Supplier;
public class FunctionalExpressionCanBeFoldedInspection extends BaseJavaBatchLocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
@@ -31,18 +33,39 @@ public class TrivialMethodReferenceInspection extends BaseJavaBatchLocalInspecti
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
final PsiExpression qualifierExpression = expression.getQualifierExpression();
final PsiElement referenceNameElement = expression.getReferenceNameElement();
doCheckCall(expression, () -> expression.resolve(), qualifierExpression, referenceNameElement,
"Method reference can be replaced with qualifier");
}
@Override
public void visitLambdaExpression(PsiLambdaExpression lambdaExpression) {
PsiElement body = lambdaExpression.getBody();
PsiExpression asMethodReference = LambdaCanBeMethodReferenceInspection
.canBeMethodReferenceProblem(body, lambdaExpression.getParameterList().getParameters(), lambdaExpression.getFunctionalInterfaceType(), null);
if (asMethodReference instanceof PsiMethodCallExpression) {
PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)asMethodReference).getMethodExpression();
PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
doCheckCall(lambdaExpression, () -> ((PsiMethodCallExpression)asMethodReference).resolveMethod(), qualifierExpression, asMethodReference,
"Lambda can be replaced with call qualifier");
}
}
private void doCheckCall(PsiFunctionalExpression expression,
Supplier<PsiElement> resolver,
PsiExpression qualifierExpression,
PsiElement referenceNameElement,
final String errorMessage) {
if (qualifierExpression != null && referenceNameElement != null && !(qualifierExpression instanceof PsiSuperExpression)) {
final PsiType qualifierType = qualifierExpression.getType();
if (qualifierType != null) {
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
if (interfaceMethod != null) {
final PsiElement resolve = expression.resolve();
final PsiElement resolve = resolver.get();
if (resolve instanceof PsiMethod &&
(interfaceMethod == resolve || MethodSignatureUtil.isSuperMethod(interfaceMethod, (PsiMethod)resolve)) &&
TypeConversionUtil.isAssignable(functionalInterfaceType, qualifierType)) {
holder.registerProblem(referenceNameElement, "Method reference can be replaced with qualifier",
new ReplaceMethodRefWithQualifierFix());
holder.registerProblem(referenceNameElement, errorMessage, new ReplaceMethodRefWithQualifierFix());
}
}
}
@@ -69,6 +92,15 @@ public class TrivialMethodReferenceInspection extends BaseJavaBatchLocalInspecti
parent.replace(qualifierExpression);
}
}
else if (parent instanceof PsiLambdaExpression) {
PsiExpression expression = LambdaUtil.extractSingleExpressionFromBody(((PsiLambdaExpression)parent).getBody());
if (expression instanceof PsiMethodCallExpression) {
PsiExpression qualifierExpression = ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression();
if (qualifierExpression != null) {
parent.replace(qualifierExpression);
}
}
}
}
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
This inspection reports method references or lambda expressions which point to a method of their own functional interface type and hence can be replaced with their qualifiers.
</body>
</html>

View File

@@ -1,5 +0,0 @@
<html>
<body>
This inspection reports method references which point to a method of their own functional interface type and hence can be replaced with their qualifiers.
</body>
</html>

View File

@@ -818,9 +818,9 @@
<localInspection groupPath="Java" language="JAVA" shortName="InvalidComparatorMethodReference" displayName="Invalid method reference used for Comparator"
groupKey="group.names.probable.bugs" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.InvalidComparatorMethodReferenceInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="TrivialMethodReference" displayName="Method reference can be replaced with its qualifier"
<localInspection groupPath="Java" language="JAVA" shortName="FunctionalExpressionCanBeFolded" displayName="Functional expression can be folded"
groupKey="group.names.declaration.redundancy" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.TrivialMethodReferenceInspection"/>
implementationClass="com.intellij.codeInspection.FunctionalExpressionCanBeFoldedInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="TrivialFunctionalExpressionUsage" displayName="Trivial usage of functional expression"
groupKey="group.names.declaration.redundancy" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.TrivialFunctionalExpressionUsageInspection"/>