Skip to content

Fix #6988: add test #7009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions library/src/scala/tasty/reflect/TreeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,22 @@ trait TreeOps extends Core {

object Ref {

/** Create a reference tree */
/** Create a reference tree from a symbol
*
* If `sym` refers to a class member `foo` in class `C`,
* returns a tree representing `C.this.foo`.
*
* If `sym` refers to a local definition `foo`, returns
* a tree representing `foo`.
*
* @note In both cases, the constructed tree should only
* be spliced into the places where such accesses make sense.
* For example, it is incorrect to have `C.this.foo` outside
* the class body of `C`, or have `foo` outside the lexical
* scope for the definition of `foo`.
*/
def apply(sym: Symbol)(given ctx: Context): Ref =
internal.Ref_apply(sym)

// TODO def copy(original: Tree)(name: String)(given ctx: Context): Ref

}

given (given Context): IsInstanceOf[Ident] = internal.isInstanceOfIdent
Expand Down
32 changes: 32 additions & 0 deletions tests/run-macros/i6988/FirstArg_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package foo

case class FirstArg(value: Any, source: String)
object FirstArg {
inline given create: FirstArg = ${Macros.argsImpl}
}

object Macros {
import scala.quoted._

def argsImpl(given qctx: QuoteContext): Expr[FirstArg] = {
import qctx.tasty.{_, given}

def enclosingClass(cur: Symbol = rootContext.owner): Symbol =
if (cur.isClassDef) cur
else enclosingClass(cur.owner)

def enclosingParamList(owner: Symbol): Seq[Seq[Symbol]] =
if owner.isClassDef then
owner.tree match
case tdef: ClassDef =>
tdef.constructor.paramss map { _ map {_.symbol }}
else enclosingParamList(owner.owner)

def literal(value: String): Expr[String] =
Literal(Constant(value)).seal.asInstanceOf[Expr[String]]
val paramss = enclosingParamList(rootContext.owner)
val firstArg = paramss.flatten.head
val ref = Select.unique(This(enclosingClass()), firstArg.name)
'{ FirstArg(${ref.seal}, ${Expr(firstArg.name)}) }
}
}
16 changes: 16 additions & 0 deletions tests/run-macros/i6988/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
object Test {
var firstArgName = ""
var firstArgValue: Any = ""
def main(args: Array[String]): Unit = {
val x = new Foo("something", 2L, false)
assert("p1" == firstArgName)
assert("something" == firstArgValue)
}
def debug(given foo.FirstArg): Unit = {
firstArgName = summon[foo.FirstArg].source
firstArgValue = summon[foo.FirstArg].value
}
class Foo(p1: String, p2: Long, p3: Boolean) {
debug
}
}