Skip to content

Commit a9daba1

Browse files
author
jbwheatley
committed
add circe14 module
1 parent 1f13142 commit a9daba1

File tree

16 files changed

+605
-59
lines changed

16 files changed

+605
-59
lines changed

build.sbt

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ lazy val compilerOptions212 = Seq(
2020
)
2121

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

3535
lazy val compilerOptionsAll = Seq(
@@ -69,7 +69,7 @@ def compilerOptionsVersion(scalaVersion: String) =
6969

7070
lazy val scalaVersion212: String = "2.12.13"
7171
lazy val scalaVersion213: String = "2.13.6"
72-
lazy val supportedScalaVersions = List(scalaVersion212, scalaVersion213)
72+
lazy val supportedScalaVersions = List(scalaVersion212, scalaVersion213)
7373

7474
ThisBuild / scalaVersion := scalaVersion212
7575

@@ -176,10 +176,10 @@ lazy val http4s021 =
176176
.settings(
177177
name := "scalapact-http4s-0-21",
178178
libraryDependencies ++= Seq(
179-
"org.http4s" %% "http4s-blaze-server" % "0.21.18" exclude("org.scala-lang.modules", "scala-xml"),
180-
"org.http4s" %% "http4s-blaze-client" % "0.21.18" exclude("org.scala-lang.modules", "scala-xml"),
181-
"org.http4s" %% "http4s-dsl" % "0.21.18",
182-
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
179+
"org.http4s" %% "http4s-blaze-server" % "0.21.18" exclude ("org.scala-lang.modules", "scala-xml"),
180+
"org.http4s" %% "http4s-blaze-client" % "0.21.18" exclude ("org.scala-lang.modules", "scala-xml"),
181+
"org.http4s" %% "http4s-dsl" % "0.21.18",
182+
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
183183
)
184184
)
185185
.dependsOn(shared)
@@ -191,10 +191,10 @@ lazy val http4s023 =
191191
.settings(
192192
name := "scalapact-http4s-0-23",
193193
libraryDependencies ++= Seq(
194-
"org.http4s" %% "http4s-blaze-server" % "0.23.0-RC1" exclude("org.scala-lang.modules", "scala-xml"),
195-
"org.http4s" %% "http4s-blaze-client" % "0.23.0-RC1" exclude("org.scala-lang.modules", "scala-xml"),
196-
"org.http4s" %% "http4s-dsl" % "0.23.0-RC1",
197-
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
194+
"org.http4s" %% "http4s-blaze-server" % "0.23.1" exclude ("org.scala-lang.modules", "scala-xml"),
195+
"org.http4s" %% "http4s-blaze-client" % "0.23.1" exclude ("org.scala-lang.modules", "scala-xml"),
196+
"org.http4s" %% "http4s-dsl" % "0.23.1",
197+
"com.github.tomakehurst" % "wiremock" % "2.25.1" % "test"
198198
)
199199
)
200200
.dependsOn(shared)
@@ -236,6 +236,21 @@ lazy val circe13 =
236236
.dependsOn(shared)
237237
.dependsOn(testShared % "test->compile")
238238

239+
lazy val circe14 =
240+
(project in file("scalapact-circe-0-14"))
241+
.settings(commonSettings: _*)
242+
.settings(publishSettings: _*)
243+
.settings(
244+
name := "scalapact-circe-0-14",
245+
libraryDependencies ++= Seq(
246+
"io.circe" %% "circe-core",
247+
"io.circe" %% "circe-generic",
248+
"io.circe" %% "circe-parser"
249+
).map(_ % "0.14.1")
250+
)
251+
.dependsOn(shared)
252+
.dependsOn(testShared % "test->compile")
253+
239254
lazy val pluginShared =
240255
(project in file("sbt-scalapact-shared"))
241256
.settings(commonSettings: _*)
@@ -252,11 +267,11 @@ lazy val plugin =
252267
.settings(publishSettings: _*)
253268
.settings(
254269
name := "sbt-scalapact",
255-
sbtPlugin := true,
270+
sbtPlugin := true
256271
)
257272
.dependsOn(pluginShared)
258-
.dependsOn(circe13)
259-
.dependsOn(http4s021)
273+
.dependsOn(circe14)
274+
.dependsOn(http4s023)
260275
.settings(scala212OnlySettings)
261276

262277
lazy val pluginNoDeps =
@@ -265,11 +280,11 @@ lazy val pluginNoDeps =
265280
.settings(publishSettings: _*)
266281
.settings(
267282
name := "sbt-scalapact-nodeps",
268-
sbtPlugin := true,
283+
sbtPlugin := true
269284
)
270285
.dependsOn(pluginShared)
271-
.dependsOn(circe13 % "provided")
272-
.dependsOn(http4s021 % "provided")
286+
.dependsOn(circe14 % "provided")
287+
.dependsOn(http4s023 % "provided")
273288
.settings(scala212OnlySettings)
274289

275290
lazy val framework =
@@ -295,8 +310,8 @@ lazy val frameworkWithDeps =
295310
}
296311
)
297312
.dependsOn(framework)
298-
.dependsOn(circe13)
299-
.dependsOn(http4s021)
313+
.dependsOn(circe14)
314+
.dependsOn(http4s023)
300315

