mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
[java] [overload resolution] actively prune lambdas with wrong number of parameters (IDEA-279558)
GitOrigin-RevId: e6fdb4b920ec38c8f51cef14c33bc2c26321dd09
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6698b10397
commit
1b3bddda3b
@@ -23,17 +23,26 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
* Utilities around java 8 functional expressions.
|
||||
*/
|
||||
public final class LambdaUtil {
|
||||
private static final Logger LOG = Logger.getInstance(LambdaUtil.class);
|
||||
|
||||
public static @Nullable PsiType getFunctionalInterfaceReturnType(PsiFunctionalExpression expr) {
|
||||
/**
|
||||
* @return substituted return type of expression's SAM method
|
||||
*/
|
||||
public static @Nullable PsiType getFunctionalInterfaceReturnType(@NotNull PsiFunctionalExpression expr) {
|
||||
return getFunctionalInterfaceReturnType(expr.getFunctionalInterfaceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return substituted return type of method which corresponds to the {@code functionalInterfaceType} SAM,
|
||||
* null when {@code functionalInterfaceType} doesn't correspond to functional interface type
|
||||
*/
|
||||
public static @Nullable PsiType getFunctionalInterfaceReturnType(@Nullable PsiType functionalInterfaceType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(normalizeFunctionalType(functionalInterfaceType));
|
||||
PsiType functionalType = normalizeFunctionalType(functionalInterfaceType);
|
||||
if (!(functionalType instanceof PsiClassType)) return null;
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalType);
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
if (psiClass != null) {
|
||||
final MethodSignature methodSignature = getFunction(psiClass);
|
||||
@@ -45,9 +54,26 @@ public final class LambdaUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return abstract method of SAM interface which corresponds to {@code functionalInterfaceType}, null otherwise
|
||||
*/
|
||||
@Contract("null -> null")
|
||||
public static @Nullable PsiMethod getFunctionalInterfaceMethod(@Nullable PsiType functionalInterfaceType) {
|
||||
return getFunctionalInterfaceMethod(PsiUtil.resolveGenericsClassInType(normalizeFunctionalType(functionalInterfaceType)));
|
||||
return getFunctionalInterfaceMethod(PsiUtil.resolveClassInClassTypeOnly(normalizeFunctionalType(functionalInterfaceType)));
|
||||
}
|
||||
|
||||
public static PsiMethod getFunctionalInterfaceMethod(@Nullable PsiElement element) {
|
||||
return element instanceof PsiFunctionalExpression ? getFunctionalInterfaceMethod(((PsiFunctionalExpression)element).getFunctionalInterfaceType()) : null;
|
||||
}
|
||||
|
||||
public static @Nullable PsiMethod getFunctionalInterfaceMethod(@NotNull PsiClassType.ClassResolveResult result) {
|
||||
return getFunctionalInterfaceMethod(result.getElement());
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
public static @Nullable PsiMethod getFunctionalInterfaceMethod(PsiClass aClass) {
|
||||
final MethodSignature methodSignature = getFunction(aClass);
|
||||
return methodSignature != null ? getMethod(aClass, methodSignature) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,27 +90,6 @@ public final class LambdaUtil {
|
||||
return functionalInterfaceType;
|
||||
}
|
||||
|
||||
public static PsiMethod getFunctionalInterfaceMethod(@Nullable PsiElement element) {
|
||||
if (element instanceof PsiFunctionalExpression) {
|
||||
final PsiType samType = ((PsiFunctionalExpression)element).getFunctionalInterfaceType();
|
||||
return getFunctionalInterfaceMethod(samType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @Nullable PsiMethod getFunctionalInterfaceMethod(@NotNull PsiClassType.ClassResolveResult result) {
|
||||
return getFunctionalInterfaceMethod(result.getElement());
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
public static @Nullable PsiMethod getFunctionalInterfaceMethod(PsiClass aClass) {
|
||||
final MethodSignature methodSignature = getFunction(aClass);
|
||||
if (methodSignature != null) {
|
||||
return getMethod(aClass, methodSignature);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PsiSubstitutor getSubstitutor(@NotNull PsiMethod method, @NotNull PsiClassType.ClassResolveResult resolveResult) {
|
||||
final PsiClass derivedClass = resolveResult.getElement();
|
||||
LOG.assertTrue(derivedClass != null);
|
||||
@@ -106,11 +111,7 @@ public final class LambdaUtil {
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean isFunctionalClass(PsiClass aClass) {
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return false;
|
||||
return getFunction(aClass) != null;
|
||||
}
|
||||
return false;
|
||||
return getFunction(aClass) != null;
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
@@ -173,14 +174,14 @@ public final class LambdaUtil {
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
public static @Nullable MethodSignature getFunction(final PsiClass psiClass) {
|
||||
public static @Nullable MethodSignature getFunction(@Nullable final PsiClass psiClass) {
|
||||
if (isPlainInterface(psiClass)) {
|
||||
return CachedValuesManager.getProjectPsiDependentCache(psiClass, LambdaUtil::calcFunction);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isPlainInterface(PsiClass psiClass) {
|
||||
private static boolean isPlainInterface(@Nullable PsiClass psiClass) {
|
||||
return psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.psi.infos;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -297,7 +297,13 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
return ThreeState.YES;
|
||||
}
|
||||
|
||||
if (!LambdaUtil.isFunctionalType(formalType)) {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(formalType);
|
||||
if (interfaceMethod == null) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
|
||||
if (expression instanceof PsiLambdaExpression &&
|
||||
((PsiLambdaExpression)expression).getParameterList().getParametersCount() != interfaceMethod.getParameterList().getParametersCount()) {
|
||||
return ThreeState.NO;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package p;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
class MyTest {
|
||||
void m(Predicate<String> p) {}
|
||||
void m(BiFunction<String, Integer, String> f) {}
|
||||
|
||||
{
|
||||
m((s, i) -> {//m should be resolved here
|
||||
if (s.equals("a")) {
|
||||
|
||||
}
|
||||
<error descr="Missing return statement">}</error>);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
@@ -281,6 +267,7 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testPotentialCompatibilityWithArrayCreation() { doTest(false);}
|
||||
public void testOverloadsWithOneNonCompatible() { doTest(false);}
|
||||
public void testOverloadedConstructors() { doTest(false);}
|
||||
public void testIncompleteLambdasWithDifferentSignatures() { doTest(false);}
|
||||
public void testTwoFunctionalInterfacesWithVarargs() { doTest(false);}
|
||||
public void testSecondSearchOverloadsBoxing() {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
|
||||
Reference in New Issue
Block a user