Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Jan 10, 2021
1 parent 880c7be commit bc4fe66
Show file tree
Hide file tree
Showing 51 changed files with 973 additions and 550 deletions.
5 changes: 3 additions & 2 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ assumeStandardLibraryStripMargin = true
danglingParentheses = true
docstrings = JavaDoc
maxColumn = 120
project.excludeFilters += core/play/src/main/scala/play/core/hidden/ObjectMappings.scala
#scalafmt does not support Scala 3 syntax yet (`inline`)
project.excludeFilters += scala-3
project.git = true
rewrite.rules = [ AvoidInfix, ExpandImportSelectors, RedundantParens, SortModifiers, PreferCurlyFors ]
rewrite.neverInfix.excludeFilters = [
Expand All @@ -19,4 +20,4 @@ version = 2.3.2

literals.long=Upper
literals.float=Upper
literals.double=Upper
literals.double=Upper
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object Employee {
"lastName" -> e.lastName,
"city" -> e.city,
"country" -> e.country,
"tags" -> JsArray(e.tags.map(JsString.apply))
"tags" -> JsArray(e.tags.map(JsString.apply _))
)
}

Expand Down
69 changes: 51 additions & 18 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ val joda = Seq(
"joda-time" % "joda-time" % "2.10.8"
)

def jsonDependencies(scalaVersion: String) = Seq(
def scalaReflect(scalaVersion: String) = Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion
)

