highlighting for caught exceptions

This commit is contained in:
Maxim.Medvedev
2012-05-12 19:53:59 +04:00
parent 731b34a439
commit fe7611e129
3 changed files with 116 additions and 0 deletions
@@ -308,3 +308,6 @@ closure.is.too.complex.to.analyze=Closure is complex to analyze.\nTypes of local
create.parameter.from.usage=Create Parameter ''{0}''
wrong.number.of.type.arguments=Wrong number of type arguments\: {0}; required\: {1}
type.argument.0.is.not.in.its.bound.should.extend.1=Type parameter ''{0}'' is not in its bound; should extend ''{1}''
catch.statement.parameter.type.should.be.a.subclass.of.throwable=Catch statement parameter type should be a subclass of Throwable
exception.0.has.already.been.caught=Exception ''{0}'' has already been caught
unnecessary.type=Unnecessary exception ''{0}''. ''{1}'' is already declared
@@ -227,6 +227,71 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
}
@Override
public void visitTryStatement(GrTryCatchStatement statement) {
final GrCatchClause[] clauses = statement.getCatchClauses();
List<PsiType> usedExceptions = new ArrayList<PsiType>();
final PsiClassType throwable = PsiType.getJavaLangThrowable(statement.getManager(), statement.getResolveScope());
for (GrCatchClause clause : clauses) {
final GrParameter parameter = clause.getParameter();
if (parameter == null) continue;
final GrTypeElement typeElement = parameter.getTypeElementGroovy();
PsiType type = typeElement != null ? typeElement.getType() : null;
if (type == null) {
type = throwable;
}
if (!throwable.isAssignableFrom(type)) {
LOG.assertTrue(typeElement != null);
myHolder.createErrorAnnotation(typeElement,
GroovyBundle.message("catch.statement.parameter.type.should.be.a.subclass.of.throwable"));
continue;
}
if (typeElement instanceof GrDisjunctionTypeElement) {
final GrTypeElement[] elements = ((GrDisjunctionTypeElement)typeElement).getTypeElements();
PsiType[] types = new PsiType[elements.length];
for (int i = 0; i < elements.length; i++) {
types[i] = elements[i].getType();
}
List<PsiType> usedInsideDisjunction = new ArrayList<PsiType>();
for (int i = 0; i < types.length; i++) {
if (checkExceptionUsed(usedExceptions, parameter, elements[i], types[i])) {
usedInsideDisjunction.add(types[i]);
for (int j = 0; j < types.length; j++) {
if (i != j && types[j].isAssignableFrom(types[i])) {
myHolder.createWarningAnnotation(elements[i], GroovyBundle.message("unnecessary.type", types[i].getCanonicalText(),
types[j].getCanonicalText()));
}
}
}
}
usedExceptions.addAll(usedInsideDisjunction);
}
else {
if (checkExceptionUsed(usedExceptions, parameter, typeElement, type)) {
usedExceptions.add(type);
}
}
}
}
private boolean checkExceptionUsed(List<PsiType> usedExceptions, GrParameter parameter, GrTypeElement typeElement, PsiType type) {
for (PsiType exception : usedExceptions) {
if (exception.isAssignableFrom(type)) {
myHolder.createWarningAnnotation(typeElement != null ? typeElement : parameter.getNameIdentifierGroovy(), GroovyBundle.message("exception.0.has.already.been.caught", type.getCanonicalText()));
return false;
}
}
return true;
}
@Override
public void visitReferenceExpression(final GrReferenceExpression referenceExpression) {
checkStringNameIdentifier(referenceExpression);
@@ -936,4 +936,52 @@ def test() {
}
''', GroovyAssignabilityCheckInspection)
}
void testTryCatch1() {
testHighlighting('''\
try {}
catch (Exception e){}
catch (<warning descr="Exception 'java.io.IOException' has already been caught">IOException</warning> e){}
''')
}
void testTryCatch2() {
testHighlighting('''\
try {}
catch (e){}
catch (<warning descr="Exception 'java.lang.Throwable' has already been caught">e</warning>){}
''')
}
void testTryCatch3() {
testHighlighting('''\
try {}
catch (e){}
catch (<warning descr="Exception 'java.io.IOException' has already been caught">IOException</warning> e){}
''')
}
void testTryCatch4() {
testHighlighting('''\
try {}
catch (Exception | <warning descr="Unnecessary exception 'java.io.IOException'. 'java.lang.Exception' is already declared">IOException</warning> e){}
''')
}
void testTryCatch5() {
testHighlighting('''\
try {}
catch (RuntimeException | IOException e){}
catch (<warning descr="Exception 'java.lang.NullPointerException' has already been caught">NullPointerException</warning> e){}
''')
}
void testTryCatch6() {
testHighlighting('''\
try {}
catch (NullPointerException | IOException e){}
catch (ClassNotFoundException | <warning descr="Exception 'java.lang.NullPointerException' has already been caught">NullPointerException</warning> e){}
''')
}
}