From cd07f9f9656ea1bdc6c27ef2be9192d52cd987a5 Mon Sep 17 00:00:00 2001 From: Den Shabalin Date: Thu, 5 Sep 2013 13:40:38 +0200 Subject: better support for ValDefs, VarDefs and DefDefs --- .../scala/tools/reflect/quasiquotes/Reifiers.scala | 7 ++++++ src/reflect/scala/reflect/api/BuildUtils.scala | 16 ++++++++++++ .../scala/reflect/internal/BuildUtils.scala | 29 ++++++++++++++++++++++ src/reflect/scala/reflect/internal/StdNames.scala | 3 +++ .../DefinitionDeconstructionProps.scala | 9 +++++++ 5 files changed, 64 insertions(+) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 2e134ddd34..069ef09bc7 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -8,6 +8,7 @@ import scala.reflect.internal.Flags._ trait Reifiers { self: Quasiquotes => import global._ import global.build.{SyntacticClassDef, SyntacticTraitDef, SyntacticModuleDef, + SyntacticDefDef, SyntacticValDef, SyntacticVarDef, SyntacticBlock, SyntacticApplied, SyntacticTypeApplied, SyntacticFunction, SyntacticNew} import global.treeInfo._ @@ -64,6 +65,12 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticModuleDef, mods, name, earlyDefs, parents, selfdef, body) case SyntacticNew(earlyDefs, parents, selfdef, body) => reifyBuildCall(nme.SyntacticNew, earlyDefs, parents, selfdef, body) + case SyntacticDefDef(mods, name, tparams, vparamss, tpt, rhs) => + reifyBuildCall(nme.SyntacticDefDef, mods, name, tparams, vparamss, tpt, rhs) + case SyntacticValDef(mods, name, tpt, rhs) => + reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs) + case SyntacticVarDef(mods, name, tpt, rhs) => + reifyBuildCall(nme.SyntacticVarDef, mods, name, tpt, rhs) case SyntacticApplied(fun, argss) if argss.length > 1 => reifyBuildCall(nme.SyntacticApplied, fun, argss) case SyntacticApplied(fun, argss @ (_ :+ (_ :+ Placeholder(_, _, DotDotDot)))) => diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index b80159d051..ee6515b547 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -175,5 +175,21 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Option[(List[ValDef], Tree)] } + + val SyntacticDefDef: SyntacticDefDefExtractor + + trait SyntacticDefDefExtractor { + def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef + + def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)] + } + + val SyntacticValDef: SyntacticValDefExtractor + val SyntacticVarDef: SyntacticValDefExtractor + + trait SyntacticValDefExtractor { + def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef + def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)] + } } } diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 0cbad0d641..7091b0e875 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -358,6 +358,35 @@ trait BuildUtils { self: SymbolTable => None } } + + object SyntacticDefDef extends SyntacticDefDefExtractor { + def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = + DefDef(mods, name, mkTparams(tparams), mkVparamss(vparamss), tpt, rhs) + + def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)] = tree match { + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => Some((mods, name, tparams, vparamss, tpt, rhs)) + case _ => None + } + } + + trait SyntacticValDefBase extends SyntacticValDefExtractor { + val isMutable: Boolean + + def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) = { + val mods1 = if (isMutable) mods | MUTABLE else mods + ValDef(mods1, name, tpt, rhs) + } + + def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)] = tree match { + case ValDef(mods, name, tpt, rhs) if mods.hasFlag(MUTABLE) == isMutable => + Some((mods, name, tpt, rhs)) + case _ => + None + } + } + + object SyntacticValDef extends SyntacticValDefBase { val isMutable = false } + object SyntacticVarDef extends SyntacticValDefBase { val isMutable = true } } val build: BuildApi = new BuildImpl diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index e52f3140c3..17a084f461 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -592,6 +592,7 @@ trait StdNames { val SyntacticApplied: NameType = "SyntacticApplied" val SyntacticBlock: NameType = "SyntacticBlock" val SyntacticClassDef: NameType = "SyntacticClassDef" + val SyntacticDefDef: NameType = "SyntacticDefDef" val SyntacticFunction: NameType = "SyntacticFunction" val SyntacticFunctionType: NameType= "SyntacticFunctionType" val SyntacticModuleDef: NameType = "SyntacticModuleDef" @@ -600,6 +601,8 @@ trait StdNames { val SyntacticTuple: NameType = "SyntacticTuple" val SyntacticTupleType: NameType = "SyntacticTupleType" val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" + val SyntacticValDef: NameType = "SyntacticValDef" + val SyntacticVarDef: NameType = "SyntacticVarDef" val This: NameType = "This" val ThisType: NameType = "ThisType" val True : NameType = "True" diff --git a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala index d6b60c4351..fdfbfe871c 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala @@ -134,5 +134,14 @@ trait ValVarDeconstruction { self: QuasiquoteProperties => matches("val x: Int = 1") matches("lazy val x: Int = 1") matches("implicit val x = 1") + assertThrows[MatchError] { matches("var x = 1") } + } + + property("exhaustive var matcher") = test { + def matches(line: String) { val q"$mods var $name: $tpt = $rhs" = parse(line) } + matches("var x: Int") + matches("var x: Int = 1") + matches("var x = 1") + assertThrows[MatchError] { matches("val x = 1") } } } \ No newline at end of file -- cgit v1.2.3