diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-09-05 13:35:42 +0200 |
---|---|---|
committer | Den Shabalin <den.shabalin@gmail.com> | 2013-09-05 20:42:10 +0200 |
commit | a455858fc19e47dca10f446df0f61297d0d60276 (patch) | |
tree | 002b867b22f973757c76ca70b506451987f6cf73 | |
parent | 546e94099d667c6395582fcba321ef95578121a5 (diff) | |
download | scala-a455858fc19e47dca10f446df0f61297d0d60276.tar.gz scala-a455858fc19e47dca10f446df0f61297d0d60276.tar.bz2 scala-a455858fc19e47dca10f446df0f61297d0d60276.zip |
SI-7723 better support for deconstruction of new expressions
5 files changed, 43 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index fa305f3d07..cb84b5d8c7 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -9,7 +9,7 @@ trait Reifiers { self: Quasiquotes => import global._ import global.build.{SyntacticClassDef, SyntacticTraitDef, SyntacticModuleDef, SyntacticBlock, SyntacticApplied, SyntacticTypeApplied, - SyntacticFunction} + SyntacticFunction, SyntacticNew} import global.treeInfo._ import global.definitions._ import Cardinality._ @@ -62,6 +62,8 @@ trait Reifiers { self: Quasiquotes => earlyDefs, parents, selfdef, body) case SyntacticModuleDef(mods, name, earlyDefs, parents, selfdef, body) => reifyBuildCall(nme.SyntacticModuleDef, mods, name, earlyDefs, parents, selfdef, body) + case SyntacticNew(earlyDefs, parents, selfdef, body) => + reifyBuildCall(nme.SyntacticNew, earlyDefs, parents, selfdef, body) 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 8b2e02c639..7b3e287da7 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -154,6 +154,13 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Option[List[Tree]] } + val SyntacticNew: SyntacticNewExtractor + + trait SyntacticNewExtractor { + def apply(earlyDefs: List[Tree], parents: List[Tree], selfdef: ValDef, body: List[Tree]): Tree + def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] + } + val SyntacticFunctionType: SyntacticFunctionTypeExtractor trait SyntacticFunctionTypeExtractor { diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 936ca91c68..eaa4f7cba8 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -343,6 +343,21 @@ trait BuildUtils { self: SymbolTable => case _ => None } } + + object SyntacticNew extends SyntacticNewExtractor { + def apply(earlyDefs: List[Tree], parents: List[Tree], selfdef: ValDef, body: List[Tree]): Tree = + gen.mkNew(parents, selfdef, earlyDefs ::: body, NoPosition, NoPosition) + + def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { + case SyntacticApplied(Select(New(SyntacticTypeApplied(ident, targs)), nme.CONSTRUCTOR), argss) => + Some((Nil, SyntacticApplied(SyntacticTypeApplied(ident, targs), argss) :: Nil, emptyValDef, Nil)) + case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, List(Nil), earlyDefs, parents, selfdef, body) :: + Apply(Select(New(Ident(tpnme.ANON_CLASS_NAME)), nme.CONSTRUCTOR), Nil) :: Nil) => + Some((earlyDefs, parents, selfdef, body)) + case _ => + None + } + } } val build: BuildApi = new BuildImpl diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index b9a32c481f..9ae86059f1 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -595,6 +595,7 @@ trait StdNames { val SyntacticFunction: NameType = "SyntacticFunction" val SyntacticFunctionType: NameType= "SyntacticFunctionType" val SyntacticModuleDef: NameType = "SyntacticModuleDef" + val SyntacticNew: NameType = "SyntacticNew" val SyntacticTraitDef: NameType = "SyntacticTraitDef" val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" val This: NameType = "This" diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala index 762625a46a..45c7ee4bb7 100644 --- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala @@ -74,4 +74,21 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction matches("(y: Y) => y oh y") matches("(x: X, y: Y) => x and y") } + + property("exhaustive new pattern") = test { + def matches(line: String) { + val q"new { ..$early } with $name[..$targs](...$vargss) with ..$mixin { $self => ..$body }" = parse(line) + } + matches("new foo") + matches("new foo { body }") + matches("new foo[t]") + matches("new foo(x)") + matches("new foo[t](x)") + matches("new foo[t](x) { body }") + matches("new foo with bar") + matches("new foo with bar { body }") + matches("new { anonymous }") + matches("new { val early = 1} with Parent[Int] { body }") + matches("new Foo { selfie => }") + } } |