@@ -7,6 +7,16 @@ import scala.collection.mutable
77import scala .language .higherKinds
88import scala .reflect .macros ._
99
10+ private case class MagnoliaConfig [ProxyType , IgnoreType ](
11+ proxyType : ProxyType ,
12+ ignoreType : IgnoreType ,
13+ readOnly : Boolean = false ,
14+ minFields : Int = - 1 ,
15+ maxFields : Int = Int .MaxValue ,
16+ minCases : Int = - 1 ,
17+ maxCases : Int = Int .MaxValue
18+ )
19+
1020/** the object which defines the Magnolia macro */
1121object Magnolia {
1222 import CompileTimeState ._
@@ -42,12 +52,32 @@ object Magnolia {
4252 * split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ... </pre> will suffice, however the qualifications regarding
4353 * additional type parameters and implicit parameters apply equally to `split` as to `join`.
4454 */
45- def gen [T : c.WeakTypeTag ](c : whitebox.Context ): c.Tree = Stack .withContext(c) { (stack, depth) =>
55+ def genWith [T : c.WeakTypeTag , C <: Config with Singleton : c.WeakTypeTag ](c : whitebox.Context ): c.Tree = {
56+ import c .universe ._
57+
58+ val weakConfig = weakTypeOf[C ]
59+ val proxyType : c.Type = weakConfig.decl(TypeName (" Proxy" )).info
60+ val ignoreType : c.Type = weakConfig.decl(TypeName (" Ignore" )).info
61+ val NullaryMethodType (ConstantType (Constant (readOnly : Boolean ))) = weakConfig.decl(TermName (" readOnly" )).info
62+ val NullaryMethodType (ConstantType (Constant (minFields : Int ))) = weakConfig.decl(TermName (" minFields" )).info
63+ val NullaryMethodType (ConstantType (Constant (maxFields : Int ))) = weakConfig.decl(TermName (" maxFields" )).info
64+ val NullaryMethodType (ConstantType (Constant (minCases : Int ))) = weakConfig.decl(TermName (" minCases" )).info
65+ val NullaryMethodType (ConstantType (Constant (maxCases : Int ))) = weakConfig.decl(TermName (" maxCases" )).info
66+
67+ genMacro[T , c.Type , c.Type ](c, Some (MagnoliaConfig (proxyType, ignoreType, readOnly, minFields, maxFields, minCases, maxCases)))
68+ }
69+
70+ def gen [T : c.WeakTypeTag ](c : whitebox.Context ): c.Tree = {
71+ genMacro(c, None )
72+ }
73+
74+ private def genMacro [T : c.WeakTypeTag , ProxyType , IgnoreType ](c : whitebox.Context , config : Option [MagnoliaConfig [ProxyType , IgnoreType ]]): c.Tree = Stack .withContext(c) { (stack, depth) =>
4675 import c .internal ._
4776 import c .universe ._
4877 import definitions ._
4978
5079 val genericType = weakTypeOf[T ]
80+
5181 val genericSymbol = genericType.typeSymbol
5282
5383 def error (message : => String ): Nothing = c.abort(c.enclosingPosition, if (depth > 1 ) " " else s " magnolia: $message" )
@@ -318,6 +348,12 @@ object Magnolia {
318348 val resultType = appliedType(typeConstructor, genericType)
319349 val typeName = c.freshName(TermName (" typeName" ))
320350
351+ def isIgnored (termSymbol : c.universe.TermSymbol ): Boolean = {
352+ config.map(_.ignoreType).exists { ignoreType =>
353+ termSymbol.annotations.map(_.tree.symbol).contains(ignoreType)
354+ }
355+ }
356+
321357 def typeNameOf (tpe : Type ): Tree = {
322358 val symbol = tpe.typeSymbol
323359 val typeArgNames = for (typeArg <- tpe.typeArgs) yield typeNameOf(typeArg)
@@ -383,8 +419,11 @@ object Magnolia {
383419 .map(_.map(_.asTerm))
384420
385421 val caseClassParameters = genericType.decls.sorted.collect(
386- if (isValueClass) { case p : TermSymbol if p.isParamAccessor && p.isMethod => p }
387- else { case p : TermSymbol if p.isCaseAccessor && ! p.isMethod => p }
422+ if (isValueClass) {
423+ case p : TermSymbol if p.isParamAccessor && p.isMethod => p
424+ } else {
425+ case p : TermSymbol if p.isCaseAccessor && ! p.isMethod && ! isIgnored(p) => p
426+ }
388427 )
389428
390429 val (factoryObject, factoryMethod) = {
0 commit comments