binary-compatibility-validator icon indicating copy to clipboard operation
binary-compatibility-validator copied to clipboard

After upgrading to kotlin 1.5.0, the kotlin-parcelize generated code started to be reported as public by binary-compatibility-validator

Open 4brunu opened this issue 2 years ago • 0 comments

Related to: https://github.com/Kotlin/binary-compatibility-validator/issues/55

Hi,

I'm using kotlin-parcelize plugin to generate the parcelable code in the internal data classes in my project.

Let's consider the following kotlin data class, that is marked as internal.

@Parcelize
internal data class Country (
    val code: String,
    val name: String
) : Parcelable

I have made the following tests with binary-compatibility-validator 0.5.0. And there is a difference when using kotlin 1.5.0 and 1.4.32.

Before upgrading to kotlin 1.5.0, using kotlin 1.4.32, the command ./gradlew teleconsultationandroid:apiDump wouldn't return any output related to the class Country. And to help debug this issue, here is the compiled code of Country in kotlin 1.4.32.

Compiled `Country` data class using kotlin 1.4.32. import android.os.Parcel; import android.os.Parcelable; import kotlin.Metadata; import kotlin.jvm.internal.Intrinsics; import kotlinx.parcelize.Parcelize; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable;

@Parcelize @Metadata(...) /* compiled from: Country.kt */ public final class Country implements Parcelable { public static final Parcelable.Creator<Country> CREATOR = new Creator(); @NotNull private final String code; @NotNull private final String name;

@Metadata(bv = {1, 0, 3}, d1 = {}, d2 = {}, k = 3, mv = {1, 4, 2})
public static class Creator implements Parcelable.Creator<Country> {
    @Override // android.os.Parcelable.Creator
    @NotNull
    public final Country createFromParcel(@NotNull Parcel parcel) {
        Intrinsics.checkNotNullParameter(parcel, "in");
        return new Country(parcel.readString(), parcel.readString());
    }

    @Override // android.os.Parcelable.Creator
    @NotNull
    public final Country[] newArray(int i) {
        return new Country[i];
    }
}

public Country(@NotNull String str, @NotNull String str2) {
    Intrinsics.checkNotNullParameter(str, "code");
    Intrinsics.checkNotNullParameter(str2, "name");
    this.code = str;
    this.name = str2;
}

public static /* synthetic */ Country copy$default(Country country, String str, String str2, int i, Object obj) {
    if ((i & 1) != 0) {
        str = country.code;
    }
    if ((i & 2) != 0) {
        str2 = country.name;
    }
    return country.copy(str, str2);
}

@NotNull
public final String component1() {
    return this.code;
}

@NotNull
public final String component2() {
    return this.name;
}

@NotNull
public final Country copy(@NotNull String str, @NotNull String str2) {
    Intrinsics.checkNotNullParameter(str, "code");
    Intrinsics.checkNotNullParameter(str2, "name");
    return new Country(str, str2);
}

public int describeContents() {
    return 0;
}

public boolean equals(@Nullable Object obj) {
    if (this != obj) {
        if (obj instanceof Country) {
            Country country = (Country) obj;
            if (!Intrinsics.areEqual(this.code, country.code) || !Intrinsics.areEqual(this.name, country.name)) {
                return false;
            }
        }
        return false;
    }
    return true;
}

@NotNull
public final String getCode() {
    return this.code;
}

@NotNull
public final String getName() {
    return this.name;
}

public int hashCode() {
    int i = 0;
    String str = this.code;
    int hashCode = (str != null ? str.hashCode() : 0) * 31;
    String str2 = this.name;
    if (str2 != null) {
        i = str2.hashCode();
    }
    return hashCode + i;
}

@NotNull
public String toString() {
    return "Country(code=" + this.code + ", name=" + this.name + ")";
}

public void writeToParcel(@NotNull Parcel parcel, int i) {
    Intrinsics.checkNotNullParameter(parcel, "parcel");
    parcel.writeString(this.code);
    parcel.writeString(this.name);
}

}

