Annotating libraries with the skeleton class generator

Contents:

Introduction

When annotated code uses unannotated code (e.g., libraries or the JDK), a checker plug-in may issue warnings. Several methods exist for avoiding such annotations; this document discusses an approach in which a programmer generates and annotates "skeleton classes" — classes with method bodies stripped away — and subsequently runs a checker plug-in against the annotated skeleton class.

Obtaining the skeleton class generator

Source code for the skeleton class generator tool is included in the checkers distribution, but because the tool has additional dependencies, the provided build script does not build the tool by default.

Follow these steps to obtain the skeleton class generator:

  1. Install the annotation file utilities.
  2. Update the build.properties file in the checkers distribution so that the “annotation-utils.lib” property specifies the location of the annotation-file-utilities.jar library.
  3. Build the skeleton class generator tool by running ant skeleton-util dist in the checkers utility.
  4. Add the checkers.jar file (which is produced by a successful build) to your classpath, if you have not already done so during installation of the checkers and framework.
  5. Add the annotation-file-utilities.jar file (which you installed in the first step) to your classpath.

Creating a skeleton class

To create a skeleton class, run the skeleton class generator with the fully-qualified name of the class for which you wish to generate a skeleton class.

  java checkers.util.Skeleton class_name

The skeleton class generator currently prints the skeleton class to standard out; you may wish to redirect its output to a file.

Using the skeleton class

Once you have created a skeleton class, you may add annotations as necessary. To include the annotated skeleton class for type-checking, invoke the checker plug-in on both your source code and the source code of the annotated skeleton classes. The checker plug-in will read annotations from the skeleton class source instead of the original class on the classpath.

Before running the compiled code, you should first ensure that the skeleton classes are not included in the classpath; if this is the case, your program will throw a RuntimeException when a skeleton method gets called instead of the true library method.

Example: Adding @NonNull to java.util.Set

The following steps will create a NonNull-annotated version of the Set interface, for use in a program that uses Sets of NonNull objects.

  1. Build the skeleton class generator as outlined above.
  2. Run the skeleton class generator on Set, redirecting its output to a file:
    
        java checkers.util.Skeleton java.util.Set > Set.java
    
    The generator produces the following output:
    
    package java.util;
    
    public interface Set<E> extends java.util.Collection<E> {
      public abstract int size();
      public abstract boolean isEmpty();
      public abstract boolean contains(java.lang.Object a1);
      public abstract java.util.Iterator<E> iterator();
      public abstract java.lang.Object[] toArray();
      public abstract <T> T[] toArray(T[] a1);
      public abstract boolean add(E a1);
      public abstract boolean remove(java.lang.Object a1);
      public abstract boolean containsAll(java.util.Collection<?> a1);
      public abstract boolean addAll(java.util.Collection<? extends E> a1);
      public abstract boolean retainAll(java.util.Collection<?> a1);
      public abstract boolean removeAll(java.util.Collection<?> a1);
      public abstract void clear();
      public abstract boolean equals(java.lang.Object a1);
      public abstract int hashCode();
    }
        
  3. Add NonNull annotations to the Set skeleton class. For example, we might annotate the iterator() method as follows:
    
      public abstract @NonNull java.util.Iterator<E> iterator();
        
  4. Invoke the JSR 308 compiler on the source code for both the program to check and the skeleton Set class:
    
        javac -typeprocessor checkers.nonnull.NonnullChecker source_files Set.java
        

How to report bugs

If you have any problems using the skeleton class generator, please let us know. See the JSR 308 bug-reporting instructions for guidelines, and use the same email address for reporting bugs.


Back to the JSR 308 checkers framework.