Javac Tree API - check for empty catch blocks

I wrote about javac's APIs in my last blog entry. But, I did not mention an example for Javac's Tree API. How about a simple example that uses javac's tree API? Here it is... In the following example, we implement a checker for empty catch blocks (because "eating exceptions silently" is considered bad) and warn the user.

We implement EmptyCatchChecker as a JSR-269 processor. In the process method, we get each ClassTree node and run it through a verifier visitor - which is a TreeScanner. In the TreeScanner subclass, whenever CatchTree node is visited, we check whether it's block has any statements or not. If not, we issue a warning message. To give a better warning message, we print the class and the method in which empty catch block occurs [To print source file and line number, we need CompilationUnitTree and I don't know how to get that!].

Update: I had missed HTML escaping < characters in source code [for generics] and so the code below was not compiling. Thanks to Jaya Hangal for notifying this issue. I've fixed it now.


import java.util.\*;

// import all JSR 199, JSR 269 and Tree API stuff
import javax.annotation.processing.\*;
import javax.lang.model.\*;
import javax.lang.model.element.\*;
import javax.lang.model.type.\*;
import javax.tools.\*;

import com.sun.source.tree.\*;
import com.sun.source.util.\*;

// An annotation processor that processes all classes
@SupportedAnnotationTypes("\*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class EmptyCatchChecker extends AbstractProcessor {
    private Trees treeUtils;
   
    public void init(ProcessingEnvironment pe) {
        super.init(pe);
        treeUtils = Trees.instance(pe);
    }

    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
        if (! roundEnv.processingOver()) {
            Set<? extends Element> elements =
                roundEnv.getRootElements();

            for (Element e: elements) {
                Tree tree = treeUtils.getTree(e);                
                if (tree.getKind().equals(Tree.Kind.CLASS)) {
                    verify((ClassTree)tree);
                }
            }
        }
        return true;
    }

    // verify each class tree
    private void verify(ClassTree ct) {
        ct.accept(new TreeScanner<Object, Void>() {
            private String currentClass, currentMethod;

            public Object visitClass(ClassTree node, Void v) {
                currentClass = node.getSimpleName().toString();
                return super.visitClass(node, v);
            }

            public Object visitMethod(MethodTree node, Void v) {
                currentMethod = node.getName().toString();
                return super.visitMethod(node, v);
            }

            public Object visitCatch(CatchTree node, Void v) {
                BlockTree block = node.getBlock();
                if (block.getStatements().isEmpty()) {
                    warn("empty catch block in " + currentMethod +
                       " method of " + currentClass);
                }                 
                return super.visitCatch(node, v);
            }
        }, null);
    }

    private void warn(String msg) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg);
    }
}

To compile the above code, you can use the following command:


javac -classpath $JDK_HOME/lib/tools.jar EmptyCatchChecker.java

To use this empty catch checker, you can use the following command:

javac -processor EmptyCatchChecker YourClass.java

Note that the above checker can be fooled by adding a simple ';' in catch block - because ';' is a statement. How do we check for that? That is an exercise to the reader ;-) [Hint: EmptyStatementTree]

Comments:

hi sundararajan, nice post. thanks for the tip. BR, ~A

Posted by anjan bacchu on November 15, 2006 at 03:01 AM IST #

Hi Sundar, Nice post.can u please tell me about where to read about the java compiler architecture,classes and related stuffs? Thanks in advance...

Posted by Mehmood on November 15, 2006 at 04:25 AM IST #

Hi Mehmood: you may want to start here. Reading compiler sources requires understanding compiler theory. In javac's case, understanding Java Language Specification is also needed (which is available online). Also, you may want to read Peter Ahe's (http://blogs.sun.com/ahe) blogs.

Posted by A. Sundararajan on November 15, 2006 at 10:39 AM IST #

Post a Comment:
Comments are closed for this entry.
About

sundararajan

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks
Links

No bookmarks in folder

Blogroll

No bookmarks in folder

News

No bookmarks in folder