new overload resolution: remember candidate when argument type is to be calculated (IDEA-137921)

This commit is contained in:
Anna Kozlova
2015-03-20 20:08:50 +01:00
parent f4cf2a934c
commit 858119b775
4 changed files with 60 additions and 42 deletions
@@ -115,34 +115,23 @@ public class MethodCandidateInfo extends CandidateInfo{
if (myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
return getApplicabilityLevel();
}
@ApplicabilityLevelConstant int level;
final PsiSubstitutor substitutor = getSubstitutor(false);
Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
if (map == null) {
map = ContainerUtil.createConcurrentWeakMap();
CURRENT_CANDIDATE.set(map);
}
final PsiMethod method = getElement();
final CurrentCandidateProperties properties = new CurrentCandidateProperties(method, substitutor, isVarargs(), true);
final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), properties);
try {
PsiType[] argumentTypes = getArgumentTypes();
if (argumentTypes == null) {
return ApplicabilityLevel.NOT_APPLICABLE;
}
@ApplicabilityLevelConstant int level = computeForOverloadedCandidate(new Computable<Integer>() {
@Override
public Integer compute() {
PsiType[] argumentTypes = getArgumentTypes();
if (argumentTypes == null) {
return ApplicabilityLevel.NOT_APPLICABLE;
}
level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel);
if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) {
return ApplicabilityLevel.NOT_APPLICABLE;
int level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel);
if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) {
return ApplicabilityLevel.NOT_APPLICABLE;
}
return level;
}
}
finally {
if (alreadyThere == null) {
map.remove(getMarkerList());
} else {
map.put(getMarkerList(), alreadyThere);
}
}
}, substitutor);
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(new Computable<PsiSubstitutor>() {
@Override
public PsiSubstitutor compute() {
@@ -154,6 +143,34 @@ public class MethodCandidateInfo extends CandidateInfo{
return level;
}
public PsiType[] getPertinentArgumentTypes() {
return computeForOverloadedCandidate(new Computable<PsiType[]>() {
public PsiType[] compute() {
return getArgumentTypes();
}
}, getSubstitutor(false));
}
private <T> T computeForOverloadedCandidate(final Computable<T> computable, final PsiSubstitutor substitutor) {
Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
if (map == null) {
map = ContainerUtil.createConcurrentWeakMap();
CURRENT_CANDIDATE.set(map);
}
final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(),
new CurrentCandidateProperties(getElement(), substitutor, isVarargs(), true));
try {
return computable.compute();
}
finally {
if (alreadyThere == null) {
map.remove(getMarkerList());
} else {
map.put(getMarkerList(), alreadyThere);
}
}
}
@NotNull
public PsiSubstitutor getSiteSubstitutor() {
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
@@ -422,16 +422,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
(method.getCurrentFileResolveScope() instanceof PsiImportStaticStatement ? 0 : 1);
}
@NotNull
private PsiType[] getActualParameterTypes() {
PsiType[] types = myActualParameterTypes;
if (types == null) {
LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList);
myActualParameterTypes = types = getArgumentTypes();
}
return types;
}
private int getActualParametersLength() {
if (myActualParameterTypes == null) {
LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList);
@@ -440,11 +430,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
return myActualParameterTypes.length;
}
@NotNull
protected PsiType[] getArgumentTypes() {
return ((PsiExpressionList)myArgumentsList).getExpressionTypes();
}
private enum Specifics {
FIRST,
SECOND,
@@ -509,20 +494,23 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
boolean sameBoxing = true;
int[] boxingHappened = new int[2];
final PsiType[] argTypes1 = myActualParameterTypes != null ? myActualParameterTypes : info1.getPertinentArgumentTypes();
final PsiType[] argTypes2 = myActualParameterTypes != null ? myActualParameterTypes : info2.getPertinentArgumentTypes();
for (int i = 0; i < types1.length; i++) {
ProgressManager.checkCanceled();
PsiType type1 = classSubstitutor1.substitute(types1[i]);
PsiType type2 = classSubstitutor2.substitute(types2[i]);
PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null;
final PsiType argType1 = i < getActualParametersLength() ? argTypes1[i] : null;
final PsiType argType2 = i < getActualParametersLength() ? argTypes2[i] : null;
boolean boxingInFirst = false;
if (isBoxingHappened(argType, type1, languageLevel)) {
if (isBoxingHappened(argType1, type1, languageLevel)) {
boxingHappened[0] += 1;
boxingInFirst = true;
}
boolean boxingInSecond = false;
if (isBoxingHappened(argType, type2, languageLevel)) {
if (isBoxingHappened(argType2, type2, languageLevel)) {
boxingHappened[1] += 1;
boxingInSecond = true;
}
@@ -0,0 +1,9 @@
import java.lang.String;
abstract class Test {
abstract <T> T get();
void foo() {
String.valueOf(get());
}
}
@@ -98,6 +98,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
}).assertTiming();
}
public void testMultipleOverloadsWithNestedGeneric() throws Exception {
doTest(false);
}
private void doTest() {
doTest(true);
}