Fix precise type calculation for degenerate case

This commit is contained in:
Roman Shevchenko
2012-10-30 11:58:55 +01:00
parent 29e57548a0
commit ce4ed7a604
2 changed files with 37 additions and 23 deletions
@@ -106,36 +106,40 @@ public class PsiCatchSectionImpl extends CompositePsiElement implements PsiCatch
final PsiType declaredType = parameter.getType();
// When the thrown expression is a ... exception parameter Ej (parameter) of a catch clause Cj (this) ...
final LanguageLevel level = PsiUtil.getLanguageLevel(parameter);
if (level.isAtLeast(LanguageLevel.JDK_1_7) && isCatchParameterEffectivelyFinal(parameter, getCatchBlock())) {
// When the thrown expression is an ... exception parameter Ej (parameter) of a catch clause Cj (this) ...
if (PsiUtil.getLanguageLevel(parameter).isAtLeast(LanguageLevel.JDK_1_7) &&
isCatchParameterEffectivelyFinal(parameter, getCatchBlock())) {
final PsiCodeBlock tryBlock = getTryStatement().getTryBlock();
if (tryBlock != null) {
// ... and the try block of the try statement which declares Cj (tryBlock) can throw T ...
final List<PsiClassType> thrownTypes = ExceptionUtil.getThrownExceptions(tryBlock);
// ... and for all exception parameters Ei declared by any catch clauses Ci, 1 <= i < j,
// declared to the left of Cj for the same try statement, T is not assignable to Ei ...
final PsiParameter[] parameters = getTryStatement().getCatchBlockParameters();
final List<PsiType> uncaughtTypes = ContainerUtil.mapNotNull(thrownTypes, new NullableFunction<PsiClassType, PsiType>() {
@Override
public PsiType fun(final PsiClassType thrownType) {
for (int i = 0; i < parameters.length && parameters[i] != parameter && thrownTypes.size() > 0; i++) {
final PsiType catchType = parameters[i].getType();
if (catchType.isAssignableFrom(thrownType)) return null;
if (!thrownTypes.isEmpty()) {
// ... and for all exception parameters Ei declared by any catch clauses Ci, 1 <= i < j,
// declared to the left of Cj for the same try statement, T is not assignable to Ei ...
final PsiParameter[] parameters = getTryStatement().getCatchBlockParameters();
final List<PsiType> uncaughtTypes = ContainerUtil.mapNotNull(thrownTypes, new NullableFunction<PsiClassType, PsiType>() {
@Override
public PsiType fun(final PsiClassType thrownType) {
for (int i = 0; i < parameters.length && parameters[i] != parameter; i++) {
final PsiType catchType = parameters[i].getType();
if (catchType.isAssignableFrom(thrownType)) return null;
}
return thrownType;
}
return thrownType;
}
});
// ... and T is assignable to Ej ...
boolean passed = true;
for (PsiType type : uncaughtTypes) {
if (!declaredType.isAssignableFrom(type)) {
passed = false;
break;
});
// ... and T is assignable to Ej ...
if (!uncaughtTypes.isEmpty()) {
boolean passed = true;
for (PsiType type : uncaughtTypes) {
if (!declaredType.isAssignableFrom(type)) {
passed = false;
break;
}
}
// ... the throw statement throws precisely the set of exception types T.
if (passed) return uncaughtTypes;
}
}
// ... the throw statement throws precisely the set of exception types T.
if (passed) return uncaughtTypes;
}
}
@@ -155,4 +155,14 @@ class C {
<error descr="Unhandled exception: C.E">throw x;</error>
}
}
void m11() throws E1 {
try {
System.out.println();
}
catch (Exception e) {
// test for precise types calculation fix
<error descr="Unhandled exception: java.lang.Exception">throw e;</error>
}
}
}