summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugin.scala93
-rw-r--r--src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala15
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala4
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Holes.scala280
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala7
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala41
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala183
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala55
-rw-r--r--src/reflect/scala/reflect/api/Liftable.scala32
-rw-r--r--src/reflect/scala/reflect/api/StandardLiftables.scala230
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala14
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala133
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala27
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala13
-rw-r--r--src/reflect/scala/reflect/internal/util/StringOps.scala16
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala4
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala5
-rw-r--r--test/files/instrumented/InstrumentationTest.check4
-rw-r--r--test/files/instrumented/InstrumentationTest.scala27
-rw-r--r--test/files/instrumented/inline-in-constructors.check4
-rw-r--r--test/files/instrumented/inline-in-constructors/test_3.scala21
-rw-r--r--test/files/neg/quasiquotes-unliftable-not-found.check4
-rw-r--r--test/files/neg/quasiquotes-unliftable-not-found.scala5
-rw-r--r--test/files/neg/si7980.check4
-rw-r--r--test/files/neg/si7980.scala8
-rwxr-xr-xtest/files/neg/t6446-missing.check2
-rw-r--r--test/files/pos/macro-implicit-invalidate-on-error.scala17
-rw-r--r--test/files/pos/t8054.scala31
-rw-r--r--test/files/run/macro-subpatterns.check3
-rw-r--r--test/files/run/macro-subpatterns/Macro_1.scala18
-rw-r--r--test/files/run/macro-subpatterns/Test_2.scala5
-rw-r--r--test/files/run/t4841-isolate-plugins.check2
-rw-r--r--test/files/run/t4841-isolate-plugins/ploogin.scala30
-rw-r--r--test/files/run/t4841-isolate-plugins/t4841-isolate-plugin.scala39
-rw-r--r--test/files/run/t4841-no-plugin.check1
-rw-r--r--test/files/run/t4841-no-plugin.scala17
-rw-r--r--test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala11
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala27
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala16
-rw-r--r--test/files/scalacheck/quasiquotes/ErrorProps.scala21
-rw-r--r--test/files/scalacheck/quasiquotes/LiftableProps.scala35
-rw-r--r--test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala4
-rw-r--r--test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala75
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala21
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala6
-rw-r--r--test/files/scalacheck/quasiquotes/Test.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/TypecheckedProps.scala25
-rw-r--r--test/files/scalacheck/quasiquotes/UnliftableProps.scala160
-rw-r--r--test/junit/scala/reflect/internal/util/StringOpsTest.scala52
52 files changed, 1388 insertions, 488 deletions
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
index d194c095f8..183752d4a2 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
@@ -12,7 +12,8 @@ import scala.reflect.io.{ Directory, File, Path }
import java.io.InputStream
import java.util.zip.ZipException
-import scala.collection.mutable.ListBuffer
+import scala.collection.mutable
+import mutable.ListBuffer
import scala.util.{ Try, Success, Failure }
/** Information about a plugin loaded from a jar file.
@@ -99,7 +100,7 @@ object Plugin {
private def loadDescriptionFromJar(jarp: Path): Try[PluginDescription] = {
// XXX Return to this once we have more ARM support
def read(is: Option[InputStream]) = is match {
- case None => throw new RuntimeException(s"Missing $PluginXML in $jarp")
+ case None => throw new PluginLoadException(jarp.path, s"Missing $PluginXML in $jarp")
case Some(is) => PluginDescription.fromXML(is)
}
Try(new Jar(jarp.jfile).withEntryStream(PluginXML)(read))
@@ -113,11 +114,14 @@ object Plugin {
/** Use a class loader to load the plugin class.
*/
def load(classname: String, loader: ClassLoader): Try[AnyClass] = {
- Try[AnyClass] {
- loader loadClass classname
- } recoverWith {
- case _: Exception =>
- Failure(new RuntimeException(s"Warning: class not found: ${classname}"))
+ import scala.util.control.NonFatal
+ try {
+ Success[AnyClass](loader loadClass classname)
+ } catch {
+ case NonFatal(e) =>
+ Failure(new PluginLoadException(classname, s"Error: unable to load class: $classname"))
+ case e: NoClassDefFoundError =>
+ Failure(new PluginLoadException(classname, s"Error: class not found: ${e.getMessage} required by $classname"))
}
}
@@ -128,33 +132,54 @@ object Plugin {
* A single classloader is created and used to load all of them.
*/
def loadAllFrom(
- jars: List[Path],
+ paths: List[List[Path]],
dirs: List[Path],
ignoring: List[String]): List[Try[AnyClass]] =
{
- // List[(jar, Success(descriptor))] in dir
- def scan(d: Directory) = for {
- f <- d.files.toList sortBy (_.name)
- if Jar isJarOrZip f
- pd = loadDescriptionFromJar(f)
- if pd.isSuccess
- } yield (f, pd)
- // (dir, Try(descriptor))
- def explode(d: Directory) = d -> loadDescriptionFromFile(d / PluginXML)
- // (j, Try(descriptor))
- def required(j: Path) = j -> loadDescriptionFromJar(j)
-
- type Paired = Tuple2[Path, Try[PluginDescription]]
- val included: List[Paired] = (dirs flatMap (_ ifDirectory scan)).flatten
- val exploded: List[Paired] = jars flatMap (_ ifDirectory explode)
- val explicit: List[Paired] = jars flatMap (_ ifFile required)
- def ignored(p: Paired) = p match {
- case (path, Success(pd)) => ignoring contains pd.name
- case _ => false
+ // List[(jar, Try(descriptor))] in dir
+ def scan(d: Directory) =
+ d.files.toList sortBy (_.name) filter (Jar isJarOrZip _) map (j => (j, loadDescriptionFromJar(j)))
+
+ type PDResults = List[Try[(PluginDescription, ScalaClassLoader)]]
+
+ // scan plugin dirs for jars containing plugins, ignoring dirs with none and other jars
+ val fromDirs: PDResults = dirs filter (_.isDirectory) flatMap { d =>
+ scan(d.toDirectory) collect {
+ case (j, Success(pd)) => Success((pd, loaderFor(Seq(j))))
+ }
+ }
+
+ // scan jar paths for plugins, taking the first plugin you find.
+ // a path element can be either a plugin.jar or an exploded dir.
+ def findDescriptor(ps: List[Path]) = {
+ def loop(qs: List[Path]): Try[PluginDescription] = qs match {
+ case Nil => Failure(new MissingPluginException(ps))
+ case p :: rest =>
+ if (p.isDirectory) loadDescriptionFromFile(p.toDirectory / PluginXML)
+ else if (p.isFile) loadDescriptionFromJar(p.toFile)
+ else loop(rest)
+ }
+ loop(ps)
+ }
+ val fromPaths: PDResults = paths map (p => (p, findDescriptor(p))) map {
+ case (p, Success(pd)) => Success((pd, loaderFor(p)))
+ case (_, Failure(e)) => Failure(e)
}
- val (locs, pds) = ((explicit ::: exploded ::: included) filterNot ignored).unzip
- val loader = loaderFor(locs.distinct)
- (pds filter (_.isSuccess) map (_.get.classname)).distinct map (Plugin load (_, loader))
+
+ val seen = mutable.HashSet[String]()
+ val enabled = (fromPaths ::: fromDirs) map {
+ case Success((pd, loader)) if seen(pd.classname) =>
+ // a nod to SI-7494, take the plugin classes distinctly
+ Failure(new PluginLoadException(pd.name, s"Ignoring duplicate plugin ${pd.name} (${pd.classname})"))
+ case Success((pd, loader)) if ignoring contains pd.name =>
+ Failure(new PluginLoadException(pd.name, s"Disabling plugin ${pd.name}"))
+ case Success((pd, loader)) =>
+ seen += pd.classname
+ Plugin.load(pd.classname, loader)
+ case Failure(e) =>
+ Failure(e)
+ }
+ enabled // distinct and not disabled
}
/** Instantiate a plugin class, given the class and
@@ -164,3 +189,11 @@ object Plugin {
(clazz getConstructor classOf[Global] newInstance global).asInstanceOf[Plugin]
}
}
+
+class PluginLoadException(val path: String, message: String, cause: Exception) extends Exception(message, cause) {
+ def this(path: String, message: String) = this(path, message, null)
+}
+
+class MissingPluginException(path: String) extends PluginLoadException(path, s"No plugin in path $path") {
+ def this(paths: List[Path]) = this(paths mkString File.pathSeparator)
+}
diff --git a/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala b/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala
deleted file mode 100644
index c5da24993e..0000000000
--- a/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2007-2013 LAMP/EPFL
- * @author Lex Spoon
- */
-
-package scala.tools.nsc
-package plugins
-
-/** ...
- *
- * @author Lex Spoon
- * @version 1.0, 2007-5-21
- */
-class PluginLoadException(filename: String, cause: Exception)
-extends Exception(cause)
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index 4769705404..12f9aeba27 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -8,6 +8,7 @@ package scala.tools.nsc
package plugins
import scala.reflect.io.{ File, Path }
+import scala.tools.nsc.util.ClassPath
import scala.tools.util.PathResolver.Defaults
/** Support for run-time loading of compiler plugins.
@@ -16,8 +17,7 @@ import scala.tools.util.PathResolver.Defaults
* @version 1.1, 2009/1/2
* Updated 2009/1/2 by Anders Bach Nielsen: Added features to implement SIP 00002
*/
-trait Plugins {
- self: Global =>
+trait Plugins { global: Global =>
/** Load a rough list of the plugins. For speed, it
* does not instantiate a compiler run. Therefore it cannot
@@ -25,13 +25,20 @@ trait Plugins {
* filtered from the final list of plugins.
*/
protected def loadRoughPluginsList(): List[Plugin] = {
- val jars = settings.plugin.value map Path.apply
- def injectDefault(s: String) = if (s.isEmpty) Defaults.scalaPluginPath else s
- val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map injectDefault map Path.apply
- val maybes = Plugin.loadAllFrom(jars, dirs, settings.disable.value)
+ def asPath(p: String) = ClassPath split p
+ val paths = settings.plugin.value filter (_ != "") map (s => asPath(s) map Path.apply)
+ val dirs = {
+ def injectDefault(s: String) = if (s.isEmpty) Defaults.scalaPluginPath else s
+ asPath(settings.pluginsDir.value) map injectDefault map Path.apply
+ }
+ val maybes = Plugin.loadAllFrom(paths, dirs, settings.disable.value)
val (goods, errors) = maybes partition (_.isSuccess)
// Explicit parameterization of recover to suppress -Xlint warning about inferred Any
- errors foreach (_.recover[Any] { case e: Exception => inform(e.getMessage) })
+ errors foreach (_.recover[Any] {
+ // legacy behavior ignores altogether, so at least warn devs
+ case e: MissingPluginException => if (global.isDeveloper) warning(e.getMessage)
+ case e: Exception => inform(e.getMessage)
+ })
val classes = goods map (_.get) // flatten
// Each plugin must only be instantiated once. A common pattern
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index ba135d7d25..069d6d5fb2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -391,8 +391,10 @@ trait PatternTypers {
else freshUnapplyArgType()
)
)
+ val unapplyArgTree = Ident(unapplyArg) updateAttachment SubpatternsAttachment(args)
+
// clearing the type is necessary so that ref will be stabilized; see bug 881
- val fun1 = typedPos(fun.pos)(Apply(Select(fun.clearType(), unapplyMethod), Ident(unapplyArg) :: Nil))
+ val fun1 = typedPos(fun.pos)(Apply(Select(fun.clearType(), unapplyMethod), unapplyArgTree :: Nil))
def makeTypedUnApply() = {
// the union of the expected type and the inferred type of the argument to unapply
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
index f92c9aa845..f5bcaf68e0 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
@@ -3,6 +3,7 @@ package quasiquotes
import scala.collection.{immutable, mutable}
import scala.reflect.internal.Flags._
+import scala.reflect.macros.TypecheckException
class Cardinality private[Cardinality](val value: Int) extends AnyVal {
def pred = { assert(value - 1 >= 0); new Cardinality(value - 1) }
@@ -30,158 +31,173 @@ trait Holes { self: Quasiquotes =>
import definitions._
import universeTypes._
- /** Location characterizes a kind of a non-terminal in Scala syntax where something is going to be spliced.
- * A location is typically associated with a type of the things that can be spliced there.
- * Associated type might be different from an actual tpe of a splicee due to lifting.
- * This is the first pillar of modularity in the quasiquote reifier.
- */
- sealed abstract class Location(val tpe: Type)
- case object UnknownLocation extends Location(NoType)
- case class TreeLocation(override val tpe: Type) extends Location(tpe)
- case object NameLocation extends Location(nameType)
- case object ModsLocation extends Location(modsType)
- case object FlagsLocation extends Location(flagsType)
- case object SymbolLocation extends Location(symbolType)
- case class IterableLocation(card: Cardinality, sublocation: TreeLocation) extends Location(NoType) {
- override val tpe = {
- def loop(n: Cardinality, tpe: Type): Type =
- if (n == NoDot) tpe
- else appliedType(IterableClass.toType, List(loop(n.pred, tpe)))
- loop(card, sublocation.tpe)
+ protected lazy val IterableTParam = IterableClass.typeParams(0).asType.toType
+ protected def inferParamImplicit(tfun: Type, targ: Type) = c.inferImplicitValue(appliedType(tfun, List(targ)), silent = true)
+ protected def inferLiftable(tpe: Type): Tree = inferParamImplicit(liftableType, tpe)
+ protected def inferUnliftable(tpe: Type): Tree = inferParamImplicit(unliftableType, tpe)
+ protected def isLiftableType(tpe: Type) = inferLiftable(tpe) != EmptyTree
+ protected def isNativeType(tpe: Type) =
+ (tpe <:< treeType) || (tpe <:< nameType) || (tpe <:< modsType) ||
+ (tpe <:< flagsType) || (tpe <:< symbolType)
+ protected def isBottomType(tpe: Type) =
+ tpe <:< NothingClass.tpe || tpe <:< NullClass.tpe
+ protected def stripIterable(tpe: Type, limit: Option[Cardinality] = None): (Cardinality, Type) =
+ if (limit.map { _ == NoDot }.getOrElse { false }) (NoDot, tpe)
+ else if (tpe != null && !isIterableType(tpe)) (NoDot, tpe)
+ else if (isBottomType(tpe)) (NoDot, tpe)
+ else {
+ val targ = IterableTParam.asSeenFrom(tpe, IterableClass)
+ val (card, innerTpe) = stripIterable(targ, limit.map { _.pred })
+ (card.succ, innerTpe)
}
+ protected def iterableTypeFromCard(n: Cardinality, tpe: Type): Type = {
+ if (n == NoDot) tpe
+ else appliedType(IterableClass.toType, List(iterableTypeFromCard(n.pred, tpe)))
}
- /** Hole type describes location, cardinality and a pre-reification routine associated with a hole.
- * An interesting thing about HoleType is that it can be completely inferred from the type of the splicee.
- * This is the second pillar of modularity in the quasiquote reifier.
+ /** Hole encapsulates information about splices in quasiquotes.
+ * It packs together a cardinality of a splice, pre-reified tree
+ * representation (possibly preprocessed) and position.
*/
- case class HoleType(preprocessor: Tree => Tree, location: Location, cardinality: Cardinality) {
- def makeHole(tree: Tree) = Hole(preprocessor(tree), location, cardinality)
+ abstract class Hole {
+ val tree: Tree
+ val pos: Position
+ val cardinality: Cardinality
}
- object HoleType {
- def unapply(tpe: Type): Option[HoleType] = tpe match {
- case NativeType(holeTpe) => Some(holeTpe)
- case LiftableType(holeTpe) => Some(holeTpe)
- case IterableTreeType(holeTpe) => Some(holeTpe)
- case IterableLiftableType(holeTpe) => Some(holeTpe)
- case _ => None
- }
- trait HoleTypeExtractor {
- def unapply(tpe: Type): Option[HoleType] = {
- for {
- preprocessor <- this.preprocessor(tpe)
- location <- this.location(tpe)
- cardinality <- Some(this.cardinality(tpe))
- } yield HoleType(preprocessor, location, cardinality)
- }
- def preprocessor(tpe: Type): Option[Tree => Tree]
- def location(tpe: Type): Option[Location]
- def cardinality(tpe: Type): Cardinality = parseCardinality(tpe)._1
-
- def lifter(tpe: Type): Option[Tree => Tree] = {
- val lifterTpe = appliedType(LiftableClass.toType, List(tpe))
- val lifter = c.inferImplicitValue(lifterTpe, silent = true)
- if (lifter != EmptyTree) Some(tree => {
- val lifted = Apply(lifter, List(u, tree))
- val targetType = Select(u, tpnme.Tree)
- atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType)))
- }) else None
- }
+ object Hole {
+ def apply(card: Cardinality, tree: Tree): Hole =
+ if (method != nme.unapply) new ApplyHole(card, tree)
+ else new UnapplyHole(card, tree)
+ def unapply(hole: Hole): Some[(Tree, Cardinality)] = Some((hole.tree, hole.cardinality))
+ }
- def iterator(tpe: Type)(elementTransform: Tree => Tree): Option[Tree => Tree] = {
- def reifyIterable(tree: Tree, n: Cardinality): Tree = {
- def loop(tree: Tree, n: Cardinality) =
- if (n == NoDot) elementTransform(tree)
- else {
- val x: TermName = c.freshName()
- val wrapped = reifyIterable(Ident(x), n.pred)
- val xToWrapped = Function(List(ValDef(Modifiers(PARAM), x, TypeTree(), EmptyTree)), wrapped)
- Select(Apply(Select(tree, nme.map), List(xToWrapped)), nme.toList)
- }
- if (tree.tpe != null && (tree.tpe <:< listTreeType || tree.tpe <:< listListTreeType)) tree
- else atPos(tree.pos)(loop(tree, n))
- }
- val card = parseCardinality(tpe)._1
- if (card != NoDot) Some(reifyIterable(_, card)) else None
- }
+ class ApplyHole(card: Cardinality, splicee: Tree) extends Hole {
+ val (strippedTpe, tpe): (Type, Type) = {
+ if (stripIterable(splicee.tpe)._1.value < card.value) cantSplice()
+ val (_, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card))
+ if (isBottomType(strippedTpe)) cantSplice()
+ else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, strippedTpe))
+ else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, treeType))
+ else cantSplice()
}
- object NativeType extends HoleTypeExtractor {
- def preprocessor(tpe: Type) = Some(identity)
- def location(tpe: Type) = {
- if (tpe <:< treeType) Some(TreeLocation(tpe))
- else if (tpe <:< nameType) Some(NameLocation)
- else if (tpe <:< modsType) Some(ModsLocation)
- else if (tpe <:< flagsType) Some(FlagsLocation)
- else if (tpe <:< symbolType) Some(SymbolLocation)
- else None
- }
+ val tree = {
+ def inner(itpe: Type)(tree: Tree) =
+ if (isNativeType(itpe)) tree
+ else if (isLiftableType(itpe)) lifted(itpe)(tree)
+ else global.abort("unreachable")
+ if (card == NoDot) inner(strippedTpe)(splicee)
+ else iterated(card, strippedTpe, inner(strippedTpe))(splicee)
}
- object LiftableType extends HoleTypeExtractor {
- def preprocessor(tpe: Type) = lifter(tpe)
- def location(tpe: Type) = Some(TreeLocation(treeType))
+ val pos = splicee.pos
+
+ val cardinality = stripIterable(tpe)._1
+
+ protected def cantSplice(): Nothing = {
+ val (iterableCard, iterableType) = stripIterable(splicee.tpe)
+ val holeCardMsg = if (card != NoDot) s" with $card" else ""
+ val action = "splice " + splicee.tpe + holeCardMsg
+ val suggestCard = card != iterableCard || card != NoDot
+ val spliceeCardMsg = if (card != iterableCard && iterableCard != NoDot) s"using $iterableCard" else "omitting the dots"
+ val cardSuggestion = if (suggestCard) spliceeCardMsg else ""
+ val suggestLifting = (card == NoDot || iterableCard != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType)
+ val liftedTpe = if (card != NoDot) iterableType else splicee.tpe
+ val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else ""
+ val advice =
+ if (isBottomType(iterableType)) "bottom type values often indicate programmer mistake"
+ else "consider " + List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ")
+ c.abort(splicee.pos, s"Can't $action, $advice")
}
- object IterableTreeType extends HoleTypeExtractor {
- def preprocessor(tpe: Type) = iterator(tpe)(identity)
- def location(tpe: Type) = {
- val (card, elementTpe) = parseCardinality(tpe)
- if (card != NoDot && elementTpe <:< treeType) Some(IterableLocation(card, TreeLocation(elementTpe)))
- else None
- }
+ protected def lifted(tpe: Type)(tree: Tree): Tree = {
+ val lifter = inferLiftable(tpe)
+ assert(lifter != EmptyTree, s"couldnt find a liftable for $tpe")
+ val lifted = Apply(lifter, List(tree))
+ val targetType = Select(u, tpnme.Tree)
+ atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType)))
}
- object IterableLiftableType extends HoleTypeExtractor {
- def preprocessor(tpe: Type) = {
- val (_, elementTpe) = parseCardinality(tpe)
- for {
- lifter <- this.lifter(elementTpe)
- iterator <- this.iterator(tpe)(lifter)
- } yield iterator
+ protected def iterated(card: Cardinality, tpe: Type, elementTransform: Tree => Tree = identity)(tree: Tree): Tree = {
+ assert(card != NoDot)
+ def reifyIterable(tree: Tree, n: Cardinality): Tree = {
+ def loop(tree: Tree, n: Cardinality): Tree =
+ if (n == NoDot) elementTransform(tree)
+ else {
+ val x: TermName = c.freshName()
+ val wrapped = reifyIterable(Ident(x), n.pred)
+ val xToWrapped = Function(List(ValDef(Modifiers(PARAM), x, TypeTree(), EmptyTree)), wrapped)
+ Select(Apply(Select(tree, nme.map), List(xToWrapped)), nme.toList)
+ }
+ if (tree.tpe != null && (tree.tpe <:< listTreeType || tree.tpe <:< listListTreeType)) tree
+ else atPos(tree.pos)(loop(tree, n))
}
- def location(tpe: Type) = Some(IterableLocation(cardinality(tpe), TreeLocation(treeType)))
+ reifyIterable(tree, card)
}
}
- /** Hole encapsulates information about splices in quasiquotes.
- * It packs together a cardinality of a splice, a splicee (possibly preprocessed)
- * and the description of the location in Scala syntax where the splicee can be spliced.
- * This is the third pillar of modularity in the quasiquote reifier.
- */
- case class Hole(tree: Tree, location: Location, cardinality: Cardinality)
-
- object Hole {
- def apply(splicee: Tree, holeCard: Cardinality): Hole = {
- if (method == nme.unapply) return new Hole(splicee, UnknownLocation, holeCard)
- val (spliceeCard, elementTpe) = parseCardinality(splicee.tpe)
- def cantSplice() = {
- val holeCardMsg = if (holeCard != NoDot) s" with $holeCard" else ""
- val action = "splice " + splicee.tpe + holeCardMsg
- val suggestCard = holeCard != spliceeCard || holeCard != NoDot
- val spliceeCardMsg = if (holeCard != spliceeCard && spliceeCard != NoDot) s"using $spliceeCard" else "omitting the dots"
- val cardSuggestion = if (suggestCard) spliceeCardMsg else ""
- def canBeLifted(tpe: Type) = HoleType.LiftableType.unapply(tpe).nonEmpty
- val suggestLifting = (holeCard == NoDot || spliceeCard != NoDot) && !(elementTpe <:< treeType) && !canBeLifted(elementTpe)
- val liftedTpe = if (holeCard != NoDot) elementTpe else splicee.tpe
- val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else ""
- val advice = List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ")
- c.abort(splicee.pos, s"Can't $action, consider $advice")
- }
- val holeTpe = splicee.tpe match {
- case _ if holeCard != spliceeCard => cantSplice()
- case HoleType(holeTpe) => holeTpe
- case _ => cantSplice()
- }
- holeTpe.makeHole(splicee)
+ class UnapplyHole(val cardinality: Cardinality, pat: Tree) extends Hole {
+ val (placeholderName, pos, tptopt) = pat match {
+ case Bind(pname, inner @ Bind(_, Typed(Ident(nme.WILDCARD), tpt))) => (pname, inner.pos, Some(tpt))
+ case Bind(pname, inner @ Typed(Ident(nme.WILDCARD), tpt)) => (pname, inner.pos, Some(tpt))
+ case Bind(pname, inner) => (pname, inner.pos, None)
}
+ val treeNoUnlift = Bind(placeholderName, Ident(nme.WILDCARD))
+ lazy val tree =
+ tptopt.map { tpt =>
+ val TypeDef(_, _, _, typedTpt) =
+ try c.typeCheck(TypeDef(NoMods, TypeName("T"), Nil, tpt))
+ catch { case TypecheckException(pos, msg) => c.abort(pos.asInstanceOf[c.Position], msg) }
+ val tpe = typedTpt.tpe
+ val (iterableCard, _) = stripIterable(tpe)
+ if (iterableCard.value < cardinality.value)
+ c.abort(pat.pos, s"Can't extract $tpe with $cardinality, consider using $iterableCard")
+ val (_, strippedTpe) = stripIterable(tpe, limit = Some(cardinality))
+ if (strippedTpe <:< treeType) treeNoUnlift
+ else
+ unlifters.spawn(strippedTpe, cardinality).map {
+ Apply(_, treeNoUnlift :: Nil)
+ }.getOrElse {
+ c.abort(pat.pos, s"Can't find $unliftableType[$strippedTpe], consider providing it")
+ }
+ }.getOrElse { treeNoUnlift }
}
- def parseCardinality(tpe: Type): (Cardinality, Type) = {
- if (tpe != null && isIterableType(tpe)) {
- val (card, innerTpe) = parseCardinality(tpe.typeArguments.head)
- (card.succ, innerTpe)
- } else (NoDot, tpe)
+ /** Full support for unliftable implies that it's possible to interleave
+ * deconstruction with higher cardinality and unlifting of the values.
+ * In particular extraction of List[Tree] as List[T: Unliftable] requires
+ * helper extractors that would do the job: UnliftHelper1[T]. Similarly
+ * List[List[Tree]] needs UnliftHelper2[T].
+ *
+ * See also "unlift list" tests in UnapplyProps.scala
+ */
+ object unlifters {
+ private var records = List.empty[(Type, Cardinality)]
+ // Request an UnliftHelperN[T] where n == card and T == tpe.
+ // If card == 0 then helper is not needed and plain instance
+ // of unliftable is returned.
+ def spawn(tpe: Type, card: Cardinality): Option[Tree] = {
+ val unlifter = inferUnliftable(tpe)
+ if (unlifter == EmptyTree) None
+ else if (card == NoDot) Some(unlifter)
+ else {
+ val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == card }
+ val resIdx = if (idx != -1) idx else { records +:= (tpe, card); records.length - 1}
+ Some(Ident(TermName(nme.QUASIQUOTE_UNLIFT_HELPER + resIdx)))
+ }
+ }
+ // Returns a list of vals that will defined required unlifters
+ def preamble(): List[Tree] =
+ records.zipWithIndex.map { case ((tpe, card), idx) =>
+ val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx)
+ val helperName = card match { case DotDot => nme.UnliftHelper1 case DotDotDot => nme.UnliftHelper2 }
+ val lifter = inferUnliftable(tpe)
+ assert(helperName.isTermName)
+ // q"val $name: $u.build.${helperName.toTypeName} = $u.build.$helperName($lifter)"
+ ValDef(NoMods, name,
+ AppliedTypeTree(Select(Select(u, nme.build), helperName.toTypeName), List(TypeTree(tpe))),
+ Apply(Select(Select(u, nme.build), helperName), lifter :: Nil))
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index 126c14ac81..6e6b617e5c 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -161,7 +161,12 @@ trait Parsers { self: Quasiquotes =>
}
object TermParser extends Parser {
- def entryPoint = { parser => gen.mkTreeOrBlock(parser.templateOrTopStatSeq()) }
+ def entryPoint = { parser =>
+ parser.templateOrTopStatSeq() match {
+ case head :: Nil => Block(Nil, head)
+ case lst => gen.mkTreeOrBlock(lst)
+ }
+ }
}
object TypeParser extends Parser {
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
index 54be9123c7..bdb44ad9a2 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
@@ -13,6 +13,7 @@ import scala.collection.{immutable, mutable}
trait Placeholders { self: Quasiquotes =>
import global._
import Cardinality._
+ import universeTypes._
// Step 1: Transform Scala source with holes into vanilla Scala source
@@ -32,13 +33,17 @@ trait Placeholders { self: Quasiquotes =>
def appendHole(tree: Tree, cardinality: Cardinality) = {
val placeholderName = c.freshName(TermName(nme.QUASIQUOTE_PREFIX + sessionSuffix))
sb.append(placeholderName)
- val holeTree = if (method == nme.unapply) Bind(placeholderName, Ident(nme.WILDCARD)) else tree
- holeMap(placeholderName) = Hole(holeTree, cardinality)
+ val holeTree =
+ if (method != nme.unapply) tree
+ else Bind(placeholderName, tree)
+ holeMap(placeholderName) = Hole(cardinality, holeTree)
}
val iargs = method match {
case nme.apply => args
- case nme.unapply => List.fill(parts.length - 1)(EmptyTree)
+ case nme.unapply =>
+ val (dummy @ Ident(nme.SELECTOR_DUMMY)) :: Nil = args
+ dummy.attachments.get[SubpatternsAttachment].get.patterns
case _ => global.abort("unreachable")
}
@@ -78,9 +83,9 @@ trait Placeholders { self: Quasiquotes =>
trait HolePlaceholder {
def matching: PartialFunction[Any, Name]
- def unapply(scrutinee: Any): Option[(Tree, Location, Cardinality)] = {
+ def unapply(scrutinee: Any): Option[Hole] = {
val name = matching.lift(scrutinee)
- name.flatMap { holeMap.get(_).map { case Hole(repr, loc, card) => (repr, loc, card) } }
+ name.flatMap { holeMap.get(_) }
}
}
@@ -128,44 +133,44 @@ trait Placeholders { self: Quasiquotes =>
}
object SymbolPlaceholder {
- def unapply(scrutinee: Any): Option[Tree] = scrutinee match {
- case Placeholder(tree, SymbolLocation, _) => Some(tree)
+ def unapply(scrutinee: Any): Option[Hole] = scrutinee match {
+ case Placeholder(hole: ApplyHole) if hole.tpe <:< symbolType => Some(hole)
case _ => None
}
}
object CasePlaceholder {
- def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
- case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(tree, location, card))), EmptyTree, EmptyTree) => Some((tree, location, card))
+ def unapply(tree: Tree): Option[Hole] = tree match {
+ case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(hole))), EmptyTree, EmptyTree) => Some(hole)
case _ => None
}
}
object RefineStatPlaceholder {
- def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
- case ValDef(_, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some((tree, location, card))
+ def unapply(tree: Tree): Option[Hole] = tree match {
+ case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some(hole)
case _ => None
}
}
object EarlyDefPlaceholder {
- def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
- case ValDef(_, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some((tree, location, card))
+ def unapply(tree: Tree): Option[Hole] = tree match {
+ case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some(hole)
case _ => None
}
}
object PackageStatPlaceholder {
- def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
- case ValDef(NoMods, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some((tree, location, card))
+ def unapply(tree: Tree): Option[Hole] = tree match {
+ case ValDef(NoMods, Placeholder(hole), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some(hole)
case _ => None
}
}
object ForEnumPlaceholder {
- def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
- case build.SyntacticValFrom(Bind(Placeholder(tree, location, card), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) =>
- Some((tree, location, card))
+ def unapply(tree: Tree): Option[Hole] = tree match {
+ case build.SyntacticValFrom(Bind(Placeholder(hole), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) =>
+ Some(hole)
case _ => None
}
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index b28c85cfc2..6d7aafe266 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -13,7 +13,7 @@ trait Reifiers { self: Quasiquotes =>
import Cardinality._
import universeTypes._
- abstract class Reifier extends {
+ abstract class Reifier(val isReifyingExpressions: Boolean) extends {
val global: self.global.type = self.global
val universe = self.universe
val reifee = EmptyTree
@@ -22,7 +22,6 @@ trait Reifiers { self: Quasiquotes =>
} with ReflectReifier {
lazy val typer = throw new UnsupportedOperationException
- def isReifyingExpressions: Boolean
def isReifyingPatterns: Boolean = !isReifyingExpressions
def action = if (isReifyingExpressions) "splice" else "extract"
def holesHaveTypes = isReifyingExpressions
@@ -94,12 +93,12 @@ trait Reifiers { self: Quasiquotes =>
// cq"$tree if $guard => $succ" :: cq"_ => $fail" :: Nil
CaseDef(tree, guard, succ) :: CaseDef(Ident(nme.WILDCARD), EmptyTree, fail) :: Nil
}
- // q"new { def unapply(tree: $AnyClass) = tree match { case ..$cases } }.unapply(..$args)"
+ // q"new { def unapply(tree: $AnyClass) = { ..${unlifters.preamble()}; tree match { case ..$cases } } }.unapply(..$args)"
Apply(
Select(
SyntacticNew(Nil, Nil, noSelfType, List(
DefDef(NoMods, nme.unapply, Nil, List(List(ValDef(NoMods, nme.tree, TypeTree(AnyClass.toType), EmptyTree))), TypeTree(),
- Match(Ident(nme.tree), cases)))),
+ SyntacticBlock(unlifters.preamble() :+ Match(Ident(nme.tree), cases))))),
nme.unapply),
args)
}
@@ -107,7 +106,7 @@ trait Reifiers { self: Quasiquotes =>
def reifyFillingHoles(tree: Tree): Tree = {
val reified = reifyTree(tree)
holeMap.unused.foreach { hole =>
- c.abort(holeMap(hole).tree.pos, s"Don't know how to $action here")
+ c.abort(holeMap(hole).pos, s"Don't know how to $action here")
}
wrap(reified)
}
@@ -117,21 +116,27 @@ trait Reifiers { self: Quasiquotes =>
reifyTreeSyntactically(tree)
def reifyTreePlaceholder(tree: Tree): Tree = tree match {
- case Placeholder(tree, TreeLocation(_), _) if isReifyingExpressions => tree
- case Placeholder(tree, _, NoDot) if isReifyingPatterns => tree
- case Placeholder(tree, _, card @ Dot()) => c.abort(tree.pos, s"Can't $action with $card here")
+ case Placeholder(hole: ApplyHole) if hole.tpe <:< treeType => hole.tree
+ case Placeholder(Hole(tree, NoDot)) if isReifyingPatterns => tree
+ case Placeholder(hole @ Hole(_, card @ Dot())) => c.abort(hole.pos, s"Can't $action with $card here")
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 RefineStatPlaceholder(tree, _, _) => reifyRefineStat(tree)
- case EarlyDefPlaceholder(tree, _, _) => reifyEarlyDef(tree)
- case PackageStatPlaceholder(tree, _, _) => reifyPackageStat(tree)
- case ForEnumPlaceholder(tree, _, _) => tree
+ case CasePlaceholder(hole) => hole.tree
+ case RefineStatPlaceholder(hole) => reifyRefineStat(hole)
+ case EarlyDefPlaceholder(hole) => reifyEarlyDef(hole)
+ case PackageStatPlaceholder(hole) => reifyPackageStat(hole)
+ // for enumerators are checked not during splicing but during
+ // desugaring of the for loop in SyntacticFor & SyntacticForYield
+ case ForEnumPlaceholder(hole) => hole.tree
case _ => EmptyTree
}
override def reifyTreeSyntactically(tree: Tree) = tree match {
+ case RefTree(qual, SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions =>
+ mirrorBuildCall(nme.RefTree, reify(qual), tree)
+ case This(SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions =>
+ 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) =>
@@ -161,17 +166,24 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticForYield, enums, body)
case SyntacticAssign(lhs, rhs) =>
reifyBuildCall(nme.SyntacticAssign, lhs, rhs)
- case SyntacticApplied(fun, List(args))
- if args.forall { case Placeholder(_, _, DotDotDot) => false case _ => true } =>
- reifyBuildCall(nme.SyntacticApply, fun, args)
case SyntacticApplied(fun, argss) if argss.nonEmpty =>
reifyBuildCall(nme.SyntacticApplied, fun, argss)
case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)
case SyntacticFunction(args, body) =>
reifyBuildCall(nme.SyntacticFunction, args, body)
+ case SyntacticIdent(name, isBackquoted) =>
+ reifyBuildCall(nme.SyntacticIdent, name, isBackquoted)
+ case Block(Nil, Placeholder(Hole(tree, DotDot))) =>
+ mirrorBuildCall(nme.SyntacticBlock, tree)
+ case Block(Nil, other) =>
+ 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
@@ -183,9 +195,10 @@ trait Reifiers { self: Quasiquotes =>
}
override def reifyName(name: Name): Tree = name match {
- case Placeholder(tree, location, _) =>
- if (holesHaveTypes && !(location.tpe <:< nameType)) c.abort(tree.pos, s"$nameType expected but ${location.tpe} found")
- tree
+ case Placeholder(hole: ApplyHole) =>
+ if (!(hole.tpe <:< nameType)) c.abort(hole.pos, s"$nameType expected but ${hole.tpe} found")
+ hole.tree
+ case Placeholder(hole: UnapplyHole) => hole.treeNoUnlift
case FreshName(prefix) if prefix != nme.QUASIQUOTE_NAME_PREFIX =>
def fresh() = c.freshName[TermName](nme.QUASIQUOTE_NAME_PREFIX)
def introduceName() = { val n = fresh(); nameMap(name) += n; n}
@@ -196,15 +209,10 @@ 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)
- case List(Placeholder(_, _, _)) => reifyBuildCall(nme.SyntacticTuple, args)
+ case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole)
+ case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTuple, args)
// in a case we only have one element tuple without
// any cardinality annotations this means that this is
// just an expression wrapped in parentheses
@@ -214,8 +222,8 @@ trait Reifiers { self: Quasiquotes =>
def reifyTupleType(args: List[Tree]) = args match {
case Nil => reify(Select(Ident(nme.scala_), tpnme.Unit))
- case List(hole @ Placeholder(_, _, NoDot)) => reify(hole)
- case List(Placeholder(_, _, _)) => reifyBuildCall(nme.SyntacticTupleType, args)
+ case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole)
+ case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTupleType, args)
case List(other) => reify(other)
case _ => reifyBuildCall(nme.SyntacticTupleType, args)
}
@@ -223,13 +231,18 @@ trait Reifiers { self: Quasiquotes =>
def reifyFunctionType(argtpes: List[Tree], restpe: Tree) =
reifyBuildCall(nme.SyntacticFunctionType, argtpes, restpe)
- def reifyRefineStat(tree: Tree) = tree
+ def reifyConstructionCheck(name: TermName, hole: Hole) = hole match {
+ case _: UnapplyHole => hole.tree
+ case _: ApplyHole => mirrorBuildCall(name, hole.tree)
+ }
+
+ def reifyRefineStat(hole: Hole) = reifyConstructionCheck(nme.mkRefineStat, hole)
- def reifyEarlyDef(tree: Tree) = tree
+ def reifyEarlyDef(hole: Hole) = reifyConstructionCheck(nme.mkEarlyDef, hole)
- def reifyAnnotation(tree: Tree) = tree
+ def reifyAnnotation(hole: Hole) = reifyConstructionCheck(nme.mkAnnotation, hole)
- def reifyPackageStat(tree: Tree) = tree
+ def reifyPackageStat(hole: Hole) = reifyConstructionCheck(nme.mkPackageStat, hole)
/** Splits list into a list of groups where subsequent elements are considered
* similar by the corresponding function.
@@ -262,7 +275,7 @@ trait Reifiers { self: Quasiquotes =>
*
* reifyMultiCardinalityList(lst) {
* // first we define patterns that extract high-cardinality holeMap (currently ..)
- * case Placeholder(CorrespondsTo(tree, tpe)) if tpe <:< iterableTreeType => tree
+ * case Placeholder(IterableType(_, _)) => tree
* } {
* // in the end we define how single elements are reified, typically with default reify call
* reify(_)
@@ -281,21 +294,22 @@ trait Reifiers { self: Quasiquotes =>
* elements.
*/
override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs) {
- case Placeholder(tree, _, DotDot) => tree
- case CasePlaceholder(tree, _, DotDot) => tree
- case RefineStatPlaceholder(tree, _, DotDot) => reifyRefineStat(tree)
- case EarlyDefPlaceholder(tree, _, DotDot) => reifyEarlyDef(tree)
- case PackageStatPlaceholder(tree, _, DotDot) => reifyPackageStat(tree)
- case ForEnumPlaceholder(tree, _, DotDot) => tree
- case List(Placeholder(tree, _, DotDotDot)) => tree
+ case Placeholder(Hole(tree, DotDot)) => tree
+ case CasePlaceholder(Hole(tree, DotDot)) => tree
+ case RefineStatPlaceholder(h @ Hole(_, DotDot)) => reifyRefineStat(h)
+ case EarlyDefPlaceholder(h @ Hole(_, DotDot)) => reifyEarlyDef(h)
+ case PackageStatPlaceholder(h @ Hole(_, DotDot)) => reifyPackageStat(h)
+ case ForEnumPlaceholder(Hole(tree, DotDot)) => tree
+ case List(Placeholder(Hole(tree, DotDotDot))) => tree
} {
reify(_)
}
def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) {
- case AnnotPlaceholder(tree, _, DotDot) => reifyAnnotation(tree)
+ case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h)
} {
- case AnnotPlaceholder(tree, UnknownLocation | TreeLocation(_), NoDot) => reifyAnnotation(tree)
+ case AnnotPlaceholder(h: ApplyHole) if h.tpe <:< treeType => reifyAnnotation(h)
+ case AnnotPlaceholder(h: UnapplyHole) if h.cardinality == NoDot => reifyAnnotation(h)
case other => reify(other)
}
@@ -321,78 +335,55 @@ trait Reifiers { self: Quasiquotes =>
override def mirrorBuildCall(name: TermName, args: Tree*): Tree =
Apply(Select(Select(universe, nme.build), name), args.toList)
- }
-
- class ApplyReifier extends Reifier {
- def isReifyingExpressions = true
- override def reifyTreeSyntactically(tree: Tree): Tree = tree match {
- case RefTree(qual, SymbolPlaceholder(tree)) =>
- mirrorBuildCall(nme.RefTree, reify(qual), tree)
- case This(SymbolPlaceholder(tree)) =>
- mirrorCall(nme.This, tree)
- case _ =>
- super.reifyTreeSyntactically(tree)
- }
+ override def scalaFactoryCall(name: String, args: Tree*): Tree =
+ call("scala." + name, args: _*)
+ }
- override def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match {
- case Nil => mkList(Nil)
- case _ =>
+ class ApplyReifier extends Reifier(isReifyingExpressions = true) {
+ def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree =
+ if (xs.isEmpty) mkList(Nil)
+ else {
def reifyGroup(group: List[T]): Tree = group match {
case List(elem) if fill.isDefinedAt(elem) => fill(elem)
case elems => mkList(elems.map(fallback))
}
val head :: tail = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) }
tail.foldLeft[Tree](reifyGroup(head)) { (tree, lst) => Apply(Select(tree, nme.PLUSPLUS), List(reifyGroup(lst))) }
- }
+ }
override def reifyModifiers(m: Modifiers) =
if (m == NoMods) super.reifyModifiers(m)
else {
val (modsPlaceholders, annots) = m.annotations.partition {
- case ModsPlaceholder(_, _, _) => true
+ case ModsPlaceholder(_) => true
case _ => false
}
val (mods, flags) = modsPlaceholders.map {
- case ModsPlaceholder(tree, location, card) => (tree, location)
- }.partition { case (tree, location) =>
- location match {
- case ModsLocation => true
- case FlagsLocation => false
- case _ => c.abort(tree.pos, s"$flagsType or $modsType expected but ${tree.tpe} found")
- }
+ case ModsPlaceholder(hole: ApplyHole) => hole
+ }.partition { hole =>
+ if (hole.tpe <:< modsType) true
+ else if (hole.tpe <:< flagsType) false
+ else c.abort(hole.pos, s"$flagsType or $modsType expected but ${hole.tpe} found")
}
mods match {
- case (tree, _) :: Nil =>
- if (flags.nonEmpty) c.abort(flags(0)._1.pos, "Can't splice flags together with modifiers, consider merging flags into modifiers")
- if (annots.nonEmpty) c.abort(tree.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers")
- ensureNoExplicitFlags(m, tree.pos)
- tree
- case _ :: (second, _) :: Nil =>
- c.abort(second.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance")
+ case hole :: Nil =>
+ if (flags.nonEmpty) c.abort(flags(0).pos, "Can't splice flags together with modifiers, consider merging flags into modifiers")
+ if (annots.nonEmpty) c.abort(hole.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers")
+ ensureNoExplicitFlags(m, hole.pos)
+ hole.tree
+ case _ :: hole :: Nil =>
+ c.abort(hole.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance")
case _ =>
val baseFlags = reifyFlags(m.flags)
- val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, (tree, _)) => Apply(Select(flag, nme.OR), List(tree)) }
+ val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, hole) => Apply(Select(flag, nme.OR), List(hole.tree)) }
mirrorFactoryCall(nme.Modifiers, reifiedFlags, reify(m.privateWithin), reifyAnnotList(annots))
}
}
- override def reifyRefineStat(tree: Tree) = mirrorBuildCall(nme.mkRefineStat, tree)
-
- override def reifyEarlyDef(tree: Tree) = mirrorBuildCall(nme.mkEarlyDef, tree)
-
- override def reifyAnnotation(tree: Tree) = mirrorBuildCall(nme.mkAnnotation, tree)
-
- override def reifyPackageStat(tree: Tree) = mirrorBuildCall(nme.mkPackageStat, tree)
}
-
- class UnapplyReifier extends Reifier {
- def isReifyingExpressions = false
-
- override def scalaFactoryCall(name: String, args: Tree*): Tree =
- call("scala." + name, args: _*)
-
- override def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree) = xs match {
+ class UnapplyReifier extends Reifier(isReifyingExpressions = false) {
+ def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match {
case init :+ last if fill.isDefinedAt(last) =>
init.foldRight[Tree](fill(last)) { (el, rest) =>
val cons = Select(Select(Select(Ident(nme.scala_), nme.collection), nme.immutable), nme.CONS)
@@ -405,14 +396,14 @@ trait Reifiers { self: Quasiquotes =>
override def reifyModifiers(m: Modifiers) =
if (m == NoMods) super.reifyModifiers(m)
else {
- val mods = m.annotations.collect { case ModsPlaceholder(tree, _, _) => tree }
+ val mods = m.annotations.collect { case ModsPlaceholder(hole: UnapplyHole) => hole }
mods match {
- case tree :: Nil =>
- if (m.annotations.length != 1) c.abort(tree.pos, "Can't extract modifiers together with annotations, consider extracting just modifiers")
- ensureNoExplicitFlags(m, tree.pos)
- tree
- case _ :: second :: rest =>
- c.abort(second.pos, "Can't extract multiple modifiers together, consider extracting a single modifiers instance")
+ case hole :: Nil =>
+ if (m.annotations.length != 1) c.abort(hole.pos, "Can't extract modifiers together with annotations, consider extracting just modifiers")
+ ensureNoExplicitFlags(m, hole.pos)
+ hole.treeNoUnlift
+ case _ :: hole :: _ =>
+ c.abort(hole.pos, "Can't extract multiple modifiers together, consider extracting a single modifiers instance")
case Nil =>
mirrorFactoryCall(nme.Modifiers, reifyFlags(m.flags), reify(m.privateWithin), reifyAnnotList(m.annotations))
}
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index cf05aefe72..9baf3ec179 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -122,19 +122,12 @@ private[reflect] trait BuildUtils { self: Universe =>
def unapply(tree: Tree): Some[(Tree, List[List[Tree]])]
}
- val SyntacticApply: SyntacticApplyExtractor
-
- trait SyntacticApplyExtractor {
- def apply(tree: Tree, args: List[Tree]): Tree
- def unapply(tree: Tree): Some[(Tree, List[Tree])]
- }
-
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])]
}
@@ -142,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])]
}
@@ -152,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])]
}
@@ -160,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])]
}
@@ -182,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])]
}
@@ -196,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)]
}
@@ -204,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)]
}
@@ -252,5 +245,33 @@ private[reflect] trait BuildUtils { self: Universe =>
def apply(enums: List[Tree], body: Tree): Tree
def unapply(tree: Tree): Option[(List[Tree], Tree)]
}
+
+ def UnliftHelper1[T](unliftable: Unliftable[T]): UnliftHelper1[T]
+ trait UnliftHelper1[T] {
+ def unapply(lst: List[Tree]): Option[List[T]]
+ }
+
+ def UnliftHelper2[T](unliftable: Unliftable[T]): UnliftHelper2[T]
+ trait UnliftHelper2[T] {
+ def unapply(lst: List[List[Tree]]): Option[List[List[T]]]
+ }
+
+ 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
+ def unapply(tree: Ident): Option[(Name, Boolean)]
+ }
}
}
diff --git a/src/reflect/scala/reflect/api/Liftable.scala b/src/reflect/scala/reflect/api/Liftable.scala
deleted file mode 100644
index 8f6fe066dd..0000000000
--- a/src/reflect/scala/reflect/api/Liftable.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package scala.reflect
-package api
-
-trait Liftable[T] {
- def apply(universe: api.Universe, value: T): universe.Tree
-}
-
-object Liftable {
- private class LiftableConstant[T] extends Liftable[T] {
- def apply(universe: Universe, value: T): universe.Tree =
- universe.Literal(universe.Constant(value))
- }
-
- implicit lazy val liftByte: Liftable[Byte] = new LiftableConstant[Byte]
- implicit lazy val liftShort: Liftable[Short] = new LiftableConstant[Short]
- implicit lazy val liftChar: Liftable[Char] = new LiftableConstant[Char]
- implicit lazy val liftInt: Liftable[Int] = new LiftableConstant[Int]
- implicit lazy val liftLong: Liftable[Long] = new LiftableConstant[Long]
- implicit lazy val liftFloat: Liftable[Float] = new LiftableConstant[Float]
- implicit lazy val liftDouble: Liftable[Double] = new LiftableConstant[Double]
- implicit lazy val liftBoolean: Liftable[Boolean] = new LiftableConstant[Boolean]
- implicit lazy val liftString: Liftable[String] = new LiftableConstant[String]
- implicit lazy val liftUnit: Liftable[Unit] = new LiftableConstant[Unit]
-
- implicit lazy val liftScalaSymbol: Liftable[scala.Symbol] = new Liftable[scala.Symbol] {
- def apply(universe: Universe, value: scala.Symbol): universe.Tree = {
- import universe._
- val symbol = Select(Ident(TermName("scala")), TermName("Symbol"))
- Apply(symbol, List(Literal(Constant(value.name))))
- }
- }
-}
diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala
index ecea550225..57464459be 100644
--- a/src/reflect/scala/reflect/api/StandardLiftables.scala
+++ b/src/reflect/scala/reflect/api/StandardLiftables.scala
@@ -2,35 +2,225 @@ package scala.reflect
package api
trait StandardLiftables { self: Universe =>
+ import build.{SyntacticTuple, ScalaDot}
- private def requireSameUniverse[T](universe: Universe, tp: String, value: T) =
- require(universe eq self, s"Can't lift $tp ${showRaw(value)} from universe ${showRaw(universe)} using lift$tp defined for ${showRaw(self)}.")
+ trait Liftable[T] {
+ def apply(value: T): Tree
+ }
+
+ object Liftable {
+ def apply[T](f: T => Tree): Liftable[T] =
+ new Liftable[T] { def apply(value: T): Tree = f(value) }
+
+ private def lift[T: Liftable](value: T): Tree = implicitly[Liftable[T]].apply(value)
+ private def selectScala(names: Name*) = names.tail.foldLeft(ScalaDot(names.head)) { Select(_, _) }
+ private def callScala(names: Name*)(args: List[Tree]) = Apply(selectScala(names: _*), args)
+ private def callCollection(name: Name)(args: List[Tree]) = callScala(nme.collection, nme.immutable, name)(args)
+ private def liftAsLiteral[T]: Liftable[T] = Liftable { v => Literal(Constant(v)) }
+
+ implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftBoolean: Liftable[Boolean] = liftAsLiteral[Boolean]
+ implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit]
+ implicit def liftString: Liftable[String] = liftAsLiteral[String]
- implicit def liftExpr[T <: Expr[_]]: Liftable[T] = new Liftable[T] {
- def apply(universe: Universe, value: T): universe.Tree = {
- requireSameUniverse(universe, "Expr", value)
- value.tree.asInstanceOf[universe.Tree]
+ implicit def liftScalaSymbol: Liftable[scala.Symbol] = Liftable { v =>
+ callScala(nme.Symbol)(Literal(Constant(v.name)) :: Nil)
}
- }
- implicit def liftType[T <: Type]: Liftable[T] = new Liftable[T] {
- def apply(universe: Universe, value: T): universe.Tree = {
- requireSameUniverse(universe, "Type", value)
- universe.TypeTree(value.asInstanceOf[universe.Type])
+ implicit def liftName[T <: Name]: Liftable[T] = Liftable { name => Ident(name) }
+ implicit def liftExpr[T <: Expr[_]]: Liftable[T] = Liftable { expr => expr.tree }
+ implicit def liftType[T <: Type]: Liftable[T] = Liftable { tpe => TypeTree(tpe) }
+ implicit def liftTypeTag[T <: WeakTypeTag[_]]: Liftable[T] = Liftable { ttag => TypeTree(ttag.tpe) }
+ implicit def liftConstant[T <: Constant]: Liftable[T] = Liftable { const => Literal(const) }
+
+ implicit def liftArray[T: Liftable]: Liftable[Array[T]] = Liftable { arr => callScala(nme.Array)(arr.map(lift(_)).toList) }
+ implicit def liftVector[T: Liftable]: Liftable[Vector[T]] = Liftable { vect => callCollection(nme.Vector)(vect.map(lift(_)).toList) }
+ implicit def liftList[T: Liftable]: Liftable[List[T]] = Liftable { lst => callCollection(nme.List)(lst.map(lift(_))) }
+ implicit def liftMap[K: Liftable, V: Liftable]: Liftable[Map[K, V]] = Liftable { m => callCollection(nme.Map)(m.toList.map(lift(_))) }
+ implicit def liftSet[T: Liftable]: Liftable[Set[T]] = Liftable { s => callCollection(nme.Set)(s.toList.map(lift(_))) }
+
+ implicit def liftOption[T: Liftable]: Liftable[Option[T]] = Liftable {
+ case Some(v) => callScala(nme.Some)(lift(v) :: Nil)
+ case None => selectScala(nme.None)
+ }
+ implicit def liftEither[L: Liftable, R: Liftable]: Liftable[Either[L, R]] = Liftable {
+ case Left(l) => callScala(nme.util, nme.Left)(lift(l) :: Nil)
+ case Right(r) => callScala(nme.util, nme.Right)(lift(r) :: Nil)
}
- }
- implicit def liftTypeTag[T <: WeakTypeTag[_]]: Liftable[T] = new Liftable[T] {
- def apply(universe: Universe, value: T): universe.Tree = {
- requireSameUniverse(universe, "TypeTag", value)
- universe.TypeTree(value.asInstanceOf[universe.WeakTypeTag[_]].tpe)
+ implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: Nil)
+ }
+ implicit def liftTuple2[T1, T2](implicit liftT1: Liftable[T1], liftT2: Liftable[T2]): Liftable[Tuple2[T1, T2]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: Nil)
+ }
+ implicit def liftTuple3[T1, T2, T3](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3]): Liftable[Tuple3[T1, T2, T3]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: Nil)
+ }
+ implicit def liftTuple4[T1, T2, T3, T4](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4]): Liftable[Tuple4[T1, T2, T3, T4]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: Nil)
+ }
+ implicit def liftTuple5[T1, T2, T3, T4, T5](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5]): Liftable[Tuple5[T1, T2, T3, T4, T5]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: Nil)
+ }
+ implicit def liftTuple6[T1, T2, T3, T4, T5, T6](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6]): Liftable[Tuple6[T1, T2, T3, T4, T5, T6]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: Nil)
+ }
+ implicit def liftTuple7[T1, T2, T3, T4, T5, T6, T7](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7]): Liftable[Tuple7[T1, T2, T3, T4, T5, T6, T7]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: Nil)
+ }
+ implicit def liftTuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8]): Liftable[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: Nil)
+ }
+ implicit def liftTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9]): Liftable[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: Nil)
+ }
+ implicit def liftTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10]): Liftable[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: Nil)
+ }
+ implicit def liftTuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11]): Liftable[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: Nil)
+ }
+ implicit def liftTuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12]): Liftable[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: Nil)
+ }
+ implicit def liftTuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13]): Liftable[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: Nil)
+ }
+ implicit def liftTuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14]): Liftable[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: Nil)
+ }
+ implicit def liftTuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15]): Liftable[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: Nil)
+ }
+ implicit def liftTuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16]): Liftable[Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: Nil)
+ }
+ implicit def liftTuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17]): Liftable[Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: Nil)
+ }
+ implicit def liftTuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18]): Liftable[Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: Nil)
+ }
+ implicit def liftTuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19]): Liftable[Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: Nil)
+ }
+ implicit def liftTuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20]): Liftable[Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: Nil)
+ }
+ implicit def liftTuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20], liftT21: Liftable[T21]): Liftable[Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: liftT21(t._21) :: Nil)
+ }
+ implicit def liftTuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20], liftT21: Liftable[T21], liftT22: Liftable[T22]): Liftable[Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]] = Liftable { t =>
+ SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: liftT21(t._21) :: liftT22(t._22) :: Nil)
}
}
- implicit def liftConstant[T <: Constant]: Liftable[T] = new Liftable[T] {
- def apply(universe: Universe, value: T): universe.Tree = {
- requireSameUniverse(universe, "Constant", value)
- universe.Literal(value.asInstanceOf[universe.Constant])
+ trait Unliftable[T] {
+ def unapply(tree: Tree): Option[T]
+ }
+
+ object Unliftable {
+ def apply[T](pf: PartialFunction[Tree, T]): Unliftable[T] = new Unliftable[T] {
+ def unapply(value: Tree): Option[T] = pf.lift(value)
+ }
+
+ private def unliftPrimitive[Unboxed: ClassTag, Boxed: ClassTag] = Unliftable[Unboxed] {
+ case Literal(Constant(value))
+ if value.getClass == implicitly[ClassTag[Boxed]].runtimeClass
+ || value.getClass == implicitly[ClassTag[Unboxed]].runtimeClass =>
+ value.asInstanceOf[Unboxed]
+ }
+ implicit def unliftByte: Unliftable[Byte] = unliftPrimitive[Byte, java.lang.Byte]
+ implicit def unliftShort: Unliftable[Short] = unliftPrimitive[Short, java.lang.Short]
+ implicit def unliftChar: Unliftable[Char] = unliftPrimitive[Char, java.lang.Character]
+ implicit def unliftInt: Unliftable[Int] = unliftPrimitive[Int, java.lang.Integer]
+ implicit def unliftLong: Unliftable[Long] = unliftPrimitive[Long, java.lang.Long]
+ implicit def unliftFloat: Unliftable[Float] = unliftPrimitive[Float, java.lang.Float]
+ implicit def unliftDouble: Unliftable[Double] = unliftPrimitive[Double, java.lang.Double]
+ implicit def unliftBoolean: Unliftable[Boolean] = unliftPrimitive[Boolean, java.lang.Boolean]
+ implicit def unliftUnit: Unliftable[Unit] = unliftPrimitive[Unit, scala.runtime.BoxedUnit]
+ implicit def unliftString: Unliftable[String] = Unliftable { case Literal(Constant(s: String)) => s }
+
+ implicit def unliftScalaSymbol: Unliftable[scala.Symbol] = Unliftable {
+ case Apply(ScalaDot(nme.Symbol), List(Literal(Constant(name: String)))) => scala.Symbol(name)
+ }
+
+ implicit def unliftName[T <: Name : ClassTag]: Unliftable[T] = Unliftable[T] { case Ident(name: T) => name; case Bind(name: T, Ident(nme.WILDCARD)) => name}
+ implicit def unliftType: Unliftable[Type] = Unliftable[Type] { case tt: TypeTree if tt.tpe != null => tt.tpe }
+ implicit def unliftConstant: Unliftable[Constant] = Unliftable[Constant] { case Literal(const) => const }
+
+ implicit def unliftTuple1[T1](implicit UnliftT1: Unliftable[T1]): Unliftable[Tuple1[T1]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: Nil) => Tuple1(v1)
+ }
+ implicit def unliftTuple2[T1, T2](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2]): Unliftable[Tuple2[T1, T2]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: Nil) => Tuple2(v1, v2)
+ }
+ implicit def unliftTuple3[T1, T2, T3](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3]): Unliftable[Tuple3[T1, T2, T3]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: Nil) => Tuple3(v1, v2, v3)
+ }
+ implicit def unliftTuple4[T1, T2, T3, T4](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4]): Unliftable[Tuple4[T1, T2, T3, T4]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: Nil) => Tuple4(v1, v2, v3, v4)
+ }
+ implicit def unliftTuple5[T1, T2, T3, T4, T5](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5]): Unliftable[Tuple5[T1, T2, T3, T4, T5]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: Nil) => Tuple5(v1, v2, v3, v4, v5)
+ }
+ implicit def unliftTuple6[T1, T2, T3, T4, T5, T6](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6]): Unliftable[Tuple6[T1, T2, T3, T4, T5, T6]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: Nil) => Tuple6(v1, v2, v3, v4, v5, v6)
+ }
+ implicit def unliftTuple7[T1, T2, T3, T4, T5, T6, T7](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7]): Unliftable[Tuple7[T1, T2, T3, T4, T5, T6, T7]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: Nil) => Tuple7(v1, v2, v3, v4, v5, v6, v7)
+ }
+ implicit def unliftTuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8]): Unliftable[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: Nil) => Tuple8(v1, v2, v3, v4, v5, v6, v7, v8)
+ }
+ implicit def unliftTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9]): Unliftable[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: Nil) => Tuple9(v1, v2, v3, v4, v5, v6, v7, v8, v9)
+ }
+ implicit def unliftTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10]): Unliftable[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: Nil) => Tuple10(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)
+ }
+ implicit def unliftTuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11]): Unliftable[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: Nil) => Tuple11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
+ }
+ implicit def unliftTuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12]): Unliftable[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: Nil) => Tuple12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
+ }
+ implicit def unliftTuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13]): Unliftable[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: Nil) => Tuple13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
+ }
+ implicit def unliftTuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14]): Unliftable[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: Nil) => Tuple14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
+ }
+ implicit def unliftTuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15]): Unliftable[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: Nil) => Tuple15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
+ }
+ implicit def unliftTuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16]): Unliftable[Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: Nil) => Tuple16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
+ }
+ implicit def unliftTuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17]): Unliftable[Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: Nil) => Tuple17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
+ }
+ implicit def unliftTuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18]): Unliftable[Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: Nil) => Tuple18(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
+ }
+ implicit def unliftTuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19]): Unliftable[Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: Nil) => Tuple19(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
+ }
+ implicit def unliftTuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20]): Unliftable[Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: Nil) => Tuple20(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
+ }
+ implicit def unliftTuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20], UnliftT21: Unliftable[T21]): Unliftable[Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: UnliftT21(v21) :: Nil) => Tuple21(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
+ }
+ implicit def unliftTuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20], UnliftT21: Unliftable[T21], UnliftT22: Unliftable[T22]): Unliftable[Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]] = Unliftable {
+ case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: UnliftT21(v21) :: UnliftT22(v22) :: Nil) => Tuple22(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
}
}
}
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index aec5f19fa0..4ea6ddc7f8 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -96,6 +96,20 @@ trait StandardNames {
* of non-private vals and vars are renamed using `LOCAL_SUFFIX_STRING`.
*/
val LOCAL_SUFFIX_STRING: String
+
+ protected[reflect] val Array: NameType
+ protected[reflect] val collection: NameType
+ protected[reflect] val immutable: NameType
+ protected[reflect] val Left: NameType
+ protected[reflect] val List: NameType
+ protected[reflect] val Map: NameType
+ protected[reflect] val None: NameType
+ protected[reflect] val Right: NameType
+ protected[reflect] val Set: NameType
+ protected[reflect] val Some: NameType
+ protected[reflect] val Symbol: NameType
+ protected[reflect] val util: NameType
+ protected[reflect] val Vector: NameType
}
/** Defines standard type names that can be accessed via the [[tpnme]] member.
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 8fc1869dd2..13c2268227 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] =
@@ -159,18 +163,11 @@ trait BuildUtils { self: SymbolTable =>
def apply(tree: Tree, argss: List[List[Tree]]): Tree =
argss.foldLeft(tree) { (f, args) => Apply(f, args.map(treeInfo.assignmentToMaybeNamedArg)) }
- def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = {
- val treeInfo.Applied(fun, targs, argss) = tree
- Some((SyntacticTypeApplied(fun, targs), argss))
- }
- }
-
- object SyntacticApply extends SyntacticApplyExtractor {
- def apply(tree: Tree, args: List[Tree]): Tree = SyntacticApplied(tree, List(args))
-
- def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match {
- case Apply(fun, args) => Some((fun, args))
- case other => Some((other, Nil))
+ def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = tree match {
+ case UnApply(treeInfo.Unapplied(Select(fun, nme.unapply)), pats) =>
+ Some((fun, pats :: Nil))
+ case treeInfo.Applied(fun, targs, argss) =>
+ Some((SyntacticTypeApplied(fun, targs), argss))
}
}
@@ -215,24 +212,41 @@ trait BuildUtils { self: SymbolTable =>
case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail
case other => other
}
- // undo flag modifications by mergeing flag info from constructor args and fieldDefs
+ // undo flag modifications by merging flag info from constructor args and fieldDefs
val modsMap = fieldDefs.map { case ValDef(mods, name, _, _) => name -> mods }.toMap
- val vparamss = mmap(vparamssRestoredImplicits) { vd =>
- val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM)
- atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs))
+ def ctorArgsCorrespondToFields = vparamssRestoredImplicits.flatten.forall { vd => modsMap.contains(vd.name) }
+ if (!ctorArgsCorrespondToFields) None
+ else {
+ val vparamss = mmap(vparamssRestoredImplicits) { vd =>
+ val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM)
+ atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs))
+ }
+ result(ctorMods, vparamss, edefs, body)
}
- result(ctorMods, vparamss, edefs, body)
}
}
}
}
+ 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 {
@@ -241,7 +255,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)
}
@@ -256,10 +271,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)
}
@@ -274,8 +289,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)) =>
@@ -287,7 +302,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 {
@@ -377,11 +392,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 parameters with default values")
Function(params0, body)
}
@@ -392,8 +405,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) =>
@@ -407,7 +420,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 {
@@ -442,6 +455,20 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ def UnliftHelper1[T](unliftable: Unliftable[T]) = new UnliftHelper1[T] {
+ def unapply(lst: List[Tree]): Option[List[T]] = {
+ val unlifted = lst.flatMap { unliftable.unapply(_) }
+ if (unlifted.length == lst.length) Some(unlifted) else None
+ }
+ }
+
+ def UnliftHelper2[T](unliftable: Unliftable[T]) = new UnliftHelper2[T] {
+ def unapply(lst: List[List[Tree]]): Option[List[List[T]]] = {
+ val unlifted = lst.map { l => l.flatMap { unliftable.unapply(_) } }
+ if (unlifted.flatten.length == lst.flatten.length) Some(unlifted) else None
+ }
+ }
+
object SyntacticValFrom extends SyntacticValFromExtractor {
def apply(pat: Tree, rhs: Tree): Tree = gen.ValFrom(pat, gen.mkCheckIfRefutable(pat, rhs))
def unapply(tree: Tree): Option[(Tree, Tree)] = tree match {
@@ -672,6 +699,30 @@ trait BuildUtils { self: SymbolTable =>
case annottee => Some(annottee)
}
}
+
+ 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)
+ if (isBackquoted) id updateAttachment BackquotedIdentifierAttachment
+ id
+ }
+ def unapply(tree: Ident): Some[(Name, Boolean)] = Some((tree.name, tree.hasAttachment[BackquotedIdentifierAttachment.type]))
+ }
}
val build: BuildImpl = new BuildImpl
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 19f06894c8..1fe6f249b8 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -481,7 +481,6 @@ trait Definitions extends api.StandardDefinitions {
lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful
lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful
- lazy val LiftableClass = getClassIfDefined("scala.reflect.api.Liftable") // defined in scala-reflect.jar, so we need to be careful
lazy val BlackboxMacroClass = getClassIfDefined("scala.reflect.macros.BlackboxMacro") // defined in scala-reflect.jar, so we need to be careful
def BlackboxMacroContextValue = BlackboxMacroClass.map(sym => getMemberValue(sym, nme.c))
@@ -1371,6 +1370,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val symbolType = universeMemberType(tpnme.Symbol)
lazy val treeType = universeMemberType(tpnme.Tree)
lazy val caseDefType = universeMemberType(tpnme.CaseDef)
+ lazy val liftableType = universeMemberType(tpnme.Liftable)
+ lazy val unliftableType = universeMemberType(tpnme.Unliftable)
lazy val iterableTreeType = appliedType(IterableClass, treeType)
lazy val listTreeType = appliedType(ListClass, treeType)
lazy val listListTreeType = appliedType(ListClass, listTreeType)
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 46f241643b..09fd996f39 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -35,4 +35,7 @@ trait StdAttachments {
/** Identifies trees are either result or intermidiate value of for loop desugaring.
*/
case object ForAttachment extends PlainAttachment
+
+ /** Untyped list of subpatterns attached to selector dummy. */
+ case class SubpatternsAttachment(patterns: List[Tree])
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index c26e815df1..5ad2b15e8c 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -124,8 +124,15 @@ trait StdNames {
final val AnyRef: NameType = "AnyRef"
final val Array: NameType = "Array"
final val List: NameType = "List"
+ final val Left: NameType = "Left"
+ final val Right: NameType = "Right"
+ final val Vector: NameType = "Vector"
final val Seq: NameType = "Seq"
+ final val Set: NameType = "Set"
+ final val Some: NameType = "Some"
final val Symbol: NameType = "Symbol"
+ final val Map: NameType = "Map"
+ final val None: NameType = "None"
final val WeakTypeTag: NameType = "WeakTypeTag"
final val TypeTag : NameType = "TypeTag"
final val Expr: NameType = "Expr"
@@ -239,6 +246,8 @@ trait StdNames {
final val Enum: NameType = "Enum"
final val Group: NameType = "Group"
final val implicitNotFound: NameType = "implicitNotFound"
+ final val Liftable: NameType = "Liftable"
+ final val Unliftable: NameType = "Unliftable"
final val Name: NameType = "Name"
final val Tree: NameType = "Tree"
final val TermName: NameType = "TermName"
@@ -328,6 +337,7 @@ trait StdNames {
val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_CASE: NameType = "$quasiquote$case$"
val QUASIQUOTE_FOR_ENUM: NameType = "$quasiquote$for$enum$"
+ val QUASIQUOTE_UNLIFT_HELPER: String = "$quasiquote$unlift$helper$"
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: NameType = "$outer"
@@ -588,7 +598,6 @@ trait StdNames {
val Select: NameType = "Select"
val SelectFromTypeTree: NameType = "SelectFromTypeTree"
val SyntacticApplied: NameType = "SyntacticApplied"
- val SyntacticApply: NameType = "SyntacticApply"
val SyntacticAssign: NameType = "SyntacticAssign"
val SyntacticBlock: NameType = "SyntacticBlock"
val SyntacticClassDef: NameType = "SyntacticClassDef"
@@ -598,10 +607,13 @@ trait StdNames {
val SyntacticForYield: NameType = "SyntacticForYield"
val SyntacticFunction: NameType = "SyntacticFunction"
val SyntacticFunctionType: NameType = "SyntacticFunctionType"
- val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
- val SyntacticObjectDef: NameType = "SyntacticObjectDef"
+ 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"
@@ -751,10 +763,13 @@ trait StdNames {
val typedProductIterator: NameType = "typedProductIterator"
val TypeName: NameType = "TypeName"
val typeTagToManifest: NameType = "typeTagToManifest"
+ val util: NameType = "util"
val unapply: NameType = "unapply"
val unapplySeq: NameType = "unapplySeq"
val unbox: NameType = "unbox"
val universe: NameType = "universe"
+ val UnliftHelper1: NameType = "UnliftHelper1"
+ val UnliftHelper2: NameType = "UnliftHelper2"
val update: NameType = "update"
val updateDynamic: NameType = "updateDynamic"
val value: NameType = "value"
@@ -784,7 +799,7 @@ trait StdNames {
final val STAR : NameType = "*"
final val TILDE: NameType = "~"
- final val isUnary: Set[Name] = Set(MINUS, PLUS, TILDE, BANG)
+ final val isUnary: Set[Name] = scala.collection.immutable.Set(MINUS, PLUS, TILDE, BANG)
}
// value-conversion methods
@@ -837,8 +852,8 @@ trait StdNames {
val UNARY_! = encode("unary_!")
// Grouped here so Cleanup knows what tests to perform.
- val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE)
- val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames
+ val CommonOpNames = scala.collection.immutable.Set[Name](OR, XOR, AND, EQ, NE)
+ val BooleanOpNames = scala.collection.immutable.Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames
val add: NameType = "add"
val complement: NameType = "complement"
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index e483fa6ba8..99e6ae633f 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3392,11 +3392,14 @@ trait Types
/** Rebind symbol `sym` to an overriding member in type `pre`. */
private def rebind(pre: Type, sym: Symbol): Symbol = {
if (!sym.isOverridableMember || sym.owner == pre.typeSymbol) sym
- else pre.nonPrivateMember(sym.name).suchThat(sym =>
- // SI-7928 `isModuleNotMethod` is here to avoid crashing with overloaded module accessor and module symbols
- // after refchecks eliminates a ModuleDef that implements and interface.
- sym.isType || (!sym.isModuleNotMethod && sym.isStable && !sym.hasVolatileType)
- ) orElse sym
+ else pre.nonPrivateMember(sym.name).suchThat { sym =>
+ // SI-7928 `isModuleNotMethod` is here to avoid crashing with spuriously "overloaded" module accessor and module symbols.
+ // These appear after refchecks eliminates ModuleDefs that implement an interface.
+ // Here, we exclude the module symbol, which allows us to bind to the accessor.
+ // SI-8054 We must only do this after refchecks, otherwise we exclude the module symbol which does not yet have an accessor!
+ val isModuleWithAccessor = phase.refChecked && sym.isModuleNotMethod
+ sym.isType || (!isModuleWithAccessor && sym.isStable && !sym.hasVolatileType)
+ } orElse sym
}
/** Convert a `super` prefix to a this-type if `sym` is abstract or final. */
diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala
index 14f349f502..efb8126ff0 100644
--- a/src/reflect/scala/reflect/internal/util/StringOps.scala
+++ b/src/reflect/scala/reflect/internal/util/StringOps.scala
@@ -23,12 +23,16 @@ trait StringOps {
def oempty(xs: String*) = xs filterNot (x => x == null || x == "")
def ojoin(xs: String*): String = oempty(xs: _*) mkString " "
def longestCommonPrefix(xs: List[String]): String = xs match {
- case Nil => ""
- case xs if xs contains "" => ""
- case x :: xs =>
- val ch = x charAt 0
- if (xs exists (_.head != ch)) ""
- else "" + ch + longestCommonPrefix(xs map (_ substring 1))
+ case Nil => ""
+ case w :: Nil => w
+ case _ =>
+ def lcp(ss: List[String]): String = {
+ val w :: ws = ss
+ if (w == "") ""
+ else if (ws exists (s => s == "" || (s charAt 0) != (w charAt 0))) ""
+ else w.substring(0, 1) + lcp(ss map (_ substring 1))
+ }
+ lcp(xs)
}
/** Like String#trim, but trailing whitespace only.
*/
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 344f7682c1..0f41506382 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -57,6 +57,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.CompoundTypeTreeOriginalAttachment
this.BackquotedIdentifierAttachment
this.ForAttachment
+ this.SubpatternsAttachment
this.noPrint
this.typeDebug
// inaccessible: this.maxFree
@@ -204,6 +205,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.TermName
this.TypeName
this.BooleanFlag
+ this.Liftable
+ this.Unliftable
this.WeakTypeTag
this.TypeTag
this.Expr
@@ -315,7 +318,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.MirrorClass
definitions.TypeCreatorClass
definitions.TreeCreatorClass
- definitions.LiftableClass
definitions.BlackboxMacroClass
definitions.WhiteboxMacroClass
definitions.BlackboxContextClass
diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
index 1b3d60d41a..53c7c82e89 100644
--- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -294,7 +294,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
// This is jline's entry point for completion.
override def complete(buf: String, cursor: Int): Candidates = {
verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
- repldbg("\ncomplete(%s, %d) last = (%s, %d), verbosity: %s".format(buf, cursor, lastBuf, lastCursor, verbosity))
+ repldbg(f"%ncomplete($buf, $cursor%d) last = ($lastBuf, $lastCursor%d), verbosity: $verbosity")
// we don't try lower priority completions unless higher ones return no results.
def tryCompletion(p: Parsed, completionFunction: Parsed => List[String]): Option[Candidates] = {
@@ -307,8 +307,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
val advance = longestCommonPrefix(winners)
lastCursor = p.position + advance.length
lastBuf = (buf take p.position) + advance
- repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format(
- p, lastBuf, lastCursor, p.position))
+ repldbg(s"tryCompletion($p, _) lastBuf = $lastBuf, lastCursor = $lastCursor, p.position = ${p.position}")
p.position
}
diff --git a/test/files/instrumented/InstrumentationTest.check b/test/files/instrumented/InstrumentationTest.check
index 0c570fa12c..c82d16bd34 100644
--- a/test/files/instrumented/InstrumentationTest.check
+++ b/test/files/instrumented/InstrumentationTest.check
@@ -1,3 +1,4 @@
+#partest !avian
true
Method call statistics:
1 Foo1.<init>()V
@@ -8,3 +9,6 @@ Method call statistics:
1 scala/Predef$.println(Ljava/lang/Object;)V
1 scala/io/AnsiColor$class.$init$(Lscala/io/AnsiColor;)V
1 scala/runtime/BoxesRunTime.boxToBoolean(Z)Ljava/lang/Boolean;
+#partest avian
+!!!TEST SKIPPED!!!
+Instrumentation is not supported on Avian.
diff --git a/test/files/instrumented/InstrumentationTest.scala b/test/files/instrumented/InstrumentationTest.scala
index 0e53f80857..458fd4974b 100644
--- a/test/files/instrumented/InstrumentationTest.scala
+++ b/test/files/instrumented/InstrumentationTest.scala
@@ -15,16 +15,21 @@ package instrumented {
/** Tests if instrumentation itself works correctly */
object Test {
def main(args: Array[String]) {
- // force predef initialization before profiling
- Predef
- startProfiling()
- val foo1 = new Foo1
- foo1.someMethod
- val foo2 = new instrumented.Foo2
- foo2.someMethod
- // should box the boolean
- println(true)
- stopProfiling()
- printStatistics()
+ if (scala.tools.partest.utils.Properties.isAvian) {
+ println("!!!TEST SKIPPED!!!")
+ println("Instrumentation is not supported on Avian.")
+ } else {
+ // force predef initialization before profiling
+ Predef
+ startProfiling()
+ val foo1 = new Foo1
+ foo1.someMethod
+ val foo2 = new instrumented.Foo2
+ foo2.someMethod
+ // should box the boolean
+ println(true)
+ stopProfiling()
+ printStatistics()
+ }
}
}
diff --git a/test/files/instrumented/inline-in-constructors.check b/test/files/instrumented/inline-in-constructors.check
index c6c9ae4e15..b58c1d77d5 100644
--- a/test/files/instrumented/inline-in-constructors.check
+++ b/test/files/instrumented/inline-in-constructors.check
@@ -1,3 +1,7 @@
+#partest !avian
Method call statistics:
1 instrumented/Bar.<init>(Z)V
1 instrumented/Foo.<init>(I)V
+#partest avian
+!!!TEST SKIPPED!!!
+Instrumentation is not supported on Avian.
diff --git a/test/files/instrumented/inline-in-constructors/test_3.scala b/test/files/instrumented/inline-in-constructors/test_3.scala
index c4d4cc5f37..949e9945e7 100644
--- a/test/files/instrumented/inline-in-constructors/test_3.scala
+++ b/test/files/instrumented/inline-in-constructors/test_3.scala
@@ -3,13 +3,18 @@ import instrumented._
object Test {
def main(args: Array[String]) {
- // force predef initialization before profiling
- Predef
- MyPredef
- startProfiling()
- val a = new Foo(2)
- val b = new Bar(true)
- stopProfiling()
- printStatistics()
+ if (scala.tools.partest.utils.Properties.isAvian) {
+ println("!!!TEST SKIPPED!!!")
+ println("Instrumentation is not supported on Avian.")
+ } else {
+ // force predef initialization before profiling
+ Predef
+ MyPredef
+ startProfiling()
+ val a = new Foo(2)
+ val b = new Bar(true)
+ stopProfiling()
+ printStatistics()
+ }
}
}
diff --git a/test/files/neg/quasiquotes-unliftable-not-found.check b/test/files/neg/quasiquotes-unliftable-not-found.check
new file mode 100644
index 0000000000..5594aa1b15
--- /dev/null
+++ b/test/files/neg/quasiquotes-unliftable-not-found.check
@@ -0,0 +1,4 @@
+quasiquotes-unliftable-not-found.scala:4: error: Can't find reflect.runtime.universe.Unliftable[Test.C], consider providing it
+ val q"${c: C}" = q"()"
+ ^
+one error found
diff --git a/test/files/neg/quasiquotes-unliftable-not-found.scala b/test/files/neg/quasiquotes-unliftable-not-found.scala
new file mode 100644
index 0000000000..6a5efae43b
--- /dev/null
+++ b/test/files/neg/quasiquotes-unliftable-not-found.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ class C
+ val q"${c: C}" = q"()"
+} \ No newline at end of file
diff --git a/test/files/neg/si7980.check b/test/files/neg/si7980.check
new file mode 100644
index 0000000000..b085cabf1d
--- /dev/null
+++ b/test/files/neg/si7980.check
@@ -0,0 +1,4 @@
+si7980.scala:7: error: Can't splice Nothing, bottom type values often indicate programmer mistake
+ println(q"class ${Name(X)} { }")
+ ^
+one error found
diff --git a/test/files/neg/si7980.scala b/test/files/neg/si7980.scala
new file mode 100644
index 0000000000..b21907de54
--- /dev/null
+++ b/test/files/neg/si7980.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ def Name[T:TypeTag](name:String): T = implicitly[TypeTag[T]] match {
+ case t => newTypeName(name).asInstanceOf[T]
+ }
+ val X = "ASDF"
+ println(q"class ${Name(X)} { }")
+}
diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check
index cd867289c3..029c8057c3 100755
--- a/test/files/neg/t6446-missing.check
+++ b/test/files/neg/t6446-missing.check
@@ -1,4 +1,4 @@
-Warning: class not found: t6446.Ploogin
+Error: unable to load class: t6446.Ploogin
phase name id description
---------- -- -----------
parser 1 parse source into ASTs, perform simple desugaring
diff --git a/test/files/pos/macro-implicit-invalidate-on-error.scala b/test/files/pos/macro-implicit-invalidate-on-error.scala
index 22cd2d34b4..f9756d965f 100644
--- a/test/files/pos/macro-implicit-invalidate-on-error.scala
+++ b/test/files/pos/macro-implicit-invalidate-on-error.scala
@@ -1,23 +1,20 @@
-package scala.reflect
-package api
-
import scala.language.experimental.macros
import scala.reflect.macros.Context
-trait Liftable[T] {
- def apply(universe: api.Universe, value: T): universe.Tree
+trait LegacyLiftable[T] {
+ def apply(universe: scala.reflect.api.Universe, value: T): universe.Tree
}
-object Liftable {
- implicit def liftCaseClass[T <: Product]: Liftable[T] = macro liftCaseClassImpl[T]
+object LegacyLiftable {
+ implicit def liftCaseClass[T <: Product]: LegacyLiftable[T] = macro liftCaseClassImpl[T]
- def liftCaseClassImpl[T: c.WeakTypeTag](c: Context): c.Expr[Liftable[T]] = {
+ def liftCaseClassImpl[T: c.WeakTypeTag](c: Context): c.Expr[LegacyLiftable[T]] = {
import c.universe._
val tpe = weakTypeOf[T]
if (!tpe.typeSymbol.asClass.isCaseClass) c.abort(c.enclosingPosition, "denied")
val p = List(q"Literal(Constant(1))")
- c.Expr[Liftable[T]] { q"""
- new scala.reflect.api.Liftable[$tpe] {
+ c.Expr[LegacyLiftable[T]] { q"""
+ new LegacyLiftable[$tpe] {
def apply(universe: scala.reflect.api.Universe, value: $tpe): universe.Tree = {
import universe._
Apply(Select(Ident(TermName("C")), TermName("apply")), List(..$p))
diff --git a/test/files/pos/t8054.scala b/test/files/pos/t8054.scala
new file mode 100644
index 0000000000..a7bb44b1ed
--- /dev/null
+++ b/test/files/pos/t8054.scala
@@ -0,0 +1,31 @@
+trait D {
+ trait Manifest {
+ class Entry
+ }
+
+ val M: Manifest
+
+ def m: M.Entry = ???
+}
+
+object D1 extends D {
+ object M extends Manifest
+}
+
+object D2 extends D {
+ val M: Manifest = ???
+}
+
+object Hello {
+
+ def main(args: Array[String]) {
+ // 2.10.3 - ok
+ // 2.11.0-M7 - type mismatch; found : Seq[DB1.MANIFEST.Entry]
+ // required: Seq[DB1.MANIFEST.Entry]
+ val t1: D1.M.Entry = D1.m
+
+ // 2.10.3 - ok
+ // 2.11.0-M7 - ok
+ val t2: D2.M.Entry = D2.m
+ }
+}
diff --git a/test/files/run/macro-subpatterns.check b/test/files/run/macro-subpatterns.check
new file mode 100644
index 0000000000..b34d4bf4a1
--- /dev/null
+++ b/test/files/run/macro-subpatterns.check
@@ -0,0 +1,3 @@
+List((a @ Extractor((b @ Extractor((c @ _))))))
+List((b @ Extractor((c @ _))))
+List((c @ _))
diff --git a/test/files/run/macro-subpatterns/Macro_1.scala b/test/files/run/macro-subpatterns/Macro_1.scala
new file mode 100644
index 0000000000..d8e86e27c6
--- /dev/null
+++ b/test/files/run/macro-subpatterns/Macro_1.scala
@@ -0,0 +1,18 @@
+import scala.reflect.macros.WhiteboxContext
+import language.experimental.macros
+
+object Extractor {
+ def unapply(x: Any): Any = macro unapplyImpl
+ def unapplyImpl(c: WhiteboxContext)(x: c.Tree) = {
+ val st = c.universe.asInstanceOf[reflect.internal.SymbolTable]
+ import st._
+ val subpatterns = x.attachments.get[SubpatternsAttachment].get.patterns
+ q"""
+ new {
+ def isEmpty = false
+ def get = ${subpatterns.toString}
+ def unapply(x: Any) = this
+ }.unapply(${x.asInstanceOf[st.Tree]})
+ """.asInstanceOf[c.Tree]
+ }
+}
diff --git a/test/files/run/macro-subpatterns/Test_2.scala b/test/files/run/macro-subpatterns/Test_2.scala
new file mode 100644
index 0000000000..dc6e668877
--- /dev/null
+++ b/test/files/run/macro-subpatterns/Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ 42 match {
+ case Extractor(a @ Extractor(b @ Extractor(c))) => println(a); println(b); println(c)
+ }
+}
diff --git a/test/files/run/t4841-isolate-plugins.check b/test/files/run/t4841-isolate-plugins.check
new file mode 100644
index 0000000000..a6462b424b
--- /dev/null
+++ b/test/files/run/t4841-isolate-plugins.check
@@ -0,0 +1,2 @@
+My phase name is ploogin1_1
+My phase name is ploogin1_2
diff --git a/test/files/run/t4841-isolate-plugins/ploogin.scala b/test/files/run/t4841-isolate-plugins/ploogin.scala
new file mode 100644
index 0000000000..bd8c7275ec
--- /dev/null
+++ b/test/files/run/t4841-isolate-plugins/ploogin.scala
@@ -0,0 +1,30 @@
+
+package t4841
+
+import scala.tools.nsc.{ Global, Phase }
+import scala.tools.nsc.plugins.{ Plugin, PluginComponent }
+import scala.reflect.io.Path
+import scala.reflect.io.File
+
+/** A test plugin. */
+class Ploogin(val global: Global, val name: String = "ploogin") extends Plugin {
+ import global._
+
+ val description = "A sample plugin for testing."
+ val components = List[PluginComponent](TestComponent)
+
+ private object TestComponent extends PluginComponent {
+ val global: Ploogin.this.global.type = Ploogin.this.global
+ //override val runsBefore = List("refchecks")
+ val runsAfter = List("jvm")
+ val phaseName = Ploogin.this.name
+ override def description = "A sample phase that does so many things it's kind of hard to describe briefly."
+ def newPhase(prev: Phase) = new TestPhase(prev)
+ class TestPhase(prev: Phase) extends StdPhase(prev) {
+ override def description = TestComponent.this.description
+ def apply(unit: CompilationUnit) {
+ if (settings.developer) inform(s"My phase name is $phaseName")
+ }
+ }
+ }
+}
diff --git a/test/files/run/t4841-isolate-plugins/t4841-isolate-plugin.scala b/test/files/run/t4841-isolate-plugins/t4841-isolate-plugin.scala
new file mode 100644
index 0000000000..5421922c9c
--- /dev/null
+++ b/test/files/run/t4841-isolate-plugins/t4841-isolate-plugin.scala
@@ -0,0 +1,39 @@
+
+import tools.nsc.plugins.PluginDescription
+import tools.partest.DirectTest
+
+import java.io.File
+
+// show that plugins are on isolated class loaders
+object Test extends DirectTest {
+ override def code = "class Code"
+
+ override def extraSettings = s"-usejavacp"
+
+ // plugin named ploogin1_1 or ploogin1_2, but not ploogin2_x
+ // Although the samples are in different classloaders, the plugin
+ // loader checks for distinctness by class name, so the names must differ.
+ def pluginCode(index: Int) = s"""
+ |package t4841 {
+ | class SamplePloogin$index(global: scala.tools.nsc.Global) extends Ploogin(global, s"$${PlooginCounter.named}_$index")
+ | object PlooginCounter {
+ | val count = new java.util.concurrent.atomic.AtomicInteger
+ | def named = s"ploogin$${count.incrementAndGet}"
+ | }
+ |}""".stripMargin.trim
+
+ def compilePlugin(i: Int) = {
+ val out = (testOutput / s"p$i").createDirectory()
+ val args = Seq("-usejavacp", "-d", out.path)
+ compileString(newCompiler(args: _*))(pluginCode(i))
+ val xml = PluginDescription(s"p$i", s"t4841.SamplePloogin$i").toXML
+ (out / "scalac-plugin.xml").toFile writeAll xml
+ out
+ }
+
+ override def show() = {
+ val dirs = 1 to 2 map (compilePlugin(_))
+ compile("-Xdev", s"-Xplugin:${dirs mkString ","}", "-usejavacp", "-d", testOutput.path)
+ }
+}
+
diff --git a/test/files/run/t4841-no-plugin.check b/test/files/run/t4841-no-plugin.check
new file mode 100644
index 0000000000..4338f0ce23
--- /dev/null
+++ b/test/files/run/t4841-no-plugin.check
@@ -0,0 +1 @@
+warning: No plugin in path t4841-no-plugin-run.obj/plugins.partest
diff --git a/test/files/run/t4841-no-plugin.scala b/test/files/run/t4841-no-plugin.scala
new file mode 100644
index 0000000000..d91bf7ee21
--- /dev/null
+++ b/test/files/run/t4841-no-plugin.scala
@@ -0,0 +1,17 @@
+
+import tools.partest.DirectTest
+
+import java.io.File
+
+// warn only if no plugin on Xplugin path
+object Test extends DirectTest {
+ override def code = "class Code"
+
+ override def extraSettings = s"-usejavacp -d ${testOutput.path}"
+
+ override def show() = {
+ val tmp = new File(testOutput.jfile, "plugins.partest").getAbsolutePath
+ compile("-Xdev", s"-Xplugin:$tmp", "-Xpluginsdir", tmp)
+ }
+}
+
diff --git a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala
index 7905a2ca15..c5cac3ea45 100644
--- a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala
+++ b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala
@@ -1,5 +1,4 @@
import org.scalacheck._, Prop._, Gen._, Arbitrary._
-import scala.reflect.api.{Liftable, Universe}
import scala.reflect.runtime.universe._, Flag._
trait ArbitraryTreesAndNames {
@@ -265,14 +264,8 @@ trait ArbitraryTreesAndNames {
def genTreeIsTypeWrapped(size: Int) =
for(tit <- genTreeIsType(size)) yield TreeIsType(tit)
- implicit object liftTreeIsTerm extends Liftable[TreeIsTerm] {
- def apply(universe: Universe, value: TreeIsTerm): universe.Tree =
- value.tree.asInstanceOf[universe.Tree]
- }
- implicit object liftTreeIsType extends Liftable[TreeIsType] {
- def apply(universe: Universe, value: TreeIsType): universe.Tree =
- value.tree.asInstanceOf[universe.Tree]
- }
+ implicit val liftTreeIsTerm = Liftable[TreeIsTerm] { _.tree }
+ implicit val liftTreeIsType = Liftable[TreeIsType] { _.tree }
implicit def treeIsTerm2tree(tit: TreeIsTerm): Tree = tit.tree
implicit def treeIsType2tree(tit: TreeIsType): Tree = tit.tree
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/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
index dbd26bf72a..94465930ed 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
@@ -88,6 +88,22 @@ trait ClassDeconstruction { self: QuasiquoteProperties =>
matches("class Foo { self => bar(self) }")
matches("case class Foo(x: Int)")
}
+
+ property("SI-7979") = test {
+ val PARAMACCESSOR = (1 << 29).toLong.asInstanceOf[FlagSet]
+ assertThrows[MatchError] {
+ val build.SyntacticClassDef(_, _, _, _, _, _, _, _, _) =
+ ClassDef(
+ Modifiers(), TypeName("Foo"), List(),
+ Template(
+ List(Select(Ident(TermName("scala")), TypeName("AnyRef"))),
+ noSelfType,
+ List(
+ //ValDef(Modifiers(PRIVATE | LOCAL | PARAMACCESSOR), TermName("x"), Ident(TypeName("Int")), EmptyTree),
+ DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List(ValDef(Modifiers(PARAM | PARAMACCESSOR), TermName("x"),
+ Ident(TypeName("Int")), EmptyTree))), TypeTree(), Block(List(pendingSuperCall), Literal(Constant(())))))))
+ }
+ }
}
trait ModsDeconstruction { self: QuasiquoteProperties =>
diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala
index cb46a60dbe..92d299bede 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",
"""
@@ -179,6 +172,20 @@ object ErrorProps extends QuasiquoteProperties("errors") {
val q"$m1 $m2 def foo" = EmptyTree
""")
+ property("can't splice values of Null") = fails(
+ "Can't splice Null, bottom type values often indicate programmer mistake",
+ """
+ val n = null
+ q"$n"
+ """)
+
+ property("can't splice values of Nothing") = fails(
+ "Can't splice Nothing, bottom type values often indicate programmer mistake",
+ """
+ def n = ???
+ q"$n"
+ """)
+
// // Make sure a nice error is reported in this case
// { import Flag._; val mods = NoMods; q"lazy $mods val x: Int" }
} \ No newline at end of file
diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala
index 1271e1accd..539375d905 100644
--- a/test/files/scalacheck/quasiquotes/LiftableProps.scala
+++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala
@@ -76,4 +76,39 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
val const = Constant(0)
assert(q"$const" ≈ q"0")
}
+
+ property("lift list variants") = test {
+ val lst = List(1, 2)
+ val immutable = q"$scalapkg.collection.immutable"
+ assert(q"$lst" ≈ q"$immutable.List(1, 2)")
+ assert(q"f(..$lst)" ≈ q"f(1, 2)")
+ val llst = List(List(1), List(2))
+ assert(q"f(..$llst)" ≈ q"f($immutable.List(1), $immutable.List(2))")
+ assert(q"f(...$llst)" ≈ q"f(1)(2)")
+ }
+
+ property("lift tuple") = test {
+ assert(q"${Tuple1(1)}" ≈ q"scala.Tuple1(1)")
+ assert(q"${(1, 2)}" ≈ q"(1, 2)")
+ assert(q"${(1, 2, 3)}" ≈ q"(1, 2, 3)")
+ assert(q"${(1, 2, 3, 4)}" ≈ q"(1, 2, 3, 4)")
+ assert(q"${(1, 2, 3, 4, 5)}" ≈ q"(1, 2, 3, 4, 5)")
+ assert(q"${(1, 2, 3, 4, 5, 6)}" ≈ q"(1, 2, 3, 4, 5, 6)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7)}" ≈ q"(1, 2, 3, 4, 5, 6, 7)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)")
+ assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)")
+ }
} \ No newline at end of file
diff --git a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
index b331c4b6b6..5411e664a2 100644
--- a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
+++ b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
@@ -120,4 +120,6 @@ trait Helpers {
def annot(name: TypeName): Tree = annot(name, Nil)
def annot(name: String, args: List[Tree]): Tree = annot(TypeName(name), args)
def annot(name: TypeName, args: List[Tree]): Tree = q"new $name(..$args)"
-} \ No newline at end of file
+
+ val scalapkg = build.setSymbol(Ident(TermName("scala")), definitions.ScalaPackage)
+}
diff --git a/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala b/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala
new file mode 100644
index 0000000000..a3b6137f68
--- /dev/null
+++ b/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala
@@ -0,0 +1,75 @@
+import org.scalacheck._, Prop._, Gen._, Arbitrary._
+import scala.reflect.runtime.universe._, Flag._
+
+object RuntimeErrorProps extends QuasiquoteProperties("errors") {
+ def testFails[T](block: =>T) = test {
+ assertThrows[IllegalArgumentException] {
+ block
+ }
+ }
+
+ property("default param anon function") = testFails {
+ val param = q"val x: Int = 1"
+ q"{ $param => x + 1 }"
+ }
+
+ property("non-casedef case") = testFails {
+ val x = q"x"
+ q"foo match { case $x }"
+ }
+
+ property("non-new annotation") = testFails {
+ val annot = q"foo"
+ q"@$annot def foo"
+ }
+
+ property("non-valdef param") = testFails {
+ val param = q"foo"
+ q"def foo($param)"
+ }
+
+ property("non-valdef class param") = testFails {
+ val param = q"foo"
+ q"class Foo($param)"
+ }
+
+ property("non-typedef type param") = testFails {
+ val tparam = tq"T"
+ q"class C[$tparam]"
+ }
+
+ property("non-definition refine stat") = testFails {
+ val stat = q"foo"
+ tq"Foo { $stat }"
+ }
+
+ property("non-definition early def") = testFails {
+ val stat = q"foo"
+ q"class Foo extends { $stat } with Bar"
+ }
+
+ property("type apply for definition") = testFails {
+ val defn = q"def foo"
+ q"$defn[foo]"
+ }
+
+ property("non-val selftype") = testFails {
+ val foo = q"foo"
+ q"class Foo { $foo => }"
+ }
+
+ property("for empty enums") = testFails {
+ val enums = List.empty[Tree]
+ q"for(..$enums) 0"
+ }
+
+ property("for starts with non-from enum") = testFails {
+ val enums = fq"foo = bar" :: Nil
+ q"for(..$enums) 0"
+ }
+
+ property("for inlalid enum") = testFails {
+ val enums = q"foo" :: Nil
+ q"for(..$enums) 0"
+ }
+}
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index cdd96205de..6fb05ff9a4 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -203,4 +203,25 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
assert(q"f(..${l1 ++ l2}, $baz)" ≈ q"f(foo, bar, baz)")
assert(q"f(${if (true) q"a" else q"b"})" ≈ q"f(a)")
}
+
+ property("splice iterable of non-parametric type") = test {
+ object O extends Iterable[Tree] { def iterator = List(q"foo").iterator }
+ q"f(..$O)"
+ }
+
+ property("SI-8016") = test {
+ val xs = q"1" :: q"2" :: Nil
+ assertEqAst(q"..$xs", "{1; 2}")
+ 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
+ }
}
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index bd81afa125..8d1ada342a 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -3,8 +3,10 @@ import scala.reflect.runtime.universe._, Flag._
object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction") {
property("f(..x) = f") = test {
- val q"f(..$args)" = q"f"
- assert(args ≈ Nil)
+ // see SI-8008
+ assertThrows[MatchError] {
+ val q"f(..$args)" = q"f"
+ }
}
property("f(x)") = forAll { (x: Tree) =>
diff --git a/test/files/scalacheck/quasiquotes/Test.scala b/test/files/scalacheck/quasiquotes/Test.scala
index 8b1e779ab2..7a26fa4923 100644
--- a/test/files/scalacheck/quasiquotes/Test.scala
+++ b/test/files/scalacheck/quasiquotes/Test.scala
@@ -8,7 +8,9 @@ object Test extends Properties("quasiquotes") {
include(PatternConstructionProps)
include(PatternDeconstructionProps)
include(LiftableProps)
+ include(UnliftableProps)
include(ErrorProps)
+ include(RuntimeErrorProps)
include(DefinitionConstructionProps)
include(DefinitionDeconstructionProps)
include(DeprecationProps)
diff --git a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala
index f443330e0b..2f501435e3 100644
--- a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala
+++ b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala
@@ -50,4 +50,29 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") {
assert(enums1 ≈ enums)
assert(body1 ≈ body)
}
+
+ property("extract UnApply (1)") = test {
+ val q"object $_ { $_; $_; $m }" = typecheck(q"""
+ object Test {
+ class Cell(val x: Int)
+ object Cell { def unapply(c: Cell) = Some(c.x) }
+ new Cell(0) match { case Cell(v) => v }
+ }
+ """)
+ val q"$_ match { case $f(..$args) => $_ }" = m
+ assert(f ≈ pq"Test.this.Cell")
+ assert(args ≈ List(pq"v"))
+ }
+
+ property("extract UnApply (2)") = test {
+ val q"object $_ { $_; $_; $m }" = typecheck(q"""
+ object Test {
+ case class Cell(val x: Int)
+ new Cell(0) match { case Cell(v) => v }
+ }
+ """)
+ val q"$_ match { case ${f: TypeTree}(..$args) => $_ }" = m
+ assert(f.original ≈ pq"Test.this.Cell")
+ assert(args ≈ List(pq"v"))
+ }
} \ No newline at end of file
diff --git a/test/files/scalacheck/quasiquotes/UnliftableProps.scala b/test/files/scalacheck/quasiquotes/UnliftableProps.scala
new file mode 100644
index 0000000000..8b827c98ff
--- /dev/null
+++ b/test/files/scalacheck/quasiquotes/UnliftableProps.scala
@@ -0,0 +1,160 @@
+import org.scalacheck._, Prop._, Gen._, Arbitrary._
+import scala.reflect.runtime.universe._, Flag._
+
+object UnliftableProps extends QuasiquoteProperties("unliftable") {
+ property("unlift name") = test {
+ val termname0 = TermName("foo")
+ val typename0 = TypeName("foo")
+ val q"${termname1: TermName}" = Ident(termname0)
+ assert(termname1 == termname0)
+ val q"${typename1: TypeName}" = Ident(typename0)
+ assert(typename1 == typename0)
+ val q"${name1: Name}" = Ident(termname0)
+ assert(name1 == termname0)
+ val q"${name2: Name}" = Ident(typename0)
+ assert(name2 == typename0)
+ }
+
+ property("unlift type") = test {
+ val q"${tpe: Type}" = TypeTree(typeOf[Int])
+ assert(tpe =:= typeOf[Int])
+ }
+
+ property("unlift constant") = test {
+ val q"${const: Constant}" = Literal(Constant("foo"))
+ assert(const == Constant("foo"))
+ }
+
+ property("unlift char") = test {
+ val q"${c: Char}" = Literal(Constant('0'))
+ assert(c.isInstanceOf[Char] && c == '0')
+ }
+
+ property("unlift byte") = test {
+ val q"${b: Byte}" = Literal(Constant(0: Byte))
+ assert(b.isInstanceOf[Byte] && b == 0)
+ }
+
+ property("unlift short") = test {
+ val q"${s: Short}" = Literal(Constant(0: Short))
+ assert(s.isInstanceOf[Short] && s == 0)
+ }
+
+ property("unlift int") = test {
+ val q"${i: Int}" = Literal(Constant(0: Int))
+ assert(i.isInstanceOf[Int] && i == 0)
+ }
+
+ property("unlift long") = test {
+ val q"${l: Long}" = Literal(Constant(0L: Long))
+ assert(l.isInstanceOf[Long] && l == 0L)
+ }
+
+ property("unlift float") = test {
+ val q"${f: Float}" = Literal(Constant(0.0f: Float))
+ assert(f.isInstanceOf[Float] && f == 0.0f)
+ }
+
+ property("unlift double") = test {
+ val q"${d: Double}" = Literal(Constant(0.0: Double))
+ assert(d.isInstanceOf[Double] && d == 0.0)
+ }
+
+ property("unlift bool") = test {
+ val q"${b: Boolean}" = q"true"
+ assert(b.isInstanceOf[Boolean] && b == true)
+ }
+
+ property("unlift string") = test {
+ val q"${s: String}" = q""" "foo" """
+ assert(s.isInstanceOf[String] && s == "foo")
+ }
+
+ property("unlift scala.symbol") = test {
+ val q"${s: scala.Symbol}" = q"'foo"
+ assert(s.isInstanceOf[scala.Symbol] && s == 'foo)
+ }
+
+ implicit def unliftList[T: Unliftable]: Unliftable[List[T]] = Unliftable {
+ case q"scala.collection.immutable.List(..$args)" if args.forall { implicitly[Unliftable[T]].unapply(_).nonEmpty } =>
+ val ut = implicitly[Unliftable[T]]
+ args.flatMap { ut.unapply(_) }
+ }
+
+ property("unlift list (1)") = test {
+ val orig = List(1, 2)
+ val q"${l1: List[Int]}" = q"$orig" // q"List(1, 2)"
+ assert(l1 == orig)
+ val q"f(..${l2: List[Int]})" = q"f(..$orig)" // q"f(1, 2)
+ assert(l2 == orig)
+ }
+
+ property("unlift list (2)") = test {
+ val orig2 = List(List(1, 2), List(3))
+ val q"f(${l3: List[List[Int]]})" = q"f($orig2)" // q"f(List(List(1, 2), List(3)))
+ assert(l3 == orig2)
+ val q"f(..${l4: List[List[Int]]})" = q"f(..$orig2)" // q"f(List(1, 2), List(3))"
+ assert(l4 == orig2)
+ val q"f(...${l5: List[List[Int]]})" = q"f(...$orig2)" // q"f(1, 2)(3)
+ assert(l5 == orig2)
+ }
+
+ property("don't unlift non-tree splicee (1)") = test {
+ val q"${a: TermName}.${b: TermName}" = q"a.b"
+ assert(a == TermName("a"))
+ assert(b == TermName("b"))
+ }
+
+ property("don't unlift non-tree splicee (2)") = test {
+ val q"${mods: Modifiers} def foo" = q"def foo"
+ assert(mods == Modifiers(DEFERRED))
+ }
+
+ property("unlift tuple") = test {
+ // fails due to SI-8045
+ // val q"${t1: Tuple1[Int]}" = q"_root_.scala.Tuple1(1)"
+ val q"${t2: (Int, Int)}" = q"(1, 2)"
+ val q"${t3: (Int, Int, Int)}" = q"(1, 2, 3)"
+ val q"${t4: (Int, Int, Int, Int)}" = q"(1, 2, 3, 4)"
+ val q"${t5: (Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5)"
+ val q"${t6: (Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6)"
+ val q"${t7: (Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7)"
+ val q"${t8: (Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8)"
+ val q"${t9: (Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9)"
+ val q"${t10: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)"
+ val q"${t11: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)"
+ val q"${t12: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)"
+ val q"${t13: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)"
+ val q"${t14: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)"
+ val q"${t15: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)"
+ val q"${t16: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)"
+ val q"${t17: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)"
+ val q"${t18: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)"
+ val q"${t19: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)"
+ val q"${t20: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)"
+ val q"${t21: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)"
+ val q"${t22: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)}" = q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)"
+ // assert(t1 == Tuple1(1))
+ assert(t2 == (1, 2))
+ assert(t3 == (1, 2, 3))
+ assert(t4 == (1, 2, 3, 4))
+ assert(t5 == (1, 2, 3, 4, 5))
+ assert(t6 == (1, 2, 3, 4, 5, 6))
+ assert(t7 == (1, 2, 3, 4, 5, 6, 7))
+ assert(t8 == (1, 2, 3, 4, 5, 6, 7, 8))
+ assert(t9 == (1, 2, 3, 4, 5, 6, 7, 8, 9))
+ assert(t10 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+ assert(t11 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))
+ assert(t12 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))
+ assert(t13 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13))
+ assert(t14 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14))
+ assert(t15 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15))
+ assert(t16 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))
+ assert(t17 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17))
+ assert(t18 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18))
+ assert(t19 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19))
+ assert(t20 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))
+ assert(t21 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21))
+ assert(t22 == (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22))
+ }
+}
diff --git a/test/junit/scala/reflect/internal/util/StringOpsTest.scala b/test/junit/scala/reflect/internal/util/StringOpsTest.scala
new file mode 100644
index 0000000000..13d3a6435e
--- /dev/null
+++ b/test/junit/scala/reflect/internal/util/StringOpsTest.scala
@@ -0,0 +1,52 @@
+package scala.reflect.internal.util
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class StringOpsTest {
+ @Test
+ def prefixOfNone(): Unit = {
+ val so = new StringOps { }
+ val ss = Nil
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "")
+ }
+ @Test
+ def prefixWithEmpty(): Unit = {
+ val so = new StringOps { }
+ val ss = List("abc", "", "abd")
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "")
+ }
+ @Test
+ def prefixOfOne(): Unit = {
+ val so = new StringOps { }
+ val ss = List("abc")
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "abc")
+ }
+ @Test
+ def prefixOfMany(): Unit = {
+ val so = new StringOps { }
+ val ss = List("abc", "abd", "abe")
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "ab")
+ }
+ @Test
+ def prefixOfPrefix(): Unit = {
+ val so = new StringOps { }
+ val ss = List("abc", "abcd")
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "abc")
+ }
+ @Test
+ def prefixOfPrefixMiddling(): Unit = {
+ val so = new StringOps { }
+ val ss = List("abce", "abc", "abcd")
+ val lcp = so longestCommonPrefix ss
+ assert(lcp == "abc")
+ }
+}