From cc3f46f9966b57a60bad948343950dcaba38e5ab Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 21 Jun 2017 14:41:23 +0100 Subject: [PATCH 1/3] Move HListFormats to collection to drop cache->collection dep Looks like the reason that util-cache depended on util-collection was to define the sjson-new formats (HListFormats) for util-collection's HList. Given that util-collection already depends on sjsonnew, HListFormats can also be defined in util-collection. All that was left then was (a) HListFormatSpec requires sjsonnewScalaJson, so that was added in test scope, and (b) HListFormats had to be dropped from sbt.util.CacheImplicits - HListFormats will have to be imported and/or mixed-in where required downstream. For importing convenience I defined a companion object. --- .../sbt/internal/util/HListFormats.scala | 70 +++++++++++++++++++ .../src/test/scala/HListFormatSpec.scala | 28 ++++++++ 2 files changed, 98 insertions(+) create mode 100644 internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala create mode 100644 internal/util-collection/src/test/scala/HListFormatSpec.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala b/internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala new file mode 100644 index 000000000..6abae921c --- /dev/null +++ b/internal/util-collection/src/main/scala/sbt/internal/util/HListFormats.scala @@ -0,0 +1,70 @@ +package sbt +package internal +package util + +import sjsonnew._ +import Types.:+: + +trait HListFormats { + implicit val lnilFormat1: JsonFormat[HNil] = forHNil(HNil) + implicit val lnilFormat2: JsonFormat[HNil.type] = forHNil(HNil) + + private def forHNil[A <: HNil](hnil: A): JsonFormat[A] = new JsonFormat[A] { + def write[J](x: A, builder: Builder[J]): Unit = { + builder.beginArray() + builder.endArray() + } + + def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): A = jsOpt match { + case None => hnil + case Some(js) => unbuilder.beginArray(js); unbuilder.endArray(); hnil + } + } + + implicit def hconsFormat[H, T <: HList](implicit hf: JsonFormat[H], tf: HListJF[T]): JsonFormat[H :+: T] = + new JsonFormat[H :+: T] { + def write[J](hcons: H :+: T, builder: Builder[J]) = { + builder.beginArray() + hf.write(hcons.head, builder) + tf.write(hcons.tail, builder) + builder.endArray() + } + + def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = jsOpt match { + case None => HCons(hf.read(None, unbuilder), tf.read(None, unbuilder)) + case Some(js) => + unbuilder.beginArray(js) + val hcons = HCons(hf.read(Some(unbuilder.nextElement), unbuilder), tf.read(Some(js), unbuilder)) + unbuilder.endArray() + hcons + } + } + + trait HListJF[A <: HList] { + def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): A + def write[J](obj: A, builder: Builder[J]): Unit + } + + implicit def hconsHListJF[H, T <: HList](implicit hf: JsonFormat[H], tf: HListJF[T]): HListJF[H :+: T] = + new HListJF[H :+: T] { + def write[J](hcons: H :+: T, builder: Builder[J]) = { + hf.write(hcons.head, builder) + tf.write(hcons.tail, builder) + } + + def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = jsOpt match { + case None => HCons(hf.read(None, unbuilder), tf.read(None, unbuilder)) + case Some(js) => HCons(hf.read(Some(unbuilder.nextElement), unbuilder), tf.read(Some(js), unbuilder)) + } + } + + implicit val lnilHListJF1: HListJF[HNil] = hnilHListJF(HNil) + implicit val lnilHListJF2: HListJF[HNil.type] = hnilHListJF(HNil) + + implicit def hnilHListJF[A <: HNil](hnil: A): HListJF[A] = new HListJF[A] { + def write[J](hcons: A, builder: Builder[J]) = () + def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = hnil + } +} + +object HListFormats extends HListFormats diff --git a/internal/util-collection/src/test/scala/HListFormatSpec.scala b/internal/util-collection/src/test/scala/HListFormatSpec.scala new file mode 100644 index 000000000..8f6e9a73b --- /dev/null +++ b/internal/util-collection/src/test/scala/HListFormatSpec.scala @@ -0,0 +1,28 @@ +package sbt +package internal +package util + +import scalajson.ast.unsafe._ +import sjsonnew._, BasicJsonProtocol._, support.scalajson.unsafe._ +import HListFormats._ + +class HListFormatSpec extends UnitSpec { + val quux = 23 :+: "quux" :+: true :+: HNil + + it should "round trip quux" in assertRoundTrip(quux) + it should "round trip hnil" in assertRoundTrip(HNil) + + it should "have a flat structure for quux" in assertJsonString(quux, """[23,"quux",true]""") + it should "have a flat structure for hnil" in assertJsonString(HNil, "[]") + + def assertRoundTrip[A: JsonWriter: JsonReader](x: A) = { + val jsonString: String = toJsonString(x) + val jValue: JValue = Parser.parseUnsafe(jsonString) + val y: A = Converter.fromJson[A](jValue).get + assert(x === y) + } + + def assertJsonString[A: JsonWriter](x: A, s: String) = assert(toJsonString(x) === s) + + def toJsonString[A: JsonWriter](x: A): String = CompactPrinter(Converter.toJson(x).get) +} From 2cc93f2382030967188fc37a4169298b36128fd5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 23 Jun 2017 14:06:53 +0100 Subject: [PATCH 2/3] Move Showlines to logging to drop logging->collection dep --- .../src/main/scala/sbt/util/ShowLines.scala | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 internal/util-collection/src/main/scala/sbt/util/ShowLines.scala diff --git a/internal/util-collection/src/main/scala/sbt/util/ShowLines.scala b/internal/util-collection/src/main/scala/sbt/util/ShowLines.scala deleted file mode 100644 index 65729d747..000000000 --- a/internal/util-collection/src/main/scala/sbt/util/ShowLines.scala +++ /dev/null @@ -1,15 +0,0 @@ -package sbt.util - -trait ShowLines[A] { - def showLines(a: A): Seq[String] -} -object ShowLines { - def apply[A](f: A => Seq[String]): ShowLines[A] = - new ShowLines[A] { - def showLines(a: A): Seq[String] = f(a) - } - - implicit class ShowLinesOp[A: ShowLines](a: A) { - def lines: Seq[String] = implicitly[ShowLines[A]].showLines(a) - } -} From a77d3146ab6427b72b6ceefef9d60fce9f139d7b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 23 Jun 2017 14:12:02 +0100 Subject: [PATCH 3/3] Breakout Position to drop lm->collection dep --- .../scala/sbt/internal/util/Positions.scala | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 internal/util-collection/src/main/scala/sbt/internal/util/Positions.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Positions.scala b/internal/util-collection/src/main/scala/sbt/internal/util/Positions.scala deleted file mode 100644 index a11ae9c24..000000000 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Positions.scala +++ /dev/null @@ -1,20 +0,0 @@ -package sbt.internal.util - -sealed trait SourcePosition - -sealed trait FilePosition extends SourcePosition { - def path: String - def startLine: Int -} - -case object NoPosition extends SourcePosition - -final case class LinePosition(path: String, startLine: Int) extends FilePosition - -final case class LineRange(start: Int, end: Int) { - def shift(n: Int) = new LineRange(start + n, end + n) -} - -final case class RangePosition(path: String, range: LineRange) extends FilePosition { - def startLine = range.start -}