[Checkers] r2622: modifying visitNewClass on TypeFromTree

Telmo telmo at MIT.EDU
Mon Jun 2 18:35:16 EDT 2008


Hello.
The current implementation of visitNewClass in TypeFromTree is:

   return f.fromTypeTree(node.getIdentifier);


as opposed to the implementation of visitMethodInvocation, which is

   AnnotatedExecutableType ex = f.methodFromUse(node);
   return ex.getReturnType();


I am moving the treatment of polymorphism on constructors from the 
TreePreAnnotator to constructorFromUse on the factory itself; conceivably 
I could move all the functionality away and have one less annotator.

Namely, I need to be able to modify the generated object annotation from 
constructorFromUse. However, right now, this is not possible. A 
NewClassTree nct is parsed as follows:

getAnnotatedType(nct)    			at AnnotatedTypeFactory
fromExpression(nct)      			at AnnotatedTypeFactory
 	fromTreeWithVisitor(nct)		at AnnotatedTypeFactory (private)
 	TypeFromExpression.visitNewClass(nct)	at TypeFromTree
 	fromTypeTree(nct.getIdentifier())	at {Javari}AnnotatedTypeFactory
 	...
         which gets a type result, based on nc.getIdentifier()
annotateInheritedFromClass(result)		at AnnotatedTypeFactory
...

As you see, information about the receiver of the AnnotatedExecutableType 
is lost during the factory process, and it is impossible to fix it locally 
on the JavariChecker, other than by overriding fromExpression, which would 
be an ugly hack.

constructorFromUse(node), however, is being called, from visitNewClass on 
BaseTypeVisitor. In other words, it is being used to check whether the 
arguments can be assigned to the parameters, but it is not being used to 
check for the "return value" of a constructor, as methodFromUse is.

As non-intuitive as this is, Javari needs this feature, due to the 
polymorphism of new class trees. A possible replacement would be to change 
visitNewClass in TypeFromTree to:

   AnnotatedExecutableType ex = f.constructorFromUse(node);
   return ex.getReceiverType();


and modify constructorFromUse on AnnotatedTypeFactory to:


   ExecutableElement ctor = InternalUtils.constructor(tree);
   AnnotatedTypeMirror type = fromTypeTree(tree.getIdentifier());
   annotateImplicit(tree.getIdentifier(), type);
   AnnotatedExecutableType exType = atypes.asMemberOf(type, ctor);
   Map<? extends AnnotatedTypeMirror, AnnotatedTypeMirror> receiverTypeMap
 	= Collections.singletonMap<exType.getReceiverType(), type);
   return exType.substitute(receiverTypeMap);


This doesn't break any of the other tests, and exposes the required 
functionality, by overriding constructorFromUse; namely, writing something 
that looks like

   ExecutableElement executableElt = InternalUtils.constructor(tree);
   AnnotatedExecutableType type = (AnnotatedExecutableType) fromElement(ExecutableElement);
   AnnotatedTypeMirror receiverType = type.getReceiverType();
   // use the original annotations
   AnnotatedTypeMirror returnType = fromTypeTree(tree.getIdentifier());
   annotateImplicit(tree.getIdentifier(), returnType());
   ...
   <javari polymorphic constructor code>
   ...


There is lots of type rewriting being done, which makes the code somewhat 
slower. Also, now JavariAnnotatedTypeFactory must use InternalUtils, but 
that feels justifiable since it is performing a somewhat low level 
operation on the types.

Any better ideas on how to implement this are welcome.

-Telmo



More information about the checkers mailing list