Expand All @@ -43,6 +43,7 @@ def jsonDependencies(scalaVersion: String) = Seq(
// Do not check for previous JS artifacts for upgrade to Scala.js 1.0 because no sjs1 artifacts exist
def playJsonMimaSettings = Seq(
mimaPreviousArtifacts := ((crossProjectPlatform.?.value, previousStableVersion.value) match {
case _ if isDotty.value => Set.empty // no releases for Scala 3 yet
case (Some(JSPlatform), Some("2.8.1")) => Set.empty
case (_, Some(previousVersion)) => Set(organization.value %%% moduleName.value % previousVersion)
case _ => throw new Error("Unable to determine previous version")
Expand Down Expand Up @@ -74,10 +75,14 @@ val scalacOpts = Seq(

val silencerVersion = "1.7.1"

libraryDependencies in ThisBuild ++= Seq(
compilerPlugin(("com.github.ghik" % "silencer-plugin" % silencerVersion).cross(CrossVersion.full)),
("com.github.ghik" % "silencer-lib" % silencerVersion % Provided).cross(CrossVersion.full)
)
libraryDependencies in ThisBuild ++= {
if (isDotty.value) Nil
else
Seq(
compilerPlugin(("com.github.ghik" % "silencer-plugin" % silencerVersion).cross(CrossVersion.full)),
("com.github.ghik" % "silencer-lib" % silencerVersion % Provided).cross(CrossVersion.full)
)
}

// Customise sbt-dynver's behaviour to make it work with tags which aren't v-prefixed
dynverVTagPrefix in ThisBuild := false
Expand All @@ -104,12 +109,12 @@ lazy val commonSettings = Def.settings(
Tests.Argument(TestFrameworks.ScalaTest, "-l", "play.api.libs.json.UnstableInScala213")
),
headerLicense := Some(HeaderLicense.Custom(s"Copyright (C) 2009-2020 Lightbend Inc. <https://www.lightbend.com>")),
scalaVersion := Dependencies.Scala212,
crossScalaVersions := Seq(Dependencies.Scala212, Dependencies.Scala213),
scalaVersion := Dependencies.Scala3, // 212,
crossScalaVersions := Seq(Dependencies.Scala212, Dependencies.Scala213, Dependencies.Scala3),
javacOptions in Compile ++= javacSettings,
javacOptions in Test ++= javacSettings,
javacOptions in (Compile, compile) ++= Seq("-target", "1.8"), // sbt #1785, avoids passing to javadoc
scalacOptions ++= scalacOpts,
scalacOptions ++= (if (isDotty.value) Nil else scalacOpts),
scalacOptions in (Compile, doc) ++= Seq(
// Work around 2.12 bug which prevents javadoc in nested java classes from compiling.
"-no-java-comments",
Expand All @@ -136,28 +141,53 @@ lazy val `play-json` = crossProject(JVMPlatform, JSPlatform)
.enablePlugins(Omnidoc, Publish, Playdoc)
.configs(Docs)
.settings(
commonSettings ++ playJsonMimaSettings ++ Seq(
libraryDependencies ++= jsonDependencies(scalaVersion.value) ++ Seq(
"org.scalatest" %%% "scalatest" % "3.1.2" % Test,
"org.scalatestplus" %%% "scalacheck-1-14" % "3.1.2.0" % Test,
"org.scalacheck" %%% "scalacheck" % "1.14.3" % Test,
"com.chuusai" %% "shapeless" % "2.3.3" % Test,
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided"
commonSettings ++ playJsonMimaSettings ++ Def.settings(
libraryDependencies ++= (if (isDotty.value) Nil else scalaReflect(scalaVersion.value)),
libraryDependencies ++= Seq(
"org.scalatest" %%% "scalatest" % "3.1.2" % Test,
"org.scalatestplus" %%% "scalacheck-1-14" % "3.1.2.0" % Test,
"org.scalacheck" %%% "scalacheck" % "1.14.3" % Test,
"com.chuusai" %% "shapeless" % "2.3.3" % Test,
),
libraryDependencies += {
if (isDotty.value)
"org.scala-lang" %% "scala3-compiler" % scalaVersion.value % Provided
else
"org.scala-lang" % "scala-compiler" % scalaVersion.value % Provided
},
libraryDependencies := libraryDependencies.value.map(_.withDottyCompat(scalaVersion.value)),
libraryDependencies := libraryDependencies.value.map {
// I think because we're using an old sbt-scalajs we're not getting the right scala3-library
// specifically withDottyCompat doesn't exclude the sjs1 artefact, so it gets incorrectly "fixed" to _2.13
case m if m.name == "scala3-library_sjs1" => m.cross(CrossVersion.constant(scalaVersion.value))
case m => m
},
libraryDependencies ++=
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Seq()
case Some((3, _)) => Nil
case _ => Seq(compilerPlugin(("org.scalamacros" % "paradise" % "2.1.1").cross(CrossVersion.full)))
}),
unmanagedSourceDirectories in Compile += {
//val sourceDir = (sourceDirectory in Compile).value
// ^ gives jvm/src/main, for some reason
val sourceDir = baseDirectory.value.getParentFile / "shared/src/main"
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+"
case _ => sourceDir / "scala-2.13-"
case Some((2, n)) if n < 12 => sourceDir / "scala-2.13-"
case _ => sourceDir / "scala-2.13+"
}
},
Seq((Compile, "main"), (Test, "test")).map {
case (conf, dir) =>
conf / unmanagedSourceDirectories ++= {
val sourceDir = baseDirectory.value.getParentFile / s"shared/src/$dir"
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, _)) => List(sourceDir / "scala-2")
case Some((3, _)) => List(sourceDir / "scala-3")
case _ => Nil
}
},
},
sourceGenerators in Compile += Def.task {
val dir = (sourceManaged in Compile).value
val file = dir / "Generated.scala"
Expand Down Expand Up @@ -220,6 +250,7 @@ lazy val `play-jsonJVM` = `play-json`.jvm.settings(
jacksons ++ specs2 :+ (
"ch.qos.logback" % "logback-classic" % "1.2.3" % Test
),
libraryDependencies := libraryDependencies.value.map(_.withDottyCompat(scalaVersion.value)),
unmanagedSourceDirectories in Test ++= (baseDirectory.value.getParentFile.getParentFile / "docs/manual/working/scalaGuide" ** "code").get
)

Expand All @@ -228,7 +259,8 @@ lazy val `play-json-joda` = project
.enablePlugins(Omnidoc, Publish)
.settings(
commonSettings ++ playJsonMimaSettings ++ Seq(
libraryDependencies ++= joda ++ specs2
libraryDependencies ++= joda ++ specs2,
libraryDependencies := libraryDependencies.value.map(_.withDottyCompat(scalaVersion.value)),
)
)
.dependsOn(`play-jsonJVM`)
Expand Down Expand Up @@ -260,6 +292,7 @@ lazy val docs = project
.settings(
publish / skip := true,
libraryDependencies ++= specs2,
libraryDependencies := libraryDependencies.value.map(_.withDottyCompat(scalaVersion.value)),
PlayDocsKeys.scalaManualSourceDirectories := (baseDirectory.value / "manual" / "working" / "scalaGuide" ** "code").get,
PlayDocsKeys.resources += {
val apiDocs = (doc in (`play-jsonJVM`, Compile)).value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import play.api.libs.json.JsonNaming.SnakeCase
final class IdText(val value: String) extends AnyVal
//#valueClass

class ScalaJsonAutomatedSpec extends Specification {
object ScalaJsonAutomatedSpec {
//#model
case class Resident(name: String, age: Int, role: Option[String])
//#model
Expand All @@ -23,17 +23,8 @@ class ScalaJsonAutomatedSpec extends Specification {

//#model3
sealed trait Role
case object Admin extends Role
class Contributor(val organization: String) extends Role {
override def equals(obj: Any): Boolean = obj match {
case other: Contributor if obj != null => this.organization == other.organization
case _ => false
}
}
object Contributor {
def apply(organization: String): Contributor = new Contributor(organization)
def unapply(contributor: Contributor): Option[(String)] = Some(contributor.organization)
}
case object Admin extends Role
case class Contributor(organization: String) extends Role
//#model3

val sampleJson = Json.parse(
Expand Down Expand Up @@ -67,14 +58,18 @@ class ScalaJsonAutomatedSpec extends Specification {
"role": null
}"""
)
}

class ScalaJsonAutomatedSpec extends Specification {
import ScalaJsonAutomatedSpec._

"Scala JSON automated" should {
"for case class" >> {
"produce a Reads" in {
//#auto-reads
import play.api.libs.json._

implicit val residentReads = Json.reads[Resident]
implicit val residentReads: Reads[Resident] = Json.reads[Resident]
//#auto-reads

sampleJson.as[Resident].must_===(sampleData)
Expand All @@ -85,11 +80,11 @@ class ScalaJsonAutomatedSpec extends Specification {
import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val residentReads = (
implicit val residentReads: Reads[Resident] = (
(__ \ "name").read[String] and
(__ \ "age").read[Int] and
(__ \ "role").readNullable[String]
)(Resident)
)(Resident.apply _)
//#manual-reads

sampleJson.as[Resident].must_===(sampleData)
Expand All @@ -99,7 +94,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-writes
import play.api.libs.json._

implicit val residentWrites = Json.writes[Resident]
implicit val residentWrites: OWrites[Resident] = Json.writes[Resident]
//#auto-writes

Json.toJson(sampleData).must_===(sampleJson)
Expand All @@ -109,7 +104,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-format
import play.api.libs.json._

implicit val residentFormat = Json.format[Resident]
implicit val residentFormat: Format[Resident] = Json.format[Resident]
//#auto-format

sampleJson.as[Resident].must_===(sampleData) and {
Expand All @@ -121,7 +116,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-naming-writes
import play.api.libs.json._

implicit val config = JsonConfiguration(SnakeCase)
implicit val config: JsonConfiguration = JsonConfiguration(SnakeCase)

implicit val userWrites: OWrites[PlayUser] = Json.writes[PlayUser]
//#auto-naming-writes
Expand All @@ -133,7 +128,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-naming-format
import play.api.libs.json._

implicit val config = JsonConfiguration(SnakeCase)
implicit val config: JsonConfiguration = JsonConfiguration(SnakeCase)

implicit val userFormat: OFormat[PlayUser] = Json.format[PlayUser]
//#auto-naming-format
Expand All @@ -147,7 +142,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-naming-reads
import play.api.libs.json._

implicit val config = JsonConfiguration(SnakeCase)
implicit val config: JsonConfiguration = JsonConfiguration(SnakeCase)

implicit val userReads: Reads[PlayUser] = Json.reads[PlayUser]
//#auto-naming-reads
Expand All @@ -163,7 +158,7 @@ class ScalaJsonAutomatedSpec extends Specification {
override def apply(property: String): String = s"lightbend_$property"
}

implicit val config = JsonConfiguration(Lightbend)
implicit val config: JsonConfiguration = JsonConfiguration(Lightbend)

implicit val customWrites: OFormat[PlayUser] = Json.format[PlayUser]
//#auto-custom-naming-format
Expand All @@ -177,7 +172,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-case-class-to-JSON
import play.api.libs.json._

implicit val residentWrites = Json.writes[Resident]
implicit val residentWrites: OWrites[Resident] = Json.writes[Resident]

val resident = Resident(name = "Fiver", age = 4, role = None)

Expand All @@ -191,7 +186,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-JSON-to-case-class
import play.api.libs.json._

implicit val residentReads = Json.reads[Resident]
implicit val residentReads: Reads[Resident] = Json.reads[Resident]

// In a request, a JsValue is likely to come from `request.body.asJson`
// or just `request.body` if using the `Action(parse.json)` body parser
Expand All @@ -218,12 +213,14 @@ class ScalaJsonAutomatedSpec extends Specification {
}
}

// lampepfl/dotty#7000 No Mirrors for value classes
/*
"for value class" >> {
"produce a Reads" in {
//#value-reads
import play.api.libs.json._
implicit val idTextReads = Json.valueReads[IdText]
implicit val idTextReads: Reads[IdText] = Json.valueReads[IdText]
//#value-reads
JsString("foo").as[IdText].must_===(new IdText("foo"))
Expand All @@ -233,7 +230,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#value-writes
import play.api.libs.json._
implicit val idTextWrites = Json.valueWrites[IdText]
implicit val idTextWrites: Writes[IdText] = Json.valueWrites[IdText]
//#value-writes
Json.toJson(new IdText("bar")).must_===(JsString("bar"))
Expand All @@ -243,7 +240,7 @@ class ScalaJsonAutomatedSpec extends Specification {
//#value-format
import play.api.libs.json._
implicit val idTextFormat = Json.valueFormat[IdText]
implicit val idTextFormat: Format[IdText] = Json.valueFormat[IdText]
//#value-format
val id = new IdText("lorem")
Expand All @@ -253,16 +250,17 @@ class ScalaJsonAutomatedSpec extends Specification {
}
}
}
*/

"automatically convert JSON for a sealed family" in {
//#trait-representation
val adminJson = Json.parse("""
{ "_type": "scalaguide.json.ScalaJsonAutomatedSpec.Admin" }
{ "_type": "Admin" }
""")

val contributorJson = Json.parse("""
{
"_type":"scalaguide.json.ScalaJsonAutomatedSpec.Contributor",
"_type":"Contributor",
"organization":"Foo"
}
""")
Expand All @@ -282,7 +280,7 @@ class ScalaJsonAutomatedSpec extends Specification {
Json.obj()
})

implicit val contributorFormat = Json.format[Contributor]
implicit val contributorFormat: OFormat[Contributor] = Json.format[Contributor]

// Finally able to generate format for the sealed family 'Role'
implicit val roleFormat: OFormat[Role] = Json.format[Role]
Expand Down Expand Up @@ -320,12 +318,12 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-JSON-custom-trait
import play.api.libs.json._

implicit val cfg = JsonConfiguration(
implicit val cfg: JsonConfiguration = JsonConfiguration(
// Each JSON objects is marked with the admTpe, ...
discriminator = "admTpe",
// ... indicating the lower-cased name of sub-type
typeNaming = JsonNaming { fullName =>
fullName.drop(39 /* remove pkg */ ).toLowerCase
fullName.toLowerCase
}
)

Expand All @@ -337,7 +335,7 @@ class ScalaJsonAutomatedSpec extends Specification {
Json.obj()
})

implicit val contributorFormat = Json.format[Contributor]
implicit val contributorFormat: OFormat[Contributor] = Json.format[Contributor]

// Finally able to generate format for the sealed family 'Role'
implicit val roleFormat: OFormat[Role] = Json.format[Role]
Expand All @@ -362,8 +360,8 @@ class ScalaJsonAutomatedSpec extends Specification {
//#auto-writes-null
import play.api.libs.json._

implicit val config = JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)
implicit val residentWrites = Json.writes[Resident]
implicit val config: JsonConfiguration = JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)
implicit val residentWrites: OWrites[Resident] = Json.writes[Resident]
//#auto-writes-null

val resident = Resident(name = "Fiver", age = 4, role = None)
Expand Down
Loading

0 comments on commit bc4fe66

Please sign in to comment.