grandstaish / paperparcel

Auto-generate Parcelable implementations for Java and Kotlin
https://grandstaish.github.io/paperparcel/
Apache License 2.0
500 stars 29 forks source link

Fields generated by `@Memoized` should be excluded automatically #181

Open ansman opened 7 years ago

ansman commented 7 years ago

This class:

public abstract class Foo {
    @Memoized
    public String someMethod() {
        return "foo";
    }
}

Will generate a field called someMethod that unfortunately isn't transient so PaperParcel complains. Ideally they should be excluded automatically.

grandstaish commented 7 years ago

Are you able to decompile the bytecode into Java and post it here? (I don't have any means of doing this myself because I'm currently in the process of moving overseas)

ansman commented 7 years ago

This class:

@AutoValue
public abstract class Foo {
    @Memoized
    public String foo() {
        return "foo";
    }
}

generates

@Generated("com.google.auto.value.processor.AutoValueProcessor")
 abstract class $AutoValue_Foo extends Foo {

  $AutoValue_Foo(
 ) {
  }

  @Override
  public String toString() {
    return "Foo{"
        + "}";
  }

  @Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }
    if (o instanceof Foo) {
      return true;
    }
    return false;
  }

  @Override
  public int hashCode() {
    int h = 1;
    return h;
  }

}

and

@Generated("com.google.auto.value.extension.memoized.MemoizeExtension")
final class AutoValue_Foo extends $AutoValue_Foo {
  private volatile String foo;

  AutoValue_Foo() {
    super();
  }

  @Override
  public String foo() {
    if (foo == null) {
      synchronized (this) {
        if (foo == null) {
          foo = super.foo();
          if (foo == null) {
            throw new NullPointerException("foo() cannot return null");
          }
        }
      }
    }
    return foo;
  }
}

The field always has the same name as the method.

If the field is nullable or primitive this is generated:

@Generated("com.google.auto.value.extension.memoized.MemoizeExtension")
final class AutoValue_Foo extends $AutoValue_Foo {
  private volatile String foo;

  private volatile boolean foo$Memoized;

  AutoValue_Foo() {
    super();
  }

  @Override
  @Nullable
  public String foo() {
    if (!foo$Memoized) {
      synchronized (this) {
        if (!foo$Memoized) {
          foo = super.foo();
          foo$Memoized = true;
        }
      }
    }
    return foo;
  }
}
grandstaish commented 7 years ago

It's a workaround, but for now you could exclude all volatile fields from being parcelled. You can do it globally via the ProcessorConfig:

@ProcessorConfig(
  options = @PaperParcel.Options(
    excludeModifiers = { Modifier.TRANSIENT, Modifier.STATIC, Modifier.VOLATILE }
  )
)
ansman commented 7 years ago

Yeah, that's what I did now. Ideally this issue should be fixed: https://github.com/google/auto/issues/406