Skip to content

Commit

Permalink
Use compat classes to derive old Decoder[Update] instances
Browse files Browse the repository at this point in the history
  • Loading branch information
fthomas committed Jan 15, 2025
1 parent 757f9bb commit 95bbc64
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 239 deletions.
134 changes: 77 additions & 57 deletions modules/core/src/main/scala/org/scalasteward/core/data/Update.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ package org.scalasteward.core.data
import cats.Order
import cats.implicits.*
import io.circe.generic.semiauto.*
import io.circe.syntax.*
import io.circe.{Decoder, Encoder, HCursor, Json}
import io.circe.{Codec, Decoder, Encoder, Json}
import org.scalasteward.core.repoconfig.PullRequestGroup
import org.scalasteward.core.util
import org.scalasteward.core.util.Nel
Expand Down Expand Up @@ -198,66 +197,87 @@ object Update {
}
}

// TODO: Derive all instances of `Encoder`/`Decoder` here using `deriveCodec`
// Partially manually implemented so we don't fail reading old caches (those
// still using `Single`/`Group`)

implicit val ForArtifactIdEncoder: Encoder[ForArtifactId] = {
val derived = deriveEncoder[ForArtifactId]

derived.mapJson(json => Json.obj("ForArtifactId" -> json))
}

implicit val ForArtifactIdDecoder: Decoder[ForArtifactId] = {
val derived = deriveDecoder[ForArtifactId]
derived
.prepare(_.downField("ForArtifactId"))
.or(derived.prepare(_.downField("Single")))
}
implicit val SingleOrder: Order[Single] =
Order.by((u: Single) => (u.crossDependencies, u.newerVersions))

implicit val ForGroupIdEncoder: Encoder[ForGroupId] = {
val derived = deriveEncoder[ForGroupId]
implicit val forArtifactIdEncoder: Encoder[ForArtifactId] =
deriveEncoder[ForArtifactId].mapJson(json => Json.obj("ForArtifactId" -> json))

derived.mapJson(json => Json.obj("ForGroupId" -> json))
}
implicit val forArtifactIdDecoder: Decoder[ForArtifactId] =
deriveDecoder[ForArtifactId].prepare(_.downField("ForArtifactId"))

private val oldForGroupIdDecoder: Decoder[ForGroupId] =
(c: HCursor) =>
for {
crossDependencies <- c.downField("crossDependencies").as[Nel[CrossDependency]]
newerVersions <- c.downField("newerVersions").as[Nel[Version]]
forArtifactIds = crossDependencies
.map(crossDependency => ForArtifactId(crossDependency, newerVersions))
} yield ForGroupId(forArtifactIds)

implicit val ForGroupIdDecoder: Decoder[ForGroupId] =
deriveDecoder[ForGroupId]
.prepare(_.downField("ForGroupId"))
.or(oldForGroupIdDecoder.prepare(_.downField("ForGroupId")))
.or(oldForGroupIdDecoder.prepare(_.downField("Group")))

implicit val GroupedEncoder: Encoder[Grouped] = {
val derived = deriveEncoder[Grouped]

derived.mapJson(json => Json.obj("Grouped" -> json))
implicit val updateEncoder: Encoder[Update] = {
case update: ForArtifactId => forArtifactIdEncoder.apply(update)
case update => deriveEncoder[Update].apply(update)
}

implicit val GroupedDecoder: Decoder[Grouped] =
deriveDecoder[Grouped].prepare(_.downField("Grouped"))

implicit val SingleOrder: Order[Single] =
Order.by((u: Single) => (u.crossDependencies, u.newerVersions))
implicit val updateDecoder: Decoder[Update] =
deriveDecoder[Update]
.or(deriveDecoder[compat.v2.Update].map(_.toV3))
.or(deriveDecoder[compat.v1.Update].map(_.toV3))

object compat {
// the current version
import org.scalasteward.core.data as v3

// before https://github.com/scala-steward-org/scala-steward/pull/2898
object v2 {
sealed trait Update {
def toV3: v3.Update =
this match {
case forArtifactId: ForArtifactId =>
forArtifactId.toV3
case ForGroupId(crossDependencies, newerVersions) =>
v3.Update.ForGroupId(crossDependencies.map(v3.Update.ForArtifactId(_, newerVersions)))
case Grouped(name, title, updates) =>
v3.Update.Grouped(name, title, updates.map(_.toV3))
}
}
sealed trait Single extends Update
final case class ForArtifactId(
crossDependency: CrossDependency,
newerVersions: Nel[Version],
newerGroupId: Option[GroupId],
newerArtifactId: Option[String]
) extends Single {
override def toV3: v3.Update.ForArtifactId =
v3.Update.ForArtifactId(crossDependency, newerVersions, newerGroupId, newerArtifactId)
}
implicit val forArtifactIdDecoder: Decoder[ForArtifactId] =
deriveDecoder[ForArtifactId] // .prepare(_.downField("ForArtifactId"))
final case class ForGroupId(
crossDependencies: Nel[CrossDependency],
newerVersions: Nel[Version]
) extends Single
final case class Grouped(
name: String,
title: Option[String],
updates: List[ForArtifactId]
) extends Update
}

implicit val UpdateEncoder: Encoder[Update] = {
case update: Grouped => update.asJson
case update: ForArtifactId => update.asJson
case update: ForGroupId => update.asJson
// before https://github.com/scala-steward-org/scala-steward/pull/2714
object v1 {
sealed trait Update {
def toV3: v3.Update = toV2.toV3
private def toV2: v2.Update =
this match {
case Single(crossDependency, newerVersions, newerGroupId, newerArtifactId) =>
v2.ForArtifactId(crossDependency, newerVersions, newerGroupId, newerArtifactId)
case Group(crossDependencies, newerVersions) =>
v2.ForGroupId(crossDependencies, newerVersions)
}
}
final case class Single(
crossDependency: CrossDependency,
newerVersions: Nel[Version],
newerGroupId: Option[GroupId],
newerArtifactId: Option[String]
) extends Update
final case class Group(
crossDependencies: Nel[CrossDependency],
newerVersions: Nel[Version]
) extends Update
}
}

implicit val UpdateDecoder: Decoder[Update] =
ForArtifactIdDecoder
.widen[Update]
.or(ForGroupIdDecoder.widen[Update])
.or(Decoder[Grouped].widen[Update])

}
Loading

0 comments on commit 95bbc64

Please sign in to comment.