@Override public void visitNode(Tree tree) { ListTree<TypeTree> thrownList = ((MethodTree) tree).throwsClauses(); Set<String> reported = new HashSet<>(); for (TypeTree typeTree : thrownList) { Type symbolType = typeTree.symbolType(); String fullyQualifiedName = symbolType.fullyQualifiedName(); if (!reported.contains(fullyQualifiedName)) { String superTypeName = isSubclassOfAny(symbolType, thrownList); if (superTypeName != null) { addIssue( typeTree, "Remove the declaration of thrown exception '" + fullyQualifiedName + "' which is a subclass of '" + superTypeName + "'."); } else if (symbolType.isSubtypeOf("java.lang.RuntimeException")) { addIssue( typeTree, "Remove the declaration of thrown exception '" + fullyQualifiedName + "' which is a runtime exception."); } else if (declaredMoreThanOnce(fullyQualifiedName, thrownList)) { addIssue( typeTree, "Remove the redundant '" + fullyQualifiedName + "' thrown exception declaration(s)."); } reported.add(fullyQualifiedName); } } }
private static String isSubclassOfAny(Type type, ListTree<TypeTree> thrownList) { for (TypeTree thrown : thrownList) { String name = thrown.symbolType().fullyQualifiedName(); if (!type.is(name) && type.isSubtypeOf(name)) { return name; } } return null; }
private static boolean isSubtypeOf(Type type, Type superType) { return type.isSubtypeOf(superType); }
private static boolean isCloseable(Type type) { return type.isSubtypeOf(JAVA_IO_AUTO_CLOSEABLE) || type.isSubtypeOf(JAVA_IO_CLOSEABLE); }