@@ -36,16 +36,41 @@ trait ConfigurationMacroUtils:
36
36
case failure : ImplicitSearchFailure =>
37
37
None
38
38
39
+ private val FieldStyleAlreadyConfigured = " FieldStyle is already configured"
40
+
41
+ private def showUnknownConfigTree (tree : String ): String =
42
+ s " Unknown tree. Config must be an inlined given. \n Tree: $tree"
43
+
44
+ private def mergeWriterMacroConfigs (
45
+ writerBuilderConfig : WriterBuilderMacroConfig ,
46
+ jsonConfig : WriterBuilderMacroConfig
47
+ ): WriterBuilderMacroConfig =
48
+ writerBuilderConfig.copy(fieldStyle =
49
+ writerBuilderConfig.fieldStyle.orElse(jsonConfig.fieldStyle)
50
+ )
51
+
52
+ private def mergeReaderMacroConfigs (
53
+ readerBuilderConfig : ReaderBuilderMacroConfig ,
54
+ jsonConfig : ReaderBuilderMacroConfig
55
+ ): ReaderBuilderMacroConfig =
56
+ readerBuilderConfig.copy(
57
+ fieldStyle = readerBuilderConfig.fieldStyle.orElse(jsonConfig.fieldStyle),
58
+ isStrict = readerBuilderConfig.isStrict.orElse(jsonConfig.isStrict)
59
+ )
60
+
39
61
def prepareWriterProductFields [T : Type ](
40
- config : Expr [WriterBuilder [T ]]
62
+ config : Expr [WriterBuilder [T ]],
63
+ jsonConfig : Expr [JsonConfiguration ]
41
64
): List [WriterField ] =
42
- val macroConfig = parseWriterBuilderMacroConfig[T ](config)
43
- val updates = macroConfig.update.map(it => it.name -> it).toMap
65
+ val writerConfig = parseWriterBuilderMacroConfig[T ](config)
66
+ val parsedJsonConfig = parseWriterMacroJsonConfig(jsonConfig)
67
+ val mergedConfig = mergeWriterMacroConfigs(writerConfig, parsedJsonConfig)
68
+ val updates = mergedConfig.update.map(it => it.name -> it).toMap
44
69
val tpe = TypeRepr .of[T ]
45
70
tpe.typeSymbol.caseFields.zipWithIndex
46
- .filterNot((symbol, _) => macroConfig .delete(symbol.name))
71
+ .filterNot((symbol, _) => mergedConfig .delete(symbol.name))
47
72
.collect { (symbol, idx) =>
48
- val name = macroConfig .fieldStyle.fold(symbol.name)(
73
+ val name = mergedConfig .fieldStyle.fold(symbol.name)(
49
74
FieldStyle .applyStyle(symbol.name, _)
50
75
)
51
76
updates.get(symbol.name) match
@@ -65,7 +90,49 @@ trait ConfigurationMacroUtils:
65
90
tpe = tpe.memberType(symbol),
66
91
newName = None
67
92
)
68
- } ::: macroConfig.add
93
+ } ::: mergedConfig.add
94
+
95
+ private def parseWriterMacroJsonConfig (
96
+ config : Expr [JsonConfiguration ]
97
+ ): WriterBuilderMacroConfig = {
98
+ @ tailrec
99
+ def loop (
100
+ config : Expr [JsonConfiguration ],
101
+ acc : WriterBuilderMacroConfig = WriterBuilderMacroConfig ()
102
+ ): WriterBuilderMacroConfig =
103
+ config match
104
+ case ' {
105
+ JsonConfiguration .default
106
+ } =>
107
+ acc
108
+
109
+ case ' {
110
+ ($rest : JsonConfiguration ).strict
111
+ } =>
112
+ loop(rest, acc)
113
+
114
+ case ' {
115
+ ($rest : JsonConfiguration ).fieldStyle($ { fieldStyle }: FieldStyle )
116
+ } =>
117
+ acc.fieldStyle match
118
+ case None =>
119
+ loop(rest, acc.copy(fieldStyle = Some (fieldStyle.valueOrAbort)))
120
+ case Some (_) =>
121
+ report.errorAndAbort(FieldStyleAlreadyConfigured )
122
+
123
+ case other =>
124
+ other.asTerm match
125
+ case Inlined (_, _, term) =>
126
+ loop(term.asExprOf[JsonConfiguration ])
127
+ case _ =>
128
+ report.errorAndAbort(
129
+ showUnknownConfigTree(
130
+ other.asTerm.show(using Printer .TreeStructure )
131
+ )
132
+ )
133
+
134
+ loop(traverseTree(config.asTerm).asExprOf[JsonConfiguration ])
135
+ }
69
136
70
137
private def parseWriterBuilderMacroConfig [T : Type ](
71
138
config : Expr [WriterBuilder [T ]]
@@ -362,24 +429,28 @@ trait ConfigurationMacroUtils:
362
429
loop(term.asExprOf[WriterBuilder [T ]])
363
430
case _ =>
364
431
report.errorAndAbort(
365
- s " Unknown tree. Config must be an inlined given. \n Tree: ${other.asTerm
366
- .show(using Printer .TreeStructure )}"
432
+ showUnknownConfigTree(
433
+ other.asTerm.show(using Printer .TreeStructure )
434
+ )
367
435
)
368
436
369
437
loop(traverseTree(config.asTerm).asExprOf[WriterBuilder [T ]])._1
370
438
371
439
end parseWriterBuilderMacroConfig
372
440
373
441
def prepareReaderProductFields [T : Type ](
374
- config : Expr [ReaderBuilder [T ]]
442
+ config : Expr [ReaderBuilder [T ]],
443
+ jsonConfig : Expr [JsonConfiguration ]
375
444
): (List [ReaderField ], IsStrict ) =
376
- val macroConfig = parseReaderBuilderMacroConfig[T ](config)
445
+ val readerConfig = parseReaderBuilderMacroConfig[T ](config)
446
+ val parsedJsonConfig = parseReaderMacroJsonConfig(jsonConfig)
447
+ val mergedConfig = mergeReaderMacroConfigs(readerConfig, parsedJsonConfig)
377
448
val tpe = TypeRepr .of[T ]
378
449
val defaults = collectDefaults[T ]
379
450
val fields = tpe.typeSymbol.caseFields.zipWithIndex
380
451
.map { case (symbol, idx) =>
381
452
val default = defaults.get(idx).map(_.asExprOf[Any ])
382
- macroConfig .extracted.get(symbol.name) match
453
+ mergedConfig .extracted.get(symbol.name) match
383
454
case Some (field : ReaderField .Basic ) =>
384
455
val updatedDefault = field.extractor match
385
456
case None => default
@@ -392,15 +463,15 @@ trait ConfigurationMacroUtils:
392
463
)
393
464
.map(_.asExprOf[Any ])
394
465
395
- field.update(idx, updatedDefault, macroConfig .fieldStyle)
466
+ field.update(idx, updatedDefault, mergedConfig .fieldStyle)
396
467
397
468
case Some (field) =>
398
- field.update(idx, default, macroConfig .fieldStyle)
469
+ field.update(idx, default, mergedConfig .fieldStyle)
399
470
400
471
case None =>
401
472
ReaderField
402
473
.Basic (symbol.name, tpe.memberType(symbol), None )
403
- .update(idx, default, macroConfig .fieldStyle)
474
+ .update(idx, default, mergedConfig .fieldStyle)
404
475
}
405
476
val existingFieldNames = fields.map(_.name).toSet
406
477
val additionalFields = fields
@@ -420,7 +491,47 @@ trait ConfigurationMacroUtils:
420
491
.distinctBy(_.name)
421
492
val allFields = fields ::: additionalFields
422
493
checkLoops(allFields)
423
- (sortDependencies(allFields), macroConfig.isStrict)
494
+ (sortDependencies(allFields), mergedConfig.isStrict.getOrElse(false ))
495
+
496
+ private def parseReaderMacroJsonConfig (
497
+ jsonConfig : Expr [JsonConfiguration ]
498
+ ): ReaderBuilderMacroConfig =
499
+ @ tailrec
500
+ def loop (
501
+ config : Expr [JsonConfiguration ],
502
+ acc : ReaderBuilderMacroConfig = ReaderBuilderMacroConfig ()
503
+ ): ReaderBuilderMacroConfig =
504
+ config match
505
+ case ' {
506
+ JsonConfiguration .default
507
+ } =>
508
+ acc
509
+
510
+ case ' {
511
+ ($rest : JsonConfiguration ).strict
512
+ } =>
513
+ acc.copy(isStrict = Some (true ))
514
+
515
+ case ' {
516
+ ($rest : JsonConfiguration ).fieldStyle($fieldStyle : FieldStyle )
517
+ } =>
518
+ acc.fieldStyle match
519
+ case None =>
520
+ loop(rest, acc.copy(fieldStyle = Some (fieldStyle.valueOrAbort)))
521
+ case Some (_) =>
522
+ report.errorAndAbort(FieldStyleAlreadyConfigured )
523
+
524
+ case other =>
525
+ other.asTerm match
526
+ case Inlined (_, _, term) =>
527
+ loop(term.asExprOf[JsonConfiguration ])
528
+ case _ =>
529
+ report.errorAndAbort(
530
+ showUnknownConfigTree(
531
+ other.asTerm.show(using Printer .TreeStructure )
532
+ )
533
+ )
534
+ loop(traverseTree(jsonConfig.asTerm).asExprOf[JsonConfiguration ])
424
535
425
536
private def sortDependencies (fields : List [ReaderField ]): List [ReaderField ] =
426
537
val known = fields.map(_.name).toSet
@@ -526,6 +637,7 @@ trait ConfigurationMacroUtils:
526
637
s " Field ' $name' exists in your model, use selector or .extract(_. $name).as[...] instead "
527
638
)
528
639
640
+ @ tailrec
529
641
def loop (
530
642
config : Expr [ReaderBuilder [T ]],
531
643
acc : ReaderBuilderMacroConfig = ReaderBuilderMacroConfig (Map .empty)
@@ -583,9 +695,10 @@ trait ConfigurationMacroUtils:
583
695
case ' { ($rest : ReaderBuilder [T ]).strict } =>
584
696
loop(
585
697
config = rest,
586
- acc = acc.copy(isStrict = true )
698
+ acc = acc.copy(isStrict = Some ( true ) )
587
699
)
588
700
case other =>
701
+ @ tailrec
589
702
def loopInner (
590
703
term : Term ,
591
704
extractors : List [(String , TypeRepr )] = Nil ,
@@ -664,8 +777,9 @@ trait ConfigurationMacroUtils:
664
777
)
665
778
case other =>
666
779
report.errorAndAbort(
667
- s " Unknown tree. Config must be an inlined given. \n Tree: ${other
668
- .show(using Printer .TreeStructure )}"
780
+ showUnknownConfigTree(
781
+ other.show(using Printer .TreeStructure )
782
+ )
669
783
)
670
784
671
785
loopInner(other.asTerm)
@@ -1056,7 +1170,7 @@ trait ConfigurationMacroUtils:
1056
1170
case class ReaderBuilderMacroConfig (
1057
1171
extracted : Map [String , ReaderField ] = Map .empty,
1058
1172
fieldStyle : Option [FieldStyle ] = None ,
1059
- isStrict : IsStrict = false
1173
+ isStrict : Option [ IsStrict ] = None
1060
1174
):
1061
1175
def withExtracted (field : ReaderField ): ReaderBuilderMacroConfig =
1062
1176
copy(extracted = extracted.updated(field.name, field))
0 commit comments