From dfe12f27063874ca6ff86dee98c85b82236e1762 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 5 Nov 2017 00:19:06 -0700 Subject: Turn on `lihaoyi:acyclic` plugin, enforce it, and break up whatever import cycles exist --- build.sbt | 7 +- core/src/main/scala/forge/JsonFormatters.scala | 47 +++++++++++++ core/src/main/scala/forge/Target.scala | 3 +- core/src/main/scala/forge/ZipTarget.scala | 40 +++++++++++ core/src/main/scala/forge/package.scala | 81 +--------------------- core/src/main/scala/forge/util/PathRef.scala | 3 + .../main/scala/forge/scalaplugin/Subproject.scala | 1 - 7 files changed, 99 insertions(+), 83 deletions(-) create mode 100644 core/src/main/scala/forge/JsonFormatters.scala create mode 100644 core/src/main/scala/forge/ZipTarget.scala diff --git a/build.sbt b/build.sbt index ea2db92e..cb233365 100644 --- a/build.sbt +++ b/build.sbt @@ -13,7 +13,12 @@ val sharedSettings = Seq( // G1 Garbage Collector is awesome https://github.com/lihaoyi/Ammonite/issues/216 Seq("#!/usr/bin/env sh", """exec java -jar -Xmx500m -XX:+UseG1GC $JAVA_OPTS "$0" "$@"""") ) - ) + ), + + libraryDependencies += "com.lihaoyi" %% "acyclic" % "0.1.7" % "provided", + scalacOptions += "-P:acyclic:force", + autoCompilerPlugins := true, + addCompilerPlugin("com.lihaoyi" %% "acyclic" % "0.1.7") ) lazy val core = project diff --git a/core/src/main/scala/forge/JsonFormatters.scala b/core/src/main/scala/forge/JsonFormatters.scala new file mode 100644 index 00000000..4e772128 --- /dev/null +++ b/core/src/main/scala/forge/JsonFormatters.scala @@ -0,0 +1,47 @@ +package forge + +import ammonite.ops.{Bytes, Path} +import play.api.libs.json._ +object JsonFormatters extends JsonFormatters +trait JsonFormatters { + implicit object pathFormat extends Format[ammonite.ops.Path]{ + def reads(json: JsValue) = json match{ + case JsString(v) => JsSuccess(Path(v)) + case _ => JsError("Paths must be a String") + } + def writes(o: Path) = JsString(o.toString) + } + + implicit object bytesFormat extends Format[Bytes]{ + def reads(json: JsValue) = json match{ + case JsString(v) => JsSuccess( + new Bytes(javax.xml.bind.DatatypeConverter.parseBase64Binary(v)) + ) + case _ => JsError("Bytes must be a String") + } + def writes(o: Bytes) = { + JsString(javax.xml.bind.DatatypeConverter.printBase64Binary(o.array)) + } + } + + implicit def EitherFormat[T: Format, V: Format] = new Format[Either[T, V]]{ + def reads(json: JsValue) = json match{ + case JsObject(struct) => + (struct.get("type"), struct.get("value")) match{ + case (Some(JsString("Left")), Some(v)) => implicitly[Reads[T]].reads(v).map(Left(_)) + case (Some(JsString("Right")), Some(v)) => implicitly[Reads[V]].reads(v).map(Right(_)) + case _ => JsError("Either object layout is unknown") + } + case _ => JsError("Either must be an Object") + } + def writes(o: Either[T, V]) = o match{ + case Left(v) => Json.obj("type" -> "Left", "value" -> implicitly[Writes[T]].writes(v)) + case Right(v) => Json.obj("type" -> "Right", "value" -> implicitly[Writes[V]].writes(v)) + } + } + + implicit lazy val crFormat: Format[ammonite.ops.CommandResult] = Json.format + implicit lazy val modFormat: Format[coursier.Module] = Json.format + implicit lazy val depFormat: Format[coursier.Dependency]= Json.format + implicit lazy val attrFormat: Format[coursier.Attributes] = Json.format +} diff --git a/core/src/main/scala/forge/Target.scala b/core/src/main/scala/forge/Target.scala index 71d8e52b..9aa4877e 100644 --- a/core/src/main/scala/forge/Target.scala +++ b/core/src/main/scala/forge/Target.scala @@ -1,7 +1,7 @@ package forge -import ammonite.ops.{ls, mkdir} +import ammonite.ops.{CommandResult, ls, mkdir} import forge.util.{Args, PathRef} import play.api.libs.json.{Format, JsValue, Json} @@ -166,6 +166,7 @@ object Target{ object Subprocess{ case class Result(result: ammonite.ops.CommandResult, dest: PathRef) object Result{ + private implicit val crFormat: Format[CommandResult] = JsonFormatters.crFormat implicit val tsFormat: Format[Target.Subprocess.Result] = Json.format } } diff --git a/core/src/main/scala/forge/ZipTarget.scala b/core/src/main/scala/forge/ZipTarget.scala new file mode 100644 index 00000000..e02bbc19 --- /dev/null +++ b/core/src/main/scala/forge/ZipTarget.scala @@ -0,0 +1,40 @@ +package forge + +import forge.util.Args + +object ZipTarget +trait ZipTarget { + val T = Target + type T[V] = Target[V] + def zipMap[R]()(f: () => R) = new Target.Target0(f()) + def zipMap[A, R](a: T[A])(f: A => R) = a.map(f) + def zipMap[A, B, R](a: T[A], b: T[B])(f: (A, B) => R) = zip(a, b).map(f.tupled) + def zipMap[A, B, C, R](a: T[A], b: T[B], c: T[C])(f: (A, B, C) => R) = zip(a, b, c).map(f.tupled) + def zipMap[A, B, C, D, R](a: T[A], b: T[B], c: T[C], d: T[D])(f: (A, B, C, D) => R) = zip(a, b, c, d).map(f.tupled) + def zipMap[A, B, C, D, E, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E])(f: (A, B, C, D, E) => R) = zip(a, b, c, d, e).map(f.tupled) + def zipMap[A, B, C, D, E, F, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F])(cb: (A, B, C, D, E, F) => R) = zip(a, b, c, d, e, f).map(cb.tupled) + def zipMap[A, B, C, D, E, F, G, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G])(cb: (A, B, C, D, E, F, G) => R) = zip(a, b, c, d, e, f, g).map(cb.tupled) + def zip() = new Target.Target0(()) + def zip[A](a: T[A]) = a.map(Tuple1(_)) + def zip[A, B](a: T[A], b: T[B]) = a.zip(b) + def zip[A, B, C](a: T[A], b: T[B], c: T[C]) = new T[(A, B, C)]{ + val inputs = Seq(a, b, c) + def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2)) + } + def zip[A, B, C, D](a: T[A], b: T[B], c: T[C], d: T[D]) = new T[(A, B, C, D)]{ + val inputs = Seq(a, b, c, d) + def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3)) + } + def zip[A, B, C, D, E](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E]) = new T[(A, B, C, D, E)]{ + val inputs = Seq(a, b, c, d, e) + def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4)) + } + def zip[A, B, C, D, E, F](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F]) = new T[(A, B, C, D, E, F)]{ + val inputs = Seq(a, b, c, d, e, f) + def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5)) + } + def zip[A, B, C, D, E, F, G](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G]) = new T[(A, B, C, D, E, F, G)]{ + val inputs = Seq(a, b, c, d, e, f, g) + def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6)) + } +} diff --git a/core/src/main/scala/forge/package.scala b/core/src/main/scala/forge/package.scala index 31a79b6a..4163237e 100644 --- a/core/src/main/scala/forge/package.scala +++ b/core/src/main/scala/forge/package.scala @@ -1,80 +1 @@ -import play.api.libs.json._ -import ammonite.ops.{Bytes, Path} -import coursier.Dependency -import forge.util.Args -package object forge { - - val T = Target - type T[T] = Target[T] - def zipMap[R]()(f: () => R) = new Target.Target0(f()) - def zipMap[A, R](a: T[A])(f: A => R) = a.map(f) - def zipMap[A, B, R](a: T[A], b: T[B])(f: (A, B) => R) = zip(a, b).map(f.tupled) - def zipMap[A, B, C, R](a: T[A], b: T[B], c: T[C])(f: (A, B, C) => R) = zip(a, b, c).map(f.tupled) - def zipMap[A, B, C, D, R](a: T[A], b: T[B], c: T[C], d: T[D])(f: (A, B, C, D) => R) = zip(a, b, c, d).map(f.tupled) - def zipMap[A, B, C, D, E, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E])(f: (A, B, C, D, E) => R) = zip(a, b, c, d, e).map(f.tupled) - def zipMap[A, B, C, D, E, F, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F])(cb: (A, B, C, D, E, F) => R) = zip(a, b, c, d, e, f).map(cb.tupled) - def zipMap[A, B, C, D, E, F, G, R](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G])(cb: (A, B, C, D, E, F, G) => R) = zip(a, b, c, d, e, f, g).map(cb.tupled) - def zip() = new Target.Target0(()) - def zip[A](a: T[A]) = a.map(Tuple1(_)) - def zip[A, B](a: T[A], b: T[B]) = a.zip(b) - def zip[A, B, C](a: T[A], b: T[B], c: T[C]) = new T[(A, B, C)]{ - val inputs = Seq(a, b, c) - def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2)) - } - def zip[A, B, C, D](a: T[A], b: T[B], c: T[C], d: T[D]) = new T[(A, B, C, D)]{ - val inputs = Seq(a, b, c, d) - def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3)) - } - def zip[A, B, C, D, E](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E]) = new T[(A, B, C, D, E)]{ - val inputs = Seq(a, b, c, d, e) - def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4)) - } - def zip[A, B, C, D, E, F](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F]) = new T[(A, B, C, D, E, F)]{ - val inputs = Seq(a, b, c, d, e, f) - def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5)) - } - def zip[A, B, C, D, E, F, G](a: T[A], b: T[B], c: T[C], d: T[D], e: T[E], f: T[F], g: T[G]) = new T[(A, B, C, D, E, F, G)]{ - val inputs = Seq(a, b, c, d, e, f, g) - def evaluate(args: Args) = (args[A](0), args[B](1), args[C](2), args[D](3), args[E](4), args[F](5), args[G](6)) - } - implicit object pathFormat extends Format[ammonite.ops.Path]{ - def reads(json: JsValue) = json match{ - case JsString(v) => JsSuccess(Path(v)) - case _ => JsError("Paths must be a String") - } - def writes(o: Path) = JsString(o.toString) - } - - implicit object bytesFormat extends Format[Bytes]{ - def reads(json: JsValue) = json match{ - case JsString(v) => JsSuccess( - new Bytes(javax.xml.bind.DatatypeConverter.parseBase64Binary(v)) - ) - case _ => JsError("Bytes must be a String") - } - def writes(o: Bytes) = { - JsString(javax.xml.bind.DatatypeConverter.printBase64Binary(o.array)) - } - } - - implicit def EitherFormat[T: Format, V: Format] = new Format[Either[T, V]]{ - def reads(json: JsValue) = json match{ - case JsObject(struct) => - (struct.get("type"), struct.get("value")) match{ - case (Some(JsString("Left")), Some(v)) => implicitly[Reads[T]].reads(v).map(Left(_)) - case (Some(JsString("Right")), Some(v)) => implicitly[Reads[V]].reads(v).map(Right(_)) - case _ => JsError("Either object layout is unknown") - } - case _ => JsError("Either must be an Object") - } - def writes(o: Either[T, V]) = o match{ - case Left(v) => Json.obj("type" -> "Left", "value" -> implicitly[Writes[T]].writes(v)) - case Right(v) => Json.obj("type" -> "Right", "value" -> implicitly[Writes[V]].writes(v)) - } - } - - implicit lazy val crFormat: Format[ammonite.ops.CommandResult] = Json.format - implicit lazy val modFormat: Format[coursier.Module] = Json.format - implicit lazy val depFormat: Format[coursier.Dependency]= Json.format - implicit lazy val attrFormat: Format[coursier.Attributes] = Json.format -} +package object forge extends ZipTarget with JsonFormatters diff --git a/core/src/main/scala/forge/util/PathRef.scala b/core/src/main/scala/forge/util/PathRef.scala index dbe1ebbd..333f225e 100644 --- a/core/src/main/scala/forge/util/PathRef.scala +++ b/core/src/main/scala/forge/util/PathRef.scala @@ -6,6 +6,8 @@ import java.nio.file.{FileVisitResult, FileVisitor} import java.nio.file.attribute.BasicFileAttributes import java.security.MessageDigest import java.nio.{file => jnio} + +import ammonite.ops.Path import play.api.libs.json.{Format, Json} @@ -53,5 +55,6 @@ case class PathRef(path: ammonite.ops.Path){ } object PathRef{ + private implicit val pathFormat: Format[Path] = JsonFormatters.pathFormat implicit def jsonFormatter: Format[PathRef] = Json.format } diff --git a/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala b/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala index a8981564..cc573d88 100644 --- a/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala +++ b/scalaplugin/src/main/scala/forge/scalaplugin/Subproject.scala @@ -6,7 +6,6 @@ import java.io.File import ammonite.ops.{Path, ls, mkdir, pwd} import coursier.{Cache, Dependency, Fetch, MavenRepository, Module, Repository, Resolution} import forge.Target.Cacher -import forge.{Target => T} import forge.util.PathRef import play.api.libs.json._ import sbt.internal.inc.{FreshCompilerCache, ScalaInstance, ZincUtil} -- cgit v1.2.3