But after upgrading to kotlin 1.5.0, the command ./gradlew teleconsultationandroid:apiDump started returing the following output.

public final class com/sample/project/Country$Creator : android/os/Parcelable$Creator {
	public fun <init> ()V
	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
	public final fun createFromParcel (Landroid/os/Parcel;)L com/sample/project/Country;
	public synthetic fun newArray (I)[Ljava/lang/Object;
	public final fun newArray (I)[Lcom/sample/project/Country;
}

And here is the output of the compiled code in kotlin 1.5.0.

Compiled `Country` data class using kotlin 1.5.0. import android.os.Parcel; import android.os.Parcelable; import kotlin.Metadata; import kotlin.jvm.internal.Intrinsics; import kotlinx.parcelize.Parcelize; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable;

@Parcelize @Metadata(...) /* compiled from: Country.kt */ public final class Country implements Parcelable { @NotNull public static final Parcelable.Creator<Country> CREATOR = new Creator(); @NotNull private final String code; @NotNull private final String name;

@Metadata(bv = {1, 0, 3}, d1 = {}, d2 = {}, k = 3, mv = {1, 5, 1})
/* compiled from: Country.kt */
public static final class Creator implements Parcelable.Creator<Country> {
    @Override // android.os.Parcelable.Creator
    @NotNull
    public final Country createFromParcel(@NotNull Parcel parcel) {
        Intrinsics.checkNotNullParameter(parcel, "parcel");
        return new Country(parcel.readString(), parcel.readString());
    }

    @Override // android.os.Parcelable.Creator
    @NotNull
    public final Country[] newArray(int i) {
        return new Country[i];
    }
}

public Country(@NotNull String str, @NotNull String str2) {
    Intrinsics.checkNotNullParameter(str, "code");
    Intrinsics.checkNotNullParameter(str2, "name");
    this.code = str;
    this.name = str2;
}

public static /* synthetic */ Country copy$default(Country country, String str, String str2, int i, Object obj) {
    if ((i & 1) != 0) {
        str = country.code;
    }
    if ((i & 2) != 0) {
        str2 = country.name;
    }
    return country.copy(str, str2);
}

@NotNull
public final String component1() {
    return this.code;
}

@NotNull
public final String component2() {
    return this.name;
}

@NotNull
public final Country copy(@NotNull String str, @NotNull String str2) {
    Intrinsics.checkNotNullParameter(str, "code");
    Intrinsics.checkNotNullParameter(str2, "name");
    return new Country(str, str2);
}

public int describeContents() {
    return 0;
}

public boolean equals(@Nullable Object obj) {
    if (this == obj) {
        return true;
    }
    if (!(obj instanceof Country)) {
        return false;
    }
    Country country = (Country) obj;
    if (!Intrinsics.areEqual(this.code, country.code)) {
        return false;
    }
    return Intrinsics.areEqual(this.name, country.name);
}

@NotNull
public final String getCode() {
    return this.code;
}

@NotNull
public final String getName() {
    return this.name;
}

public int hashCode() {
    return (this.code.hashCode() * 31) + this.name.hashCode();
}

@NotNull
public String toString() {
    return "Country(code=" + this.code + ", name=" + this.name + ')';
}

public void writeToParcel(@NotNull Parcel parcel, int i) {
    Intrinsics.checkNotNullParameter(parcel, "out");
    parcel.writeString(this.code);
    parcel.writeString(this.name);
}

}

Here is the sample project

https://github.com/4brunu/kotlin-binary-compatibility-validator-issue

To dump the API, just run make or ./gradlew mylibrary:apiDump and check the result file under mylibrary/api/mylibrary.api.

Here is the api file with kotlin 1.4.32

Commit

mylibrary.api

Here is the api file with kotlin 1.5.0

Commit

mylibrary.api

This PR https://github.com/Kotlin/binary-compatibility-validator/pull/60 tried to fix this issue, but it seems that it didn't worked.

I have update the sample project to Kotlin 1.7.20 and binary-compatibility-validator 0.12.1 but the issue is still there.

Thanks

4brunu avatar Nov 21 '22 14:11 4brunu