Scala 类型参数与WeakTypeTag反射不匹配+;准液化(我想!)

Scala 类型参数与WeakTypeTag反射不匹配+;准液化(我想!),scala,scala-macros,scala-reflect,Scala,Scala Macros,Scala Reflect,受此启发,我尝试使用宏来创建一些“智能构造函数” 给定 包mypkg [答] 案例类Ohayo[A,B](A:(A,B))扩展了Hello[A] 及 val smartConstructors=FreeMacros.liftConstructors[Hello] 宏应该找到Hello的所有子类,查看它们的构造函数,并提取一些元素来填充此树中的“智能构造函数”: q”“” def$methodName[…$typeParams](…$ParamList):$baseType= $company

受此启发,我尝试使用宏来创建一些“智能构造函数”

给定

包mypkg
[答]
案例类Ohayo[A,B](A:(A,B))扩展了Hello[A]

val smartConstructors=FreeMacros.liftConstructors[Hello]
宏应该找到
Hello
的所有子类,查看它们的构造函数,并提取一些元素来填充此树中的“智能构造函数”:

q”“”
def$methodName[…$typeParams](…$ParamList):$baseType=
$companysymbol[…$typeArgs](…$argLists)
"""
我希望得到:

val smartConstructors=新建{
def ohayo[A,B](A:(A,B)):Hello[A]=ohayo[A,B](A)
}
但是,你可以得到:

错误:类型不匹配;
发现:(A(Ohayo类),B(Ohayo类))
所需:((一些其他)A(在Ohayo类中),(一些其他)B(在Ohayo类中))
val liftedConstructors=FreeMacros.liftConstructors[Hello]
乍一看,这棵树看起来还不错:

scala>q“新建{..$welltypted}”
res1:美国树=
{
最后一个类$anon扩展了scala.AnyRef{
def()={
超级(;
()
};
def ohayo[A,B](A:(A,B)):net.arya.constructors.Hello[A]=ohayo[A,B](A)
};
新$anon()
}
但我想它在无形中不是。如果我天真地尝试用
info.typeParams.map(p=>TypeName(p.name.toString))
刷新typeParams,那么在执行准量化时,我会得到“无法拼接as-type参数”

我哪里做错了?谢谢你看

-雅利雅

导入scala.language.experimental.macros
导入scala.reflect.api.Universe
导入scala.reflect.macros.whitebox
类FreeMacros(val c:whitebox.Context){
导入c.universe_
导入自由宏_
def liftedImpl[F[]](隐式t:c.WeakTypeTag[F[]]):树={
val atc=t.tpe
val childSymbols:Set[ClassSymbol]=子类符号(c.universe)(atc.typeSymbol.asClass)
val welltypted=childSymbols.map(ctorsForSymbol(c.universe)(atc)).unzip
q“新建{..${wellTyped}}”
}
}
对象自由宏{
def liftConstructors[F[]]:Any=宏FreeMacros.liftedImpl[F]
def smartName(名称:字符串):字符串=(
name.toList匹配{
案例h::t=>h.toLower::t
案例Nil=>Nil
}
).mkString
def子类别符号(u:Universe)(根:u.ClassSymbol):设置[u.ClassSymbol]={
val subclass=root.knownDirectSubclass
val cast=subclasses.map(u.asInstanceOf[u.ClassSymbol])
val partitioned=mapped.partition(uu.isCaseClass)
分区匹配{
case(caseClasses,regularClasses)=>caseClasses++regularClasses.flatMap(r=>subseclassssymbols(u)(r))
}
}
def-ctorsForSymbol(u:Universe)(atc:u.Type)(案例类别:u.ClassSymbol):(u.DefDef,u.DefDef)={
进口美国_
导入内部_
//这些都没用
//def clearTypeSymbol(s:Symbol):TypeSymbol=内部.newTypeSymbol(NoSymbol,s.name.toTypeName,s.pos,if(s.isImplicit)Flag.IMPLICIT else NoFlags)
//def clearTypeSymbol2(s:Symbol):TypeSymbol=内部.newTypeSymbol(NoSymbol,s.name.toTypeName,NoPosition,if(s.isImplicit)Flag.IMPLICIT else NoFlags)
//def clearTypeDef(d:TypeDef):TypeDef=internal.TypeDef(cleartypessymbol(d.symbol))
val companionSymbol:Symbol=caseClass.companion
val info:Type=caseClass.info
val primaryCtor:Symbol=caseClass.primaryConstructor
val方法=PrimaryActor.asMethod
val typeParams=info.typeParams.map(internal.typeDef()
//val typeParams=info.typeParams.map(s=>typeDef(newTypeSymbol(NoSymbol,s.name.toTypeName,NoPosition,NoFlags)))
//val typeParams=info.typeParams.map(s=>internal.typeDef(clearTypeSymbol2)))
val-typeArgs=info.typeParams.map(uz.name)
val paramLists=method.paramLists.map(0.map(internal.valDef(0)))
val argLists=method.paramLists.map(u.map(u.asTerm.name))
val baseType=info.baseType(atc.typeSymbol)
val列表(returnType)=baseType.typeArgs
val methodName=TermName(smartName(caseClass.name.toString))
瓦尔好打字=
q”“”
def$methodName[…$typeParams](…$ParamList):$baseType=
$companysymbol[…$typeArgs](…$argLists)
"""
优秀的
}
}
另外,我一直在试验toolbox.untypecheck/typecheck per,但还没有找到一个有效的组合。

您需要使用

clas.typeArgs.map(_.toString).map(name => {
  TypeDef(Modifiers(Flag.PARAM),TypeName(name), List(),TypeBoundsTree(EmptyTree, EmptyTree))
      }
替换
info.typeParams.map(p=>TypeName(p.name.toString))

这是我的密码

object GetSealedSubClass {

  def ol3[T]: Any = macro GetSealedSubClassImpl.ol3[T]
}

class GetSealedSubClassImpl(val c: Context) {

  import c.universe._

  def showInfo(s: String) =
    c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)

  def ol3[T: c.WeakTypeTag]: c.universe.Tree = {

    //get all sub class
    val subClass = c.weakTypeOf[T]
      .typeSymbol.asClass.knownDirectSubclasses
      .map(e => e.asClass.toType)

    //check type params must ia s sealed class
    if (subClass.size < 1)
      c.abort(c.enclosingPosition, s"${c.weakTypeOf[T]} is not a sealed class")

    // get sub class constructor params
    val subConstructorParams = subClass.map { e =>
      //get constructor
      e.members.filter(_.isConstructor)
        //if the class has many Constructor then you need filter the main Constructor
        .head.map(s => s.asMethod)
      //get function param list
    }.map(_.asMethod.paramLists.head)
      .map(_.map(e => q"""${e.name.toTermName}:${e.info} """))

    val outfunc = subClass zip subConstructorParams map {
      case (clas, parm) =>
        q"def smartConstructors[..${
          clas.typeArgs.map(_.toString).map(name => {
            TypeDef(Modifiers(Flag.PARAM), TypeName(name), List(), TypeBoundsTree(EmptyTree, EmptyTree))
          })
        }](..${parm})=${clas.typeSymbol.name.toTermName} (..${parm})"
    }

    val outClass =
      q"""
         object Term{
                 ..${outfunc}
                 }
          """
    showInfo(show(outClass))
    q"""{
      $outClass
        Term
      }
      """
  }
}
sealed trait Hello[A]

case class Ohayo[A, B](a: (A, B)) extends Hello[A]

object GetSealed extends App {
  val a = GetSealedSubClass.ol3[Hello[_]]
  val b=a.asInstanceOf[ {def smartConstructors[A, B](a: (A, B)): Ohayo[A, B]}].smartConstructors(1, 2).a
  println(b)
}