summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Shabalin <denys.shabalin@typesafe.com>2014-02-24 16:03:20 +0100
committerDenys Shabalin <denys.shabalin@typesafe.com>2014-03-02 20:11:46 +0200
commit04c55c8d467097d69f3b2d7995e6f1d767b7e7ed (patch)
tree35e169bd7fd608c1ee7c8c4c624b5964f97f6b04
parentda124b33956f83be8b2ebbb77208c4aecde1c6dc (diff)
downloadscala-04c55c8d467097d69f3b2d7995e6f1d767b7e7ed.tar.gz
scala-04c55c8d467097d69f3b2d7995e6f1d767b7e7ed.tar.bz2
scala-04c55c8d467097d69f3b2d7995e6f1d767b7e7ed.zip
SI-8332 implicit class param unquoting in quasiquotes
A new api that simplifies handling of implicit parameters has been mistakingly supporting just methods parameters. This commit adds support for class parameters too.
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala23
-rw-r--r--src/reflect/scala/reflect/api/Internals.scala2
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala16
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala5
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala14
5 files changed, 40 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 481897d0ec..5eae3b6e6f 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -151,21 +151,20 @@ trait Reifiers { self: Quasiquotes =>
mirrorCall(nme.This, tree)
case SyntacticTraitDef(mods, name, tparams, earlyDefs, parents, selfdef, body) =>
reifyBuildCall(nme.SyntacticTraitDef, mods, name, tparams, earlyDefs, parents, selfdef, body)
- case SyntacticClassDef(mods, name, tparams, constrmods, vparamss, earlyDefs, parents, selfdef, body) =>
- reifyBuildCall(nme.SyntacticClassDef, mods, name, tparams, constrmods, vparamss,
- earlyDefs, parents, selfdef, body)
+ case SyntacticClassDef(mods, name, tparams, constrmods, vparamss,
+ earlyDefs, parents, selfdef, body) =>
+ mirrorBuildCall(nme.SyntacticClassDef, reify(mods), reify(name), reify(tparams), reify(constrmods),
+ reifyVparamss(vparamss), reify(earlyDefs), reify(parents),
+ reify(selfdef), reify(body))
case SyntacticPackageObjectDef(name, earlyDefs, parents, selfdef, body) =>
reifyBuildCall(nme.SyntacticPackageObjectDef, name, earlyDefs, parents, selfdef, body)
case SyntacticObjectDef(mods, name, earlyDefs, parents, selfdef, body) =>
reifyBuildCall(nme.SyntacticObjectDef, mods, name, earlyDefs, parents, selfdef, body)
case SyntacticNew(earlyDefs, parents, selfdef, body) =>
reifyBuildCall(nme.SyntacticNew, earlyDefs, parents, selfdef, body)
- case SyntacticDefDef(mods, name, tparams, build.ImplicitParams(vparamss, implparams), tpt, rhs) =>
- if (implparams.nonEmpty)
- mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams),
- reifyBuildCall(nme.ImplicitParams, vparamss, implparams), reify(tpt), reify(rhs))
- else
- reifyBuildCall(nme.SyntacticDefDef, mods, name, tparams, vparamss, tpt, rhs)
+ case SyntacticDefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams),
+ reifyVparamss(vparamss), reify(tpt), reify(rhs))
case SyntacticValDef(mods, name, tpt, rhs) if tree != noSelfType =>
reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs)
case SyntacticVarDef(mods, name, tpt, rhs) =>
@@ -270,6 +269,12 @@ trait Reifiers { self: Quasiquotes =>
def reifyPackageStat(hole: Hole) = reifyConstructionCheck(nme.mkPackageStat, hole)
+ def reifyVparamss(vparamss: List[List[ValDef]]) = {
+ val build.ImplicitParams(paramss, implparams) = vparamss
+ if (implparams.isEmpty) reify(paramss)
+ else reifyBuildCall(nme.ImplicitParams, paramss, implparams)
+ }
+
/** Splits list into a list of groups where subsequent elements are considered
* similar by the corresponding function.
*
diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala
index 01700345d1..01f928ed61 100644
--- a/src/reflect/scala/reflect/api/Internals.scala
+++ b/src/reflect/scala/reflect/api/Internals.scala
@@ -581,7 +581,7 @@ trait Internals { self: Universe =>
val ImplicitParams: ImplicitParamsExtractor
trait ImplicitParamsExtractor {
- def apply(paramss: List[List[ValDef]], implparams: List[ValDef]): List[List[ValDef]]
+ def apply(paramss: List[List[Tree]], implparams: List[Tree]): List[List[Tree]]
def unapply(vparamss: List[List[ValDef]]): Some[(List[List[ValDef]], List[ValDef])]
}
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 7f345845fe..66ac4bc751 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -110,14 +110,14 @@ trait ReificationSupport { self: SymbolTable =>
def mkAnnotation(trees: List[Tree]): List[Tree] = trees.map(mkAnnotation)
- def mkParam(argss: List[List[Tree]], extraFlags: FlagSet = NoFlags): List[List[ValDef]] =
- argss.map { args => args.map { mkParam(_, extraFlags) } }
+ def mkParam(argss: List[List[Tree]], extraFlags: FlagSet = NoFlags, excludeFlags: FlagSet = DEFERRED): List[List[ValDef]] =
+ argss.map { args => args.map { mkParam(_, extraFlags, excludeFlags) } }
- def mkParam(tree: Tree, extraFlags: FlagSet): ValDef = tree match {
+ def mkParam(tree: Tree, extraFlags: FlagSet, excludeFlags: FlagSet): ValDef = tree match {
case Typed(Ident(name: TermName), tpt) =>
- mkParam(ValDef(NoMods, name, tpt, EmptyTree), extraFlags)
+ mkParam(ValDef(NoMods, name, tpt, EmptyTree), extraFlags, excludeFlags)
case vd: ValDef =>
- var newmods = vd.mods & (~DEFERRED)
+ var newmods = vd.mods & (~excludeFlags)
if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM
copyValDef(vd)(mods = newmods | extraFlags)
case _ =>
@@ -127,7 +127,7 @@ trait ReificationSupport { self: SymbolTable =>
def mkImplicitParam(args: List[Tree]): List[ValDef] = args.map(mkImplicitParam)
- def mkImplicitParam(tree: Tree): ValDef = mkParam(tree, IMPLICIT | PARAM)
+ def mkImplicitParam(tree: Tree): ValDef = mkParam(tree, IMPLICIT | PARAM, NoFlags)
def mkTparams(tparams: List[Tree]): List[TypeDef] =
tparams.map {
@@ -187,7 +187,7 @@ trait ReificationSupport { self: SymbolTable =>
protected implicit def fresh: FreshNameCreator = self.currentFreshNameCreator
object ImplicitParams extends ImplicitParamsExtractor {
- def apply(paramss: List[List[ValDef]], implparams: List[ValDef]): List[List[ValDef]] =
+ def apply(paramss: List[List[Tree]], implparams: List[Tree]): List[List[Tree]] =
if (implparams.nonEmpty) paramss :+ mkImplicitParam(implparams) else paramss
def unapply(vparamss: List[List[ValDef]]): Some[(List[List[ValDef]], List[ValDef])] = vparamss match {
@@ -300,7 +300,7 @@ trait ReificationSupport { self: SymbolTable =>
constrMods: Modifiers, vparamss: List[List[Tree]],
earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = {
val extraFlags = PARAMACCESSOR | (if (mods.isCase) CASEACCESSOR else 0L)
- val vparamss0 = mkParam(vparamss, extraFlags)
+ val vparamss0 = mkParam(vparamss, extraFlags, excludeFlags = DEFERRED | PARAM)
val tparams0 = mkTparams(tparams)
val parents0 = gen.mkParents(mods,
if (mods.isCase) parents.filter {
diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
index c6ad453c45..69aef12668 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
@@ -85,6 +85,11 @@ trait ClassConstruction { self: QuasiquoteProperties =>
property("SI-8333") = test {
assertEqAst(q"{ $NoMods class C }", "{ class C }")
}
+
+ property("SI-8332") = test {
+ val args = q"val a: Int; val b: Int"
+ assertEqAst(q"class C(implicit ..$args)", "class C(implicit val a: Int, val b: Int)")
+ }
}
trait TraitConstruction { self: QuasiquoteProperties =>
diff --git a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
index 996ac65b36..af7f2164a0 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
@@ -73,8 +73,11 @@ trait ClassDeconstruction { self: QuasiquoteProperties =>
property("exhaustive class matcher") = test {
def matches(line: String) {
- val q"""$classMods class $name[..$targs] $ctorMods(...$argss)
- extends { ..$early } with ..$parents { $self => ..$body }""" = parse(line)
+ val tree = parse(line)
+ val q"""$classMods0 class $name0[..$targs0] $ctorMods0(...$argss0)
+ extends { ..$early0 } with ..$parents0 { $self0 => ..$body0 }""" = tree
+ val q"""$classMods1 class $name1[..$targs1] $ctorMods1(...$argss1)(implicit ..$impl)
+ extends { ..$early1 } with ..$parents1 { $self1 => ..$body1 }""" = tree
}
matches("class Foo")
matches("class Foo[T]")
@@ -106,6 +109,13 @@ trait ClassDeconstruction { self: QuasiquoteProperties =>
Ident(TypeName("Int")), EmptyTree))), TypeTree(), Block(List(pendingSuperCall), Literal(Constant(())))))))
}
}
+
+ property("SI-8332") = test {
+ val q"class C(implicit ..$args)" = q"class C(implicit i: I, j: J)"
+ val q"$imods val i: I" :: q"$jmods val j: J" :: Nil = args
+ assert(imods.hasFlag(IMPLICIT))
+ assert(jmods.hasFlag(IMPLICIT))
+ }
}
trait ModsDeconstruction { self: QuasiquoteProperties =>