docs: @Nullable
    public static <A extends AbstractValue<A>, S extends Store<S>, T extends TransferFunction<A, S>>
        A expressionDataflow(TreePath exprPath, Context context, T transfer) {
      final Tree leaf = exprPath.getLeaf();
      Preconditions.checkArgument(
          leaf instanceof ExpressionTree,
          "Leaf of exprPath must be of type ExpressionTree, but was %s",
          leaf.getClass().getName());
  
      final ExpressionTree expr = (ExpressionTree) leaf;
      final TreePath enclosingMethodPath = findEnclosingMethodOrLambdaOrInitializer(exprPath);
      if (enclosingMethodPath == null) {
        // expression is not part of a method, lambda, or initializer
        return null;
      }
  
      final Tree method = enclosingMethodPath.getLeaf();
      if (method instanceof MethodTree && ((MethodTree) method).getBody() == null) {
        // expressions can occur in abstract methods, for example {@code Map.Entry} in:
        //
        //   abstract Set<Map.Entry<K, V>> entries();
        return null;
      }
  
      return methodDataflow(enclosingMethodPath, context, transfer).getAnalysis().getValue(expr);
    }