ducktape 0.2.8
Highlights of this release:
- Support for field and case name transformations via
Field.modifySourceNames
,Field.modifyDestNames
,Case.modifySourceNames
andCase.modifyDestNames
and modifiers for those config options that let you fine-tune the transformations further:.regional(_.path.to.field)
- this will apply renames to all transformations 'below' the path you've picked (this is the default).typeSpecific[SomeType]
- this will apply the renames to subtypes of a type you've picked.local(_.path.to.field)
- this will apply renames to the field corresponding to that field/enum subcase (but not the field and the enum subcase themselves!)
Head on over to the docs to see more.
Examples
test("dest field regional flag covers the selected case class and everything below it") {
case class Source(int: Int, str: String, level1: SourceLevel1)
case class SourceLevel1(INT: Int, STR: String, LEVEL2: SourceLevel2)
case class SourceLevel2(INT: Int, STR: String)
case class Dest(int: Int, str: String, level1: DestLevel1)
case class DestLevel1(INT: Int, STR: String, LEVEL2: DestLevel2)
case class DestLevel2(INT: Int, STR: String)
val source = Source(1, "1", SourceLevel1(2, "2", SourceLevel2(3, "3")))
val expected = Dest(1, "1", DestLevel1(2, "2", DestLevel2(3, "3")))
assertTransformsConfigured(source, expected)(
Field.modifyDestNames(_.toUpperCase).regional(_.level1)
)
}
test("source case regional flag covers the selected subtype and everything below (picked as a field in case class)") {
case class Source(int: Int, level1: SourceEnum)
case class Dest(int: Int, level1: DestEnum)
enum DestEnum {
case one(int: Int, str: String)
case two(int: Int, str: String, level1: DestLevel1, level2: DestLevel1Enum)
case three(int: Int, str: String)
}
enum SourceEnum {
case ONE(int: Int, str: String)
case TWO(int: Int, str: String, level1: SourceLevel1, level2: SourceLevel1Enum)
case THREE(int: Int, str: String)
}
enum SourceLevel1Enum {
case One
case Two
}
enum DestLevel1Enum {
case one
case two
}
case class SourceLevel1(int: Int)
case class DestLevel1(int: Int)
assertTransformsConfigured(
Source(1, SourceEnum.TWO(2, "2", SourceLevel1(3), SourceLevel1Enum.Two)),
Dest(1, DestEnum.two(2, "2", DestLevel1(3), DestLevel1Enum.two))
)(
Case.modifySourceNames(_.toLowerCase).regional(_.level1)
)
}
Examples of local flags:
test("dest field local flag covers the selected case class and nothing else") {
case class Source(int: Int, str: String, level1: SourceLevel1)
case class SourceLevel1(INT: Int, STR: String, LEVEL2: SourceLevel2)
case class SourceLevel2(int: Int, str: String)
case class Dest(int: Int, str: String, level1: DestLevel1)
case class DestLevel1(int: Int, str: String, level2: DestLevel2)
case class DestLevel2(int: Int, str: String)
val source = Source(1, "1", SourceLevel1(2, "2", SourceLevel2(3, "3")))
val expected = Dest(1, "1", DestLevel1(2, "2", DestLevel2(3, "3")))
assertTransformsConfigured(source, expected)(
Field.modifyDestNames(_.toUpperCase).local(_.level1)
)
}
and an example of a type specific flags:
test("source field type specific flag covers all subtypes of an enum and nothing else (even when the enum is nested)") {
case class Source(int: Int, level1: SourceEnum)
case class Dest(int: Int, level1: DestEnum)
sealed trait SourceEnum
object SourceEnum {
sealed trait NestLevel1 extends SourceEnum
sealed trait NestLevel2 extends SourceEnum
case class One(int: Int, str: String) extends NestLevel2
case class Two(int: Int, str: String, level1: SourceLevel1) extends NestLevel1
case class Three(int: Int, str: String) extends NestLevel2
}
sealed trait DestEnum
object DestEnum {
sealed trait NestLevel1 extends DestEnum
sealed trait NestLevel2 extends DestEnum
case class One(INT: Int, STR: String) extends NestLevel2
case class Two(INT: Int, STR: String, LEVEL1: DestLevel1) extends NestLevel1
case class Three(INT: Int, STR: String) extends NestLevel2
}
case class SourceLevel1(int: Int)
case class DestLevel1(int: Int)
assertTransformsConfigured(
Source(1, SourceEnum.Two(2, "2", SourceLevel1(3))),
Dest(1, DestEnum.Two(2, "2", DestLevel1(3)))
)(
Field.modifySourceNames(_.toUpperCase).typeSpecific[SourceEnum]
)
}
Renamer
is the thing that fuels the rename DSL:
sealed trait Renamer {
/**
* Equivalent to `String#toUpperCase`
*/
def toUpperCase: Renamer
/**
* Equivalent to `String#toLowerCase`
*/
def toLowerCase: Renamer
/**
* Equivalent to the function `(str: String) => if str == from then to else str`
*/
def rename(from: String, to: String): Renamer
/**
* Equivalent to `String#replace(target, replacement)`
*/
def replace(target: String, replacement: String): Renamer
/**
* Equivalent to the function `(str: String) => Pattern.compile(pattern).matcher(str).replaceAll(replacement)`
*/
def regexReplace(pattern: String, replacement: String): Renamer
/**
* Equivalent to `String#stripPrefix(prefix)`
*/
def stripPrefix(prefix: String): Renamer
/**
* Equivalent to `String#stripSuffix(suffix)`
*/
def stripSuffix(suffix: String): Renamer
/**
* Equivalent to `String#capitalize`
*/
def capitalize: Renamer
}
- Most of the API has finally had scaladoc with examples added to it
What's Changed
- Update sbt-typelevel-ci-release, ... to 0.7.5 by @scala-steward in #228
- Update sbt-scalajs, scalajs-library_2.13, ... to 1.18.1 by @scala-steward in #230
- Update munit to 1.0.4 by @scala-steward in #229
- Update munit to 1.1.0 by @scala-steward in #237
- Update sbt-typelevel-ci-release, ... to 0.7.6 by @scala-steward in #236
- Update scalafmt-core to 3.8.5 by @scala-steward in #235
- Update sbt-scalafmt to 2.5.4 by @scala-steward in #234
- Update sbt-typelevel-ci-release, ... to 0.7.7 by @scala-steward in #240
- Update scalafmt-core to 3.8.6 by @scala-steward in #239
- Update sbt-scalajs, scalajs-library_2.13, ... to 1.18.2 by @scala-steward in #238
- Update sbt-scalafix to 0.14.0 by @scala-steward in #233
- Update scala3-library, ... to 3.3.5 by @scala-steward in #241
- Update sbt-mdoc to 2.6.3 by @scala-steward in #242
- Update scalafmt-core to 3.9.0 by @scala-steward in #244
- Update sbt-mdoc to 2.6.4 by @scala-steward in #243
- Update sbt-scalafix to 0.14.2 by @scala-steward in #245
- Update scalafmt-core to 3.9.1 by @scala-steward in #246
- Update auxlib, clib, javalib, nativelib, ... to 0.5.7 by @scala-steward in #247
- Update scalafmt-core to 3.9.2 by @scala-steward in #248
- Update sbt, scripted-plugin to 1.10.8 by @scala-steward in #249
- Update sbt, scripted-plugin to 1.10.10 by @scala-steward in #250
- [Issue #75] Add support for field/case renames via flags by @arainko in #252
- Update scalafmt-core to 3.9.3 by @scala-steward in #251
- Update scalafmt-core to 3.9.4 by @scala-steward in #253
- Add scaladoc to
Field
,Case
,Renamer
by @arainko in #254 Transformer
scaladoc, moreRenamer
methods, additional tests by @arainko in #255- Update sbt, scripted-plugin to 1.10.11 by @scala-steward in #256
- Update sbt-mdoc to 2.6.5 by @scala-steward in #257
- Rough renames docs by @arainko in #258
Full Changelog: v0.2.7...v0.2.8