301316
lazy val standalone =
302317
(project in file("scalapact-standalone-stubber"))
@@ -330,18 +345,18 @@ lazy val testsWithDeps =
330345
.settings(commonSettings: _*)
331346
.settings(
332347
libraryDependencies ++= Seq(
333-
"org.scalaj" %% "scalaj-http" % "2.4.2" % "test",
334-
"org.json4s" %% "json4s-native" % "3.6.11" % "test",
335-
"com.github.tomakehurst" % "wiremock" % "1.56" % "test",
336-
"fr.hmil" %% "roshttp" % "2.1.0" % "test",
337-
"io.argonaut" %% "argonaut" % "6.2.5"
348+
"org.scalaj" %% "scalaj-http" % "2.4.2" % "test",
349+
"org.json4s" %% "json4s-native" % "3.6.11" % "test",
350+
"com.github.tomakehurst" % "wiremock" % "1.56" % "test",
351+
"fr.hmil" %% "roshttp" % "2.1.0" % "test",
352+
"io.argonaut" %% "argonaut" % "6.2.5"
338353
),
339354
skip in publish := true
340355
)
341356
.settings(scala212OnlySettings)
342357
.dependsOn(framework)
343-
.dependsOn(circe13)
344-
.dependsOn(http4s021)
358+
.dependsOn(circe14)
359+
.dependsOn(http4s023)
345360

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

