IDEA-114169 (false positive for non-intersecting throwers)

This commit is contained in:
Roman Shevchenko
2013-09-30 14:52:21 +02:00
parent 335436ebd7
commit 39e5e2087f
3 changed files with 36 additions and 10 deletions
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.PsiImplUtil;
@@ -23,6 +24,7 @@ import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -414,18 +416,23 @@ public class ExceptionUtil {
final MethodResolverProcessor processor = new MethodResolverProcessor((PsiMethodCallExpression)methodCall, containingFile);
try {
PsiScopesUtil.setupAndRunProcessor(processor, methodCall, false);
final List<CandidateInfo> results = processor.getResults();
if (results.size() > 1) {
final List<Pair<PsiMethod, PsiSubstitutor>> candidates = ContainerUtil.mapNotNull(
processor.getResults(), new Function<CandidateInfo, Pair<PsiMethod, PsiSubstitutor>>() {
@Override
public Pair<PsiMethod, PsiSubstitutor> fun(CandidateInfo info) {
PsiElement element = info.getElement();
return element instanceof PsiMethod && MethodSignatureUtil.areSignaturesEqual(method, (PsiMethod)element)
? Pair.create((PsiMethod)element, info.getSubstitutor()) : null;
}
});
if (candidates.size() > 1) {
final List<PsiClassType> ex = collectSubstituted(substitutor, thrownExceptions);
for (CandidateInfo info : results) {
final PsiElement element = info.getElement();
if (element instanceof PsiMethod && MethodSignatureUtil.areSignaturesEqual(method, (PsiMethod)element)) {
final PsiClassType[] exceptions = ((PsiMethod)element).getThrowsList().getReferencedTypes();
if (exceptions.length == 0) {
return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, PsiClassType.EMPTY_ARRAY);
}
retainExceptions(ex, collectSubstituted(info.getSubstitutor(), exceptions));
for (Pair<PsiMethod, PsiSubstitutor> pair : candidates) {
final PsiClassType[] exceptions = pair.first.getThrowsList().getReferencedTypes();
if (exceptions.length == 0) {
return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, PsiClassType.EMPTY_ARRAY);
}
retainExceptions(ex, collectSubstituted(pair.second, exceptions));
}
return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, ex.toArray(new PsiClassType[ex.size()]));
}
@@ -0,0 +1,18 @@
import java.io.*;
class Test {
abstract class Target {
abstract void call(String f) throws FileNotFoundException, IOException;
abstract void call(String[] f) throws FileNotFoundException, IOException;
}
void use(Target target) throws IOException {
try {
target.call("");
} catch (FileNotFoundException e) {
System.out.println("file not found");
} catch (IOException e) {
System.out.println("failed: " + e);
}
}
}
@@ -119,6 +119,7 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testAssignToFinal() { doTest(false, false); }
public void testUnhandledExceptionsInSuperclass() { doTest(false, false); }
public void testNoUnhandledExceptionsMultipleInheritance() { doTest(false, false); }
public void testFalseExceptionsMultipleInheritance() { doTest(true, false); }
public void testAssignmentCompatible () { setLanguageLevel(LanguageLevel.JDK_1_5); doTest(false, false); }
public void testMustBeBoolean() { doTest(false, false); }