Class CalledMethodsTransfer

All Implemented Interfaces:
ForwardTransferFunction<AccumulationValue,AccumulationStore>, TransferFunction<AccumulationValue,AccumulationStore>, NodeVisitor<TransferResult<AccumulationValue,AccumulationStore>,TransferInput<AccumulationValue,AccumulationStore>>
Direct Known Subclasses:
ResourceLeakTransfer

public class CalledMethodsTransfer extends AccumulationTransfer
A transfer function that accumulates the names of methods called.
  • Constructor Details

    • CalledMethodsTransfer

      public CalledMethodsTransfer(CalledMethodsAnalysis analysis)
      Create a new CalledMethodsTransfer.
      Parameters:
      analysis - the analysis
  • Method Details

    • visitMethodInvocation

      Specified by:
      visitMethodInvocation in interface NodeVisitor<TransferResult<AccumulationValue,AccumulationStore>,TransferInput<AccumulationValue,AccumulationStore>>
      Overrides:
      visitMethodInvocation in class CFAbstractTransfer<AccumulationValue,AccumulationStore,AccumulationTransfer>
    • accumulate

      public void accumulate(Node node, TransferResult<AccumulationValue,AccumulationStore> result, String... values)
      Description copied from class: AccumulationTransfer
      Updates the estimate of how many things node has accumulated.

      If the node is an invocation of a method that returns its receiver, then its receiver's type will also be updated. In a chain of method calls, this process will continue backward as long as each receiver is itself a receiver-returning method invocation.

      For example, suppose node is the expression a.b().c(), the new value (added by the accumulation analysis because of the .c() call) is "foo", and b and c return their receiver. This method will directly update the estimate of a.b().c() to include "foo". In addition, the estimates for the expressions a.b() and a would have their estimates updated to include "foo", because c and b (respectively) return their receivers. Note that due to what kind of values can be held in the store, this information is lost outside the method chain. That is, the returns-receiver propagated information is lost outside the expression in which the returns-receiver method invocations are nested.

      As a concrete example, consider the Called Methods accumulation checker: if build requires a, b, and c to be called, then foo.a().b().c().build(); will typecheck (they are in one fluent method chain), but foo.a().b().c(); foo.build(); will not -- the store does not keep the information that a, b, and c have been called outside the chain. foo's type will be CalledMethods("a"), because only a() was called directly on foo. For such code to typecheck, the Called Methods accumulation checker uses an additional rule: the return type of a receiver-returning method rr() is CalledMethods("rr"). This rule is implemented directly in the TreeAnnotator subclass defined in the Called Methods type factory.

      Overrides:
      accumulate in class AccumulationTransfer
      Parameters:
      node - the node whose estimate should be expanded
      result - the transfer result containing the store to be modified
      values - the new accumulation values