Skip to content

Commit a3def14

Browse files
author
beha
committed
Added macro for passing all arguments of a method as implicit parameter
1 parent 8e83e38 commit a3def14

File tree

4 files changed

+70
-0
lines changed

4 files changed

+70
-0
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ The kinds of compilation-time data that `sourcecode` provides are:
7272
you have multiple statements in a `{}` block, `sourcecode.Text` will only
7373
capture the source code for the last expression that gets returned. This
7474
implicit is slightly experimental; be sure to report any bugs you find!
75+
- `sourcecode.Args`: the arguments that where provided to the nearest enclosing
76+
method
7577
- `sourcecode.Name.Machine`, `sourcecode.FullName.Machine` and
7678
`sourcecode.Enclosing.Machine` which are similar to `sourcecode.Name`,
7779
`sourcecode.FullName` and `sourcecode.Enclosing` except they do not filter
@@ -475,6 +477,21 @@ be printed. You can, or course, define your own `log` method in the same way,
475477
customizing it to print or not-print exactly what you want to see via the
476478
implicits that `sourcecode` provides!
477479

480+
`sourcecode.Args` can be used to access all parameters that where provided
481+
to a method:
482+
483+
```scala
484+
def debug(implicit name: sourcecode.Name, args: sourcecode.Args): Unit = {
485+
println(name.value + args.value.map(_.map(a => a.source + "=" + a.value).mkString("(", ", ", ")")).mkString(""))
486+
}
487+
488+
def foo(bar: String, baz: Int)(p: Boolean): Unit = {
489+
debug
490+
}
491+
492+
foo("baz", 42)(true) // foo(bar=baz, baz=42)(p=true)
493+
```
494+
478495
Embedding Domain-Specific Languages
479496
-----------------------------------
480497

sourcecode/shared/src/main/scala/sourcecode/SourceContext.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,24 @@ object Text{
111111
def apply[T](v: T): Text[T] = macro Impls.text[T]
112112

113113
}
114+
115+
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+
121+
def enclosingMethod(owner: Symbol): MethodSymbol =
122+
if (owner.isMethod) owner.asMethod else enclosingMethod(owner.owner)
123+
124+
val method = enclosingMethod(Compat.enclosingOwner(c))
125+
val param = method.asMethod.paramLists
126+
val texts = param.map(_.map(p => c.Expr[Text[_]](q"""sourcecode.Text($p, ${p.name.toString})""")))
127+
val textSeqs = texts.map(s => c.Expr(q"""Seq(..$s)"""))
128+
c.Expr[Args](q"""Seq(..$textSeqs)""")
129+
}
130+
}
131+
114132
object Impls{
115133
def text[T: c.WeakTypeTag](c: Compat.Context)(v: c.Expr[T]): c.Expr[sourcecode.Text[T]] = {
116134
import c.universe._
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package sourcecode
2+
3+
object ArgsTests {
4+
def apply() = {
5+
def debug(implicit args: sourcecode.Args): Unit = {
6+
assert(args.value.size == 2)
7+
assert(args.value(0).size == 3)
8+
assert(args.value(0)(0).source == "p1")
9+
assert(args.value(0)(0).value == "text")
10+
assert(args.value(0)(1).source == "p2")
11+
assert(args.value(0)(1).value == 42)
12+
assert(args.value(0)(2).source == "p3")
13+
assert(args.value(0)(2).value == false)
14+
assert(args.value(1)(0).source == "foo")
15+
assert(args.value(1)(0).value == "foo")
16+
assert(args.value(1)(1).source == "bar")
17+
assert(args.value(1)(1).value == "bar")
18+
}
19+
20+
def foo(p1: String, p2: Long, p3: Boolean)(foo: String, bar: String): Unit = {
21+
debug
22+
}
23+
24+
def bar(p1: String, p2: Long, p3: Boolean)(foo: String, bar: String): Unit = {
25+
val bar = {
26+
debug
27+
"bar"
28+
}
29+
}
30+
31+
foo("text", 42, false)("foo", "bar")
32+
bar("text", 42, false)("foo", "bar")
33+
}
34+
}

sourcecode/shared/src/test/scala/sourcecode/Tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ object Tests{
2020
Synthetic.run()
2121
ManualImplicit()
2222
TextTests()
23+
ArgsTests()
2324

2425
println("================LogExample================")
2526
logExample()

0 commit comments

Comments
 (0)