[Checkers] State-Type Prototype

Mahmood Ali mahmood at MIT.EDU
Mon Sep 22 19:14:06 EDT 2008


Greetings Daniel,

Please note that the provided implementation is by no means a  
reference implementation.  I realize that I should have documented it  
more.

__ Overall Usage __
Each Resource annotated type either is Opened or Closed.  Each  
resource is initialized to be closed, until a ChangeStatusTo-annotated  
method is invoked on such resource reference.  One approach is to  
utilize Flow to switch the resource qualified type throughout its scope.

__ Flow utilization __
Flow class provides a flow-sensitive analysis for qualifier  
inference.  The implementation uses Gen-Kill algorithm to infer  
qualifiers.  The default implementation in Flow handles qualifiers on  
local variables, parameters, and fields only; and by default only take  
analyzation and assignment into account.  One can extend Flow to  
customize special cases and only need to specify the generation part:  
specifying where a type gets a new qualifier.  Flow uses the new  
qualifier for the element in the scope till it gets re-assigned, out- 
of-scope, or some other special cases.

We can extend Flow to change the stateful qualifier based on method  
invocation.  The provided implementation is as follows, but with  
documentations and some re-ordering:

         @Override
         public Void visitMethodInvocation(MethodInvocationTree node,  
Void p) {
             // apply default method invocation before applying this one
             super.visitMethodInvocation(node, p);

             // Check if the invoked method is annotated with  
ChangeStatusTo or not
             ExecutableElement method = TreeUtils.elementFromUse(node);
             if (method.getAnnotation(ChangeStatusTo.class) == null)
                 return null;

             // Get the new status: the value of ChangeStatusTo
             // Look below to understand try/catch
             AnnotationUtils annoUtils = new AnnotationUtils(env);
             Name newStatusName = null;
             try { method.getAnnotation(ChangeStatusTo.class).value(); }
             catch (MirroredTypeException e) {
                 newStatusName =  
TypesUtils.getQualifiedName((DeclaredType)e.getTypeMirro
r());
             }
             AnnotationMirror newStatusAnno =  
annoUtils.fromName(newStatusName);

             // Get the element representing the call site
             // some java trees don't represent elements: new class  
expressions, ?: expressions
             // we cannot do much about 'new File().open()'
             Element site = getCallSite(node);
             if (site == null)
                 return null;

             // Check flow maintains support for the site element
             if (vars.contains(site)) {
                 int idx = vars.indexOf(site);
                 // clear the qualifiers on the site element and add  
the new status
                 for (AnnotationMirror possible: annotations)
                     annos.clear(possible, idx);
                 annos.set(newStatusAnno, idx);
             }
             return null;
         }


__ getSite implementation:
As I stated earlier, Flow would only support local variables,  
parameters, and local variable.  In this case, it simply calls  
AnnotatedTypeFactory.getReceiver() and see if the call site element is  
supported and return it if so.

This mainly excludes method elements analysis, so Flow does not do  
anything about:
   getFile().open();
   getFile().write(2);  // provided implementation would report a  
false positive here
   getFile().close();

I am not quite sure if Flow supports self elements or not, and the  
provided implementation has an incomplete empty if statement for it.

__ try/catch block related to Element.getAnnotation().value()
If an Annotation object is retrieved through Element.getAnnotation(),  
and annotation element is of type java.lang.Class, then any access to  
such element would cause a MirroredTypeException: http://java.sun.com/javase/6/docs/api/javax/lang/model/element/Element.html#getAnnotation(java.lang.Class) 
  .  The proper way for getting the value in this case is through  
MirroredTypeException.getTypeMirror() as was provided in the example.

__ limitation
This proposal needs substantial improvements: it does not provide  
aliasing analysis; and it does not allow changing the stateful type  
without direct method invocation on the resource.  For
instance, it cannot express that the following method changes the  
status of the parameter to Open
   static void open(File f) { f.open(); }
   {
       File f = new File();
       open(f);
       f.write(2); // false positive here
       ...
    }

Hope this helps,
Mahmood




More information about the checkers mailing list