diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-03-03 11:21:15 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-03-03 11:21:15 +0100 |
commit | 24ff7d7f7930ee9917465a9fe762f891251a58f6 (patch) | |
tree | 35e169bd7fd608c1ee7c8c4c624b5964f97f6b04 | |
parent | da124b33956f83be8b2ebbb77208c4aecde1c6dc (diff) | |
parent | 04c55c8d467097d69f3b2d7995e6f1d767b7e7ed (diff) | |
download | scala-24ff7d7f7930ee9917465a9fe762f891251a58f6.tar.gz scala-24ff7d7f7930ee9917465a9fe762f891251a58f6.tar.bz2 scala-24ff7d7f7930ee9917465a9fe762f891251a58f6.zip |
Merge pull request #3595 from densh/si/8332
SI-8332 implicit class param unquoting in quasiquotes
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 => |