summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala11
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala32
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala79
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala27
-rw-r--r--test/files/scalacheck/quasiquotes/ErrorProps.scala7
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala6
7 files changed, 110 insertions, 54 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index aa27f6030f..d5a310668e 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -123,7 +123,7 @@ trait Reifiers { self: Quasiquotes =>
case TuplePlaceholder(args) => reifyTuple(args)
case TupleTypePlaceholder(args) => reifyTupleType(args)
case FunctionTypePlaceholder(argtpes, restpe) => reifyFunctionType(argtpes, restpe)
- case CasePlaceholder(tree, location, _) => reifyCase(tree, location)
+ case CasePlaceholder(tree, _, _) => tree
case RefineStatPlaceholder(tree, _, _) => reifyRefineStat(tree)
case EarlyDefPlaceholder(tree, _, _) => reifyEarlyDef(tree)
case PackageStatPlaceholder(tree, _, _) => reifyPackageStat(tree)
@@ -175,6 +175,10 @@ trait Reifiers { self: Quasiquotes =>
reifyTree(other)
case Block(stats, last) =>
reifyBuildCall(nme.SyntacticBlock, stats :+ last)
+ case Try(block, catches, finalizer) =>
+ reifyBuildCall(nme.SyntacticTry, block, catches, finalizer)
+ case Match(selector, cases) =>
+ reifyBuildCall(nme.SyntacticMatch, selector, cases)
// parser emits trees with scala package symbol to ensure
// that some names hygienically point to various scala package
// members; we need to preserve this symbol to preserve
@@ -199,11 +203,6 @@ trait Reifiers { self: Quasiquotes =>
super.reifyName(name)
}
- def reifyCase(tree: Tree, location: Location) = {
- if (holesHaveTypes && !(location.tpe <:< caseDefType)) c.abort(tree.pos, s"$caseDefType expected but ${location.tpe} found")
- tree
- }
-
def reifyTuple(args: List[Tree]) = args match {
case Nil => reify(Literal(Constant(())))
case List(hole @ Placeholder(_, _, NoDot)) => reify(hole)
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 673cf0d0b4..d2b9cd20fd 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -125,9 +125,9 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticClassDef: SyntacticClassDefExtractor
trait SyntacticClassDefExtractor {
- def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef],
- constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef
+ def apply(mods: Modifiers, name: TypeName, tparams: List[Tree],
+ constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree],
+ parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef
def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]],
List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -135,8 +135,8 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticTraitDef: SyntacticTraitDefExtractor
trait SyntacticTraitDefExtractor {
- def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef],
- earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef
+ def apply(mods: Modifiers, name: TypeName, tparams: List[Tree],
+ earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef
def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef],
List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -145,7 +145,7 @@ private[reflect] trait BuildUtils { self: Universe =>
trait SyntacticObjectDefExtractor {
def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree
+ parents: List[Tree], selfType: Tree, body: List[Tree]): Tree
def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -153,7 +153,7 @@ private[reflect] trait BuildUtils { self: Universe =>
trait SyntacticPackageObjectDefExtractor {
def apply(name: TermName, earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree
+ parents: List[Tree], selfType: Tree, body: List[Tree]): Tree
def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -175,7 +175,7 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticNew: SyntacticNewExtractor
trait SyntacticNewExtractor {
- def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree
+ def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): Tree
def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -189,7 +189,7 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticFunction: SyntacticFunctionExtractor
trait SyntacticFunctionExtractor {
- def apply(params: List[ValDef], body: Tree): Tree
+ def apply(params: List[Tree], body: Tree): Tree
def unapply(tree: Tree): Option[(List[ValDef], Tree)]
}
@@ -197,7 +197,7 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticDefDef: SyntacticDefDefExtractor
trait SyntacticDefDefExtractor {
- def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
+ def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef
def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)]
}
@@ -246,6 +246,18 @@ private[reflect] trait BuildUtils { self: Universe =>
def unapply(tree: Tree): Option[(List[Tree], Tree)]
}
+ val SyntacticMatch: SyntacticMatchExtractor
+ trait SyntacticMatchExtractor {
+ def apply(selector: Tree, cases: List[Tree]): Match
+ def unapply(tree: Match): Option[(Tree, List[CaseDef])]
+ }
+
+ val SyntacticTry: SyntacticTryExtractor
+ trait SyntacticTryExtractor {
+ def apply(block: Tree, catches: List[Tree], finalizer: Tree): Try
+ def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)]
+ }
+
val SyntacticIdent: SyntacticIdentExtractor
trait SyntacticIdentExtractor {
def apply(name: Name, isBackquoted: Boolean = false): Ident
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 22c10520b5..22e2bf4cad 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -71,12 +71,16 @@ trait BuildUtils { self: SymbolTable =>
def mkAnnotation(trees: List[Tree]): List[Tree] = trees.map(mkAnnotation)
- def mkVparamss(argss: List[List[ValDef]]): List[List[ValDef]] = argss.map(_.map(mkParam))
+ def mkVparamss(argss: List[List[Tree]]): List[List[ValDef]] = argss.map(_.map(mkParam))
- def mkParam(vd: ValDef): ValDef = {
- var newmods = (vd.mods | PARAM) & (~DEFERRED)
- if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM
- copyValDef(vd)(mods = newmods)
+ def mkParam(tree: Tree): ValDef = tree match {
+ case vd: ValDef =>
+ var newmods = (vd.mods | PARAM) & (~DEFERRED)
+ if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM
+ copyValDef(vd)(mods = newmods)
+ case _ =>
+ throw new IllegalArgumentException(s"$tree is not valid represenation of function parameter, " +
+ """consider reformatting it into q"val $name: $T = $default" shape""")
}
def mkTparams(tparams: List[Tree]): List[TypeDef] =
@@ -218,12 +222,25 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ protected def mkSelfType(tree: Tree) = tree match {
+ case vd: ValDef =>
+ require(vd.rhs.isEmpty, "self types must have empty right hand side")
+ copyValDef(vd)(mods = (vd.mods | PRIVATE) & (~DEFERRED))
+ case _ =>
+ throw new IllegalArgumentException(s"$tree is not a valid representation of self type, " +
+ """consider reformatting into q"val $self: $T" shape""")
+ }
+
object SyntacticClassDef extends SyntacticClassDefExtractor {
- def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef],
- constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef = {
+ def apply(mods: Modifiers, name: TypeName, tparams: List[Tree],
+ 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 = vparamss.map { _.map { vd => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED)) } }
+ val vparamss0 = vparamss.map { _.map {
+ case vd: ValDef => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED))
+ case tree => throw new IllegalArgumentException(s"$tree is not valid representation of class parameter, " +
+ """consider reformatting it into q"val $name: $T = $default" shape""")
+ } }
val tparams0 = mkTparams(tparams)
val parents0 = gen.mkParents(mods,
if (mods.isCase) parents.filter {
@@ -232,7 +249,8 @@ trait BuildUtils { self: SymbolTable =>
} else parents
)
val body0 = earlyDefs ::: body
- val templ = gen.mkTemplate(parents0, selfType, constrMods, vparamss0, body0)
+ val selfType0 = mkSelfType(selfType)
+ val templ = gen.mkTemplate(parents0, selfType0, constrMods, vparamss0, body0)
gen.mkClassDef(mods, name, tparams0, templ)
}
@@ -247,10 +265,10 @@ trait BuildUtils { self: SymbolTable =>
}
object SyntacticTraitDef extends SyntacticTraitDefExtractor {
- def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef = {
+ def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], earlyDefs: List[Tree],
+ parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = {
val mods0 = mods | TRAIT | ABSTRACT
- val templ = gen.mkTemplate(parents, selfType, Modifiers(TRAIT), Nil, earlyDefs ::: body)
+ val templ = gen.mkTemplate(parents, mkSelfType(selfType), Modifiers(TRAIT), Nil, earlyDefs ::: body)
gen.mkClassDef(mods0, name, mkTparams(tparams), templ)
}
@@ -265,8 +283,8 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticObjectDef extends SyntacticObjectDefExtractor {
def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]) =
- ModuleDef(mods, name, gen.mkTemplate(parents, selfType, NoMods, Nil, earlyDefs ::: body))
+ parents: List[Tree], selfType: Tree, body: List[Tree]) =
+ ModuleDef(mods, name, gen.mkTemplate(parents, mkSelfType(selfType), NoMods, Nil, earlyDefs ::: body))
def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match {
case ModuleDef(mods, name, UnMkTemplate(parents, selfType, _, _, earlyDefs, body)) =>
@@ -278,7 +296,7 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticPackageObjectDef extends SyntacticPackageObjectDefExtractor {
def apply(name: TermName, earlyDefs: List[Tree],
- parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree =
+ parents: List[Tree], selfType: Tree, body: List[Tree]): Tree =
gen.mkPackageObject(SyntacticObjectDef(NoMods, name, earlyDefs, parents, selfType, body))
def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match {
@@ -368,11 +386,9 @@ trait BuildUtils { self: SymbolTable =>
}
object SyntacticFunction extends SyntacticFunctionExtractor {
- def apply(params: List[ValDef], body: Tree): Tree = {
- val params0 = params.map { arg =>
- require(arg.rhs.isEmpty, "anonymous functions don't support default values")
- mkParam(arg)
- }
+ def apply(params: List[Tree], body: Tree): Tree = {
+ val params0 :: Nil = mkVparamss(params :: Nil)
+ require(params0.forall { _.rhs.isEmpty }, "anonymous functions don't support default values")
Function(params0, body)
}
@@ -383,8 +399,8 @@ trait BuildUtils { self: SymbolTable =>
}
object SyntacticNew extends SyntacticNewExtractor {
- def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree =
- gen.mkNew(parents, selfType, earlyDefs ::: body, NoPosition, NoPosition)
+ def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): Tree =
+ gen.mkNew(parents, mkSelfType(selfType), 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) =>
@@ -398,7 +414,7 @@ trait BuildUtils { self: SymbolTable =>
}
object SyntacticDefDef extends SyntacticDefDefExtractor {
- def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef =
+ def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], 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 {
@@ -664,6 +680,21 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ protected def mkCases(cases: List[Tree]): List[CaseDef] = cases.map {
+ case c: CaseDef => c
+ case tree => throw new IllegalArgumentException("$tree is not valid representation of pattern match case")
+ }
+
+ object SyntacticMatch extends SyntacticMatchExtractor {
+ def apply(selector: Tree, cases: List[Tree]) = Match(selector, mkCases(cases))
+ def unapply(tree: Match): Option[(Tree, List[CaseDef])] = Match.unapply(tree)
+ }
+
+ object SyntacticTry extends SyntacticTryExtractor {
+ def apply(block: Tree, catches: List[Tree], finalizer: Tree) = Try(block, mkCases(catches), finalizer)
+ def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] = Try.unapply(tree)
+ }
+
object SyntacticIdent extends SyntacticIdentExtractor {
def apply(name: Name, isBackquoted: Boolean) = {
val id = self.Ident(name)
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index f6c612f4eb..6cc0199458 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -598,10 +598,12 @@ trait StdNames {
val SyntacticFunction: NameType = "SyntacticFunction"
val SyntacticFunctionType: NameType = "SyntacticFunctionType"
val SyntacticIdent: NameType = "SyntacticIdent"
+ val SyntacticMatch: NameType = "SyntacticMatch"
val SyntacticNew: NameType = "SyntacticNew"
val SyntacticObjectDef: NameType = "SyntacticObjectDef"
val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
val SyntacticTraitDef: NameType = "SyntacticTraitDef"
+ val SyntacticTry: NameType = "SyntacticTry"
val SyntacticTuple: NameType = "SyntacticTuple"
val SyntacticTupleType: NameType = "SyntacticTupleType"
val SyntacticTypeApplied: NameType = "SyntacticTypeApplied"
diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
index 2ec679e78b..2af656c7c9 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
@@ -2,12 +2,25 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._
import scala.reflect.runtime.universe._, Flag._, build.ScalaDot
object DefinitionConstructionProps
- extends QuasiquoteProperties("definition construction")
- with ClassConstruction
- with TraitConstruction
- with TypeDefConstruction
- with ValDefConstruction
- with PackageConstruction
+ extends QuasiquoteProperties("definition construction")
+ with ClassConstruction
+ with TraitConstruction
+ with TypeDefConstruction
+ with ValDefConstruction
+ with PackageConstruction {
+ property("SI-6842") = test {
+ val x: Tree = q"val x: Int"
+ assertEqAst(q"def f($x) = 0", "def f(x: Int) = 0")
+ assertEqAst(q"class C($x)", "class C(val x: Int)")
+ assertEqAst(q"class C { $x => }", "class C { x: Int => }")
+ assertEqAst(q"trait B { $x => }", "trait B { x: Int => }")
+ assertEqAst(q"object A { $x => }", "object A { x: Int => }")
+ val t: Tree = q"type T"
+ assertEqAst(q"def f[$t] = 0", "def f[T] = 0")
+ assertEqAst(q"class C[$t]", "class C[T]")
+ assertEqAst(q"trait B[$t]", "trait B[T]")
+ }
+}
trait ClassConstruction { self: QuasiquoteProperties =>
val anyRef = ScalaDot(TypeName("AnyRef"))
@@ -283,7 +296,7 @@ trait MethodConstruction { self: QuasiquoteProperties =>
assertEqAst(q"@$a def foo", "@Foo[A,B] def foo")
}
- property("splice annotation with multiple argument lists") = test{
+ property("splice annotation with multiple argument lists") = test {
val a = q"new Foo(a)(b)"
assertEqAst(q"@$a def foo", "@Foo(a)(b) def foo")
}
diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala
index cb46a60dbe..adad48fcdf 100644
--- a/test/files/scalacheck/quasiquotes/ErrorProps.scala
+++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala
@@ -105,13 +105,6 @@ object ErrorProps extends QuasiquoteProperties("errors") {
q"f($sb)"
""")
- property("casedef expected") = fails(
- "reflect.runtime.universe.CaseDef expected but reflect.runtime.universe.Tree found",
- """
- val t = EmptyTree
- q"_ { case $t }"
- """)
-
property("can't splice with ... card here") = fails(
"Can't splice with ... here",
"""
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index ded8fd9c16..338c379fc3 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -210,6 +210,12 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
assertEqAst(q"{..$xs}", "{1; 2}")
}
+ property("SI-6842") = test {
+ val cases: List[Tree] = cq"a => b" :: cq"_ => c" :: Nil
+ assertEqAst(q"1 match { case ..$cases }", "1 match { case a => b case _ => c }")
+ assertEqAst(q"try 1 catch { case ..$cases }", "try 1 catch { case a => b case _ => c }")
+ }
+
property("SI-8009") = test {
q"`foo`".asInstanceOf[reflect.internal.SymbolTable#Ident].isBackquoted
}