mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new inference: prohibit substitution during checked exception constraint processing
This commit is contained in:
@@ -16,11 +16,15 @@
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
|
||||
import com.intellij.psi.scope.processor.MethodResolverProcessor;
|
||||
import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
@@ -41,6 +45,7 @@ import java.util.*;
|
||||
*/
|
||||
public class ExceptionUtil {
|
||||
@NonNls private static final String CLONE_METHOD_NAME = "clone";
|
||||
public static final RecursionGuard ourThrowsGuard = RecursionManager.createGuard("checkedExceptionsGuard");
|
||||
|
||||
private ExceptionUtil() {}
|
||||
|
||||
@@ -417,7 +422,7 @@ public class ExceptionUtil {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
final PsiSubstitutor substitutor = getSubstitutor(result, methodCall);
|
||||
if (!isArrayClone(method, methodCall) && methodCall instanceof PsiMethodCallExpression) {
|
||||
final PsiFile containingFile = (containingMethod == null ? methodCall : containingMethod).getContainingFile();
|
||||
final MethodResolverProcessor processor = new MethodResolverProcessor((PsiMethodCallExpression)methodCall, containingFile);
|
||||
@@ -431,7 +436,7 @@ public class ExceptionUtil {
|
||||
if (element instanceof PsiMethod &&
|
||||
MethodSignatureUtil.areSignaturesEqual(method, (PsiMethod)element) &&
|
||||
!MethodSignatureUtil.isSuperMethod((PsiMethod)element, method)) {
|
||||
return Pair.create((PsiMethod)element, info.getSubstitutor());
|
||||
return Pair.create((PsiMethod)element, getSubstitutor(info, methodCall));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -456,6 +461,22 @@ public class ExceptionUtil {
|
||||
return getUnhandledExceptions(method, methodCall, topElement, substitutor);
|
||||
}
|
||||
|
||||
private static PsiSubstitutor getSubstitutor(final JavaResolveResult result, PsiCallExpression methodCall) {
|
||||
final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(methodCall, PsiLambdaExpression.class);
|
||||
final PsiSubstitutor substitutor;
|
||||
if (expression != null) {
|
||||
substitutor = ourThrowsGuard.doPreventingRecursion(expression, false, new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
return result.getSubstitutor();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
substitutor = result.getSubstitutor();
|
||||
}
|
||||
return substitutor == null ? ((MethodCandidateInfo)result).getSiteSubstitutor() : substitutor;
|
||||
}
|
||||
|
||||
public static void retainExceptions(List<PsiClassType> ex, List<PsiClassType> thrownEx) {
|
||||
final List<PsiClassType> replacement = new ArrayList<PsiClassType>();
|
||||
for (Iterator<PsiClassType> iterator = ex.iterator(); iterator.hasNext(); ) {
|
||||
|
||||
+11
-2
@@ -17,6 +17,7 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
|
||||
@@ -101,9 +102,17 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
|
||||
|
||||
final List<PsiType> thrownTypes = new ArrayList<PsiType>();
|
||||
if (myExpression instanceof PsiLambdaExpression) {
|
||||
PsiElement body = ((PsiLambdaExpression)myExpression).getBody();
|
||||
final PsiElement body = ((PsiLambdaExpression)myExpression).getBody();
|
||||
if (body != null) {
|
||||
thrownTypes.addAll(ExceptionUtil.getUnhandledExceptions(body));
|
||||
final List<PsiClassType> exceptions = ExceptionUtil.ourThrowsGuard.doPreventingRecursion(myExpression, false, new Computable<List<PsiClassType>>() {
|
||||
@Override
|
||||
public List<PsiClassType> compute() {
|
||||
return ExceptionUtil.getUnhandledExceptions(body);
|
||||
}
|
||||
});
|
||||
if (exceptions != null) {
|
||||
thrownTypes.addAll(exceptions);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
class Test {
|
||||
|
||||
interface A<T> {
|
||||
T m(T t);
|
||||
}
|
||||
|
||||
interface B<K> {
|
||||
List<K> l(K k) throws IOException;
|
||||
}
|
||||
|
||||
<F> F foo(A<F> a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<R> R bar(B<R> b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<Z> List<Z> baz(Z l) throws IOException{
|
||||
return null;
|
||||
}
|
||||
|
||||
{
|
||||
Integer i = foo(a -> bar(b -> baz(b)));
|
||||
}
|
||||
}
|
||||
+4
@@ -101,6 +101,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testDeepNestedLambdaExpressionsNoFormalParams() { doTest(); }
|
||||
public void testNestedLambdaExpressionsNoFormalParamsStopAtStandalone() { doTest(); }
|
||||
|
||||
public void testNestedLambdaCheckedExceptionsConstraints() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA127596() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user