1
1
package sourcecode
2
2
3
- import language .experimental .macros
4
3
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
- }
13
4
abstract class SourceValue [T ]{
14
5
def value : T
15
6
}
@@ -18,176 +9,32 @@ abstract class SourceCompanion[T, V <: SourceValue[T]](build: T => V){
18
9
implicit def wrap (s : T ): V = build(s)
19
10
}
20
11
case 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 {
31
13
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
41
15
}
42
16
case 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 {
56
18
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
67
20
}
68
21
case 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
78
23
case 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
87
25
case class Enclosing (value : String ) extends SourceValue [String ]
88
26
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 {
94
28
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
99
30
}
100
31
101
32
102
33
case 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
107
35
108
36
case 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
114
38
115
39
case 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