scala细化尺寸的模式匹配

scala细化尺寸的模式匹配,scala,shapeless,scala-macros,play-json,refined,Scala,Shapeless,Scala Macros,Play Json,Refined,我想根据不同的类型(包括Scala),提供case类的json模式(在编译时) 对象JsonSchema{ def jsonSchema[T]:String=macro impl[T] def impl[T:c.WeakTypeTag](c:scala.reflect.macros.whitebox.Context):c.Expr[String]={ 导入c.universe_ val r=weakTypeOf[T].decls.collect{ 案例m:MethodSymbol如果m.isCa

我想根据不同的类型(包括Scala),提供case类的json模式(在编译时)

对象JsonSchema{
def jsonSchema[T]:String=macro impl[T]
def impl[T:c.WeakTypeTag](c:scala.reflect.macros.whitebox.Context):c.Expr[String]={
导入c.universe_
val r=weakTypeOf[T].decls.collect{
案例m:MethodSymbol如果m.isCaseAccessor=>
val typeArgs=m.info匹配{
大小写NullaryMethodType(v)=>v.typeArgs
}
val supportedStringFormat=列表(“IPv4”、“IPv6”、“Uri”)
typeArgs匹配{
如果类型=:=typeOf[String]&&supportedStringFormat.contains(_predicate.typeSymbol.name.toString())=>Json.obj(m.name.decodedName.toString->Json.obj(“type”->“String”,“format”->\u predicate.typeSymbol.name.toString().toLowerCase()))
如果类型=:=typeOf[String]&&&&&&u谓词=:=typeOf[NonEmpty]=>Json.obj(m.name.decodedName.toString->Json.obj(“type”->“String”,“minLength”->1))
如果类型=:=typeOf[String]&&&&(u)谓词=:=typeOf[Size[\u 0]]=>{
val size=\u predicate.typeArgs匹配{
案例h::uu如果h 0
}
obj(m.name.decodedName.toString->Json.obj(“type”->“string”,“minLength”->size))
}
大小写类型::\if类型=:=typeOf[String]=>Json.obj(m.name.decodedName.toString->Json.obj(“type”->“String”))
如果类型=:=typeOf[Int]&&&&(u)谓词=:=typeOf[Positive]=>Json.obj(m.name.decodedName.toString->Json.obj(“type”->“Int”,“minValue”->1))
如果&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
case List()=>Json.obj(m.name.decodedName.toString->Json.obj(“type”->m.info.typeSymbol.name.decodedName.toString.toLowerCase())
case other=>Json.obj(“other”->other.map(u.toString()).mkString)
}
}
val json=r.reduce(++)
c、 Expr[String](q”““${json.toString()}”“)
}
}
我希望能够匹配所有形状不规则的自然:

typeOf[Size[\u]]
而不是
typeOf[Size[\u 0]]

但我有一个编译错误:

没有可用于eu.timepit.defined.collection.Size[\ux]的TypeTag
[错误]大小写类型::_谓词::Nil如果类型=:=typeOf[String]&&&&_谓词=:=typeOf[Size[]]=>{
我想得到一个整数表示大小

val size=\u predicate.typeArgs匹配{
案例h::uu如果h 0
}
用法:

case类StringWithMinSize22(k:String精炼MinSize[_22])
“最小尺寸为22的字符串”必须{
中的“返回最小大小的架构”{
JsonSchema.JsonSchema[StringWithMinSize22]必须为“{”k:{”type:“string”,“minLength”:22}”
}  
}
试试看

val sizect=typeOf[eu.timepit.defined.collection.Size[\u]]
val r=weakTypeOf[T].decls.collect{
// ...
大小写类型:::_谓词::如果类型=:=typeOf[String]&&&&,则为Nil{
val sizeTyp=_predicate.dealias.typeArgs.head.typeArgs.head
val-toIntTree=c.inferImplicitValue(c.typecheck(tq“\u root\uu.shapeless.ops.nat.ToInt[$sizeTyp]”,mode=c.TYPEmode)。tpe,silent=false)
val toInt=c.eval(c.Expr(c.untypecheck(toIntTree.duplicate)))
Json.obj(m.name.decodedName.toString->Json.obj(“type”->“string”,“minLength”->toInt.asInstanceOf[toInt[\u]]]].apply())
}

但是,如果您可以在类型类而不是原始宏中编码您的逻辑,这将是有意义的。

我发现eu.timepit.defined.collection.Size[\u][error]val sizeTC=typeOf[eu.timepit.defined.collection.Size[\u]][error]^[error]发现一个错误[error](宏/编译/编译增量)编译失败[错误]总时间:4秒,完成2019年9月3日20:48:22我错过了什么吗?@DamienGOUYETTE不要把
val sizect=…
放在
weakTypeOf[t]里面。decls.collect…
,让它在外面。
val sizeTC = typeOf[eu.timepit.refined.collection.Size[_]]

val r = weakTypeOf[T].decls.collect {

  // ...

  case _type :: _predicate :: Nil if _type =:= typeOf[String] && _predicate <:< sizeTC => {
    val sizeTyp = _predicate.dealias.typeArgs.head.typeArgs.head
    val toIntTree = c.inferImplicitValue(c.typecheck(tq"_root_.shapeless.ops.nat.ToInt[$sizeTyp]", mode = c.TYPEmode).tpe, silent = false)
    val toInt = c.eval(c.Expr(c.untypecheck(toIntTree.duplicate)))

    Json.obj(m.name.decodedName.toString ->  Json.obj("type" -> "string", "minLength" -> toInt.asInstanceOf[ToInt[_]].apply()))
  }