Skip to content

Commit

Permalink
SectionRename: allow remapping values on rename
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed Dec 10, 2024
1 parent d08cb3e commit 835e644
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 8 deletions.
12 changes: 10 additions & 2 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,11 @@ also support renaming sections of configuration, in case they have been
restructured but still need to provide backwards compatibility.

This can be accomplished in one of two ways:
- via a call to `.withSectionRenames(...)` with explicit rename arguments
- via a call to `.withSectionRenames(...)` with explicit rename arguments,
with each argument either:
- a tuple with `(old section name, new section name)`, or
- an explicit `metaconfig.annotation.SectionRename` instance which
also adds a partial function re-mapping `metaconfig.Conf` value
- via a call to `.detectSectionRenames` when the target type is provided
with one or more `@SectionRename(...)` annotations

Expand Down Expand Up @@ -263,7 +267,11 @@ object Human {
val decoderWithRenamesExplicit =
generic.deriveDecoderEx(Human()).noTypos.withSectionRenames(
"spouse" -> "family.spouse",
"kids" -> "family.children"
SectionRename("kids", "family.children") {
case Conf.Lst(kids) => Conf.Lst(
kids.zipWithIndex.map { case (kid, idx) => s"#$idx $kid" }
)
}
)
}
```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package metaconfig.annotation

import metaconfig.Conf

import scala.annotation.StaticAnnotation
import scala.collection.compat.immutable.ArraySeq
import scala.language.implicitConversions
Expand Down Expand Up @@ -35,8 +37,9 @@ final case class TabCompleteAsPath() extends StaticAnnotation
final case class CatchInvalidFlags() extends StaticAnnotation
final case class TabCompleteAsOneOf(options: String*) extends StaticAnnotation

final case class SectionRename(oldName: String, newName: String)
extends StaticAnnotation {
final case class SectionRename(oldName: String, newName: String)(
val conv: PartialFunction[Conf, Conf] = PartialFunction.empty,
) extends StaticAnnotation {
require(oldName.nonEmpty && newName.nonEmpty)
val oldNameAsSeq: Seq[String] = ArraySeq.unsafeWrapArray(oldName.split('.'))
val newNameAsSeq: Seq[String] = ArraySeq.unsafeWrapArray(newName.split('.'))
Expand All @@ -45,5 +48,5 @@ final case class SectionRename(oldName: String, newName: String)
}
object SectionRename {
implicit def fromTuple(obj: (String, String)): SectionRename =
SectionRename(obj._1, obj._2)
SectionRename(obj._1, obj._2)()
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ object SectionRenameDecoder {
conf.getNestedConf(oldName: _*) match {
case Configured.Ok(oldVal: Conf) =>
val del = Conf.Obj.empty.nestedWithin(oldName: _*)
val add = oldVal.nestedWithin(head.newNameAsSeq: _*)
val add = head.conv.applyOrElse(oldVal, identity[Conf])
.nestedWithin(head.newNameAsSeq: _*)
// remove on right (takes precedence), append on left (doesn't)
renameSections(rest)(ConfOps.merge(add, ConfOps.merge(conf, del)))
case _ => renameSections(rest)(conf)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package metaconfig

import metaconfig.annotation.SectionRename

class DeriveConfDecoderExJVMSuite extends munit.FunSuite {

def checkOkStr[T, A](confStr: String, out: A, in: T = null)(implicit
Expand Down Expand Up @@ -129,7 +131,13 @@ class DeriveConfDecoderExJVMSuite extends munit.FunSuite {

test("nested param with rename 2") {
implicit val nested2: ConfDecoderEx[Nested2] = generic
.deriveDecoderEx(Nested2()).noTypos.withSectionRenames("B" -> "b")
.deriveDecoderEx(Nested2()).noTypos
.withSectionRenames(SectionRename("B", "b") { case Conf.Obj(vals) =>
Conf.Obj(vals.map {
case ("param", Conf.Num(v)) => "param" -> Conf.Num(v * 2)
case x => x
})
})
implicit val nested3: ConfDecoderEx[Nested3] = generic
.deriveDecoderEx(Nested3()).noTypos
val nested: ConfDecoderEx[Nested] = generic.deriveDecoderEx(Nested())
Expand Down Expand Up @@ -157,7 +165,7 @@ class DeriveConfDecoderExJVMSuite extends munit.FunSuite {
a = "xxx",
b = Nested2(
a = "zzz",
b = OneParam(3),
b = OneParam(6),
c = Map("k2" -> OneParam(2), "k3" -> OneParam(33)),
),
),
Expand Down

0 comments on commit 835e644

Please sign in to comment.