From ae4e53ceb0fc56d9787fc1a70b71580d330c9437 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 21 Mar 2017 00:09:07 +0000 Subject: [PATCH 1/4] Define OptJsonWriter & put it on AttributeKey --- .../scala/sbt/internal/util/Attributes.scala | 20 +++++++++++-------- .../sbt/internal/util/OptJsonWriter.scala | 14 +++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala b/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala index 33591506c..b8ed058a1 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala +++ b/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala @@ -39,6 +39,8 @@ sealed trait AttributeKey[T] { /** Identifies the relative importance of a key among other keys.*/ def rank: Int + + def optJsonWriter: OptJsonWriter[T] } private[sbt] abstract class SharedAttributeKey[T] extends AttributeKey[T] { override final def toString = label @@ -50,32 +52,33 @@ private[sbt] abstract class SharedAttributeKey[T] extends AttributeKey[T] { final def isLocal: Boolean = false } object AttributeKey { - def apply[T](name: String)(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = make(name, None, Nil, Int.MaxValue) - def apply[T](name: String, rank: Int)(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String, rank: Int)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = make(name, None, Nil, rank) - def apply[T](name: String, description: String)(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String, description: String)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = apply(name, description, Nil) - def apply[T](name: String, description: String, rank: Int)(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String, description: String, rank: Int)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = apply(name, description, Nil, rank) - def apply[T](name: String, description: String, extend: Seq[AttributeKey[_]])(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String, description: String, extend: Seq[AttributeKey[_]])(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = apply(name, description, extend, Int.MaxValue) - def apply[T](name: String, description: String, extend: Seq[AttributeKey[_]], rank: Int)(implicit mf: Manifest[T]): AttributeKey[T] = + def apply[T](name: String, description: String, extend: Seq[AttributeKey[_]], rank: Int)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = make(name, Some(description), extend, rank) - private[this] def make[T](name: String, description0: Option[String], extend0: Seq[AttributeKey[_]], rank0: Int)(implicit mf: Manifest[T]): AttributeKey[T] = new SharedAttributeKey[T] { + private[this] def make[T](name: String, description0: Option[String], extend0: Seq[AttributeKey[_]], rank0: Int)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = new SharedAttributeKey[T] { def manifest = mf val label = Util.hyphenToCamel(name) def description = description0 def extend = extend0 def rank = rank0 + def optJsonWriter = ojw } - private[sbt] def local[T](implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] { + private[sbt] def local[T](implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] = new AttributeKey[T] { def manifest = mf def label = LocalLabel def description = None @@ -83,6 +86,7 @@ object AttributeKey { override def toString = label def isLocal: Boolean = true def rank = Int.MaxValue + val optJsonWriter = ojw } private[sbt] final val LocalLabel = "$" + "local" } diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala b/internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala new file mode 100644 index 000000000..f44ef44e8 --- /dev/null +++ b/internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala @@ -0,0 +1,14 @@ +package sbt.internal.util + +import sjsonnew.JsonWriter + +sealed trait OptJsonWriter[A] +final case class NoJsonWriter[A]() extends OptJsonWriter[A] +final case class SomeJsonWriter[A](value: JsonWriter[A]) extends OptJsonWriter[A] + +trait OptJsonWriter0 { + implicit def fallback[A]: NoJsonWriter[A] = NoJsonWriter() +} +object OptJsonWriter extends OptJsonWriter0 { + implicit def lift[A](implicit z: JsonWriter[A]): SomeJsonWriter[A] = SomeJsonWriter(z) +} From 9cfa17d09e3692120735649940fd53db684e2ffe Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 21 Mar 2017 10:46:58 +0000 Subject: [PATCH 2/4] Move OptJsonWriter to public API --- .../src/main/scala/sbt/internal/util/Attributes.scala | 1 + .../src/main/scala/sbt/{internal => }/util/OptJsonWriter.scala | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename internal/util-collection/src/main/scala/sbt/{internal => }/util/OptJsonWriter.scala (94%) diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala b/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala index b8ed058a1..5cf6fb65b 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala +++ b/internal/util-collection/src/main/scala/sbt/internal/util/Attributes.scala @@ -5,6 +5,7 @@ package sbt.internal.util import Types._ import scala.reflect.Manifest +import sbt.util.OptJsonWriter // T must be invariant to work properly. // Because it is sealed and the only instances go through AttributeKey.apply, diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala similarity index 94% rename from internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala rename to internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala index f44ef44e8..3a2a23f25 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/OptJsonWriter.scala +++ b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala @@ -1,4 +1,4 @@ -package sbt.internal.util +package sbt.util import sjsonnew.JsonWriter From 0713e31ceaded0cfd6b58277e4fecfeb468dfe1f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 21 Mar 2017 17:12:10 +0000 Subject: [PATCH 3/4] Allow opting out of the fallback OptJsonWriter Simply import OptJsonWriter.OptOut._ And you'll get the implicit lift, but not the implicit fallback. You get an ambiguous compile error like this: [error] /d/sbt-util/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala:28: ambiguous implicit values: [error] both method conflictingFallback1 in trait OptOut0 of type [A]=> sbt.util.NoJsonWriter[A] [error] and method conflictingFallback2 in trait OptOut0 of type [A]=> sbt.util.NoJsonWriter[A] [error] match expected type sbt.util.OptJsonWriter[Foo] [error] val x = implicitly[OptJsonWriter[Foo]] [error] ^ --- .../src/main/scala/sbt/util/OptJsonWriter.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala index 3a2a23f25..b7a793b46 100644 --- a/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala +++ b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala @@ -11,4 +11,12 @@ trait OptJsonWriter0 { } object OptJsonWriter extends OptJsonWriter0 { implicit def lift[A](implicit z: JsonWriter[A]): SomeJsonWriter[A] = SomeJsonWriter(z) + + trait OptOut0 { + implicit def conflictingFallback1[A]: NoJsonWriter[A] = NoJsonWriter() + implicit def conflictingFallback2[A]: NoJsonWriter[A] = NoJsonWriter() + } + object OptOut extends OptOut0 { + implicit def lift[A](implicit z: JsonWriter[A]): SomeJsonWriter[A] = SomeJsonWriter(z) + } } From f0057fcdec302455ad0a2519bbe8ccdce4e2bf75 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 21 Mar 2017 21:50:45 +0000 Subject: [PATCH 4/4] Rename to StrictMode --- .../src/main/scala/sbt/util/OptJsonWriter.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala index b7a793b46..e840bc689 100644 --- a/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala +++ b/internal/util-collection/src/main/scala/sbt/util/OptJsonWriter.scala @@ -12,11 +12,11 @@ trait OptJsonWriter0 { object OptJsonWriter extends OptJsonWriter0 { implicit def lift[A](implicit z: JsonWriter[A]): SomeJsonWriter[A] = SomeJsonWriter(z) - trait OptOut0 { + trait StrictMode0 { implicit def conflictingFallback1[A]: NoJsonWriter[A] = NoJsonWriter() implicit def conflictingFallback2[A]: NoJsonWriter[A] = NoJsonWriter() } - object OptOut extends OptOut0 { + object StrictMode extends StrictMode0 { implicit def lift[A](implicit z: JsonWriter[A]): SomeJsonWriter[A] = SomeJsonWriter(z) } }