mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
lambda: use incomplete substitutor when calc functional interface (IDEA-97038)
This commit is contained in:
@@ -18,6 +18,7 @@ package com.intellij.psi;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
@@ -396,11 +397,11 @@ public class LambdaUtil {
|
||||
if (lambdaIdx > -1) {
|
||||
|
||||
if (!tryToSubstitute) {
|
||||
final Map<PsiElement, PsiMethod> currentMethodCandidates = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
final PsiMethod method = currentMethodCandidates != null ? currentMethodCandidates.get(parent) : null;
|
||||
final Map<PsiElement,Pair<PsiMethod,PsiSubstitutor>> currentMethodCandidates = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
final Pair<PsiMethod, PsiSubstitutor> method = currentMethodCandidates != null ? currentMethodCandidates.get(parent) : null;
|
||||
if (method != null) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
return lambdaIdx < parameters.length ? parameters[lambdaIdx].getType() : null;
|
||||
final PsiParameter[] parameters = method.first.getParameterList().getParameters();
|
||||
return lambdaIdx < parameters.length ? method.second.substitute(parameters[lambdaIdx].getType()) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,8 +580,14 @@ public class LambdaUtil {
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiCall) {
|
||||
final Map<PsiElement, PsiMethod> map = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
myMethod = map != null ? map.get(parent) : null;
|
||||
final Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
if (map != null) {
|
||||
final Pair<PsiMethod, PsiSubstitutor> pair = map.get(parent);
|
||||
myMethod = pair != null ? pair.first : null;
|
||||
}
|
||||
else {
|
||||
myMethod = null;
|
||||
}
|
||||
if (myMethod == null) {
|
||||
myMethod = ((PsiCall)gParent).resolveMethod();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.infos;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
@@ -31,7 +32,7 @@ import java.util.Set;
|
||||
* @author ik, dsl
|
||||
*/
|
||||
public class MethodCandidateInfo extends CandidateInfo{
|
||||
public static final ThreadLocal<Map<PsiElement, PsiMethod>> CURRENT_CANDIDATE = new ThreadLocal<Map<PsiElement, PsiMethod>>();
|
||||
public static final ThreadLocal<Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>>> CURRENT_CANDIDATE = new ThreadLocal<Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>>>();
|
||||
@ApplicabilityLevelConstant private int myApplicabilityLevel = 0;
|
||||
private final PsiElement myArgumentList;
|
||||
private final PsiType[] myArgumentTypes;
|
||||
@@ -96,15 +97,15 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
|
||||
PsiMethod method = getElement();
|
||||
if (myTypeArguments == null) {
|
||||
Map<PsiElement, PsiMethod> map;
|
||||
Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>> map;
|
||||
synchronized (LOCK) {
|
||||
map = CURRENT_CANDIDATE.get();
|
||||
if (map == null) {
|
||||
map = new ConcurrentWeakHashMap<PsiElement, PsiMethod>();
|
||||
map = new ConcurrentWeakHashMap<PsiElement, Pair<PsiMethod, PsiSubstitutor>>();
|
||||
CURRENT_CANDIDATE.set(map);
|
||||
}
|
||||
}
|
||||
map.put(myArgumentList, getElement());
|
||||
map.put(myArgumentList, Pair.create(getElement(), incompleteSubstitutor));
|
||||
try {
|
||||
|
||||
final Set<PsiParameterList> lists = LambdaUtil.ourParams.get();
|
||||
|
||||
@@ -588,14 +588,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
final PsiElement parent = skipParenthesizedExprUp(lambdaExpression.getParent());
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
final PsiExpressionList expressionList = (PsiExpressionList)parent;
|
||||
final Map<PsiElement,PsiMethod> methodMap = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
final PsiMethod method = methodMap != null ? methodMap.get(expressionList) : null;
|
||||
if (method != null) {
|
||||
final Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>> methodMap = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
final Pair<PsiMethod, PsiSubstitutor> pair = methodMap != null ? methodMap.get(expressionList) : null;
|
||||
if (pair != null) {
|
||||
final int i = LambdaUtil.getLambdaIdx(expressionList, lambdaExpression);
|
||||
if (i < 0) return null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
final PsiParameter[] parameters = pair.first.getParameterList().getParameters();
|
||||
if (parameters.length <= i) return null;
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, parameters[i].getType(), lowerBound);
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, pair.second.substitute(parameters[i].getType()), lowerBound);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class Test {
|
||||
static class List<T> {
|
||||
public Stream<T> stream() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface IntFunction<T> {
|
||||
public int applyAsInt(T t);
|
||||
}
|
||||
|
||||
static class Stream<E> {
|
||||
public Stream map(IntFunction<? super E> mapper) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(List<AtomicInteger> list) {
|
||||
list.stream().map(atomic -> atomic.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUseIncompleteParentSubstitutor() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user