Skip to content

Commit

Permalink
add circe14 module
Browse files Browse the repository at this point in the history
  • Loading branch information
jbwheatley committed Aug 11, 2021
1 parent 1f13142 commit a9daba1
Show file tree
Hide file tree
Showing 16 changed files with 605 additions and 59 deletions.
124 changes: 73 additions & 51 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ lazy val compilerOptions212 = Seq(
)

lazy val compilerOptions213 = Seq(
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
"-Xlint:infer-any", // Warn when a type argument is inferred to be Any.
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
"-Xlint:unused", // Enable -Ywarn-unused:imports,privates,locals,implicits.
"-Wdead-code", // Warn when dead code is identified.
"-Wextra-implicit", // Warn when more than one implicit parameter section is defined.
"-Wnumeric-widen", // Warn when numerics are widened.
"-Wunused:patvars", // Warn if a variable bound in a pattern is unused.
"-Wvalue-discard" // Warn when non-Unit expression results are unused.
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
"-Xlint:infer-any", // Warn when a type argument is inferred to be Any.
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
"-Xlint:unused", // Enable -Ywarn-unused:imports,privates,locals,implicits.
"-Wdead-code", // Warn when dead code is identified.
"-Wextra-implicit", // Warn when more than one implicit parameter section is defined.
"-Wnumeric-widen", // Warn when numerics are widened.
"-Wunused:patvars", // Warn if a variable bound in a pattern is unused.
"-Wvalue-discard" // Warn when non-Unit expression results are unused.
)

lazy val compilerOptionsAll = Seq(
Expand Down Expand Up @@ -69,7 +69,7 @@ def compilerOptionsVersion(scalaVersion: String) =

lazy val scalaVersion212: String = "2.12.13"
lazy val scalaVersion213: String = "2.13.6"
lazy val supportedScalaVersions = List(scalaVersion212, scalaVersion213)
lazy val supportedScalaVersions = List(scalaVersion212, scalaVersion213)

ThisBuild / scalaVersion := scalaVersion212

Expand Down Expand Up @@ -176,10 +176,10 @@ lazy val http4s021 =
.settings(
name := "scalapact-http4s-0-21",
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-blaze-server" % "0.21.18" exclude("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-blaze-client" % "0.21.18" exclude("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-dsl" % "0.21.18",
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
"org.http4s" %% "http4s-blaze-server" % "0.21.18" exclude ("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-blaze-client" % "0.21.18" exclude ("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-dsl" % "0.21.18",
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
)
)
.dependsOn(shared)
Expand All @@ -191,10 +191,10 @@ lazy val http4s023 =
.settings(
name := "scalapact-http4s-0-23",
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-blaze-server" % "0.23.0-RC1" exclude("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-blaze-client" % "0.23.0-RC1" exclude("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-dsl" % "0.23.0-RC1",
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
"org.http4s" %% "http4s-blaze-server" % "0.23.1" exclude ("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-blaze-client" % "0.23.1" exclude ("org.scala-lang.modules", "scala-xml"),
"org.http4s" %% "http4s-dsl" % "0.23.1",
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
)
)
.dependsOn(shared)
Expand Down Expand Up @@ -236,6 +236,21 @@ lazy val circe13 =
.dependsOn(shared)
.dependsOn(testShared % "test->compile")

lazy val circe14 =
(project in file("scalapact-circe-0-14"))
.settings(commonSettings: _*)
.settings(publishSettings: _*)
.settings(
name := "scalapact-circe-0-14",
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % "0.14.1")
)
.dependsOn(shared)
.dependsOn(testShared % "test->compile")

lazy val pluginShared =
(project in file("sbt-scalapact-shared"))
.settings(commonSettings: _*)
Expand All @@ -252,11 +267,11 @@ lazy val plugin =
.settings(publishSettings: _*)
.settings(
name := "sbt-scalapact",
sbtPlugin := true,
sbtPlugin := true
)
.dependsOn(pluginShared)
.dependsOn(circe13)
.dependsOn(http4s021)
.dependsOn(circe14)
.dependsOn(http4s023)
.settings(scala212OnlySettings)

lazy val pluginNoDeps =
Expand All @@ -265,11 +280,11 @@ lazy val pluginNoDeps =
.settings(publishSettings: _*)
.settings(
name := "sbt-scalapact-nodeps",
sbtPlugin := true,
sbtPlugin := true
)
.dependsOn(pluginShared)
.dependsOn(circe13 % "provided")
.dependsOn(http4s021 % "provided")
.dependsOn(circe14 % "provided")
.dependsOn(http4s023 % "provided")
.settings(scala212OnlySettings)

lazy val framework =
Expand All @@ -295,8 +310,8 @@ lazy val frameworkWithDeps =
}
)
.dependsOn(framework)
.dependsOn(circe13)
.dependsOn(http4s021)
.dependsOn(circe14)
.dependsOn(http4s023)

