java completion: suggest Objects::nonNull where applicable (IDEA-192789)

This commit is contained in:
peter
2018-06-04 18:18:35 +02:00
parent a9de3ce543
commit cb981a0ef5
4 changed files with 48 additions and 6 deletions
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -257,16 +256,34 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
List<LookupElement> result = new ArrayList<>();
for (PsiClass psiClass : JBIterable.generate(PsiTreeUtil.getParentOfType(originalPosition, PsiClass.class), PsiClass::getContainingClass)) {
for (PsiMethod psiMethod : psiClass.getMethods()) {
if (psiMethod.hasModifierProperty(PsiModifier.STATIC) &&
hasAppropriateReturnType(expectedReturnType, psiMethod, substitutor) &&
isSignatureAppropriate(psiMethod, params, substitutor, 0, originalPosition)) {
if (isMatchingStaticMethod(params, originalPosition, substitutor, expectedReturnType, psiMethod)) {
result.add(createMethodRefOnClass(functionalInterfaceType, psiMethod, psiClass));
}
}
}
PsiClass objects = JavaPsiFacade.getInstance(originalPosition.getProject())
.findClass(CommonClassNames.JAVA_UTIL_OBJECTS, originalPosition.getResolveScope());
if (objects != null) {
for (PsiMethod nonNull : objects.getMethods()) {
if (isMatchingStaticMethod(params, originalPosition, substitutor, expectedReturnType, nonNull)) {
result.add(createMethodRefOnClass(functionalInterfaceType, nonNull, objects));
}
}
}
return result;
}
private static boolean isMatchingStaticMethod(PsiParameter[] params,
PsiElement originalPosition,
PsiSubstitutor substitutor,
PsiType expectedReturnType, PsiMethod psiMethod) {
return psiMethod.hasModifierProperty(PsiModifier.STATIC) &&
hasAppropriateReturnType(expectedReturnType, psiMethod, substitutor) &&
isSignatureAppropriate(psiMethod, params, substitutor, 0, originalPosition);
}
private static List<LookupElement> collectVariantsByReceiver(boolean prioritize,
PsiType functionalInterfaceType,
PsiParameter[] params,
@@ -310,7 +327,7 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
if (parameterList.getParametersCount() == params.length - offset) {
final PsiParameter[] referenceMethodParams = parameterList.getParameters();
for (int i = 0; i < params.length - offset; i++) {
if (!Comparing.equal(referenceMethodParams[i].getType(), substitutor.substitute(params[i + offset].getType()))) {
if (!TypeConversionUtil.isAssignable(referenceMethodParams[i].getType(), substitutor.substitute(params[i + offset].getType()))) {
return false;
}
}
@@ -0,0 +1,12 @@
import java.util.*;
class MyTest {
public interface Child {}
{
List<Child> children = new ArrayList<>();
children.stream().filter(Objects::nonNull)<caret>
}
}
@@ -0,0 +1,12 @@
import java.util.*;
class MyTest {
public interface Child {}
{
List<Child> children = new ArrayList<>();
children.stream().filter(non<caret>)
}
}
@@ -168,6 +168,7 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase {
public void testNoAnonymousOuterMethodReference() { doAntiTest(); }
public void testMethodReferenceOnAncestor() { doTest(true); }
public void testObjectsNonNull() { doTest(true); }
public void testNoLambdaSuggestionForGenericsFunctionalInterfaceMethod() {
configureByFile("/" + getTestName(false) + ".java");
@@ -274,7 +275,7 @@ public void testConvertToObjectStream() {
public void testPreferLambdaOverGenericGetter() {
configureByTestName();
myFixture.assertPreferredCompletionItems(0, "s -> ", "isEmpty", "getSomeGenericValue");
myFixture.assertPreferredCompletionItems(0, "s -> ", "isEmpty", "isNull", "nonNull", "getSomeGenericValue");
}
public void testNoInaccessibleConstructorRef() {