So while this is good style:
/** * ... * @throws java.lang.RuntimeException if an unrecoverable error * occurred in a user supplied component. The cause will be the * error in user code. */
This is not:
void run() throws RuntimeException;
So how can I reliably find all unchecked exceptions? Very easily if I use an annotation processor. I used this annotation processor:
@SupportedAnnotationTypes("*") @SupportedOptions("summary") public class FindRuntimeException extends AbstractProcessor { // For summary of unchecked exceptions used in throws clauses final Set<TypeMirror> uncheckedExceptions = new LinkedHashSet<TypeMirror>(); public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) { // Get various utility classes final Elements elements = processingEnv.getElementUtils(); final Types types = processingEnv.getTypeUtils(); final Messager log = processingEnv.getMessager(); // Get the types (type mirrors) of RuntimeException and Error final TypeMirror runtimeException = elements.getTypeElement("java.lang.RuntimeException").asType(); final TypeMirror error = elements.getTypeElement("java.lang.Error").asType(); // Scanner for traversing the structure of a class, interface, etc. ElementScanner6<Void,Void> scan = new ElementScanner6<Void,Void>() { @Override public Void visitExecutable(ExecutableElement e, Void p) { // Executable means method or constructor, this method is called for // every method or constructor. So we just have to look at the throws // declaration... for (TypeMirror t :e.getThrownTypes()) // ...and see if any of the thrown types are subtypes of // RuntimeException or Error. if (types.isSubtype(t, runtimeException) || types.isSubtype(t, error)) { uncheckedExceptions.add(t); // print a warning so you can use your favorite editor to jump // to the problematic method log.printMessage(WARNING, "Throwing unchecked exception " + t, e); } return null; } }; // examine all the classes provided on the command line for (TypeElement e : roundEnvironment.getSpecifiedTypeElements()) scan.scan(e); // print a summary of found unchecked exceptions if (roundEnvironment.processingOver() && processingEnv.getOptions().containsKey("summary")) { System.out.println("Summary of unchecked exceptions found in throws clauses:"); for (TypeMirror t : uncheckedExceptions) System.out.println("\t" + t); } return true; } }
UPDATE: I have updated the code with comments and colors (using htmlize.el by Hrvoje Niksic)
Then I compiled the annotation processor:
javac -classpath /usr/java/jdk1.6.0/lib/tools.jar FindRuntimeException.java
You need a fairly recent Mustang snapshot to compile this. Also, from b74 (Thanks Kelly!), you won't have to put tools.jar on the classpath anymore. Then run the annotation processor:
javac -Asummary -proc:only -processor FindRuntimeException src/share/classes/javax/tools/*.java
Enjoy...
Posted by Tako Schotanus on March 03, 2006 at 04:18 AM PST #
For those poor souls (like me) who wish to compile the example, here's the imports:
import java.util.*; import javax.annotation.processing.*; import javax.lang.model.element.*; import javax.lang.model.type.*; import javax.lang.model.util.*; import static javax.tools.DiagnosticMessage.Kind.*;
Posted by VVS on March 03, 2006 at 09:11 AM PST #
Posted by Peter von der Ahe on March 03, 2006 at 11:27 AM PST #
Besides, I only added the throws clauses to keep the tool I used to check doc comments happy.
Posted by Peter von der Ahe on March 03, 2006 at 11:30 AM PST #
http://java.sun.com/j2se/javadoc/writingdoccomments/#throwstag
To me, consistency is always a good thing.
Posted by VVS on March 03, 2006 at 06:09 PM PST #
Posted by Peter von der Ahe on March 12, 2006 at 09:34 AM PST #
I completely agree that tools should be more complicated if it makes users' lives easier. Whether or not to user the throws clause is a matter of taste.
As for whether or not JSR 199 should use the throws clause, the Javadoc guidelines referenced in an earlier comment point out that the JLS uses the throws clause in the specification of the API but not in the implementation (we're talking about specifying an API and not implementing it, right?).