lazy val standalone =
(project in file("scalapact-standalone-stubber"))
Expand Down Expand Up @@ -330,18 +345,18 @@ lazy val testsWithDeps =
.settings(commonSettings: _*)
.settings(
libraryDependencies ++= Seq(
"org.scalaj" %% "scalaj-http" % "2.4.2" % "test",
"org.json4s" %% "json4s-native" % "3.6.11" % "test",
"com.github.tomakehurst" % "wiremock" % "1.56" % "test",
"fr.hmil" %% "roshttp" % "2.1.0" % "test",
"io.argonaut" %% "argonaut" % "6.2.5"
"org.scalaj" %% "scalaj-http" % "2.4.2" % "test",
"org.json4s" %% "json4s-native" % "3.6.11" % "test",
"com.github.tomakehurst" % "wiremock" % "1.56" % "test",
"fr.hmil" %% "roshttp" % "2.1.0" % "test",
"io.argonaut" %% "argonaut" % "6.2.5"
),
skip in publish := true
)
.settings(scala212OnlySettings)
.dependsOn(framework)
.dependsOn(circe13)
.dependsOn(http4s021)
.dependsOn(circe14)
.dependsOn(http4s023)

lazy val docs =
(project in file("scalapact-docs"))
Expand All @@ -367,7 +382,7 @@ lazy val scalaPactProject =
)
.aggregate(shared, core, pluginShared, plugin, pluginNoDeps, framework, testShared)
.aggregate(http4s021, http4s023)
.aggregate(argonaut62, circe13)
.aggregate(argonaut62, circe13, circe14)
.aggregate(standalone, frameworkWithDeps)
.aggregate(docs)
.aggregate(pactSpec, testsWithDeps)
Expand All @@ -381,34 +396,41 @@ val readmeFileKey = settingKey[File]("The location of the readme")
readmeFileKey := baseDirectory.value / "README.md"

