checkers.basetype
Class BaseTypeChecker

java.lang.Object
  extended by javax.annotation.processing.AbstractProcessor
      extended by com.sun.source.util.AbstractTypeProcessor
          extended by checkers.source.SourceChecker
              extended by checkers.basetype.BaseTypeChecker
All Implemented Interfaces:
Processor
Direct Known Subclasses:
BasicChecker, FlowTestChecker, IGJChecker, InterningChecker, JavariChecker, NullnessChecker, TestChecker

public abstract class BaseTypeChecker
extends SourceChecker

An abstract SourceChecker that provides a simple SourceVisitor implementation for typical assignment and pseudo-assignment checking of annotated types. Pseudo-assignment checks include method overriding checks, parameter passing, and method invocation. Most type-checker plug-ins will want to extend this class, instead of SourceChecker. Checkers which require annotated types but not subtype checking (e.g. for testing purposes) should extend SourceChecker. Non-type checkers (e.g. for enforcing coding styles) should extend AbstractProcessor (or even SourceChecker) as the Checker Framework is not designed for such checkers. Non-type checkers (e.g. checkers to enforce coding styles) should extend SourceChecker or AbstractProcessor directly; the Checker Framework is not designed for such checkers.

It is a convention that, for a type system Foo, the checker, the visitor, and the annotated type factory are named as FooChecker, FooVisitor, and FooAnnotatedTypeFactory. Some factory methods uses this convention to construct the appriopriate classes reflectively.

BaseTypeChecker encapsulates a group for factories for various representations/classes related the type system, mainly:

Subclasses must specify the set of type qualifiers they support either by annotating the subclass with TypeQualifiers or by overriding the getSupportedTypeQualifiers() method.

If the specified type qualifiers are meta-annotated with SubtypeOf, this implementation will automatically construct the type qualifier hierarchy. Otherwise, or if this behavior must be overridden, the subclass may override the createQualifierHierarchy() method.

See Also:
checkers.quals

Field Summary
 
Fields inherited from class checkers.source.SourceChecker
currentPath, currentRoot, env, messager, messages, skipPattern, trees
 
Fields inherited from class javax.annotation.processing.AbstractProcessor
processingEnv
 
Constructor Summary
BaseTypeChecker()
           
 
Method Summary
 AnnotatedTypeFactory createFactory(CompilationUnitTree root)
          Constructs an instance of the appropriate type factory for the implemented type system.
protected  QualifierHierarchy createQualifierHierarchy()
          Returns the type qualifier hierarchy graph to be used by this processor.
protected  BaseTypeVisitor<?,?> createSourceVisitor(CompilationUnitTree root)
          Returns the appropriate visitor that type checks the compilation unit according to the type system rules.
protected  Set<Class<? extends Annotation>> createSupportedTypeQualifiers()
          If the checker class is annotated with TypeQualifiers, return an immutable set with the same set of classes as the annotation.
protected  TypeHierarchy createTypeHierarchy()
          Creates the type subtyping checker using the current type qualifier hierarchy.
 QualifierHierarchy getQualifierHierarchy()
          Returns the type qualifier hierarchy graph to be used by this processor.
 Set<String> getSupportedLintOptions()
          Specify 'flow' and 'cast' as supported lint options for all Type checkers
 Set<Class<? extends Annotation>> getSupportedTypeQualifiers()
          Returns an immutable set of the type qualifiers supported by this checker.
 void init(ProcessingEnvironment processingEnv)
          
 boolean isAssignable(AnnotatedTypeMirror varType, AnnotatedTypeMirror receiverType, Tree variable)
          Tests whether the variable accessed is an assignable variable or not, given the current scope
 boolean isSubtype(AnnotatedTypeMirror sub, AnnotatedTypeMirror sup)
          Tests whether one annotated type is a subtype of another, with respect to the annotations on these types.
 boolean isValidUse(AnnotatedTypeMirror.AnnotatedDeclaredType declarationType, AnnotatedTypeMirror.AnnotatedDeclaredType useType)
          Tests that the qualifiers present on the useType are valid qualifiers, given the qualifiers on the declaration of the type, declarationType.
 
Methods inherited from class checkers.source.SourceChecker
getLintOption, getLintOption, getMessages, getProcessingEnvironment, getShouldSkip, getSupportedAnnotationTypes, getSupportedOptions, getSupportedSourceVersion, getSuppressWarningsKey, message, report, shouldSkip, typeProcess
 
Methods inherited from class com.sun.source.util.AbstractTypeProcessor
process, typeProcessingOver
 
Methods inherited from class javax.annotation.processing.AbstractProcessor
getCompletions, isInitialized
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

BaseTypeChecker

public BaseTypeChecker()
Method Detail

init

public void init(ProcessingEnvironment processingEnv)
Description copied from class: SourceChecker

Specified by:
init in interface Processor
Overrides:
init in class SourceChecker
See Also:
AbstractProcessor.init(ProcessingEnvironment)

createSupportedTypeQualifiers

protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers()
If the checker class is annotated with TypeQualifiers, return an immutable set with the same set of classes as the annotation. If the class is not so annotated, return an empty set. Subclasses may override this method to return an immutable set of their supported type qualifiers.

Returns:
the type qualifiers supported this processor, or an empty set if none
See Also:
TypeQualifiers

getSupportedTypeQualifiers

public final Set<Class<? extends Annotation>> getSupportedTypeQualifiers()
Returns an immutable set of the type qualifiers supported by this checker.

Returns:
the type qualifiers supported this processor, or an empty set if none
See Also:
createSupportedTypeQualifiers()

createQualifierHierarchy

protected QualifierHierarchy createQualifierHierarchy()
Returns the type qualifier hierarchy graph to be used by this processor. The implementation builds the type qualifier hierarchy for the getSupportedTypeQualifiers() using the meta-annotations found in them. The current implementation returns an instance of GraphQualifierHierarchy. Subclasses may override this method to express any relationships that cannot be inferred using meta-annotations (e.g. due to lack of meta-annotations).

Returns:
an annotation relation tree representing the supported qualifiers

getQualifierHierarchy

public final QualifierHierarchy getQualifierHierarchy()
Returns the type qualifier hierarchy graph to be used by this processor.

Returns:
the QualifierHierarchy for this checker
See Also:
createQualifierHierarchy()

createTypeHierarchy

protected TypeHierarchy createTypeHierarchy()
Creates the type subtyping checker using the current type qualifier hierarchy. Subclasses may override this method to specify new type checking rules beyond the typical java subtyping rules.

Returns:
the type relations class to check type subtyping

createSourceVisitor

protected BaseTypeVisitor<?,?> createSourceVisitor(CompilationUnitTree root)
Returns the appropriate visitor that type checks the compilation unit according to the type system rules. This implementation uses the checker naming convention to create the appropriate visitor. If no visitor is found, it returns an instance of BaseTypeVisitor. It reflectively invokes the constructor that accepts this checker and the compilation unit tree (in that order) as arguments. Subclasses have to override this method to create the appropriate visitor if they do not follow the checker naming convention.

Specified by:
createSourceVisitor in class SourceChecker
Parameters:
root - the compilation unit currently being visited
Returns:
the type-checking visitor

createFactory

public AnnotatedTypeFactory createFactory(CompilationUnitTree root)
Constructs an instance of the appropriate type factory for the implemented type system. The default implementation uses the checker naming convention to create the appropriate type factory. If no factory is found, it returns BasicAnnotatedTypeFactory. It reflectively invokes the constructor that accepts this checker and compilation unit tree (in that order) as arguments. Subclasses have to override this method to create the appropriate visitor if they do not follow the checker naming convention.

Overrides:
createFactory in class SourceChecker
Parameters:
root - the currently visited compilation unit
Returns:
the appropriate type factory

isSubtype

public boolean isSubtype(AnnotatedTypeMirror sub,
                         AnnotatedTypeMirror sup)
Tests whether one annotated type is a subtype of another, with respect to the annotations on these types. Subclasses may wish to ignore annotations that are not related to the type qualifiers they check. This implementation follows the subtype rules specified in TypeHierarchy. Its behavior is undefined for any annotations not specified by either TypeQualifiers or the result of getSupportedTypeQualifiers().

Parameters:
sub - the child type
sup - the parent type
Returns:
true iff sub is a subtype of sup

isValidUse

public boolean isValidUse(AnnotatedTypeMirror.AnnotatedDeclaredType declarationType,
                          AnnotatedTypeMirror.AnnotatedDeclaredType useType)
Tests that the qualifiers present on the useType are valid qualifiers, given the qualifiers on the declaration of the type, declarationType.

The check is shallow, as it does not descend into generic or array types (i.e. only performing the validity check on the raw type or outmost array dimension). BaseTypeVisitor.validateTypeOf(Tree) would call this for each type argument or array dimention separately.

For instance, in the IGJ type system, a @Mutable is an invalid qualifier for String, as String is declared as @Immutable String.

In most cases, useType simply needs to be a subtype of declarationType, but there are exceptions. In IGJ, a variable may be declared @ReadOnly String, even though String is @Immutable String; ReadOnly is not a subtype of Immutable.

Parameters:
declarationType - the type of the class (TypeElement)
useType - the use of the class (instance type)
Returns:
if the useType is a valid use of elemType

isAssignable

public boolean isAssignable(AnnotatedTypeMirror varType,
                            AnnotatedTypeMirror receiverType,
                            Tree variable)
Tests whether the variable accessed is an assignable variable or not, given the current scope

Parameters:
varType - the annotated variable type
variable - tree used to access the variable
Returns:
true iff variable is assignable in the current scope

getSupportedLintOptions

public Set<String> getSupportedLintOptions()
Specify 'flow' and 'cast' as supported lint options for all Type checkers

Overrides:
getSupportedLintOptions in class SourceChecker
Returns:
an unmodifiable Set of the lint options recognized by this checker