Skip to content

WIP: Add sealed unions to JAVA #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

artfuldev
Copy link
Member

@artfuldev artfuldev commented Feb 22, 2025

In this PR we allow generating sealed interfaces with permits for discriminated unions, as described in JEP-409 and made available in Java 17+

ADL supports unions, for example:

/// simple
union Authorisation {
  Void public;
  String forRole;
};

/// generic with 1 type arg
union Option<A> {
  Void none;
  A some;
};

/// generic with 2 type args
union Either<L, R> {
  L left;
  R right;
};

We simplify the output to:

public sealed interface Authorisation permits Authorisation.ForRole, Authorisation.Public {
  public record Public() implements Authorisation {}
  public record ForRole(String val) implements Authorisation {}
}

public sealed interface Option<A> permits Option.None, Option.Some {
  public record None<A>() implements Option<A> {}
  public record Some<A>(A val) implements Option<A> {}
}

public sealed interface Either<L, R> permits Either.Left, Either.Right {
  public record Left<L, R>(L val) implements Either<L, R> {}
  public record Right<L, R>(R val) implements Either<L, R> {}
}

if a specific option --sealed-unions is passed to adlc java

This means we can use pattern matching in switch expressions, and also since we use records, we get equals and hash code implementations for free.

public static String x(Authorisation a) {
  return switch (a) {
    case Public() -> "anyone";
    case ForRole(String role) -> role;
  };
}

public static <L, R> String x(Either<L, R> either) {
  return switch (either) {
    case Left(L left) -> left.toString();
    case Right(R right) -> right.toString();
  };
}

public static <A> String x(Option<A> x) {
  return switch (x) {
    case None() -> "";
    case Some(String val) -> val;
    case Some(A val) -> val.toString();
  };
}

Planned work

  • Add sealed union option
  • Generate sealed union code
  • Support generics
  • Generate backwards compatible JSON binding
  • Handle parcelable
  • Generate backwards compatible factory
  • Fix Import::ScopedName

@artfuldev artfuldev added the java label Feb 22, 2025
@artfuldev artfuldev changed the title Add sealed unions Add sealed unions to JAVA Feb 22, 2025
@artfuldev artfuldev changed the base branch from master to feature/python-backend February 22, 2025 23:23
@artfuldev artfuldev changed the title Add sealed unions to JAVA WIP: Add sealed unions to JAVA Feb 22, 2025
@artfuldev artfuldev force-pushed the feature/java/sealed-unions branch from be88557 to a5aee89 Compare February 24, 2025 12:23
@artfuldev artfuldev changed the base branch from feature/python-backend to master February 24, 2025 12:23
@artfuldev artfuldev force-pushed the feature/java/sealed-unions branch from 66a542c to 97fa016 Compare February 24, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant