@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;
  }
@ 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 { tree = ( ( MethodInvocationTree ) tree ) . getMethodSelect ( ) ; pathBuilder . add ( TreeUtils . getMethodName ( tree ) + "()" ) ; } if ( tree . getKind ( ) == Kind . IDENTIFIER ) { return AccessPath . create ( null , pathBuilder . build ( ) ) ; } tree = ( ( MemberSelectTree ) tree ) . getExpression ( ) ; } if ( tree . getKind ( ) == Kind . IDENTIFIER && ( ( IdentifierTree ) tree ) . getName ( ) . contentEquals ( "this" ) ) { return AccessPath . create ( null , pathBuilder . build ( ) ) ; } if ( tree . getKind ( ) == Kind . IDENTIFIER ) { return AccessPath . create ( TreeUtils . elementFromTree ( tree ) , pathBuilder . build ( ) ) ; } return null ; }
Creates an AccessPath from field reads / AutoValue accessor we can track and returns null
otherwise (for example, when the receiver of the field access contains an array access or
non-AutoValue method call.