Skip to content

Commit 23d11b3

Browse files
Merge pull request #61 from alexarchambault/topic/refacto
Refactorings
2 parents 8c769ae + 6be8b04 commit 23d11b3

File tree

4 files changed

+213
-167
lines changed

4 files changed

+213
-167
lines changed

build.sbt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,23 @@ lazy val sourcecode = crossProject(JSPlatform, JVMPlatform, NativePlatform)
4040
libraryDependencies ++= macroDependencies(scalaVersion.value),
4141
test in Test := (run in Test).toTask("").value,
4242
unmanagedSourceDirectories in Compile ++= {
43-
CrossVersion.partialVersion(scalaVersion.value) match {
44-
case Some((2, n)) if n >= 12 =>
45-
Seq(baseDirectory.value / ".." / "shared" / "src" / "main" / "scala-2.11")
43+
val crossVer = CrossVersion.partialVersion(scalaVersion.value)
44+
45+
val scala211plus = crossVer match {
46+
case Some((2, n)) if n >= 11 =>
47+
Seq(baseDirectory.value / ".." / "shared" / "src" / "main" / "scala-2.11+")
48+
case _ =>
49+
Seq()
50+
}
51+
52+
val scala2 = crossVer match {
53+
case Some((2, _)) =>
54+
Seq(baseDirectory.value / ".." / "shared" / "src" / "main" / "scala-2.x")
4655
case _ =>
4756
Seq()
4857
}
58+
59+
scala211plus ++ scala2
4960
},
5061
// Osgi settings
5162
osgiSettings,
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package sourcecode
2+
3+
import language.experimental.macros
4+
5+
trait NameMacros {
6+
implicit def generate: Name = macro Macros.nameImpl
7+
}
8+
9+
trait NameMachineMacros {
10+
implicit def generate: Name.Machine = macro Macros.nameMachineImpl
11+
}
12+
13+
trait FullNameMacros {
14+
implicit def generate: FullName = macro Macros.fullNameImpl
15+
}
16+
17+
trait FullNameMachineMacros {
18+
implicit def generate: FullName.Machine = macro Macros.fullNameMachineImpl
19+
}
20+
21+
trait FileMacros {
22+
implicit def generate: sourcecode.File = macro Macros.fileImpl
23+
}
24+
25+
trait LineMacros {
26+
implicit def generate: sourcecode.Line = macro Macros.lineImpl
27+
}
28+
29+
trait EnclosingMacros {
30+
implicit def generate: Enclosing = macro Macros.enclosingImpl
31+
}
32+
33+
trait EnclosingMachineMacros {
34+
implicit def generate: Enclosing.Machine = macro Macros.enclosingMachineImpl
35+
}
36+
37+
trait PkgMacros {
38+
implicit def generate: Pkg = macro Macros.pkgImpl
39+
}
40+
41+
trait TextMacros {
42+
implicit def generate[T](v: T): Text[T] = macro Macros.text[T]
43+
def apply[T](v: T): Text[T] = macro Macros.text[T]
44+
}
45+
46+
trait ArgsMacros {
47+
implicit def generate: Args = macro Macros.argsImpl
48+
}
49+
50+
object Util{
51+
def isSynthetic(c: Compat.Context)(s: c.Symbol) = isSyntheticName(getName(c)(s))
52+
def isSyntheticName(name: String) = {
53+
name == "<init>" || (name.startsWith("<local ") && name.endsWith(">"))
54+
}
55+
def getName(c: Compat.Context)(s: c.Symbol) = s.name.decoded.toString.trim
56+
}
57+
58+
object Macros {
59+
60+
def nameImpl(c: Compat.Context): c.Expr[Name] = {
61+
import c.universe._
62+
var owner = Compat.enclosingOwner(c)
63+
while(Util.isSynthetic(c)(owner)) owner = owner.owner
64+
val simpleName = Util.getName(c)(owner)
65+
c.Expr[sourcecode.Name](q"""${c.prefix}($simpleName)""")
66+
}
67+
68+
def nameMachineImpl(c: Compat.Context): c.Expr[Name.Machine] = {
69+
import c.universe._
70+
val owner = Compat.enclosingOwner(c)
71+
val simpleName = Util.getName(c)(owner)
72+
c.Expr[Name.Machine](q"""${c.prefix}($simpleName)""")
73+
}
74+
75+
def fullNameImpl(c: Compat.Context): c.Expr[FullName] = {
76+
import c.universe._
77+
val owner = Compat.enclosingOwner(c)
78+
val fullName =
79+
owner.fullName.trim
80+
.split("\\.", -1)
81+
.filterNot(Util.isSyntheticName)
82+
.mkString(".")
83+
c.Expr[sourcecode.FullName](q"""${c.prefix}($fullName)""")
84+
}
85+
86+
def fullNameMachineImpl(c: Compat.Context): c.Expr[FullName.Machine] = {
87+
import c.universe._
88+
val owner = Compat.enclosingOwner(c)
89+
val fullName = owner.fullName.trim
90+
c.Expr[FullName.Machine](q"""${c.prefix}($fullName)""")
91+
}
92+
93+
def fileImpl(c: Compat.Context): c.Expr[sourcecode.File] = {
94+
import c.universe._
95+
val file = c.enclosingPosition.source.path
96+
c.Expr[sourcecode.File](q"""${c.prefix}($file)""")
97+
}
98+
99+
def lineImpl(c: Compat.Context): c.Expr[sourcecode.Line] = {
100+
import c.universe._
101+
val line = c.enclosingPosition.line
102+
c.Expr[sourcecode.Line](q"""${c.prefix}($line)""")
103+
}
104+
105+
def enclosingImpl(c: Compat.Context): c.Expr[Enclosing] = enclosing[Enclosing](c)(
106+
!Util.isSynthetic(c)(_)
107+
)
108+
109+
def enclosingMachineImpl(c: Compat.Context): c.Expr[Enclosing.Machine] =
110+
enclosing[Enclosing.Machine](c)(_ => true)
111+
112+
def pkgImpl(c: Compat.Context): c.Expr[Pkg] = enclosing[Pkg](c)(_.isPackage)
113+
114+
def argsImpl(c: Compat.Context): c.Expr[Args] = {
115+
import c.universe._
116+
val param = Compat.enclosingParamList(c)
117+
val texts = param.map(_.map(p => c.Expr[Text[_]](q"""sourcecode.Text($p, ${p.name.toString})""")))
118+
val textSeqs = texts.map(s => c.Expr(q"""Seq(..$s)"""))
119+
c.Expr[Args](q"""Seq(..$textSeqs)""")
120+
}
121+
122+
123+
def text[T: c.WeakTypeTag](c: Compat.Context)(v: c.Expr[T]): c.Expr[sourcecode.Text[T]] = {
124+
import c.universe._
125+
val fileContent = new String(v.tree.pos.source.content)
126+
val start = v.tree.collect {
127+
case treeVal => treeVal.pos match {
128+
case NoPosition Int.MaxValue
129+
case p p.startOrPoint
130+
}
131+
}.min
132+
val g = c.asInstanceOf[reflect.macros.runtime.Context].global
133+
val parser = g.newUnitParser(fileContent.drop(start))
134+
parser.expr()
135+
val end = parser.in.lastOffset
136+
val txt = fileContent.slice(start, start + end)
137+
val tree = q"""${c.prefix}(${v.tree}, $txt)"""
138+
c.Expr[sourcecode.Text[T]](tree)
139+
}
140+
sealed trait Chunk
141+
object Chunk{
142+
case class Pkg(name: String) extends Chunk
143+
case class Obj(name: String) extends Chunk
144+
case class Cls(name: String) extends Chunk
145+
case class Trt(name: String) extends Chunk
146+
case class Val(name: String) extends Chunk
147+
case class Var(name: String) extends Chunk
148+
case class Lzy(name: String) extends Chunk
149+
case class Def(name: String) extends Chunk
150+
151+
}
152+
153+
def enclosing[T](c: Compat.Context)(filter: c.Symbol => Boolean): c.Expr[T] = {
154+
155+
import c.universe._
156+
var current = Compat.enclosingOwner(c)
157+
var path = List.empty[Chunk]
158+
while(current != NoSymbol && current.toString != "package <root>"){
159+
if (filter(current)) {
160+
161+
val chunk = current match {
162+
case x if x.isPackage => Chunk.Pkg
163+
case x if x.isModuleClass => Chunk.Obj
164+
case x if x.isClass && x.asClass.isTrait => Chunk.Trt
165+
case x if x.isClass => Chunk.Cls
166+
case x if x.isMethod => Chunk.Def
167+
case x if x.isTerm && x.asTerm.isVar => Chunk.Var
168+
case x if x.isTerm && x.asTerm.isLazy => Chunk.Lzy
169+
case x if x.isTerm && x.asTerm.isVal => Chunk.Val
170+
}
171+
172+
path = chunk(Util.getName(c)(current)) :: path
173+
}
174+
current = current.owner
175+
}
176+
val renderedPath = path.map{
177+
case Chunk.Pkg(s) => s + "."
178+
case Chunk.Obj(s) => s + "."
179+
case Chunk.Cls(s) => s + "#"
180+
case Chunk.Trt(s) => s + "#"
181+
case Chunk.Val(s) => s + " "
182+
case Chunk.Var(s) => s + " "
183+
case Chunk.Lzy(s) => s + " "
184+
case Chunk.Def(s) => s + " "
185+
}.mkString.dropRight(1)
186+
c.Expr[T](q"""${c.prefix}($renderedPath)""")
187+
}
188+
}

0 commit comments

Comments
 (0)