lazy val updateVersionsInReadme: ReleaseStep = { st: State =>
st.get(ReleaseKeys.versions).flatMap { case (newVersion, _) =>
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
val readmeLines = IO.readLines(readmeFile)
val versionPrefix = "## Latest version is "
val currentVersion = readmeLines.collectFirst { case s if s.startsWith(versionPrefix) => s.replace(versionPrefix, "").dropWhile(_.isWhitespace)}
currentVersion.map { cv =>
IO.writeLines(readmeFile, readmeLines.map(_.replaceAll(cv, newVersion)))
st.get(ReleaseKeys.versions)
.flatMap { case (newVersion, _) =>
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
val readmeLines = IO.readLines(readmeFile)
val versionPrefix = "## Latest version is "
val currentVersion = readmeLines.collectFirst {
case s if s.startsWith(versionPrefix) => s.replace(versionPrefix, "").dropWhile(_.isWhitespace)
}
currentVersion.map { cv =>
IO.writeLines(readmeFile, readmeLines.map(_.replaceAll(cv, newVersion)))
}
}
}.getOrElse(())
.getOrElse(())

st
}

lazy val commitReadMeVersionBump: ReleaseStep = { st: State =>
def vcs(st: State): Vcs = {
st.extract.get(releaseVcs).getOrElse(sys.error("Aborting release. Working directory is not a repository of a recognized VCS."))
}
def vcs(st: State): Vcs =
st.extract
.get(releaseVcs)
.getOrElse(sys.error("Aborting release. Working directory is not a repository of a recognized VCS."))
val commitMessage: TaskKey[String] = releaseNextCommitMessage
val log = new ProcessLogger {
override def err(s: => String): Unit = st.log.info(s)
override def out(s: => String): Unit = st.log.info(s)
override def buffer[T](f: => T): T = st.log.buffer(f)
override def buffer[T](f: => T): T = st.log.buffer(f)
}
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
val base = vcs(st).baseDir.getCanonicalFile
val sign = st.extract.get(releaseVcsSign)
val signOff = st.extract.get(releaseVcsSignOff)
val relativePathToReadme = IO.relativize(base, readmeFile).getOrElse("Readme file [%s] is outside of this VCS repository with base directory [%s]!" format(readmeFile, base))
val base = vcs(st).baseDir.getCanonicalFile
val sign = st.extract.get(releaseVcsSign)
val signOff = st.extract.get(releaseVcsSignOff)
val relativePathToReadme = IO
.relativize(base, readmeFile)
.getOrElse("Readme file [%s] is outside of this VCS repository with base directory [%s]!" format (readmeFile, base))

vcs(st).add(relativePathToReadme) !! log

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.itv.scalapact.circe14

import com.itv.scalapact.shared.utils.ColourOutput._
import com.itv.scalapact.shared.json.IJsonConversionFunctions
import com.itv.scalapact.shared.matchir.IrNodePath.IrNodePathEmpty
import com.itv.scalapact.shared.matchir.MatchIrConstants.{rootNodeLabel, unnamedNodeLabel}
import com.itv.scalapact.shared.matchir._
import com.itv.scalapact.shared.utils.PactLogger
import io.circe._
import io.circe.parser._

object JsonConversionFunctions extends IJsonConversionFunctions {

def fromJSON(jsonString: String): Option[IrNode] =
parse(jsonString).toOption.flatMap { json =>
jsonRootToIrNode(json, IrNodePathEmpty)
}

private def jsonToIrNode(label: String, json: Json, pathToParent: IrNodePath): IrNode =
json match {
case j: Json if j.isArray =>
IrNode(label, jsonArrayToIrNodeList(label, j, pathToParent)).withPath(pathToParent).markAsArray

case j: Json if j.isObject =>
IrNode(label, jsonObjectToIrNodeList(j, pathToParent)).withPath(pathToParent)

case j: Json if j.isNumber =>
IrNode(label, j.asNumber.map(_.toDouble).map(d => IrNumberNode(d))).withPath(pathToParent)

case j: Json if j.isBoolean =>
IrNode(label, j.asBoolean.map(IrBooleanNode)).withPath(pathToParent)

case j: Json if j.isString =>
IrNode(label, j.asString.map(IrStringNode)).withPath(pathToParent)

case _ =>
IrNode(label, IrNullNode).withPath(pathToParent)
}

private def jsonObjectToIrNodeList(json: Json, pathToParent: IrNodePath): List[IrNode] =
json.hcursor.keys
.map(_.toSet)
.map(_.toList)
.getOrElse(Nil)
.map(l => if (l.isEmpty) unnamedNodeLabel else l)
.map { l =>
json.hcursor.downField(l).focus.map { q =>
jsonToIrNode(l, q, pathToParent <~ l)
}
}
.collect { case Some(s) => s }

private def jsonArrayToIrNodeList(parentLabel: String, json: Json, pathToParent: IrNodePath): List[IrNode] =
json.asArray
.map(_.toList)
.getOrElse(Nil)
.zipWithIndex
.map(j => jsonToIrNode(parentLabel, j._1, pathToParent <~ j._2))

private def jsonRootToIrNode(json: Json, initialPath: IrNodePath): Option[IrNode] =
json match {
case j: Json if j.isArray =>
Option(
IrNode(rootNodeLabel, jsonArrayToIrNodeList(unnamedNodeLabel, j, initialPath))
.withPath(initialPath)
.markAsArray
)

case j: Json if j.isObject =>
Option(
IrNode(rootNodeLabel, jsonObjectToIrNodeList(j, initialPath))
.withPath(initialPath)
)

case _ =>
PactLogger.error("JSON was not an object or an array".red)
None
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.itv.scalapact.circe14

import com.itv.scalapact.shared.{JvmPact, Pact}
import com.itv.scalapact.shared.json.{ContractDeserializer, IPactReader, IPactWriter}
import io.circe.parser.parse

trait JsonInstances {
import PactImplicits._

implicit val pactReaderInstance: IPactReader = new PactReader

implicit val pactWriterInstance: IPactWriter = new PactWriter

implicit val pactDeserializer: ContractDeserializer[Pact] = (jsonString: String) =>
parse(jsonString).flatMap(_.as[Pact]) match {
case Right(a) => Right(a)
case Left(_) => Left(s"Could not read scala-pact pact from json: $jsonString")
}

implicit val jvmPactDeserializer: ContractDeserializer[JvmPact] = (jsonString: String) =>
parse(jsonString).flatMap(_.as[JvmPact]) match {
case Right(a) => Right(a)
case Left(_) => Left(s"Could not read jvm-pact pact from json: $jsonString")
}
}
Loading

0 comments on commit a9daba1

Please sign in to comment.