[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