checkers.basetype
Class BaseTypeVisitor<R,P>

java.lang.Object
  extended by com.sun.source.util.TreeScanner<R,P>
      extended by com.sun.source.util.TreePathScanner<R,P>
          extended by checkers.source.SourceVisitor<R,P>
              extended by checkers.basetype.BaseTypeVisitor<R,P>
All Implemented Interfaces:
TreeVisitor<R,P>
Direct Known Subclasses:
InterningVisitor, JavariVisitor, NullnessVisitor

public class BaseTypeVisitor<R,P>
extends SourceVisitor<R,P>

A SourceVisitor that performs assignment and pseudo-assignment checking, method invocation checking, and assignability checking.

This implementation uses the AnnotatedTypeFactory implementation provided by an associated BaseTypeChecker; its visitor methods will invoke this factory on parts of the AST to determine the "annotated type" of an expression. Then, the visitor methods will check the types in assignments and pseudo-assignments using commonAssignmentCheck(com.sun.source.tree.Tree, com.sun.source.tree.ExpressionTree, java.lang.String, P), which ultimately calls the BaseTypeChecker.isSubtype(checkers.types.AnnotatedTypeMirror, checkers.types.AnnotatedTypeMirror) method and reports errors that violate Java's rules of assignment.

Note that since this implementation only performs assignment and pseudo-assignment checking, other rules for custom type systems must be added in subclasses (e.g., dereference checking in the NullnessChecker is implemented in the NullnessChecker's TreeScanner.visitMemberSelect(com.sun.source.tree.MemberSelectTree, P) method).

This implementation does the following checks: 1. Assignment and Pseudo-Assignment Check: It verifies that any assignment type check, using Checker.isSubtype method. This includes method invocation and method overriding checks. 2. Type Validity Check: It verifies that any user-supplied type is a valid type, using Checker.isValidUse method. 3. (Re-)Assignability Check: It verifies that any assignment is valid, using Checker.isAssignable method.

See Also:
"JLS $4", BaseTypeChecker.isSubtype(AnnotatedTypeMirror, AnnotatedTypeMirror), AnnotatedTypeFactory

Field Summary
protected  AnnotationUtils annoFactory
          The annotation factory to use for creating annotations.
protected  AnnotatedTypes annoTypes
          utilities class for annotated types
protected  BaseTypeChecker checker
          The checker corresponding to this visitor.
protected  VisitorState visitorState
          For storing visitor state
 
Fields inherited from class checkers.source.SourceVisitor
atypeFactory, elements, root, trees, types
 
Constructor Summary
BaseTypeVisitor(BaseTypeChecker checker, CompilationUnitTree root)
           
 
Method Summary
protected  void checkArguments(List<? extends AnnotatedTypeMirror> requiredArgs, List<? extends ExpressionTree> passedArgs, P p)
          A helper method to check that each passed argument is a subtype of the corresponding required argument, and issues "argument.invalid" error for each passed argument that not a subtype of the required one.
protected  void checkArrayInitialization(AnnotatedTypeMirror type, List<? extends ExpressionTree> initializers, P p)
           
protected  void checkAssignability(AnnotatedTypeMirror varType, Tree varTree)
          Tests, for a re-assignment, whether the variable is assignable or not.
protected  boolean checkMethodInvocability(AnnotatedTypeMirror.AnnotatedExecutableType method, MethodInvocationTree node)
          Tests whether the method can be invoked using the receiver of the 'node' method invocation, and issues a "method.invocation.invalid" if the invocation is invalid.
protected  boolean checkOverride(MethodTree overriderTree, AnnotatedTypeMirror.AnnotatedDeclaredType enclosingType, AnnotatedTypeMirror.AnnotatedExecutableType overridden, AnnotatedTypeMirror.AnnotatedDeclaredType overriddenType, P p)
          Checks that an overriding method's return type, parameter types, and receiver type are correct with respect to the annotations on the overridden method's return type, parameter types, and receiver type.
protected  void checkTypeArguments(List<? extends AnnotatedTypeMirror> typevars, List<? extends AnnotatedTypeMirror> typeargs, List<? extends Tree> typeargTrees, P p)
          Checks that the annotations on the type arguments supplied to a type or a method invocation are within the bounds of the type variables as declared, and issues the "generic.argument.invalid" error if they are not.
protected  void checkTypecastSafety(TypeCastTree node, P p)
           
protected  void commonAssignmentCheck(AnnotatedTypeMirror varType, AnnotatedTypeMirror valueType, Tree valueTree, String errorKey, P p)
          Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.
protected  void commonAssignmentCheck(AnnotatedTypeMirror varType, ExpressionTree valueExp, String errorKey, P p)
          Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.
protected  void commonAssignmentCheck(Tree varTree, ExpressionTree valueExp, String errorKey, P p)
          Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.
 R scan(Tree tree, P p)
           
protected  boolean shouldSkip(Element element)
          Tests whether the class owner of the passed element is an unannotated class and matches the pattern specified in the checker.skipClasses property.
protected  boolean shouldSkip(ExpressionTree exprTree)
          Tests whether the expression should not be checked because of the tree referring to unannotated classes, as specified in the checker.skipClasses property.
 void validateTypeOf(Tree tree)
          Tests whether the tree expressed by the passed type tree is a valid type, and emits an error if that is not the case (e.g.
 R visitAnnotation(AnnotationTree node, P p)
           
 R visitAssignment(AssignmentTree node, P p)
          Performs two checks: subtyping and assignability checks, using commonAssignmentCheck(Tree, ExpressionTree, String, Object).
 R visitClass(ClassTree node, P p)
           
 R visitCompilationUnit(CompilationUnitTree node, P p)
          Override Compilation Unit so we won't visit package names or imports
 R visitCompoundAssignment(CompoundAssignmentTree node, P p)
          Performs assignability check using checkAssignability(AnnotatedTypeMirror, Tree).
 R visitEnhancedForLoop(EnhancedForLoopTree node, P p)
          Performs a subtype check, to test whether the node expression iterable type is a subtype of the variable type in the enhanced for loop.
 R visitInstanceOf(InstanceOfTree node, P p)
           
 R visitMethod(MethodTree node, P p)
          Performs pseudo-assignment check: checks that the method obeys override and subtype rules to all overridden methods.
 R visitMethodInvocation(MethodInvocationTree node, P p)
          Performs a method invocation check.
 R visitNewArray(NewArrayTree node, P p)
           
 R visitNewClass(NewClassTree node, P p)
          Performs a new class invocation check.
 R visitParameterizedType(ParameterizedTypeTree node, P p)
          Checks that the annotations on the type arguments supplied to a type or a method invocation are within the bounds of the type variables as declared, and issues the "generic.argument.invalid" error if they are not.
 R visitReturn(ReturnTree node, P p)
          Checks that the type of the return expression is a subtype of the enclosing method required return type.
 R visitTypeCast(TypeCastTree node, P p)
           
 R visitUnary(UnaryTree node, P p)
          Performs assignability check using checkAssignability(AnnotatedTypeMirror, Tree).
 R visitVariable(VariableTree node, P p)
           
 
Methods inherited from class com.sun.source.util.TreePathScanner
getCurrentPath, scan
 
Methods inherited from class com.sun.source.util.TreeScanner
reduce, scan, visitAnnotatedType, visitArrayAccess, visitArrayType, visitAssert, visitBinary, visitBlock, visitBreak, visitCase, visitCatch, visitConditionalExpression, visitContinue, visitDoWhileLoop, visitEmptyStatement, visitErroneous, visitExpressionStatement, visitForLoop, visitIdentifier, visitIf, visitImport, visitLabeledStatement, visitLiteral, visitMemberSelect, visitModifiers, visitOther, visitParenthesized, visitPrimitiveType, visitSwitch, visitSynchronized, visitThrow, visitTry, visitTypeParameter, visitWhileLoop, visitWildcard
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

checker

protected final BaseTypeChecker checker
The checker corresponding to this visitor.


annoFactory

protected final AnnotationUtils annoFactory
The annotation factory to use for creating annotations.


annoTypes

protected final AnnotatedTypes annoTypes
utilities class for annotated types


visitorState

protected final VisitorState visitorState
For storing visitor state

Constructor Detail

BaseTypeVisitor

public BaseTypeVisitor(BaseTypeChecker checker,
                       CompilationUnitTree root)
Parameters:
checker - the typechecker associated with this visitor (for callbacks to BaseTypeChecker.isSubtype(checkers.types.AnnotatedTypeMirror, checkers.types.AnnotatedTypeMirror))
root - the root of the AST that this visitor operates on
Method Detail

scan

public R scan(Tree tree,
              P p)
Overrides:
scan in class TreePathScanner<R,P>

visitClass

public R visitClass(ClassTree node,
                    P p)
Specified by:
visitClass in interface TreeVisitor<R,P>
Overrides:
visitClass in class TreeScanner<R,P>

visitMethod

public R visitMethod(MethodTree node,
                     P p)
Performs pseudo-assignment check: checks that the method obeys override and subtype rules to all overridden methods. The override rule specifies that a method, m1, may override a method m2 only if: Also, it issues a "missing.this" error for static method annotated receivers.

Specified by:
visitMethod in interface TreeVisitor<R,P>
Overrides:
visitMethod in class TreeScanner<R,P>

visitVariable

public R visitVariable(VariableTree node,
                       P p)
Specified by:
visitVariable in interface TreeVisitor<R,P>
Overrides:
visitVariable in class TreeScanner<R,P>

visitAssignment

public R visitAssignment(AssignmentTree node,
                         P p)
Performs two checks: subtyping and assignability checks, using commonAssignmentCheck(Tree, ExpressionTree, String, Object). If the subtype check fails, it issues a "assignment.invalid" error.

Specified by:
visitAssignment in interface TreeVisitor<R,P>
Overrides:
visitAssignment in class TreeScanner<R,P>

visitEnhancedForLoop

public R visitEnhancedForLoop(EnhancedForLoopTree node,
                              P p)
Performs a subtype check, to test whether the node expression iterable type is a subtype of the variable type in the enhanced for loop. If the subtype check fails, it issues a "type.incompatible" error.

Specified by:
visitEnhancedForLoop in interface TreeVisitor<R,P>
Overrides:
visitEnhancedForLoop in class TreeScanner<R,P>

visitMethodInvocation

public R visitMethodInvocation(MethodInvocationTree node,
                               P p)
Performs a method invocation check. An invocation of a method, m, on the receiver, r is valid only if:

Specified by:
visitMethodInvocation in interface TreeVisitor<R,P>
Overrides:
visitMethodInvocation in class TreeScanner<R,P>

visitNewClass

public R visitNewClass(NewClassTree node,
                       P p)
Performs a new class invocation check. An invocation of a constructor, c, is valid only if:

Specified by:
visitNewClass in interface TreeVisitor<R,P>
Overrides:
visitNewClass in class TreeScanner<R,P>

visitReturn

public R visitReturn(ReturnTree node,
                     P p)
Checks that the type of the return expression is a subtype of the enclosing method required return type. If not, it issues a "return.invalid" error.

Specified by:
visitReturn in interface TreeVisitor<R,P>
Overrides:
visitReturn in class TreeScanner<R,P>

visitUnary

public R visitUnary(UnaryTree node,
                    P p)
Performs assignability check using checkAssignability(AnnotatedTypeMirror, Tree).

Specified by:
visitUnary in interface TreeVisitor<R,P>
Overrides:
visitUnary in class TreeScanner<R,P>

visitCompoundAssignment

public R visitCompoundAssignment(CompoundAssignmentTree node,
                                 P p)
Performs assignability check using checkAssignability(AnnotatedTypeMirror, Tree).

Specified by:
visitCompoundAssignment in interface TreeVisitor<R,P>
Overrides:
visitCompoundAssignment in class TreeScanner<R,P>

visitNewArray

public R visitNewArray(NewArrayTree node,
                       P p)
Specified by:
visitNewArray in interface TreeVisitor<R,P>
Overrides:
visitNewArray in class TreeScanner<R,P>

visitParameterizedType

public R visitParameterizedType(ParameterizedTypeTree node,
                                P p)
Checks that the annotations on the type arguments supplied to a type or a method invocation are within the bounds of the type variables as declared, and issues the "generic.argument.invalid" error if they are not.

Specified by:
visitParameterizedType in interface TreeVisitor<R,P>
Overrides:
visitParameterizedType in class TreeScanner<R,P>

checkTypecastSafety

protected void checkTypecastSafety(TypeCastTree node,
                                   P p)

visitTypeCast

public R visitTypeCast(TypeCastTree node,
                       P p)
Specified by:
visitTypeCast in interface TreeVisitor<R,P>
Overrides:
visitTypeCast in class TreeScanner<R,P>

visitInstanceOf

public R visitInstanceOf(InstanceOfTree node,
                         P p)
Specified by:
visitInstanceOf in interface TreeVisitor<R,P>
Overrides:
visitInstanceOf in class TreeScanner<R,P>

commonAssignmentCheck

protected void commonAssignmentCheck(Tree varTree,
                                     ExpressionTree valueExp,
                                     String errorKey,
                                     P p)
Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.

Parameters:
varTree - the AST node for the variable
valueExp - the AST node for the value
errorKey - the error message to use if the check fails
p - a checker-specified parameter

commonAssignmentCheck

protected void commonAssignmentCheck(AnnotatedTypeMirror varType,
                                     ExpressionTree valueExp,
                                     String errorKey,
                                     P p)
Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.

Parameters:
varType - the annotated type of the variable
valueExp - the AST node for the value
errorKey - the error message to use if the check fails
p - a checker-specified parameter

commonAssignmentCheck

protected void commonAssignmentCheck(AnnotatedTypeMirror varType,
                                     AnnotatedTypeMirror valueType,
                                     Tree valueTree,
                                     String errorKey,
                                     P p)
Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and emits an error message (through the compiler's messaging interface) if it does.

Parameters:
varType - the annotated type of the variable
valueType - the annotated type of the value
valueTree - the location to use when reporting the error message
errorKey - the error message to use if the check fails
p - a checker-specified parameter

checkArrayInitialization

protected void checkArrayInitialization(AnnotatedTypeMirror type,
                                        List<? extends ExpressionTree> initializers,
                                        P p)

checkTypeArguments

protected void checkTypeArguments(List<? extends AnnotatedTypeMirror> typevars,
                                  List<? extends AnnotatedTypeMirror> typeargs,
                                  List<? extends Tree> typeargTrees,
                                  P p)
Checks that the annotations on the type arguments supplied to a type or a method invocation are within the bounds of the type variables as declared, and issues the "generic.argument.invalid" error if they are not.

Parameters:
typevars - the type variables from a class or method declaration
typeargs - the type arguments from the type or method invocation
typeargTrees - the type arguments as trees, used for error reporting
p -

checkMethodInvocability

protected boolean checkMethodInvocability(AnnotatedTypeMirror.AnnotatedExecutableType method,
                                          MethodInvocationTree node)
Tests whether the method can be invoked using the receiver of the 'node' method invocation, and issues a "method.invocation.invalid" if the invocation is invalid. This implementation tests whether the receiver in the method invocation is a subtype of the method receiver type.

Parameters:
method - the type of the invoked method
node - the method invocation node
Returns:
true iff the call of 'node' is a valid call

checkArguments

protected void checkArguments(List<? extends AnnotatedTypeMirror> requiredArgs,
                              List<? extends ExpressionTree> passedArgs,
                              P p)
A helper method to check that each passed argument is a subtype of the corresponding required argument, and issues "argument.invalid" error for each passed argument that not a subtype of the required one. Note this method requires the lists to have the same length, as it does not handle cases like var args.

Parameters:
requiredArgs - the required types
passedArgs - the expressions passed to the corresponding types
p -

checkOverride

protected boolean checkOverride(MethodTree overriderTree,
                                AnnotatedTypeMirror.AnnotatedDeclaredType enclosingType,
                                AnnotatedTypeMirror.AnnotatedExecutableType overridden,
                                AnnotatedTypeMirror.AnnotatedDeclaredType overriddenType,
                                P p)
Checks that an overriding method's return type, parameter types, and receiver type are correct with respect to the annotations on the overridden method's return type, parameter types, and receiver type.

This method returns the result of the check, but also emits error messages as a side effect.

Parameters:
overriderTree - the AST node of the overriding method
enclosingType - the declared type enclosing the overrider method
overridden - the type of the overridden method
overriddenType - the declared type enclosing the overridden method
p - an optional parameter (as supplied to visitor methods)
Returns:
true if the override check passed, false otherwise

checkAssignability

protected void checkAssignability(AnnotatedTypeMirror varType,
                                  Tree varTree)
Tests, for a re-assignment, whether the variable is assignable or not. If not, it emits an assignability.invalid error.

Parameters:
varType - the type of the variable being re-assigned
varTree - the tree used to access the variable in the assignment

validateTypeOf

public void validateTypeOf(Tree tree)
Tests whether the tree expressed by the passed type tree is a valid type, and emits an error if that is not the case (e.g. '@Mutable String').

Parameters:
tree - the AST type supplied by the user

shouldSkip

protected final boolean shouldSkip(ExpressionTree exprTree)
Tests whether the expression should not be checked because of the tree referring to unannotated classes, as specified in the checker.skipClasses property. It returns true if exprTree is a method invocation or a field access to a class whose qualified name matches @{link checker.skipClasses} expression. It also return true for conditional expressions where the true or false expressions should be skipped.

Parameters:
exprTree - any expression tree
Returns:
true if checker should not test exprTree

shouldSkip

protected final boolean shouldSkip(Element element)
Tests whether the class owner of the passed element is an unannotated class and matches the pattern specified in the checker.skipClasses property.

Parameters:
element - an element
Returns:
true iff the enclosing class of element should be skipped

visitAnnotation

public R visitAnnotation(AnnotationTree node,
                         P p)
Specified by:
visitAnnotation in interface TreeVisitor<R,P>
Overrides:
visitAnnotation in class TreeScanner<R,P>

visitCompilationUnit

public R visitCompilationUnit(CompilationUnitTree node,
                              P p)
Override Compilation Unit so we won't visit package names or imports

Specified by:
visitCompilationUnit in interface TreeVisitor<R,P>
Overrides:
visitCompilationUnit in class TreeScanner<R,P>