import sbt.contraband.ast._ import sbt.contraband.CodecCodeGen object ContrabandConfig { /** Extract the only type parameter from a TpeRef */ def oneArg(tpe: Type): Type = { val pat = s"""${tpe.removeTypeParameters.name}[<\\[](.+?)[>\\]]""".r val pat(arg0) = tpe.name NamedType(arg0 split '.' toList) } /** Extract the two type parameters from a TpeRef */ def twoArgs(tpe: Type): List[Type] = { val pat = s"""${tpe.removeTypeParameters.name}[<\\[](.+?), (.+?)[>\\]]""".r val pat(arg0, arg1) = tpe.name NamedType(arg0 split '.' toList) :: NamedType(arg1 split '.' toList) :: Nil } /** Codecs that were manually written. */ val myCodecs: PartialFunction[String, Type => List[String]] = { // TODO: These are handled by BasicJsonProtocol, and sbt-contraband should handle them by default, imo case "Option" | "Set" | "scala.Vector" => { tpe => getFormats(oneArg(tpe)) } case "Map" | "Tuple2" | "scala.Tuple2" => { tpe => twoArgs(tpe).flatMap(getFormats) } case "Int" | "Long" => { _ => Nil } case "sbt.testing.Status" => { _ => "sbt.internal.testing.StatusFormats" :: Nil } case "scalajson.ast.unsafe.JValue" | "sjsonnew.shaded.scalajson.ast.unsafe.JValue" => { _ => "sbt.internal.util.codec.JValueFormats" :: Nil } } /** Returns the list of formats required to encode the given `TpeRef`. */ val getFormats: Type => List[String] = CodecCodeGen.extensibleFormatsForType { case tpe: Type if myCodecs isDefinedAt tpe.removeTypeParameters.name => myCodecs(tpe.removeTypeParameters.name)(tpe) case other => CodecCodeGen.formatsForType(other) } }