mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 21:11:28 +07:00
new inference: nothing should be cached during overload resolution (IDEA-136759)
This commit is contained in:
@@ -116,48 +116,36 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
return getApplicabilityLevel();
|
||||
}
|
||||
@ApplicabilityLevelConstant int level;
|
||||
Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
|
||||
@Override
|
||||
public Integer compute() {
|
||||
if (PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
|
||||
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;
|
||||
}
|
||||
|
||||
final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel);
|
||||
if (!isVarargs() && applicabilityLevel < ApplicabilityLevel.FIXED_ARITY) {
|
||||
return ApplicabilityLevel.NOT_APPLICABLE;
|
||||
}
|
||||
return applicabilityLevel;
|
||||
}
|
||||
finally {
|
||||
if (alreadyThere == null) {
|
||||
map.remove(getMarkerList());
|
||||
} else {
|
||||
map.put(getMarkerList(), alreadyThere);
|
||||
}
|
||||
}
|
||||
}
|
||||
return getApplicabilityLevelInner();
|
||||
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;
|
||||
}
|
||||
|
||||
});
|
||||
if (boxedLevel == null) {
|
||||
return getApplicabilityLevel();
|
||||
level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel);
|
||||
if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) {
|
||||
return ApplicabilityLevel.NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (alreadyThere == null) {
|
||||
map.remove(getMarkerList());
|
||||
} else {
|
||||
map.put(getMarkerList(), alreadyThere);
|
||||
}
|
||||
}
|
||||
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(false)) {
|
||||
level = ApplicabilityLevel.NOT_APPLICABLE;
|
||||
}
|
||||
level = boxedLevel;
|
||||
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(false)) level = ApplicabilityLevel.NOT_APPLICABLE;
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
@@ -396,8 +396,17 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return parent instanceof PsiNewExpression ? ((PsiNewExpression)parent).getArgumentList() : super.getMarkerList();
|
||||
}
|
||||
};
|
||||
if (!varargs && staticFactoryMethod.isVarArgs() && staticFactoryCandidateInfo.getPertinentApplicabilityLevel() < MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY) {
|
||||
return inferTypeParametersForStaticFactory(staticFactoryMethod, expression, parent, true);
|
||||
if (!varargs && staticFactoryMethod.isVarArgs()) {
|
||||
final Computable<Integer> computable = new Computable<Integer>() {
|
||||
@Override
|
||||
public Integer compute() {
|
||||
return staticFactoryCandidateInfo.getPertinentApplicabilityLevel();
|
||||
}
|
||||
};
|
||||
final Integer applicability = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(expression, true, computable);
|
||||
if ((applicability != null ? applicability : staticFactoryCandidateInfo.getApplicabilityLevel()) < MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY) {
|
||||
return inferTypeParametersForStaticFactory(staticFactoryMethod, expression, parent, true);
|
||||
}
|
||||
}
|
||||
return staticFactoryCandidateInfo.getSubstitutor();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.psi.impl.source.tree.java;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
@@ -212,7 +213,7 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts) {
|
||||
protected CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts) {
|
||||
if (mySignature == null) return null;
|
||||
|
||||
if (conflicts.size() > 1) checkSameSignatures(conflicts);
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
|
||||
@@ -68,7 +69,17 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
}
|
||||
|
||||
@Override
|
||||
public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts){
|
||||
public final CandidateInfo resolveConflict(@NotNull final List<CandidateInfo> conflicts){
|
||||
return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, true, new Computable<CandidateInfo>() {
|
||||
@Override
|
||||
public CandidateInfo compute() {
|
||||
return guardedOverloadResolution(conflicts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts) {
|
||||
if (conflicts.isEmpty()) return null;
|
||||
if (conflicts.size() == 1) return conflicts.get(0);
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Test {
|
||||
|
||||
public Long getKey() {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
public static void main(Stream<Test> stream) {
|
||||
stream.map(s -> Inner.of(Test::getKey, s));
|
||||
}
|
||||
|
||||
public static final class Inner<K> {
|
||||
public static <T> Inner<T> of(final Object key, final Test value) {return null;}
|
||||
public static <T> Inner<T> of(final Function< T, Long> keyMapper, final Test value) {return null;}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Test {
|
||||
|
||||
public Long getKey() {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
public static void main(Stream<Test> stream) {
|
||||
stream.map(s -> Inner.of(Test::get<ref>Key, s));
|
||||
}
|
||||
|
||||
public static final class Inner<K> {
|
||||
public static <T> Inner<T> of(final Object key, final Test value) {return null;}
|
||||
public static <T> Inner<T> of(final Function< T, Long> keyMapper, final Test value) {return null;}
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,13 @@ package com.intellij.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/newLambda";
|
||||
|
||||
@@ -178,6 +177,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA136759() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
@@ -194,7 +197,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
/*
|
||||
public static Test suite() {
|
||||
final TestSuite suite = new TestSuite();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
suite.addTestSuite(NewLambdaHighlightingTest.class);
|
||||
}
|
||||
return suite;
|
||||
|
||||
@@ -32,11 +32,15 @@ public class TypeInference18Test extends ResolveTestCase {
|
||||
}
|
||||
|
||||
public void testSecondConflictResolution() throws Exception {
|
||||
doTestMethodCall();
|
||||
}
|
||||
|
||||
public void testCachedSubstitutionDuringOverloadResolution() throws Exception {
|
||||
PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java");
|
||||
assertNotNull(ref);
|
||||
PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethodCallExpression.class);
|
||||
PsiMethodReferenceExpression methodCallExpression = PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethodReferenceExpression.class, false);
|
||||
assertNotNull(methodCallExpression);
|
||||
assertNotNull(methodCallExpression.resolveMethod());
|
||||
assertNotNull(methodCallExpression.resolve());
|
||||
}
|
||||
|
||||
private LanguageLevel myOldLanguageLevel;
|
||||
@@ -55,6 +59,14 @@ public class TypeInference18Test extends ResolveTestCase {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void doTestMethodCall() throws Exception {
|
||||
PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java");
|
||||
assertNotNull(ref);
|
||||
PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethodCallExpression.class);
|
||||
assertNotNull(methodCallExpression);
|
||||
assertNotNull(methodCallExpression.resolveMethod());
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java");
|
||||
assertNotNull(ref);
|
||||
|
||||
Reference in New Issue
Block a user