Skip to content

Commit

Permalink
Add support for Scala 2.13 and update circe to 0.13.0 (dropping Scala…
Browse files Browse the repository at this point in the history
… 2.11)
  • Loading branch information
Alex Zolotko committed Jul 29, 2020
1 parent 1a5e0bd commit 35898c8
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 98 deletions.
7 changes: 4 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
language: scala
scala:
- 2.11.7
- 2.11.8
- 2.12.1
- 2.12.12
- 2.13.3

jdk:
- oraclejdk8
- openjdk8
- openjdk11

script:
- sbt clean test
Expand Down
4 changes: 2 additions & 2 deletions CONTRIB.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ Releases are managed by the core team, but documenting the process here
because we sometimes forget too :)

The workflow for releases are managed through sbt. You need to have ```~/.sbt/0.13/sonatype.sbt```
configured with the Sonatype credientials (which core contributors should have)
configured with the Sonatype credentials (which core contributors should have)

1. Run the following and follow prompts for version bumps, etc. This script
runs the tests, bumps the version, tags the release, commits those changes,
releases the package to Sonatype, and completes the Sontatype release
releases the package to Sonatype, and completes the Sonatype release
process.

```bash
Expand Down
19 changes: 19 additions & 0 deletions argus/src/main/scala-2.12/argus/macros/AnyDecoder.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package argus.macros

import scala.reflect.api.Universe

private[macros] object AnyDecoder {
def anyDecoder[U <: Universe](u: U): u.Tree = {
import u._
q"""
def anyDecoder: Decoder[Any] = Decoder.instance((h: HCursor) => h.focus.get match {
case n if n.isNull => null
case n if n.isNumber => n.as[Double]
case b if b.isBoolean => b.as[Boolean]
case s if s.isString => s.as[String]
case o if o.isObject => o.as[Map[String, Any]](Decoder.decodeMapLike(KeyDecoder.decodeKeyString, anyDecoder, Map.canBuildFrom))
case a if a.isArray => a.as[List[Any]](Decoder.decodeIterable(anyDecoder, List.canBuildFrom[Any]))
})
"""
}
}
40 changes: 40 additions & 0 deletions argus/src/main/scala-2.12/argus/macros/ParamsASTHelper.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package argus.macros

import scala.language.experimental.macros
import scala.reflect.api.Universe

private[macros] object ParamsASTHelper {
def paramsToMap[U <: Universe](u: U)(
nameAndDefaults: List[(String, Any)],
params: List[u.Tree]): Map[String, Any] = {
import u._

def toValue(param: Tree): Any = param match {
case Ident(TermName("None")) => None
case Apply(Ident(TermName("Some")), List(Literal(Constant(value)))) =>
Some(value)
case Literal(Constant(c)) => c
case _ => param
}

// Handle positional vs. named argument separately
val (positional, named) = params splitAt (params prefixLength {
case AssignOrNamedArg(Ident(TermName(name)), _) => false; case _ => true
})

require(positional.length <= nameAndDefaults.length,
"More position arguments than specified in: " + nameAndDefaults)
val posValues = nameAndDefaults zip positional map {
case ((name, default), param) =>
(name, toValue(param))
} toMap

val namedValues = named map {
case AssignOrNamedArg(Ident(TermName(name)), t: Tree) =>
(name, toValue(t))
} toMap

nameAndDefaults.toMap ++ posValues ++ namedValues
}

}
19 changes: 19 additions & 0 deletions argus/src/main/scala-2.13/argus/macros/AnyDecoder.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package argus.macros

import scala.reflect.api.Universe

private[macros] object AnyDecoder {
def anyDecoder[U <: Universe](u: U): u.Tree = {
import u._
q"""
def anyDecoder: Decoder[Any] = Decoder.instance((h: HCursor) => h.focus.get match {
case n if n.isNull => null
case n if n.isNumber => n.as[Double]
case b if b.isBoolean => b.as[Boolean]
case s if s.isString => s.as[String]
case o if o.isObject => o.as[Map[String, Any]](Decoder.decodeMapLike(KeyDecoder.decodeKeyString, anyDecoder, Map))
case a if a.isArray => a.as[List[Any]](Decoder.decodeIterable(anyDecoder, List))
})
"""
}
}
46 changes: 46 additions & 0 deletions argus/src/main/scala-2.13/argus/macros/ParamsASTHelper.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package argus.macros

import scala.language.experimental.macros
import scala.reflect.api.Universe

private[macros] object ParamsASTHelper {

def paramsToMap[U <: Universe](u: U)(
nameAndDefaults: List[(String, Any)],
params: List[u.Tree]): Map[String, Any] = {
import u._

def toValue(param: Tree): Any = param match {
case Ident(TermName("None")) => None
case Apply(Ident(TermName("Some")), List(Literal(Constant(value)))) =>
Some(value)
case Literal(Constant(c)) => c
case _ => param
}

// Handle positional vs. named argument separately
val (positional, named) = params.splitAt(params.segmentLength {
case NamedArg(Ident(TermName(_)), _) => false
case Assign(Ident(TermName(_)), _) => false
case _ => true
})

require(positional.length <= nameAndDefaults.length,
"More position arguments than specified in: " + nameAndDefaults)
val posValues = nameAndDefaults
.zip(positional)
.map {
case ((name, default), param) =>
(name, toValue(param))
}
.toMap

val namedValues = named.map {
case NamedArg(Ident(TermName(name)), t: Tree) => (name, toValue(t))
case Assign(Ident(TermName(name)), t: Tree) => (name, toValue(t))
}.toMap

nameAndDefaults.toMap ++ posValues ++ namedValues
}

}
2 changes: 1 addition & 1 deletion argus/src/main/scala/argus/json/JsonDiff.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object JsonDiff {
case _ => {
(j1.asArray, j2.asArray) match {
case (Some(a1), Some(a2)) => {
a1.zip(a2).flatMap { case(jj1, jj2) => diffR(jj1,jj2) } toList
a1.zip(a2).flatMap { case(jj1, jj2) => diffR(jj1,jj2) }.toList
}

// Everything else
Expand Down
31 changes: 4 additions & 27 deletions argus/src/main/scala/argus/macros/ASTHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class ASTHelpers[U <: Universe](val u: U) {
* Collects and returns case classes that extend the given type.
* @return A list of tuples. Each tuple contains the path, and class def
*/
def collectExtendsType(path: List[String], typ: Tree, defs: List[Tree]): List[(List[String], Tree)] = defs collect {
def collectExtendsType(path: List[String], typ: Tree, defs: List[Tree]): List[(List[String], Tree)] = defs.collect {
case (defDef@q"case object $name extends $sTyp { ..$_ }") if sTyp.equalsStructure(typ) => (path, defDef) :: Nil
case (defDef@q"case class $name(..$params) extends $sTyp") if sTyp.equalsStructure(typ) => (path, defDef) :: Nil
case (q"object $name { ..$innerDefs }") => collectExtendsType(path :+ name.toString, typ, innerDefs)
} flatten
}.flatten

/**
* Returns a string from a given type (with path) that somewhat uniquely identifies this type. Can be useful for
Expand Down Expand Up @@ -167,29 +167,6 @@ class ASTHelpers[U <: Universe](val u: U) {
*
* @return A map of argument names and their extracted values (or their default value if not extracted)
*/
def paramsToMap(nameAndDefaults: List[(String, Any)], params: List[Tree]): Map[String, Any] = {

def toValue(param: Tree): Any = param match {
case Ident(TermName("None")) => None
case Apply(Ident(TermName("Some")), List(Literal(Constant(value)))) => Some(value)
case Literal(Constant(c)) => c
case _ => param
}

// Handle positional vs. named argument separately
val (positional, named) = params splitAt (params prefixLength {
case AssignOrNamedArg(Ident(TermName(name)), _) => false; case _ => true })

require(positional.length <= nameAndDefaults.length, "More position arguments than specified in: " + nameAndDefaults)
val posValues = nameAndDefaults zip positional map { case ((name, default), param) =>
(name, toValue(param))
} toMap

val namedValues = named map { case AssignOrNamedArg(Ident(TermName(name)), t: Tree) =>
(name, toValue(t))
} toMap

nameAndDefaults.toMap ++ posValues ++ namedValues
}

def paramsToMap(nameAndDefaults: List[(String, Any)], params: List[Tree]): Map[String, Any] =
ParamsASTHelper.paramsToMap(u)(nameAndDefaults, params)
}
12 changes: 1 addition & 11 deletions argus/src/main/scala/argus/macros/CirceCodecBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class CirceCodecBuilder[U <: Universe](val u: U) extends CodecBuilder {
q"import cats.syntax.either._" ::
q"import io.circe._" ::
q"import io.circe.syntax._" ::
q"import io.circe.java8.time._" ::
Nil

def inEncoder(typ: Tree) = tq"Encoder[$typ]"
Expand Down Expand Up @@ -48,16 +47,7 @@ class CirceCodecBuilder[U <: Universe](val u: U) extends CodecBuilder {
})
"""

val anyDecoder = q"""
def anyDecoder: Decoder[Any] = Decoder.instance((h: HCursor) => h.focus.get match {
case n if n.isNull => null
case n if n.isNumber => n.as[Double]
case b if b.isBoolean => b.as[Boolean]
case s if s.isString => s.as[String]
case o if o.isObject => o.as[Map[String, Any]](Decoder.decodeMapLike(KeyDecoder.decodeKeyString, anyDecoder, Map.canBuildFrom))
case a if a.isArray => a.as[List[Any]](Decoder.decodeIterable(anyDecoder, List.canBuildFrom[Any]))
})
"""
val anyDecoder = AnyDecoder.anyDecoder(u)

def mkAnyWrapperEncoder(typ: Tree) = q"""
Encoder.instance((wrapper: $typ) => {
Expand Down
4 changes: 2 additions & 2 deletions argus/src/main/scala/argus/macros/CodecBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ trait CodecBuilder {

def mkCodec(defs: List[Tree], path: List[String] = Nil): List[Tree] = {

def mkCodecRec(defs: List[Tree], path: List[String], unionTypes: List[Tree]): List[Tree] = defs collect {
def mkCodecRec(defs: List[Tree], path: List[String], unionTypes: List[Tree]): List[Tree] = defs.collect {

//----
// Enums
Expand Down Expand Up @@ -183,7 +183,7 @@ trait CodecBuilder {
mkCodecRec(innerDefs, path :+ name.toString, collectUnionTypes(innerDefs))
}

} flatten
}.flatten

imports ++ constants ++ mkCodecRec(defs, path, collectUnionTypes(defs))
}
Expand Down
6 changes: 3 additions & 3 deletions argus/src/test/scala/argus/macros/ASTHelpersSpec.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package argus.macros

import org.scalactic.Equality
import org.scalatest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.language.experimental.macros

/**
* @author Aish Fenton.
*/
class ASTHelpersSpec extends FlatSpec with Matchers with ASTMatchers {
class ASTHelpersSpec extends AnyFlatSpec with Matchers with ASTMatchers {

import runtimeUniverse._

Expand Down
6 changes: 4 additions & 2 deletions argus/src/test/scala/argus/macros/CirceCodecBuilderSpec.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package argus.macros

import org.scalatest.{FlatSpec, Matchers}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.reflect.api.Universe

class CirceCodecBuilderSpec extends FlatSpec with Matchers with ASTMatchers {
class CirceCodecBuilderSpec extends AnyFlatSpec with Matchers with ASTMatchers {

import runtimeUniverse._

Expand Down
5 changes: 3 additions & 2 deletions argus/src/test/scala/argus/macros/FromSchemaSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import java.util.UUID

import argus.json.JsonDiff
import argus.schema.Schema
import org.scalatest.{FlatSpec, Matchers}
import cats.syntax.either._
import io.circe._
import io.circe.syntax._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.io.Source

class FromSchemaSpec extends FlatSpec with Matchers with JsonMatchers {
class FromSchemaSpec extends AnyFlatSpec with Matchers with JsonMatchers {

"Making schemas" should "build case classes" in {
@fromSchemaJson("""
Expand Down
5 changes: 3 additions & 2 deletions argus/src/test/scala/argus/macros/ModelBuilderSpec.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package argus.macros

import org.scalatest.{FlatSpec, Matchers}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

/**
* @author Aish Fenton.
*/
class ModelBuilderSpec extends FlatSpec with Matchers with ASTMatchers {
class ModelBuilderSpec extends AnyFlatSpec with Matchers with ASTMatchers {

import runtimeUniverse._
val mb = new ModelBuilder[runtimeUniverse.type](runtimeUniverse)
Expand Down
6 changes: 3 additions & 3 deletions argus/src/test/scala/argus/schema/SchemaSpec.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package argus.schema

import argus.json.JsonDiff
import cats.syntax.either._
import io.circe._
import org.scalatest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.io.Source

class SchemaSpec extends FlatSpec with Matchers {
class SchemaSpec extends AnyFlatSpec with Matchers {
import Schema._

def diffs(parsed: Root, original: String) = JsonDiff.diff(parsed.toJson, parser.parse(original).toOption.get)
Expand Down
Loading

0 comments on commit 35898c8

Please sign in to comment.