mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
[java] method references overload resolution (IDEA-276614; IDEA-276613)
GitOrigin-RevId: a12beac2ccd0ecc2512c8b9feab5e04a868c3935
This commit is contained in:
committed by
intellij-monorepo-bot
parent
32ec2d9a30
commit
7c1c056980
@@ -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.impl.source.tree.java;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -235,12 +235,21 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
|
||||
List<CandidateInfo> firstCandidates = new ArrayList<>();
|
||||
List<CandidateInfo> secondCandidates = new ArrayList<>();
|
||||
boolean thereIsStaticInTheFirst = false;
|
||||
boolean thereIsNonStaticInTheSecond = false;
|
||||
|
||||
for (CandidateInfo conflict : conflicts) {
|
||||
if (!(conflict instanceof MethodCandidateInfo)) continue;
|
||||
Boolean applicableByFirstSearch = isApplicableByFirstSearch(conflict, argTypes, hasReceiver, myReferenceExpression, myFunctionalMethodVarArgs, myInterfaceMethod);
|
||||
if (applicableByFirstSearch != null) {
|
||||
(applicableByFirstSearch ? firstCandidates : secondCandidates).add(conflict);
|
||||
boolean isStatic = isStaticMethod(conflict);
|
||||
if (isStatic && applicableByFirstSearch) {
|
||||
thereIsStaticInTheFirst = true;
|
||||
}
|
||||
if (!isStatic && !applicableByFirstSearch) {
|
||||
thereIsNonStaticInTheSecond = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,11 +268,13 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
}
|
||||
|
||||
CandidateInfo candidateInfo = resolveConflicts(firstCandidates, secondCandidates, map, MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY);
|
||||
candidateInfo = checkStaticNonStaticConflict(candidateInfo, firstCandidates, secondCandidates, thereIsStaticInTheFirst, thereIsNonStaticInTheSecond);
|
||||
if (candidateInfo != null) {
|
||||
return candidateInfo;
|
||||
}
|
||||
|
||||
candidateInfo = resolveConflicts(firstCandidates, secondCandidates, map, MethodCandidateInfo.ApplicabilityLevel.VARARGS);
|
||||
candidateInfo = checkStaticNonStaticConflict(candidateInfo, firstCandidates, secondCandidates, thereIsStaticInTheFirst, thereIsNonStaticInTheSecond);
|
||||
if (candidateInfo != null) {
|
||||
return candidateInfo;
|
||||
}
|
||||
@@ -278,6 +289,28 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
return null;
|
||||
}
|
||||
|
||||
private CandidateInfo checkStaticNonStaticConflict(CandidateInfo candidateInfo,
|
||||
@NotNull List<CandidateInfo> firstCandidates,
|
||||
@NotNull List<CandidateInfo> secondCandidates,
|
||||
boolean thereIsStaticInTheFirst,
|
||||
boolean thereIsNonStaticInTheSecond) {
|
||||
if (candidateInfo == null ||
|
||||
!myQualifierResolveResult.isReferenceTypeQualified() ||
|
||||
!(myReferenceExpression.getReferenceNameElement() instanceof PsiIdentifier)) {
|
||||
return candidateInfo;
|
||||
}
|
||||
boolean isStatic = isStaticMethod(candidateInfo);
|
||||
if (isStatic && !thereIsNonStaticInTheSecond && firstCandidates.contains(candidateInfo) ||
|
||||
!isStatic && !thereIsStaticInTheFirst && secondCandidates.contains(candidateInfo)) {
|
||||
return candidateInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isStaticMethod(@NotNull CandidateInfo candidateInfo) {
|
||||
return ((MethodCandidateInfo) candidateInfo).getElement().hasModifierProperty(PsiModifier.STATIC);
|
||||
}
|
||||
|
||||
private static Boolean isApplicableByFirstSearch(@NotNull CandidateInfo conflict,
|
||||
PsiType @NotNull [] functionalInterfaceParamTypes,
|
||||
boolean hasReceiver,
|
||||
@@ -307,6 +340,9 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else if (hasReceiver && varargs &&
|
||||
isCorrectAssignment(parameterTypes, functionalInterfaceParamTypes, interfaceMethod, true, conflict, 1)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class Test {
|
||||
|
||||
static class A {
|
||||
void foo(A... as) {}
|
||||
static void foo(A a) {}
|
||||
}
|
||||
|
||||
interface I {
|
||||
void bar(A a);
|
||||
}
|
||||
|
||||
static void test() {
|
||||
I i = A::<error descr="Reference to 'foo' is ambiguous, both 'foo(A)' and 'foo(A...)' match">foo</error>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Test {
|
||||
|
||||
static class A {
|
||||
void foo() {}
|
||||
static void foo(A a, A... as) {}
|
||||
}
|
||||
|
||||
interface I {
|
||||
void bar(A a);
|
||||
}
|
||||
|
||||
static void test() {
|
||||
I i = A::<error descr="Reference to 'foo' is ambiguous, both 'foo(A, A...)' and 'foo()' match">foo</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;
|
||||
@@ -86,6 +72,8 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
.forEach(info -> Assert.assertEquals("<html>Reference to 'm' is ambiguous, both 'm(Test, String)' and 'm(String)' match</html>",
|
||||
info.getToolTip()));
|
||||
}
|
||||
public void testStaticWithVarargsNonStaticReferenceTypeAmbiguity() { doTest(); }
|
||||
public void testStaticNonStaticWithVarargsReferenceTypeAmbiguity() { doTest(); }
|
||||
public void testSuperClassPotentiallyApplicableMembers() { doTest(); }
|
||||
public void testExactMethodReferencePertinentToApplicabilityCheck() { doTest(); }
|
||||
public void testAmbiguityVarargs() { doTest(); }
|
||||
|
||||
Reference in New Issue
Block a user