mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
if client iterates through candidates of call resolve results and start inference for one of them, then cached top level session should be rejected if it corresponds to another candidate
This commit is contained in:
@@ -371,6 +371,9 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If iterated through all candidates, should be called under {@link #ourOverloadGuard} guard so results won't be cached on the top level call
|
||||
*/
|
||||
@NotNull
|
||||
public PsiSubstitutor inferTypeArguments(@NotNull final ParameterTypeInferencePolicy policy,
|
||||
@NotNull final PsiExpression[] arguments,
|
||||
|
||||
+17
-1
@@ -79,7 +79,7 @@ public class InferenceSessionContainer {
|
||||
});
|
||||
if (topLevelCall != null) {
|
||||
|
||||
final InferenceSession session;
|
||||
InferenceSession session;
|
||||
if (MethodCandidateInfo.isOverloadCheck() || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty() || LambdaUtil.isLambdaParameterCheck()) {
|
||||
session = startTopLevelInference(topLevelCall);
|
||||
}
|
||||
@@ -91,6 +91,22 @@ public class InferenceSessionContainer {
|
||||
return new Result<InferenceSession>(startTopLevelInference(topLevelCall), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
if (session != null) {
|
||||
//reject cached top level session if it was based on wrong candidate: check nested session if candidate (it's type parameters) are the same
|
||||
//such situations are avoided when overload resolution is performed (MethodCandidateInfo.isOverloadCheck above)
|
||||
//but situations when client code iterates through PsiResolveHelper.getReferencedMethodCandidates or similar are impossible to guess
|
||||
final Map<PsiElement, InferenceSession> sessions = session.getInferenceSessionContainer().myNestedSessions;
|
||||
final InferenceSession childSession = sessions.get(parent);
|
||||
if (childSession != null) {
|
||||
for (PsiTypeParameter parameter : typeParameters) {
|
||||
if (!childSession.getInferenceSubstitution().getSubstitutionMap().containsKey(parameter)) {
|
||||
session = startTopLevelInference(topLevelCall);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import java.util.function.Function;
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
void m(Set<String> i) {
|
||||
final List<String> getters = new ArrayList<String>(ma<caret>p(i, new Function<String, String>() {
|
||||
@Override
|
||||
public String apply(String propertyName) {
|
||||
return propertyName;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public static <T,V> List<V> map(Iterable<? extends T> iterable, Function<T, V> mapping) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T,V> List<V> map(Collection<? extends T> iterable, Function<T, V> mapping) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+20
@@ -20,6 +20,8 @@ import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -88,6 +90,24 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
doTestConfiguredFile(false, false, filePath);
|
||||
}
|
||||
|
||||
public void testRejectCachedTopLevelSessionIfItCorrespondsToTheWrongOverload() throws Exception {
|
||||
final String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
configureByFile(filePath);
|
||||
PsiMethodCallExpression methodCall =
|
||||
PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiMethodCallExpression.class);
|
||||
assertNotNull(methodCall);
|
||||
final PsiResolveHelper helper = JavaPsiFacade.getInstance(methodCall.getProject()).getResolveHelper();
|
||||
CandidateInfo[] candidates = helper.getReferencedMethodCandidates(methodCall, false, true);
|
||||
for (CandidateInfo candidate : candidates) {
|
||||
if (candidate instanceof MethodCandidateInfo) {
|
||||
//try to cache top level session
|
||||
candidate.getSubstitutor();
|
||||
}
|
||||
}
|
||||
|
||||
doTestConfiguredFile(false, false, filePath);
|
||||
}
|
||||
|
||||
private void doTestCachedUnresolved() {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
PsiMethodCallExpression callExpression =
|
||||
|
||||
Reference in New Issue
Block a user