Skip to content

Commit

Permalink
Merge branch 'master' into update/sbt-scalafmt-2.5.2
Browse files Browse the repository at this point in the history
  • Loading branch information
dos65 authored Nov 11, 2024
2 parents e0f083b + 89b5de5 commit 466c455
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/scala.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
scala: [2.12.19, 2.13.14, 3.3.0]
scala: [2.12.20, 2.13.15, 3.3.4]

steps:
- uses: actions/checkout@v4
Expand Down
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ It's advantages:
* Configurable recursive semiauto derivation
* Discriminator support for sum types derivation


Read more about library usage bellow:
- [Scala 3](https://github.com/tethys-json/tethys?tab=readme-ov-file#scala-3)
- [Scala 2](https://github.com/tethys-json/tethys?tab=readme-ov-file#scala-2)


# Scala 3

## Quick start

```scala
Expand Down Expand Up @@ -210,9 +216,9 @@ json.jsonAs[Session] == Right(session)
session.asJson == json
```

## Sealed traits and enums
### Sealed traits and enums
To derive **JsonReader** you **must** provide a discriminator.
This can be done via **selector** annotation
This can be done via **selector** annotation.
Discriminator for **JsonWriter** is optional.

If you don't need readers/writers for subtypes, you can omit them,
Expand Down Expand Up @@ -383,15 +389,14 @@ case object Direction extends Enum[Direction]

```

## scala 2
### Migration notes

### migration notes
When migrating to **scala 3** you should use **0.28.1** version.
When migrating to **scala 3** you should use **0.29.0** version.

Scala 3 derivation API in **1.0.0** has a lot of deprecations and is not fully compatible with **0.28.1**, including:
Scala 3 derivation API in **0.29.0** has a lot of deprecations and is not fully compatible in compile time with **0.28.4**, including:

1. **WriterDescription** and **ReaderDescription** are deprecated along with **describe** macro.
You can use **WriterBuilder** and **ReaderBuilder** directly instead
Use **WriterBuilder** and **ReaderBuilder** directly instead


2. **DependentField** model for **ReaderBuilder** has changed.
Expand All @@ -407,20 +412,21 @@ Scala 3 derivation API in **1.0.0** has a lot of deprecations and is not fully c
.extract(_.i).from(_.d).and[Double]("e")((d, e) => (d + e).toInt)
```

3. **0.28.1 scala 3 enum support** will not compile to prevent runtime effects during migration
3. **0.28.4 scala 3 enum support** was changed. [See more](https://github.com/tethys-json/tethys?tab=readme-ov-file#basic-enums)


4. `updatePartial` for **WriterBuilder** is deprecated. You can use ```update``` instead
4. `updatePartial` for **WriterBuilder** is deprecated. Use ```update``` instead

5. all derivation api is moved directly into core module in **tethys** package, including
5. all derivation api were moved directly into core module in **tethys** package, including
* FieldStyle
* WriterBuilder
* ReaderBuilder

6. **auto** derivation is removed
6. **auto** derivation is deprecated. Use derives on toplevel type instead

# Scala 2

### Quick start
## Quick start
Add dependencies to your `build.sbt`

```scala
Expand Down
12 changes: 4 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
lazy val scala212 = "2.12.19"
lazy val scala213 = "2.13.14"
/* FIXME
Return to use a stable version when 'scala.quoted.Quotes.reflectModuleSymbol.newClass'
and 'scala.quoted.Quotes.reflectModule.ClassDef.apply' are no longer experimental methods
*/
lazy val scala3 = "3.3.0"
lazy val scala212 = "2.12.20"
lazy val scala213 = "2.13.15"
lazy val scala3 = "3.3.4"

ThisBuild / scalaVersion := scala3

Expand Down Expand Up @@ -223,7 +219,7 @@ lazy val enumeratum = project
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, y)) =>
Seq("com.beachape" %% "enumeratum" % "1.7.3")
Seq("com.beachape" %% "enumeratum" % "1.7.5")
case _ => Seq.empty
}
}
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/main/scala-3/tethys/FieldStyle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ enum FieldStyle {
case SnakeCase, LowerSnakeCase, UpperSnakeCase, CapitalizedSnakeCase
}

private[tethys] object FieldStyle:
object FieldStyle:
private val regexp1: Pattern = Pattern.compile("([A-Z]+)([A-Z][a-z])")
private val regexp2: Pattern = Pattern.compile("([a-z\\d])([A-Z])")
private val replacement: String = "$1_$2"
Expand All @@ -22,7 +22,7 @@ private[tethys] object FieldStyle:
private val lowercase: String => String = _.toLowerCase()
private val uppercase: String => String = _.toUpperCase()

def applyStyle(string: String, style: FieldStyle): String =
private[tethys] def applyStyle(string: String, style: FieldStyle): String =
style match
case FieldStyle.Capitalize => capitalize(string)
case FieldStyle.Uncapitalize => uncapitalize(string)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -752,17 +752,19 @@ trait ConfigurationMacroUtils:
case '[t *: ts] => TypeRepr.of[t] :: typeReprsOf[ts]

def getAllChildren(tpe: TypeRepr): List[TypeRepr] =
tpe.asType match
case '[t] =>
Expr.summon[scala.deriving.Mirror.Of[t]] match
case Some('{
$m: scala.deriving.Mirror.SumOf[t] {
type MirroredElemTypes = subs
}
}) =>
typeReprsOf[subs].flatMap(getAllChildren)
case _ =>
List(tpe)
def loop(tpe: TypeRepr): List[TypeRepr] =
tpe.asType match
case '[t] =>
Expr.summon[scala.deriving.Mirror.Of[t]] match
case Some('{
$m: scala.deriving.Mirror.SumOf[t] {
type MirroredElemTypes = subs
}
}) =>
typeReprsOf[subs].flatMap(loop)
case _ =>
List(tpe)
loop(tpe).distinct

case class SelectedField(name: String, selector: Term)

Expand Down Expand Up @@ -1148,6 +1150,18 @@ trait ConfigurationMacroUtils:
Some(FieldStyle.CapitalizedSnakeCase)
case '{ tethys.derivation.builder.FieldStyle.capitalizedSnakeCase } =>
Some(FieldStyle.CapitalizedSnakeCase)
case '{ tethys.derivation.builder.FieldStyle.snakecase } =>
Some(FieldStyle.SnakeCase)
case '{ tethys.derivation.builder.FieldStyle.kebabcase } =>
Some(FieldStyle.KebabCase)
case '{ tethys.derivation.builder.FieldStyle.lowerSnakecase } =>
Some(FieldStyle.LowerSnakeCase)
case '{ tethys.derivation.builder.FieldStyle.lowerKebabcase } =>
Some(FieldStyle.LowerKebabCase)
case '{ tethys.derivation.builder.FieldStyle.upperSnakecase } =>
Some(FieldStyle.UpperSnakeCase)
case '{ tethys.derivation.builder.FieldStyle.upperKebabcase } =>
Some(FieldStyle.UpperKebabCase)
case _ => None

@deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ private[derivation] class DerivationMacro(val quotes: Quotes)
}
ReaderError.wrongJson(
"Can not extract fields from json: " + uninitializedFields
.mkString(", ")
.mkString("'", "', '", "'")
)(${ fieldName })
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ enum FieldStyle {
case capitalize, uncapitalize, lowercase, uppercase
case kebabCase, lowerKebabCase, upperKebabCase, capitalizedKebabCase
case snakeCase, lowerSnakeCase, upperSnakeCase, capitalizedSnakeCase

case kebabcase, lowerKebabcase, upperKebabcase
case snakecase, lowerSnakecase, upperSnakecase
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ class DerivationSpec extends AnyFlatSpec with Matchers {
res
}

it should "build message correctly" in {
case class Foo(bar: Int, baz: String, faz: Boolean) derives JsonReader

util.Try(read[Foo](obj("bar" -> 1))) should matchPattern {
case util.Failure(ex)
if ex.getMessage == """Illegal json at '[ROOT]': Can not extract fields from json: 'baz', 'faz'""" =>
}
}

it should "compile and correctly write and read product" in {
case class Person(
id: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ trait ReaderDerivation
if($predicate) {
val $uninitializedFields = new scala.collection.mutable.ArrayBuffer[String](${xs.size})
..$fields
$readerErrorCompanion.wrongJson("Can not extract fields from json" + $uninitializedFields.mkString("'", "', '", "'"))
$readerErrorCompanion.wrongJson("Can not extract fields from json: " + $uninitializedFields.mkString("'", "', '", "'"))
}
"""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ class SemiautoReaderDerivationTest extends AnyFlatSpec with Matchers {


behavior of "semiauto derivation"

it should "build message correctly" in {
case class Foo(bar: Int, baz: String, faz: Boolean)

implicit val reader: JsonReader[Foo] = tethys.derivation.semiauto.jsonReader

util.Try(read[Foo](obj("bar" -> 1))) should matchPattern {
case util.Failure(ex) if ex.getMessage == """Illegal json at '[ROOT]': Can not extract fields from json: 'baz', 'faz'""" =>
}
}

it should "derive readers for simple case class hierarchy" in {
implicit val dReader: JsonReader[D] = jsonReader[D]
implicit val cReader: JsonReader[C] = jsonReader[C]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,26 @@ class SemiautoReaderDerivationTest extends AnyFlatSpec with Matchers {
)
}

it should "derive reader for fieldStyle from description 3" in {
given JsonReader[CamelCaseNames] = JsonReader.derived[CamelCaseNames] {
ReaderDerivationConfig.empty.withFieldStyle(
tethys.derivation.builder.FieldStyle.lowerSnakecase
)
}

read[CamelCaseNames](
obj(
"some_param" -> 1,
"id_param" -> 2,
"simple" -> 3
)
) shouldBe CamelCaseNames(
someParam = 1,
IDParam = 2,
simple = 3
)
}

it should "derive strict reader" in {
implicit val reader: JsonReader[CamelCaseNames] =
jsonReader[CamelCaseNames](
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.4")
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.9.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")

0 comments on commit 466c455

Please sign in to comment.