383398
lazy val updateVersionsInReadme: ReleaseStep = { st: State =>
384-
st.get(ReleaseKeys.versions).flatMap { case (newVersion, _) =>
385-
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
386-
val readmeLines = IO.readLines(readmeFile)
387-
val versionPrefix = "## Latest version is "
388-
val currentVersion = readmeLines.collectFirst { case s if s.startsWith(versionPrefix) => s.replace(versionPrefix, "").dropWhile(_.isWhitespace)}
389-
currentVersion.map { cv =>
390-
IO.writeLines(readmeFile, readmeLines.map(_.replaceAll(cv, newVersion)))
399+
st.get(ReleaseKeys.versions)
400+
.flatMap { case (newVersion, _) =>
401+
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
402+
val readmeLines = IO.readLines(readmeFile)
403+
val versionPrefix = "## Latest version is "
404+
val currentVersion = readmeLines.collectFirst {
405+
case s if s.startsWith(versionPrefix) => s.replace(versionPrefix, "").dropWhile(_.isWhitespace)
406+
}
407+
currentVersion.map { cv =>
408+
IO.writeLines(readmeFile, readmeLines.map(_.replaceAll(cv, newVersion)))
409+
}
391410
}
392-
}.getOrElse(())
411+
.getOrElse(())
393412

394413
st
395414
}
396415

397416
lazy val commitReadMeVersionBump: ReleaseStep = { st: State =>
398-
def vcs(st: State): Vcs = {
399-
st.extract.get(releaseVcs).getOrElse(sys.error("Aborting release. Working directory is not a repository of a recognized VCS."))
400-
}
417+
def vcs(st: State): Vcs =
418+
st.extract
419+
.get(releaseVcs)
420+
.getOrElse(sys.error("Aborting release. Working directory is not a repository of a recognized VCS."))
401421
val commitMessage: TaskKey[String] = releaseNextCommitMessage
402422
val log = new ProcessLogger {
403423
override def err(s: => String): Unit = st.log.info(s)
404424
override def out(s: => String): Unit = st.log.info(s)
405-
override def buffer[T](f: => T): T = st.log.buffer(f)
425+
override def buffer[T](f: => T): T = st.log.buffer(f)
406426
}
407427
val readmeFile = st.extract.get(readmeFileKey).getCanonicalFile
408-
val base = vcs(st).baseDir.getCanonicalFile
409-
val sign = st.extract.get(releaseVcsSign)
410-
val signOff = st.extract.get(releaseVcsSignOff)
411-
val relativePathToReadme = IO.relativize(base, readmeFile).getOrElse("Readme file [%s] is outside of this VCS repository with base directory [%s]!" format(readmeFile, base))
428+
val base = vcs(st).baseDir.getCanonicalFile
429+
val sign = st.extract.get(releaseVcsSign)
430+
val signOff = st.extract.get(releaseVcsSignOff)
431+
val relativePathToReadme = IO
432+
.relativize(base, readmeFile)
433+
.getOrElse("Readme file [%s] is outside of this VCS repository with base directory [%s]!" format (readmeFile, base))
412434

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.itv.scalapact.circe14
2+
3+
import com.itv.scalapact.shared.utils.ColourOutput._
4+
import com.itv.scalapact.shared.json.IJsonConversionFunctions
5+
import com.itv.scalapact.shared.matchir.IrNodePath.IrNodePathEmpty
6+
import com.itv.scalapact.shared.matchir.MatchIrConstants.{rootNodeLabel, unnamedNodeLabel}
7+
import com.itv.scalapact.shared.matchir._
8+
import com.itv.scalapact.shared.utils.PactLogger
9+
import io.circe._
10+
import io.circe.parser._
11+
12+
object JsonConversionFunctions extends IJsonConversionFunctions {
13+
14+
def fromJSON(jsonString: String): Option[IrNode] =
15+
parse(jsonString).toOption.flatMap { json =>
16+
jsonRootToIrNode(json, IrNodePathEmpty)
17+
}
18+
19+
private def jsonToIrNode(label: String, json: Json, pathToParent: IrNodePath): IrNode =
20+
json match {
21+
case j: Json if j.isArray =>
22+
IrNode(label, jsonArrayToIrNodeList(label, j, pathToParent)).withPath(pathToParent).markAsArray
23+
24+
case j: Json if j.isObject =>
25+
IrNode(label, jsonObjectToIrNodeList(j, pathToParent)).withPath(pathToParent)
26+
27+
case j: Json if j.isNumber =>
28+
IrNode(label, j.asNumber.map(_.toDouble).map(d => IrNumberNode(d))).withPath(pathToParent)
29+
30+
case j: Json if j.isBoolean =>
31+
IrNode(label, j.asBoolean.map(IrBooleanNode)).withPath(pathToParent)
32+
33+
case j: Json if j.isString =>
34+
IrNode(label, j.asString.map(IrStringNode)).withPath(pathToParent)
35+
36+
case _ =>
37+
IrNode(label, IrNullNode).withPath(pathToParent)
38+
}
39+
40+
private def jsonObjectToIrNodeList(json: Json, pathToParent: IrNodePath): List[IrNode] =
41+
json.hcursor.keys
42+
.map(_.toSet)
43+
.map(_.toList)
44+
.getOrElse(Nil)
45+
.map(l => if (l.isEmpty) unnamedNodeLabel else l)
46+
.map { l =>
47+
json.hcursor.downField(l).focus.map { q =>
48+
jsonToIrNode(l, q, pathToParent <~ l)
49+
}
50+
}
51+
.collect { case Some(s) => s }
52+
53+
private def jsonArrayToIrNodeList(parentLabel: String, json: Json, pathToParent: IrNodePath): List[IrNode] =
54+
json.asArray
55+
.map(_.toList)
56+
.getOrElse(Nil)
57+
.zipWithIndex
58+
.map(j => jsonToIrNode(parentLabel, j._1, pathToParent <~ j._2))
59+
60+
private def jsonRootToIrNode(json: Json, initialPath: IrNodePath): Option[IrNode] =
61+
json match {
62+
case j: Json if j.isArray =>
63+
Option(
64+
IrNode(rootNodeLabel, jsonArrayToIrNodeList(unnamedNodeLabel, j, initialPath))
65+
.withPath(initialPath)
66+
.markAsArray
67+
)
68+
69+
case j: Json if j.isObject =>
70+
Option(
71+
IrNode(rootNodeLabel, jsonObjectToIrNodeList(j, initialPath))
72+
.withPath(initialPath)
73+
)
74+
75+
case _ =>
76+
PactLogger.error("JSON was not an object or an array".red)
77+
None
78+
}
79+
80+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.itv.scalapact.circe14
2+
3+
import com.itv.scalapact.shared.{JvmPact, Pact}
4+
import com.itv.scalapact.shared.json.{ContractDeserializer, IPactReader, IPactWriter}
5+
import io.circe.parser.parse
6+
7+
trait JsonInstances {
8+
import PactImplicits._
9+
10+
implicit val pactReaderInstance: IPactReader = new PactReader
11+
12+
implicit val pactWriterInstance: IPactWriter = new PactWriter
13+
14+
implicit val pactDeserializer: ContractDeserializer[Pact] = (jsonString: String) =>
15+
parse(jsonString).flatMap(_.as[Pact]) match {
16+
case Right(a) => Right(a)
17+
case Left(_) => Left(s"Could not read scala-pact pact from json: $jsonString")
18+
}
19+
20+
implicit val jvmPactDeserializer: ContractDeserializer[JvmPact] = (jsonString: String) =>
21+
parse(jsonString).flatMap(_.as[JvmPact]) match {
22+
case Right(a) => Right(a)
23+
case Left(_) => Left(s"Could not read jvm-pact pact from json: $jsonString")
24+
}
25+
}

0 commit comments

Comments
 (0)