public class JavariAnnotatedTypeFactory extends AnnotatedTypeFactory
ReadOnly
in the source code.
Implicit Annotations:
All literals are implicitly treated as Mutable
, including the
null literal. While they are indeed immutable, this implicit type helps
interfacing with non-annotated libraries.
Default Annotations:
ReadOnly
annotation to a type if the
tree or element is
ReadOnly
, including a method receiver of a
ReadOnly class, or
ThisMutable
field using a ReadOnly
reference (e.g. readOnlyRef.thisMutableField
with the obvious
declarations)
ThisMutable
annotation to a type if the
input is a field of a mutable class.
Mutable
annotation is inserted by default.
AnnotatedTypeFactory.InheritedFromClassAnnotator
annotations, atypes, elements, env, fromTreeCache, qualHierarchy, root, trees, types, uid, visitorState
Constructor and Description |
---|
JavariAnnotatedTypeFactory(JavariChecker checker,
@Nullable CompilationUnitTree root)
Creates a new
JavariAnnotatedTypeFactory that operates on a
particular AST. |
Modifier and Type | Method and Description |
---|---|
protected void |
annotateImplicit(@Nullable Element element,
@Mutable AnnotatedTypeMirror type)
Adds annotations to qualified types according to their provided
element, as follows:
1.
|
protected void |
annotateImplicit(Iterable<? extends @Nullable Tree> trees,
Iterable<? extends @Mutable AnnotatedTypeMirror> types)
Convenience method for annotating two corresponding iterables.
|
protected void |
annotateImplicit(@Nullable Tree tree,
@Mutable AnnotatedTypeMirror type)
Adds implicit annotations to a qualified type, based on its
tree, as follows:
1.
|
Pair<AnnotatedTypeMirror.AnnotatedExecutableType,List<@Mutable AnnotatedTypeMirror>> |
constructorFromUse(NewClassTree tree)
Determines the type of the constructed object based on the
parameters passed to the constructor.
|
boolean |
hasImmutabilityAnnotation(@Mutable AnnotatedTypeMirror type) |
Pair<AnnotatedTypeMirror.AnnotatedExecutableType,List<@Mutable AnnotatedTypeMirror>> |
methodFromUse(MethodInvocationTree tree)
Determines the type of the invoked method based on the passed method
invocation tree.
|
void |
postAsMemberOf(@Mutable AnnotatedTypeMirror type,
@Mutable AnnotatedTypeMirror owner,
@Nullable Element element)
We modify this callback method to replace
@ThisMutable
implicit annotations with the qualified supertype annotation,
if the owner doesn't have a @ReadOnly annotation. |
protected void |
postDirectSuperTypes(@Mutable AnnotatedTypeMirror type,
List<? extends @Mutable AnnotatedTypeMirror> supertypes)
A callback method for the AnnotatedTypeFactory subtypes to customize
directSuperTypes().
|
Collection<@Nullable AnnotationMirror> |
unify(Collection<@Nullable AnnotationMirror> c1,
Collection<@Nullable AnnotationMirror> c2)
Returns a singleton collection with the most restrictive immutability
annotation that is a supertype of the annotations on both collections.
|
addAliasedAnnotation, aliasedAnnotation, annotateInheritedFromClass, canHaveAnnotatedTypeParameters, createLRUCache, declarationFromElement, fromClass, fromElement, fromElement, fromElement, fromExpression, fromMember, fromNewClass, fromTypeTree, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedType, getAnnotatedTypeFromTypeTree, getBoxedType, getCurrentClassTree, getCurrentClassType, getCurrentMethodReceiver, getDeclAnnotation, getDefaultedAnnotatedType, getEnclosingType, getImplicitReceiverType, getPath, getQualifierHierarchy, getReceiverType, getSelfType, getUnboxedType, getVisitorState, isAnyEnclosingThisDeref, isMostEnclosingThisDeref, isSupportedQualifier, isWithinConstructor, postInit, toAnnotatedType, toString, typeVariablesFromUse
public JavariAnnotatedTypeFactory(JavariChecker checker, @Nullable CompilationUnitTree root)
JavariAnnotatedTypeFactory
that operates on a
particular AST.checker
- the checker to which this factory belongsroot
- the AST on which this type factory operatespublic boolean hasImmutabilityAnnotation(@Mutable AnnotatedTypeMirror type)
type
- an annotated type mirrorprotected void annotateImplicit(@Nullable Tree tree, @Mutable AnnotatedTypeMirror type)
@ThisMutable
.
@Mutable
annotation.
@Mutable
.
@ReadOnly
,
@Mutable
or @PolyRead
, according to the
qualified type of this
.
annotateImplicit
in class AnnotatedTypeFactory
tree
- an AST nodetype
- the type obtained from tree
protected void annotateImplicit(Iterable<? extends @Nullable Tree> trees, Iterable<? extends @Mutable AnnotatedTypeMirror> types)
protected void annotateImplicit(@Nullable Element element, @Mutable AnnotatedTypeMirror type)
@Mutable
annotation.
@ReadOnly
or
@ThisMutable
, according to the supertype.
annotateImplicit
in class AnnotatedTypeFactory
element
- an elementtype
- the type obtained from elt
protected void postDirectSuperTypes(@Mutable AnnotatedTypeMirror type, List<? extends @Mutable AnnotatedTypeMirror> supertypes)
AnnotatedTypeFactory
type
annotations to
supertypes
. This allows the type
and its supertypes
to have the qualifiers, e.g. the supertypes of an Immutable
type are also Immutable
.postDirectSuperTypes
in class AnnotatedTypeFactory
type
- the type whose supertypes are desiredsupertypes
- the supertypes as specified by the base AnnotatedTypeFactorypublic Collection<@Nullable AnnotationMirror> unify(Collection<@Nullable AnnotationMirror> c1, Collection<@Nullable AnnotationMirror> c2)
unify
in class AnnotatedTypeFactory
c1
- type qualifiers for the first typec2
- type qualifiers for the second typepublic Pair<AnnotatedTypeMirror.AnnotatedExecutableType,List<@Mutable AnnotatedTypeMirror>> constructorFromUse(NewClassTree tree)
@PolyRead
receiver values are resolved by looking at
the mutability of any parameters marked as @PolyRead
. The rules
are similar to the ones applicable to
method invocation resolution, but without looking at this
.
@PolyRead
receive
@Mutable
arguments, the receiver value is resolved as
@Mutable
.
@PolyRead
receive
@Mutable
or @ThisMutable
arguments and the
condition above is not satisfied, the receiver value is
resolved as @ThisMutable
.
@PolyRead
receive
@Mutable
or @PolyRead
arguments and none of
the condition above is satisfied, the receiver value is
resolved as @PolyRead
.
@ReadOnly
.
constructorFromUse
in class AnnotatedTypeFactory
tree
- the new class treepublic Pair<AnnotatedTypeMirror.AnnotatedExecutableType,List<@Mutable AnnotatedTypeMirror>> methodFromUse(MethodInvocationTree tree)
@PolyRead
at the raw level on return values by looking at the
mutability of any parameters marked as @PolyRead
. For
this purpose, a @PolyRead
annotation on the receiver
counts as if this
were being passed as an argument to a
parameter marked as @PolyRead
.
@PolyRead
receive
@Mutable
arguments, the return value is resolved as
@Mutable
.
@PolyRead
receive
@Mutable
or @ThisMutable
arguments and the
condition above is not satisfied, the return value is resolved
as @ThisMutable
.
@PolyRead
receive
@Mutable
or @PolyRead
arguments and none of
the condition above is satisfied, the return value is resolved
as @PolyRead
.
@ReadOnly
.
methodFromUse
in class AnnotatedTypeFactory
tree
- the method invocation treepublic void postAsMemberOf(@Mutable AnnotatedTypeMirror type, @Mutable AnnotatedTypeMirror owner, @Nullable Element element)
@ThisMutable
implicit annotations with the qualified supertype annotation,
if the owner doesn't have a @ReadOnly
annotation.
Note on the given example that, if @ThisMutable tmObject
were resolved as @ReadOnly tmObject
, the code snippet
would be legal. Such a class could then be created to obtain
@Mutable
access to tmObject
from a @ReadOnly
reference to it, without typechecker errors.
@PolyRead Object breakJavari(@ReadOnly MyClass this, @PolyRead Object s) { tmObject = s; return null; }
postAsMemberOf
in class AnnotatedTypeFactory
type
- the annotated type of the elementowner
- the annotated type of the receiver of the accessing treeelement
- the element of the field or method