Class OptionalImplVisitor

All Implemented Interfaces:
TreeVisitor<Void,Void>

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

    • OptionalImplVisitor

      public OptionalImplVisitor(BaseTypeChecker checker)
      Create an OptionalImplVisitor.
      Parameters:
      checker - the associated instance of OptionalImplChecker
  • Method Details

    • createTypeValidator

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

      @Pure public Set<String> getNamesOfMethodsToVerifyWithNonEmptyChecker()
      Returns the set of methods that should be verified using the NonEmptyChecker.

      This should only be called by the Non-Empty Checker.

      Returns:
      the set of methods that should be verified using the NonEmptyChecker
    • 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);

      Also matches:

           if (VAR.isPresent()) {
              x = METHOD(VAR.get());
           } else {
              x = OTHER;
           }
       
      Where x is some variable (e.g., a field, a local variable).

      Prefer: x = VAR.map(METHOD).orElse(OTHER);

      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>
    • processMethodTree

      public void processMethodTree(String className, MethodTree methodDecl)
      Description copied from class: BaseTypeVisitor
      Type-check methodTree. Subclasses should override this method instead of BaseTypeVisitor.visitMethod(MethodTree, Void).
      Overrides:
      processMethodTree in class BaseTypeVisitor<BaseAnnotatedTypeFactory>
      Parameters:
      className - the class that contains the method, for diagnostics only
      methodDecl - the method to type-check
    • 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()

      CREATION() wraps a value in an instance of Optional, and PROPAGATION() is a method (or a sequence of methods) that operate on and return Optional. ELIMINATION() is the terminal operation that unwraps the Optional value (i.e., Optional.get()).

      This creation-propagation-elimination pattern can be eliminated by directly checking whether a value is null before invoking methods on it.

      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 Optional<X> where X is impermissable: Optional or Collection
    • 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>