Class OptionalVisitor

All Implemented Interfaces:
TreeVisitor<Void,Void>

public class OptionalVisitor extends BaseTypeVisitor<BaseAnnotatedTypeFactory>
The OptionalVisitor enforces the Optional Checker rules. These rules are described in the Checker Framework Manual.
See the Checker Framework Manual:
Optional Checker
  • Constructor Details

    • OptionalVisitor

      public OptionalVisitor(BaseTypeChecker checker)
      Create an OptionalVisitor.
      Parameters:
      checker - the associated OptionalChecker
  • Method Details

    • createTypeValidator

      protected BaseTypeValidator createTypeValidator()
      Overrides:
      createTypeValidator in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
    • visitConditionalExpression

      public Void visitConditionalExpression(ConditionalExpressionTree tree, Void p)
      Specified by:
      visitConditionalExpression in interface TreeVisitor<Void,Void>
      Overrides:
      visitConditionalExpression in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
    • handleTernaryIsPresentGet

      public void handleTernaryIsPresentGet(ConditionalExpressionTree tree)
      Part of rule #3.

      Pattern match for: VAR.isPresent() ? VAR.get().METHOD() : VALUE

      Prefer: VAR.map(METHOD).orElse(VALUE);

      Parameters:
      tree - a conditional expression that can perhaps be simplified
    • visitIf

      public Void visitIf(IfTree tree, Void p)
      Specified by:
      visitIf in interface TreeVisitor<Void,Void>
      Overrides:
      visitIf in class TreeScanner<Void,Void>
    • handleConditionalStatementIsPresentGet

      public void handleConditionalStatementIsPresentGet(IfTree tree)
      Part of rule #3.

      Pattern match for: if (VAR.isPresent()) { METHOD(VAR.get()); }

      Prefer: VAR.ifPresent(METHOD);

      Parameters:
      tree - an if statement that can perhaps be simplified
    • visitMethodInvocation

      public Void visitMethodInvocation(MethodInvocationTree tree, Void p)
      Description copied from class: BaseTypeVisitor
      Performs a method invocation check.

      An invocation of a method, m, on the receiver, r is valid only if:

      • passed arguments are subtypes of corresponding m parameters
      • r is a subtype of m receiver type
      • if m is generic, passed type arguments are subtypes of m type variables
      Specified by:
      visitMethodInvocation in interface TreeVisitor<Void,Void>
      Overrides:
      visitMethodInvocation in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
    • visitBinary

      public Void visitBinary(BinaryTree tree, Void p)
      Specified by:
      visitBinary in interface TreeVisitor<Void,Void>
      Overrides:
      visitBinary in class TreeScanner<Void,Void>
    • commonAssignmentCheck

      protected boolean commonAssignmentCheck(AnnotatedTypeMirror varType, ExpressionTree valueExpTree, @CompilerMessageKey String errorKey, Object... extraArgs)
      Description copied from class: BaseTypeVisitor
      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 is not valid.
      Overrides:
      commonAssignmentCheck in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
      Parameters:
      varType - the annotated type for the lvalue (usually a variable)
      valueExpTree - the AST node for the rvalue (the new value)
      errorKey - the error message key to use if the check fails
      extraArgs - arguments to the error message key, before "found" and "expected" types
      Returns:
      true if the check succeeds, false if an error message was issued
    • handleCreationElimination

      public void handleCreationElimination(MethodInvocationTree tree)
      Rule #4.

      Pattern match for: CREATION().PROPAGATION()*.ELIMINATION()

      Prefer: VAR.ifPresent(METHOD);

      Parameters:
      tree - a method invocation that can perhaps be simplified
    • handleNestedOptionalCreation

      public void handleNestedOptionalCreation(MethodInvocationTree tree)
      Partial support for Rule #5 and Rule #7.

      Rule #5: Avoid nested Optional chains, or operations that have an intermediate Optional value.

      Rule #7: Don't use Optional to wrap any collection type.

      Certain types are illegal, such as Optional<Optional>. The type validator may see a supertype of the most precise run-time type; for example, it may see the type as Optional<? extends Object>, and it would not flag any problem with such a type. This method checks at Optional creation sites.

      TODO: This finds only some Optional<Optional>: those that consist of Optional.of(optionalExpr) or Optional.ofNullable(optionalExpr), where optionalExpr has type Optional. There are other ways that Optional<Optional> can be created, such as optionalExpr.map(Optional::of).

      TODO: Also check at collection creation sites, but there are so many of them, and there often are not values of the element type at the collection creation site.

      Parameters:
      tree - a method invocation that might create an Optional of an illegal type
    • visitVariable

      public Void visitVariable(VariableTree tree, Void p)
      Rule #6 (partial).

      Don't use Optional in fields and method parameters.

      Specified by:
      visitVariable in interface TreeVisitor<Void,Void>
      Overrides:
      visitVariable in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
    • skipBlocks

      public static StatementTree skipBlocks(StatementTree tree)
      If the given tree is a block tree with a single element, return the enclosed non-block statement. Otherwise, return the same tree.
      Parameters:
      tree - a statement tree
      Returns:
      the single enclosed statement, if it exists; otherwise, the same tree
    • visitMemberReference

      public Void visitMemberReference(MemberReferenceTree tree, Void p)
      Specified by:
      visitMemberReference in interface TreeVisitor<Void,Void>
      Overrides:
      visitMemberReference in class BaseTypeVisitor<BaseAnnotatedTypeFactory>