docs: @Nullable
    public static AccessPath fromFieldAccess(FieldAccessNode fieldAccess) {
      ImmutableList.Builder<String> pathBuilder = ImmutableList.builder();
  
      Tree tree = fieldAccess.getTree();
      boolean isFieldAccess;
      while ((isFieldAccess = TreeUtils.isFieldAccess(tree)) || isAutoValueAccessor(tree)) {
        if (isFieldAccess) {
          pathBuilder.add(TreeUtils.getFieldName(tree));
        } else {
          // Must be an AutoValue accessor, since the `while` condition held but the `if` didn't.
          // Unwrap the method select from the call
          tree = ((MethodInvocationTree) tree).getMethodSelect();
          pathBuilder.add(TreeUtils.getMethodName(tree) + "()");
        }
  
        if (tree.getKind() == Kind.IDENTIFIER) {
          // Implicit `this` receiver
          return AccessPath.create(/*base=*/ null, pathBuilder.build());
        }
  
        tree = ((MemberSelectTree) tree).getExpression();
      }
  
      // Explicit `this` receiver
      if (tree.getKind() == Kind.IDENTIFIER
          && ((IdentifierTree) tree).getName().contentEquals("this")) {
        return AccessPath.create(/*base=*/ null, pathBuilder.build());
      }
  
      // Local variable receiver
      if (tree.getKind() == Kind.IDENTIFIER) {
        return AccessPath.create(TreeUtils.elementFromTree(tree), pathBuilder.build());
      }
  
      return null;
    }