code: public static void visitCallHierarchy(GroovyExpression expr, CallHierarchyVisitor visitor) {
  
          if (expr == null) {
              visitor.visitNullCaller();
              return;
          }
          if (expr instanceof AbstractFunctionExpression) {
              AbstractFunctionExpression functionCall = (AbstractFunctionExpression)expr;
              if (!visitor.preVisitFunctionCaller(functionCall)) {
                  return;
              }
              GroovyExpression caller = functionCall.getCaller();
              visitCallHierarchy(caller, visitor);
              if (!visitor.postVisitFunctionCaller(functionCall)) {
                  return;
              }
          } else {
              visitor.visitNonFunctionCaller(expr);
          }
      }
docs: Visits all expressions in the call hierarchy of an expression.  For example,
  in the expression g.V().has('x','y'), the order would be
  <ol>
  <li>pre-visit has('x','y')</li>
  <li>pre-visit V()</li>
  <li>visit g (non-function caller)</li>
  <li>post-visit V()</li>
  <li>post-visit has('x','y')</li>
  </ol>
  @param expr
  @param visitor