Skip to content
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

Subclass discovery depends on compilation order #7

Open
manuelbernhardt opened this issue Mar 2, 2015 · 3 comments
Open

Subclass discovery depends on compilation order #7

manuelbernhardt opened this issue Mar 2, 2015 · 3 comments

Comments

@manuelbernhardt
Copy link
Contributor

I think this is yet another macro bitten by the infamous [SI-8776](https://issues.scala-lang.org/browse/SI-8776 - discussion [here]%28https://groups.google.com/forum/#!topic/scala-user/oJP9aqs88rM%29). A potential pragmatic workaround is to shuffle classes around until it forces the compilation order to be correct, i.e. to have potential subclasses been typed before the macro is invoked.

I suppose that until the issue is closed it would perhaps be a good idea to include this in the docs, under pitfalls or so.

@yanns
Copy link
Contributor

yanns commented Mar 2, 2015

(just to fix the link)
https://issues.scala-lang.org/browse/SI-8776

@OlegIlyenko
Copy link
Contributor

As far as I'm aware, deriveJSON is the only macro that uses knownDirectSubclasses. It requires the sealed abstract class or trait, so definitional spread across multiple files should not be a problem. But All within one source file all possible subclasses should be defined before macro is invoked - I guess you mean this one?

I agree, we definitely need to document it. I will add to the readme.

@manuelbernhardt
Copy link
Contributor Author

This issue arrises if the macro is invoked on any class that has not been typed yet by the compiler. What I've used as a workaround is to declare all of the classes in one file, and then to declare one object at the end of that file that contains all of the deriveJSON calls as well as two def-s for parsing and writing:

  def parse(json: String): Option[Any] =
    fromJSON[UserCommand](json).toOption

  def write[A](a: A): String = {
    val res = a match {
      case evt: UserEvent => eventJson.write(evt)
      case cmd: UserCommand => commandJson.write(cmd)
      case other => throw new RuntimeException("What the hell? " + other)
    }

    res match {
      case JNothing => "{}"
      case jval => compact(render(jval))
    }
  }

In this way the compiler seems to type all the subclasses before "seeing" the macro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants