diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2017-10-28 16:40:21 -0700 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2017-10-28 16:40:21 -0700 |
commit | fee05e6163fadff27521807cc3d97d61b74ab466 (patch) | |
tree | 505bb6c18e2c9f2ee4ac61e7cf4edbe2498ca2da /src/main/scala | |
parent | fe0579918b9a9d5530f27a0a1bea466d3f487c3c (diff) | |
download | mill-fee05e6163fadff27521807cc3d97d61b74ab466.tar.gz mill-fee05e6163fadff27521807cc3d97d61b74ab466.tar.bz2 mill-fee05e6163fadff27521807cc3d97d61b74ab466.zip |
Implemented member-reflection-based naming, set to replace the old `DefCtx`/`sourcecode.Enclosing` strategy
Diffstat (limited to 'src/main/scala')
-rw-r--r-- | src/main/scala/forge/Discovered.scala | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/main/scala/forge/Discovered.scala b/src/main/scala/forge/Discovered.scala new file mode 100644 index 00000000..2475dc18 --- /dev/null +++ b/src/main/scala/forge/Discovered.scala @@ -0,0 +1,43 @@ +package forge + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +class Discovered[T](val value: Seq[(Seq[String], T => Target[_])]){ + def apply(t: T) = { + value.map{case (a, b) => (a, b(t)) } + } +} +object Discovered { + implicit def apply[T]: Discovered[T] = macro applyImpl[T] + + def applyImpl[T: c.WeakTypeTag](c: Context): c.Expr[Discovered[T]] = { + import c.universe._ + val tpe = c.weakTypeTag[T].tpe + def rec(segments: List[String], t: c.Type): Seq[Seq[String]] = for { + m <- t.members.toSeq + if m.isTerm && (m.asTerm.isGetter || m.asTerm.isLazy) || m.isModule + res <- { + val extendedSegments = m.name.toString :: segments + val self = + if (m.typeSignature.resultType <:< c.weakTypeOf[Target[_]]) Seq(extendedSegments) + else Nil + val children = rec(extendedSegments, m.typeSignature) + self ++ children + } + } yield res + + val reversedPaths = rec(Nil, tpe) + + val result = for(reversedPath <- reversedPaths.toList) yield { + val base = q"${TermName(c.freshName())}" + val segments = reversedPath.reverse.toList + val ident = segments.foldLeft[Tree](base)((prefix, name) => + q"$prefix.${TermName(name)}" + ) + q"($segments, ($base: $tpe) => $ident)" + } + + c.Expr[Discovered[T]](q"new _root_.forge.Discovered($result)") + } +} |