From 8cd0591a85d65cfdf648afa40534e03ac3652e7f Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Mon, 5 Mar 2018 12:01:30 -0800 Subject: [PATCH 1/5] Update libraries and sbt to latest This brings docless up to: - cats 1.x - circe 0.9 - sbt 1.1.x Fixes #16 --- build.sbt | 60 ++++++++++--------- project/build.properties | 2 +- project/plugins.sbt | 8 +-- .../com/timeout/docless/swagger/Path.scala | 2 +- .../timeout/docless/swagger/SwaggerTest.scala | 2 +- 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/build.sbt b/build.sbt index ce2d357..4db2a13 100644 --- a/build.sbt +++ b/build.sbt @@ -5,32 +5,40 @@ name := "docless" version := "0.6.0-SNAPSHOT" -val circeVersion = "0.7.0" -val enumeratumVersion = "1.5.7" -val catsVersion = "0.9.0" +val circeVersion = "0.9.1" +val enumeratumVersion = "1.5.12" +val catsVersion = "1.0.1" +val shapelessVersion = "2.3.3" +val ammoniteVersion = "1.0.5" val readme = "README.md" val readmePath = file(".") / readme -scalaVersion := "2.12.1" +scalaVersion := "2.12.4" -crossScalaVersions := Seq("2.11.8", "2.12.1") +crossScalaVersions := Seq("2.11.11", "2.12.4") useGpg := true useGpgAgent := true +enablePlugins(TutPlugin) + +scalacOptions += "-Ypartial-unification" + libraryDependencies ++= Seq( "org.scala-lang" % "scala-reflect" % scalaVersion.value, - "com.chuusai" %% "shapeless" % "2.3.2", + "com.chuusai" %% "shapeless" % shapelessVersion, "com.beachape" %% "enumeratum" % enumeratumVersion, - "com.beachape" %% "enumeratum-circe" % "1.5.9", - "org.typelevel" %% "cats" % catsVersion, + "com.beachape" %% "enumeratum-circe" % enumeratumVersion, + "org.typelevel" %% "cats-core" % catsVersion, + "org.typelevel" %% "cats-kernel" % catsVersion, + "org.typelevel" %% "cats-macros" % catsVersion, "io.circe" %% "circe-core" % circeVersion, "io.circe" %% "circe-parser" % circeVersion, "io.circe" %% "circe-generic" % circeVersion, - "org.scalatest" %% "scalatest" % "3.0.0" % "test", + "org.scalatest" %% "scalatest" % "3.0.5" % "test", "com.github.fge" % "json-schema-validator" % "2.2.6" % "test", - "com.lihaoyi" % "ammonite" % "0.8.1" % "test" cross CrossVersion.full + "com.lihaoyi" % "ammonite" % ammoniteVersion % "test" cross CrossVersion.full ) val predef = Seq( @@ -66,20 +74,18 @@ copyReadme := { val pandocReadme = taskKey[Unit](s"Add a table of content to the README using pandoc") -pandocReadme := { - val readme = copyReadme.value - val log = streams.value.log - val cmd = - s"pandoc -B doc/header.md -f markdown_github --toc -s -S $readme -o $readme" - log.info(s"Running pandoc: $cmd}") - try { Process(cmd) ! log } catch { - case e: java.io.IOException => - log.error( - "You might need to install the pandoc executable! Please follow instructions here: http://pandoc.org/installing.html" - ) - throw e - } - -} - -tutSettings + pandocReadme := { + val readme = copyReadme.value + val log = streams.value.log + val cmd = + s"pandoc -B doc/header.md -f markdown_github --toc -s -S $readme -o $readme" + log.info(s"Running pandoc: $cmd}") + try { new Fork(cmd, None) } catch { + case e: java.io.IOException => + log.error( + "You might need to install the pandoc executable! Please follow instructions here: http://pandoc.org/installing.html" + ) + throw e + } + + } diff --git a/project/build.properties b/project/build.properties index b168a33..c4dc11b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 0.13.13 +sbt.version = 1.1.0 diff --git a/project/plugins.sbt b/project/plugins.sbt index 4116f75..44dc087 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,9 +1,9 @@ logLevel := Level.Warn -//addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.5.2") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.4.0") -addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.4.8") +addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.6.3") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3") diff --git a/src/main/scala/com/timeout/docless/swagger/Path.scala b/src/main/scala/com/timeout/docless/swagger/Path.scala index 7e07cfc..8b973d8 100644 --- a/src/main/scala/com/timeout/docless/swagger/Path.scala +++ b/src/main/scala/com/timeout/docless/swagger/Path.scala @@ -14,7 +14,7 @@ case class Path(id: String, def paramRefs: Set[RefWithContext] = parameters.flatMap(paramRef).toSet ++ - operations.foldMap(_.parameters.flatMap(paramRef)) + operations.values.toList.foldMap(_.parameters.flatMap(paramRef)) def responseRefs: Set[RefWithContext] = operations.flatMap { diff --git a/src/test/scala/com/timeout/docless/swagger/SwaggerTest.scala b/src/test/scala/com/timeout/docless/swagger/SwaggerTest.scala index 7705bdc..7b39a62 100644 --- a/src/test/scala/com/timeout/docless/swagger/SwaggerTest.scala +++ b/src/test/scala/com/timeout/docless/swagger/SwaggerTest.scala @@ -13,7 +13,7 @@ class SwaggerTest extends FreeSpec { val petstoreSchema = PetstoreSchema() val json = JsonLoader.fromResource("/swagger-schema.json") val schema = JsonSchemaFactory.byDefault().getJsonSchema(json) - val printer = Printer.spaces2.copy(dropNullKeys = true) + val printer = Printer.spaces2.copy(dropNullValues = true) val jsonS = printer.pretty(petstoreSchema.asJson) val report = schema.validate(JsonLoader.fromString(jsonS)) val err = System.err From c9fe78c6eb84bc299d87f7dc79cfedf46f6fa816 Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Mon, 5 Mar 2018 12:05:31 -0800 Subject: [PATCH 2/5] Update travisci builds --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 65319cf..feda565 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ # See http://about.travis-ci.org/docs/user/build-configuration/ language: scala scala: - - 2.11.8 - - 2.12.1 + - 2.11.11 + - 2.12.4 jdk: - oraclejdk8 before_install: From d0419840c67f60ec0c7c2b1c535fccc78ff56873 Mon Sep 17 00:00:00 2001 From: Andrew Kuhnhausen Date: Mon, 5 Mar 2018 14:23:52 -0800 Subject: [PATCH 3/5] Only depend on 2.11.x that all libs support --- .travis.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index feda565..88f47de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ # See http://about.travis-ci.org/docs/user/build-configuration/ language: scala scala: - - 2.11.11 + - 2.11.9 - 2.12.4 jdk: - oraclejdk8 diff --git a/build.sbt b/build.sbt index 4db2a13..0a6b21a 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,7 @@ val readmePath = file(".") / readme scalaVersion := "2.12.4" -crossScalaVersions := Seq("2.11.11", "2.12.4") +crossScalaVersions := Seq("2.11.9", "2.12.4") useGpg := true useGpgAgent := true From f8928c60d02cbf3a6019506ce691db9dfa617669 Mon Sep 17 00:00:00 2001 From: Emilien Taque Date: Wed, 4 Apr 2018 14:42:39 +0200 Subject: [PATCH 4/5] Use type args in JsonSchema ids to avoid id collision for lists Without this, lists as JsonSchema instances do share the same id, `scala.collection.immutable.List` This also further upgrade dependencies. --- build.sbt | 7 ++++--- .../com/timeout/docless/schema/JsonSchema.scala | 11 +++++++---- .../com/timeout/docless/schema/Primitives.scala | 3 +-- .../com/timeout/docless/swagger/APISchema.scala | 2 +- .../timeout/docless/schema/JsonSchemaTest.scala | 17 +++++++++++++++++ 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/build.sbt b/build.sbt index 0a6b21a..4918a2d 100644 --- a/build.sbt +++ b/build.sbt @@ -6,8 +6,9 @@ name := "docless" version := "0.6.0-SNAPSHOT" val circeVersion = "0.9.1" -val enumeratumVersion = "1.5.12" -val catsVersion = "1.0.1" +val enumeratumVersion = "1.5.13" +val enumeratumCirceVersion = "1.5.17" +val catsVersion = "1.1.0" val shapelessVersion = "2.3.3" val ammoniteVersion = "1.0.5" @@ -29,7 +30,7 @@ libraryDependencies ++= Seq( "org.scala-lang" % "scala-reflect" % scalaVersion.value, "com.chuusai" %% "shapeless" % shapelessVersion, "com.beachape" %% "enumeratum" % enumeratumVersion, - "com.beachape" %% "enumeratum-circe" % enumeratumVersion, + "com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion, "org.typelevel" %% "cats-core" % catsVersion, "org.typelevel" %% "cats-kernel" % catsVersion, "org.typelevel" %% "cats-macros" % catsVersion, diff --git a/src/main/scala/com/timeout/docless/schema/JsonSchema.scala b/src/main/scala/com/timeout/docless/schema/JsonSchema.scala index a712d30..dd3e35a 100644 --- a/src/main/scala/com/timeout/docless/schema/JsonSchema.scala +++ b/src/main/scala/com/timeout/docless/schema/JsonSchema.scala @@ -116,11 +116,14 @@ object JsonSchema fromRegex[K](".*".r) } + def tagId[A](tag: ru.WeakTypeTag[A]): String = + tag.tpe.toString + def instance[A]( obj: => JsonObject )(implicit tag: ru.WeakTypeTag[A]): JsonSchema[A] = new JsonSchema[A] { - override def id = tag.tpe.typeSymbol.fullName + override def id = tagId(tag) override def inline = false override def jsonObject = obj override def relatedDefinitions = Set.empty @@ -130,7 +133,7 @@ object JsonSchema obj: => JsonObject )(implicit tag: ru.WeakTypeTag[A]): JsonSchema[F[A]] = new JsonSchema[F[A]] { - override def id = tag.tpe.typeSymbol.fullName + override def id = tagId(tag) override def inline = false override def jsonObject = obj override def relatedDefinitions = Set.empty @@ -139,7 +142,7 @@ object JsonSchema def instanceAndRelated[A]( pair: => (JsonObject, Set[Definition]) )(implicit tag: ru.WeakTypeTag[A]): JsonSchema[A] = new JsonSchema[A] { - override def id = tag.tpe.typeSymbol.fullName + override def id = tagId(tag) override def inline = false override def jsonObject = pair._1 override def relatedDefinitions = pair._2 @@ -149,7 +152,7 @@ object JsonSchema obj: => JsonObject )(implicit tag: ru.WeakTypeTag[A]): JsonSchema[A] = new JsonSchema[A] { - override def id = tag.tpe.typeSymbol.fullName + override def id = tagId(tag) override def inline = true override def relatedDefinitions = Set.empty override def jsonObject = obj diff --git a/src/main/scala/com/timeout/docless/schema/Primitives.scala b/src/main/scala/com/timeout/docless/schema/Primitives.scala index 5b46370..e09fb72 100644 --- a/src/main/scala/com/timeout/docless/schema/Primitives.scala +++ b/src/main/scala/com/timeout/docless/schema/Primitives.scala @@ -70,8 +70,7 @@ trait Primitives { ).asJsonObject ) - implicit def listSchema[A: JsonSchema]: JsonSchema[List[A]] = { - val schema = implicitly[JsonSchema[A]] + implicit def listSchema[A: JsonSchema](implicit schema: JsonSchema[A], tag: ru.WeakTypeTag[A]): JsonSchema[List[A]] = { inlineInstance[List[A]]( JsonObject.fromMap( Map( diff --git a/src/main/scala/com/timeout/docless/swagger/APISchema.scala b/src/main/scala/com/timeout/docless/swagger/APISchema.scala index 8b9be78..57916cb 100644 --- a/src/main/scala/com/timeout/docless/swagger/APISchema.scala +++ b/src/main/scala/com/timeout/docless/swagger/APISchema.scala @@ -32,7 +32,7 @@ case class APISchema( object APISchema { - implicit val externalDocsEncoder: Encoder[ExternalDocs] = + implicit val externalDocsEncoder: Encoder[ExternalDocs] = deriveEncoder[ExternalDocs] implicit val contactEncoder: Encoder[Info.Contact] = deriveEncoder[Info.Contact] diff --git a/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala b/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala index 7491582..057c10e 100644 --- a/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala +++ b/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala @@ -136,6 +136,23 @@ class JsonSchemaTest extends FreeSpec { schema.relatedDefinitions should ===(Set(fs.NamedDefinition("fooOpt"))) } + "handles list of non-primitive types" in { + implicit val fs: JsonSchema[Foo] = fooSchema + + val schema = JsonSchema.deriveFor[List[Foo]] + parser.parse(s""" + |{ + | "type": "array", + | "items": { + | "$ref" : "#/definitions/${id[Foo]}" + | } + |} + | + """.stripMargin) should ===(Right(schema.asJson)) + + schema.id should ===(id[List[Foo]]) + } + "with types extending enumeratum.EnumEntry" - { "does not derive automatically" in { """ From 24c359d4f9711945d9a63c5bac585e30ae4a4205 Mon Sep 17 00:00:00 2001 From: Emilien Taque Date: Wed, 4 Apr 2018 14:46:49 +0200 Subject: [PATCH 5/5] Use short version of type names to avoid exposing internals. --- src/main/scala/com/timeout/docless/schema/JsonSchema.scala | 3 ++- src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/com/timeout/docless/schema/JsonSchema.scala b/src/main/scala/com/timeout/docless/schema/JsonSchema.scala index dd3e35a..d2c56d5 100644 --- a/src/main/scala/com/timeout/docless/schema/JsonSchema.scala +++ b/src/main/scala/com/timeout/docless/schema/JsonSchema.scala @@ -117,7 +117,8 @@ object JsonSchema } def tagId[A](tag: ru.WeakTypeTag[A]): String = - tag.tpe.toString + tag.tpe.typeSymbol.name + + (if (tag.tpe.typeArgs.nonEmpty) "[" + tag.tpe.typeArgs.map(_.typeSymbol.name).mkString(",") + "]" else "") def instance[A]( obj: => JsonObject diff --git a/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala b/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala index 057c10e..968082d 100644 --- a/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala +++ b/src/test/scala/com/timeout/docless/schema/JsonSchemaTest.scala @@ -12,8 +12,7 @@ object JsonSchemaTest { val ref = "$ref" def id[T: u.WeakTypeTag] = - getClass.getCanonicalName.replace('$', '.') + - implicitly[u.WeakTypeTag[T]].tpe.typeSymbol.name + JsonSchema.tagId(implicitly[u.WeakTypeTag[T]]) sealed abstract class E extends EnumEntry