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
Add possibility to separate gen
from combine
#279
Conversation
…ass derivation Make it possible to export both semiauto and auto derivations, as well as more than one auto derivation through one import
We have a lot of requests to customise the derivation but keep reaching for annotations when we don't know what to do. trait Config {
type Proxy <: Singleton { type Typeclass[A] }
type Ignore <: annotation.Annotation
val readOnly: Boolean
val minFields: Int
val maxFields: Int
val minCases: Int
val maxCases: Int
}
def genWith[T: c.WeakTypeTag, C <: Config with Singleton: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.internal._
import c.universe._
weakTypeOf[C].decls.toList.map(x => x -> x.typeSignature).foreach(println)
Magnolia.gen[T](c)
}
object CsvConfig extends Magnolia.Config {
type Proxy = Csv.type
type Ignore = transient
final val readOnly = true
final val minFields = 0
final val maxFields = -1
final val minCases = 0
final val maxCases = -1
}
implicit def deriveCsv[A]: Csv[A] = macro Magnolia.genWith[A, CsvConfig.type]
/*
(constructor CsvConfig,()magnolia.examples.Csv.CsvConfig.type)
(type Proxy,magnolia.examples.Csv.type)
(type Ignore,transient)
(value readOnly,=> Boolean(true))
(value readOnly,Boolean(true))
(value minFields,=> Int(0))
(value minFields,Int(0))
(value maxFields,=> Int(-1))
(value maxFields,Int(-1))
(value minCases,=> Int(0))
(value minCases,Int(0))
(value maxCases,=> Int(-1))
(value maxCases,Int(-1))
*/ |
Hey there @joroKr21 - sorry about the delay. I'll preface by saying I would accept any encoding for this, including the one you proposed. That said, I don't particularly think annotations are a bad fit for this. Most people have negative associations with annotations because how people use them at runtime - but as a compile-time thing I think they are completely fine! Especially for this particular usage, to pass static information to a macro. They are easy to use and easy to document. I'm a bit skeptical towards the
I don't exactly know where |
I may be traumatised by Spring when it comes to configuration with annotations 😃
I actually like that because you can see all configuration options at a glance and you have autocomplete etc.
That's a valid point. Still I'm not sure which is better or worse. |
Aren't we all :) The
If it's the discoverability we want we could scope all the annotations inside a
I like this better, but there will still be backwards compatibility issues when adding a parameter, unless we provide an overloaded constructor. |
@oyvindberg Am I understand right that if |
@plokhotnyuk As long as it doesn't cross any sbt project boundary (where an old version of magnolia might have been evicted in favour of a newever version in a downstream project) I suppose that's true. I'm just wary I suppose after seeing #266 .
I would be incredibly surprised if they didn't, but let's find out! |
In jsoniter-scala for configuration of codec derivation I've used a class with a private constructor and builder-like methods. The expression of configuration is passed to the |
So I did some hacking on a scala 3 magnolia here one afternoon, and so far my impression is that compile-time annotations work just fine, and the In fact, if we want to cross-compile code which uses magnolia between Scala 2 and 3 I think we'll have to do something in that direction, to separate |
This solves two related issues with magnolia:
auto/semiauto
Some people prefer automatic derivation, while others prefer semiauto. As it stands now the type class author has to decide which one to offer (based on the existence of
implicit
of thegen
method which is implemented by the magnolia macro)This choice should be made by users instead. The mechanism introduced in this PR enables a type class author to offer both
Bundling more than one type class derivation behind one import
As it stands now, it's not really possible to offer more than one type class derivation through a wildcard import, because they ultimately need to be implemented in an
object
, where thecombine
methods and so on would clash.Workarounds
If you look around you'll find that many projects have workarounds by writing their own macros around the magnolia macro. For instance:
Proposed solution
Add an annotation to
gen
where we can specify theobject
which has thecombine
method and the rest of the machinery.For now this annotation is called
@proxy
, but I'm sure there are better names.Example, given two non-interesting type classes called
ToString1
andToString2
: