summaryrefslogtreecommitdiff
path: root/src/main/scala
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-10-28 16:40:21 -0700
committerLi Haoyi <haoyi.sg@gmail.com>2017-10-28 16:40:21 -0700
commitfee05e6163fadff27521807cc3d97d61b74ab466 (patch)
tree505bb6c18e2c9f2ee4ac61e7cf4edbe2498ca2da /src/main/scala
parentfe0579918b9a9d5530f27a0a1bea466d3f487c3c (diff)
downloadmill-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.scala43
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)")
+ }
+}