11package sourcecode
22
3- import language .experimental .macros
43
5-
6- object Util {
7- def isSynthetic (c : Compat .Context )(s : c.Symbol ) = isSyntheticName(getName(c)(s))
8- def isSyntheticName (name : String ) = {
9- name == " <init>" || (name.startsWith(" <local " ) && name.endsWith(" >" ))
10- }
11- def getName (c : Compat .Context )(s : c.Symbol ) = s.name.decoded.toString.trim
12- }
134abstract class SourceValue [T ]{
145 def value : T
156}
@@ -18,176 +9,32 @@ abstract class SourceCompanion[T, V <: SourceValue[T]](build: T => V){
189 implicit def wrap (s : T ): V = build(s)
1910}
2011case class Name (value : String ) extends SourceValue [String ]
21- object Name extends SourceCompanion [String , Name ](new Name (_)){
22- implicit def generate : Name = macro impl
23-
24- def impl (c : Compat .Context ): c.Expr [Name ] = {
25- import c .universe ._
26- var owner = Compat .enclosingOwner(c)
27- while (Util .isSynthetic(c)(owner)) owner = owner.owner
28- val simpleName = Util .getName(c)(owner)
29- c.Expr [sourcecode.Name ](q """ ${c.prefix}( $simpleName) """ )
30- }
12+ object Name extends SourceCompanion [String , Name ](new Name (_)) with NameMacros {
3113 case class Machine (value : String ) extends SourceValue [String ]
32- object Machine extends SourceCompanion [String , Machine ](new Machine (_)){
33- implicit def generate : Machine = macro impl
34- def impl (c : Compat .Context ): c.Expr [Machine ] = {
35- import c .universe ._
36- val owner = Compat .enclosingOwner(c)
37- val simpleName = Util .getName(c)(owner)
38- c.Expr [Machine ](q """ ${c.prefix}( $simpleName) """ )
39- }
40- }
14+ object Machine extends SourceCompanion [String , Machine ](new Machine (_)) with NameMachineMacros
4115}
4216case class FullName (value : String ) extends SourceValue [String ]
43- object FullName extends SourceCompanion [String , FullName ](new FullName (_)){
44- implicit def generate : FullName = macro impl
45-
46- def impl (c : Compat .Context ): c.Expr [FullName ] = {
47- import c .universe ._
48- val owner = Compat .enclosingOwner(c)
49- val fullName =
50- owner.fullName.trim
51- .split(" \\ ." , - 1 )
52- .filterNot(Util .isSyntheticName)
53- .mkString(" ." )
54- c.Expr [sourcecode.FullName ](q """ ${c.prefix}( $fullName) """ )
55- }
17+ object FullName extends SourceCompanion [String , FullName ](new FullName (_)) with FullNameMacros {
5618 case class Machine (value : String ) extends SourceValue [String ]
57- object Machine extends SourceCompanion [String , Machine ](new Machine (_)){
58- implicit def generate : Machine = macro impl
59-
60- def impl (c : Compat .Context ): c.Expr [Machine ] = {
61- import c .universe ._
62- val owner = Compat .enclosingOwner(c)
63- val fullName = owner.fullName.trim
64- c.Expr [Machine ](q """ ${c.prefix}( $fullName) """ )
65- }
66- }
19+ object Machine extends SourceCompanion [String , Machine ](new Machine (_)) with FullNameMachineMacros
6720}
6821case class File (value : String ) extends SourceValue [String ]
69- object File extends SourceCompanion [String , File ](new File (_)){
70- implicit def generate : sourcecode.File = macro impl
71-
72- def impl (c : Compat .Context ): c.Expr [sourcecode.File ] = {
73- import c .universe ._
74- val file = c.enclosingPosition.source.path
75- c.Expr [sourcecode.File ](q """ ${c.prefix}( $file) """ )
76- }
77- }
22+ object File extends SourceCompanion [String , File ](new File (_)) with FileMacros
7823case class Line (value : Int ) extends SourceValue [Int ]
79- object Line extends SourceCompanion [Int , Line ](new Line (_)){
80- implicit def generate : sourcecode.Line = macro impl
81- def impl (c : Compat .Context ): c.Expr [sourcecode.Line ] = {
82- import c .universe ._
83- val line = c.enclosingPosition.line
84- c.Expr [sourcecode.Line ](q """ ${c.prefix}( $line) """ )
85- }
86- }
24+ object Line extends SourceCompanion [Int , Line ](new Line (_)) with LineMacros
8725case class Enclosing (value : String ) extends SourceValue [String ]
8826
89- object Enclosing extends SourceCompanion [String , Enclosing ](new Enclosing (_)){
90- implicit def generate : Enclosing = macro impl
91- def impl (c : Compat .Context ): c.Expr [Enclosing ] = Impls .enclosing[Enclosing ](c)(
92- ! Util .isSynthetic(c)(_)
93- )
27+ object Enclosing extends SourceCompanion [String , Enclosing ](new Enclosing (_)) with EnclosingMacros {
9428 case class Machine (value : String ) extends SourceValue [String ]
95- object Machine extends SourceCompanion [String , Machine ](new Machine (_)){
96- implicit def generate : Machine = macro impl
97- def impl (c : Compat .Context ): c.Expr [Machine ] = Impls .enclosing[Machine ](c)(_ => true )
98- }
29+ object Machine extends SourceCompanion [String , Machine ](new Machine (_)) with EnclosingMachineMacros
9930}
10031
10132
10233case class Pkg (value : String ) extends SourceValue [String ]
103- object Pkg extends SourceCompanion [String , Pkg ](new Pkg (_)){
104- implicit def generate : Pkg = macro impl
105- def impl (c : Compat .Context ): c.Expr [Pkg ] = Impls .enclosing[Pkg ](c)(_.isPackage)
106- }
34+ object Pkg extends SourceCompanion [String , Pkg ](new Pkg (_)) with PkgMacros
10735
10836case class Text [T ](value : T , source : String )
109- object Text {
110- implicit def generate [T ](v : T ): Text [T ] = macro Impls .text[T ]
111- def apply [T ](v : T ): Text [T ] = macro Impls .text[T ]
112-
113- }
37+ object Text extends TextMacros
11438
11539case class Args (value : Seq [Seq [Text [_]]]) extends SourceValue [Seq [Seq [Text [_]]]]
116- object Args extends SourceCompanion [Seq [Seq [Text [_]]], Args ](new Args (_)) {
117- implicit def generate : Args = macro impl
118- def impl (c : Compat .Context ): c.Expr [Args ] = {
119- import c .universe ._
120- val param = Compat .enclosingParamList(c)
121- val texts = param.map(_.map(p => c.Expr [Text [_]](q """ sourcecode.Text( $p, ${p.name.toString}) """ )))
122- val textSeqs = texts.map(s => c.Expr (q """ Seq(.. $s) """ ))
123- c.Expr [Args ](q """ Seq(.. $textSeqs) """ )
124- }
125- }
126-
127- object Impls {
128- def text [T : c.WeakTypeTag ](c : Compat .Context )(v : c.Expr [T ]): c.Expr [sourcecode.Text [T ]] = {
129- import c .universe ._
130- val fileContent = new String (v.tree.pos.source.content)
131- val start = v.tree.collect {
132- case treeVal => treeVal.pos match {
133- case NoPosition ⇒ Int .MaxValue
134- case p ⇒ p.startOrPoint
135- }
136- }.min
137- val g = c.asInstanceOf [reflect.macros.runtime.Context ].global
138- val parser = g.newUnitParser(fileContent.drop(start))
139- parser.expr()
140- val end = parser.in.lastOffset
141- val txt = fileContent.slice(start, start + end)
142- val tree = q """ ${c.prefix}( ${v.tree}, $txt) """
143- c.Expr [sourcecode.Text [T ]](tree)
144- }
145- sealed trait Chunk
146- object Chunk {
147- case class Pkg (name : String ) extends Chunk
148- case class Obj (name : String ) extends Chunk
149- case class Cls (name : String ) extends Chunk
150- case class Trt (name : String ) extends Chunk
151- case class Val (name : String ) extends Chunk
152- case class Var (name : String ) extends Chunk
153- case class Lzy (name : String ) extends Chunk
154- case class Def (name : String ) extends Chunk
155-
156- }
157-
158- def enclosing [T ](c : Compat .Context )(filter : c.Symbol => Boolean ): c.Expr [T ] = {
159-
160- import c .universe ._
161- var current = Compat .enclosingOwner(c)
162- var path = List .empty[Chunk ]
163- while (current != NoSymbol && current.toString != " package <root>" ){
164- if (filter(current)) {
165-
166- val chunk = current match {
167- case x if x.isPackage => Chunk .Pkg
168- case x if x.isModuleClass => Chunk .Obj
169- case x if x.isClass && x.asClass.isTrait => Chunk .Trt
170- case x if x.isClass => Chunk .Cls
171- case x if x.isMethod => Chunk .Def
172- case x if x.isTerm && x.asTerm.isVar => Chunk .Var
173- case x if x.isTerm && x.asTerm.isLazy => Chunk .Lzy
174- case x if x.isTerm && x.asTerm.isVal => Chunk .Val
175- }
176-
177- path = chunk(Util .getName(c)(current)) :: path
178- }
179- current = current.owner
180- }
181- val renderedPath = path.map{
182- case Chunk .Pkg (s) => s + " ."
183- case Chunk .Obj (s) => s + " ."
184- case Chunk .Cls (s) => s + " #"
185- case Chunk .Trt (s) => s + " #"
186- case Chunk .Val (s) => s + " "
187- case Chunk .Var (s) => s + " "
188- case Chunk .Lzy (s) => s + " "
189- case Chunk .Def (s) => s + " "
190- }.mkString.dropRight(1 )
191- c.Expr [T ](q """ ${c.prefix}( $renderedPath) """ )
192- }
193- }
40+ object Args extends SourceCompanion [Seq [Seq [Text [_]]], Args ](new Args (_)) with ArgsMacros
0 commit comments