diff options
25 files changed, 211 insertions, 213 deletions
@@ -1677,7 +1677,7 @@ TODO: <fileset dir="${build-docs.dir}/library"/> </copy> - <copy toDir="${dist.dir}/doc/api" overwrite="true" flatten="true"> + <copy toDir="${dist.dir}/api" overwrite="true" flatten="true"> <file file="${scala-xml-javadoc}"/> <file file="${scala-parser-combinators-javadoc}"/> <file file="${scala-continuations-plugin-javadoc}"/> diff --git a/src/build/maven/scala-actors-pom.xml b/src/build/maven/scala-actors-pom.xml index 424ac2898c..a0ebcecad1 100644 --- a/src/build/maven/scala-actors-pom.xml +++ b/src/build/maven/scala-actors-pom.xml @@ -38,17 +38,6 @@ <version>@VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-compiler-doc-pom.xml b/src/build/maven/scala-compiler-doc-pom.xml index 30161d2fea..8572e55b42 100644 --- a/src/build/maven/scala-compiler-doc-pom.xml +++ b/src/build/maven/scala-compiler-doc-pom.xml @@ -45,17 +45,6 @@ <version>@PARSER_COMBINATORS_VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-compiler-interactive-pom.xml b/src/build/maven/scala-compiler-interactive-pom.xml index d59f305a9f..ad8192b694 100644 --- a/src/build/maven/scala-compiler-interactive-pom.xml +++ b/src/build/maven/scala-compiler-interactive-pom.xml @@ -35,17 +35,6 @@ <version>@VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-compiler-pom.xml b/src/build/maven/scala-compiler-pom.xml index 4a000b27a1..8ca18f6f14 100644 --- a/src/build/maven/scala-compiler-pom.xml +++ b/src/build/maven/scala-compiler-pom.xml @@ -39,7 +39,7 @@ <artifactId>scala-reflect</artifactId> <version>@VERSION@</version> </dependency> - <!-- TODO modularize compiler: these dependencies will disappear then the compiler is modularized --> + <!-- TODO modularize compiler: these dependencies will disappear when the compiler is modularized --> <dependency> <!-- for scala-compiler-doc --> <groupId>org.scala-lang.modules</groupId> <artifactId>scala-xml_@SCALA_BINARY_VERSION@</artifactId> @@ -57,17 +57,6 @@ <optional>true</optional> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-dist-pom.xml b/src/build/maven/scala-dist-pom.xml index 413da928bb..9a566d231b 100644 --- a/src/build/maven/scala-dist-pom.xml +++ b/src/build/maven/scala-dist-pom.xml @@ -51,17 +51,6 @@ <version>@JLINE_VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-library-all-pom.xml b/src/build/maven/scala-library-all-pom.xml index f34a28e79a..b649c8c525 100644 --- a/src/build/maven/scala-library-all-pom.xml +++ b/src/build/maven/scala-library-all-pom.xml @@ -75,17 +75,6 @@ <version>@ACTORS_MIGRATION_VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml index d40cee2656..78fc05a7c3 100644 --- a/src/build/maven/scala-library-pom.xml +++ b/src/build/maven/scala-library-pom.xml @@ -33,17 +33,6 @@ </properties> <dependencies> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scala-reflect-pom.xml b/src/build/maven/scala-reflect-pom.xml index d0a9c0e274..c21caefcf2 100644 --- a/src/build/maven/scala-reflect-pom.xml +++ b/src/build/maven/scala-reflect-pom.xml @@ -38,17 +38,6 @@ <version>@VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/build/maven/scalap-pom.xml b/src/build/maven/scalap-pom.xml index 88cfce08d8..236ac999fc 100644 --- a/src/build/maven/scalap-pom.xml +++ b/src/build/maven/scalap-pom.xml @@ -35,17 +35,6 @@ <version>@VERSION@</version> </dependency> </dependencies> - <distributionManagement> - <repository> - <id>scala-tools.org</id> - <url>@RELEASE_REPOSITORY@</url> - </repository> - <snapshotRepository> - <id>scala-tools.org</id> - <url>@SNAPSHOT_REPOSITORY@</url> - <uniqueVersion>false</uniqueVersion> - </snapshotRepository> - </distributionManagement> <developers> <developer> <id>lamp</id> diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala index 5669ec731f..825d0c04f3 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala @@ -17,7 +17,6 @@ trait Placeholders { self: Quasiquotes => // Step 1: Transform Scala source with holes into vanilla Scala source - lazy val holeMap = new HoleMap() lazy val posMap = mutable.ListMap[Position, (Int, Int)]() lazy val code = { val sb = new StringBuilder() @@ -58,25 +57,27 @@ trait Placeholders { self: Quasiquotes => sb.toString } - class HoleMap { - private var underlying = immutable.SortedMap[String, Hole]() - private val accessed = mutable.Set[String]() + object holeMap { + private val underlying = mutable.LinkedHashMap.empty[String, Hole] + private val accessed = mutable.Set.empty[String] def unused: Set[Name] = (underlying.keys.toSet -- accessed).map(TermName(_)) - def contains(key: Name) = underlying.contains(key.toString) - def apply(key: Name) = { - val s = key.toString - accessed += s - underlying(s) - } - def update(key: Name, hole: Hole) = { + def contains(key: Name): Boolean = underlying.contains(key.toString) + def apply(key: Name): Hole = { + val skey = key.toString + val value = underlying(skey) + accessed += skey + value + } + def update(key: Name, hole: Hole) = underlying += key.toString -> hole + def get(key: Name): Option[Hole] = { + val skey = key.toString + underlying.get(skey).map { v => + accessed += skey + v + } } - def get(key: Name) = { - val s = key.toString - accessed += s - underlying.get(s) - } - def toList = underlying.toList + def keysIterator: Iterator[TermName] = underlying.keysIterator.map(TermName(_)) } // Step 2: Transform vanilla Scala AST into an AST with holes @@ -179,4 +180,4 @@ trait Placeholders { self: Quasiquotes => case _ => None } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala index 3e703924e8..396688c437 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala @@ -16,7 +16,7 @@ abstract class Quasiquotes extends Parsers lazy val (universe: Tree, args, parts, parse, reify, method) = c.macroApplication match { case Apply(build.SyntacticTypeApplied(Select(Select(Apply(Select(universe0, _), List(Apply(_, parts0))), interpolator0), method0), _), args0) => - debug(s"\nparse prefix:\nuniverse=$universe0\nparts=$parts0\ninterpolator=$interpolator0\nmethod=$method0\nargs=$args0\n") + debug(s"parse prefix:\nuniverse=$universe0\nparts=$parts0\ninterpolator=$interpolator0\nmethod=$method0\nargs=$args0\n") val parts1 = parts0.map { case lit @ Literal(Constant(s: String)) => s -> lit.pos case part => c.abort(part.pos, "Quasiquotes can only be used with literal strings") @@ -43,8 +43,8 @@ abstract class Quasiquotes extends Parsers lazy val universeTypes = new definitions.UniverseDependentTypes(universe) def expandQuasiquote = { - debug(s"\nmacro application:\n${c.macroApplication}\n") - debug(s"\ncode to parse:\n$code\n") + debug(s"macro application:\n${c.macroApplication}\n") + debug(s"code to parse:\n$code\n") val tree = parse(code) debug(s"parsed:\n${showRaw(tree)}\n$tree\n") val reified = reify(tree) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 273245f7bd..0c73214745 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -29,7 +29,7 @@ trait Reifiers { self: Quasiquotes => /** Map that stores freshly generated names linked to the corresponding names in the reified tree. * This information is used to reify names created by calls to freshTermName and freshTypeName. */ - var nameMap = collection.mutable.HashMap.empty[Name, Set[TermName]].withDefault { _ => Set() } + val nameMap = collection.mutable.HashMap.empty[Name, Set[TermName]].withDefault { _ => Set() } /** Wraps expressions into: * a block which starts with a sequence of vals that correspond @@ -71,7 +71,7 @@ trait Reifiers { self: Quasiquotes => // q"..$freshdefs; $tree" SyntacticBlock(freshdefs :+ tree) } else { - val freevars = holeMap.toList.map { case (name, _) => Ident(name) } + val freevars = holeMap.keysIterator.map(Ident(_)).toList val isVarPattern = tree match { case Bind(name, Ident(nme.WILDCARD)) => true case _ => false } val cases = if(isVarPattern) { @@ -162,7 +162,7 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticNew, earlyDefs, parents, selfdef, body) case SyntacticDefDef(mods, name, tparams, build.ImplicitParams(vparamss, implparams), tpt, rhs) => if (implparams.nonEmpty) - mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams), + mirrorBuildCall(nme.SyntacticDefDef, reify(mods), reify(name), reify(tparams), reifyBuildCall(nme.ImplicitParams, vparamss, implparams), reify(tpt), reify(rhs)) else reifyBuildCall(nme.SyntacticDefDef, mods, name, tparams, vparamss, tpt, rhs) @@ -305,7 +305,7 @@ trait Reifiers { self: Quasiquotes => * > reifyMultiCardinalityList(lst) { ... } { ... } * q"List($foo, $bar) ++ ${holeMap(qq$f3948f9s$1).tree}" */ - def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree + def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put * in the correct position. Fallbacks to regular reification for non-high cardinality @@ -361,10 +361,10 @@ trait Reifiers { self: Quasiquotes => } class ApplyReifier extends Reifier(isReifyingExpressions = true) { - def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = + def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = if (xs.isEmpty) mkList(Nil) else { - def reifyGroup(group: List[T]): Tree = group match { + def reifyGroup(group: List[Any]): Tree = group match { case List(elem) if fill.isDefinedAt(elem) => fill(elem) case elems => mkList(elems.map(fallback)) } @@ -403,14 +403,26 @@ trait Reifiers { self: Quasiquotes => } 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) - Apply(cons, List(fallback(el), rest)) - } - case _ => - mkList(xs.map(fallback)) + private def collection = ScalaDot(nme.collection) + private def collectionColonPlus = Select(collection, nme.COLONPLUS) + private def collectionCons = Select(Select(collection, nme.immutable), nme.CONS) + private def collectionNil = Select(Select(collection, nme.immutable), nme.Nil) + // pq"$lhs :+ $rhs" + private def append(lhs: Tree, rhs: Tree) = Apply(collectionColonPlus, lhs :: rhs :: Nil) + // pq"$lhs :: $rhs" + private def cons(lhs: Tree, rhs: Tree) = Apply(collectionCons, lhs :: rhs :: Nil) + + def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = { + val grouped = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) } + def appended(lst: List[Any], init: Tree) = lst.foldLeft(init) { (l, r) => append(l, fallback(r)) } + def prepended(lst: List[Any], init: Tree) = lst.foldRight(init) { (l, r) => cons(fallback(l), r) } + grouped match { + case init :: List(hole) :: last :: Nil if fill.isDefinedAt(hole) => appended(last, prepended(init, fill(hole))) + case init :: List(hole) :: Nil if fill.isDefinedAt(hole) => prepended(init, fill(hole)) + case List(hole) :: last :: Nil if fill.isDefinedAt(hole) => appended(last, fill(hole)) + case List(hole) :: Nil if fill.isDefinedAt(hole) => fill(hole) + case _ => prepended(xs, collectionNil) + } } override def reifyModifiers(m: Modifiers) = diff --git a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala index 4f67a22b8f..bf718c27cc 100644 --- a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala @@ -64,9 +64,12 @@ trait ContextTrees { self: Global => def locateContextTree(contexts: Contexts, pos: Position): Option[ContextTree] = { if (contexts.isEmpty) None else { + // binary search on contexts, loop invar: lo <= hi, recursion metric: `hi - lo` @tailrec def loop(lo: Int, hi: Int, previousSibling: Option[ContextTree]): Option[ContextTree] = { - if (pos properlyPrecedes contexts(lo).pos) + // [SI-8239] enforce loop invariant & ensure recursion metric decreases monotonically on every recursion + if (lo > hi) previousSibling + else if (pos properlyPrecedes contexts(lo).pos) previousSibling else if (contexts(hi).pos properlyPrecedes pos) Some(contexts(hi)) @@ -76,9 +79,18 @@ trait ContextTrees { self: Global => if (midpos includes pos) Some(contexts(mid)) else if (midpos properlyPrecedes pos) + // recursion metric: (hi - ((lo + hi)/2 + 1)) < (hi - lo) + // since (hi - ((lo + hi)/2 + 1)) - (hi - lo) = lo - ((lo + hi)/2 + 1) < 0 + // since 2*lo - lo - hi - 2 = lo - hi - 2 < 0 + // since lo < hi + 2 + // can violate lo <= hi, hence the lo > hi check at the top [SI-8239] loop(mid + 1, hi, Some(contexts(mid))) - else + else if (lo != hi) // avoid looping forever (lo == hi violates the recursion metric) [SI-8239] + // recursion metric: ((lo + hi)/2) - lo < (hi - lo) + // since ((lo + hi)/2) - lo - (hi - lo) = ((lo + hi)/2) - hi < 0 + // since 2 * (((lo + hi)/2) - hi) = lo - hi < 0 since lo < hi loop(lo, mid, previousSibling) + else previousSibling } } loop(0, contexts.length - 1, None) diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 28d799ea0c..53475be479 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -822,31 +822,32 @@ trait StdNames { def newLazyValSlowComputeName(lzyValName: Name) = lzyValName append LAZY_SLOW_SUFFIX // ASCII names for operators - val ADD = encode("+") - val AND = encode("&") - val ASR = encode(">>") - val CONS = encode("::") - val DIV = encode("/") - val EQ = encode("==") - val EQL = encode("=") - val GE = encode(">=") - val GT = encode(">") - val HASHHASH = encode("##") - val LE = encode("<=") - val LSL = encode("<<") - val LSR = encode(">>>") - val LT = encode("<") - val MINUS = encode("-") - val MOD = encode("%") - val MUL = encode("*") - val NE = encode("!=") - val OR = encode("|") - val PLUS = ADD // technically redundant, but ADD looks funny with MINUS - val PLUSPLUS = encode("++") - val SUB = MINUS // ... as does SUB with PLUS - val XOR = encode("^") - val ZAND = encode("&&") - val ZOR = encode("||") + val ADD = encode("+") + val AND = encode("&") + val ASR = encode(">>") + val CONS = encode("::") + val COLONPLUS = encode(":+") + val DIV = encode("/") + val EQ = encode("==") + val EQL = encode("=") + val GE = encode(">=") + val GT = encode(">") + val HASHHASH = encode("##") + val LE = encode("<=") + val LSL = encode("<<") + val LSR = encode(">>>") + val LT = encode("<") + val MINUS = encode("-") + val MOD = encode("%") + val MUL = encode("*") + val NE = encode("!=") + val OR = encode("|") + val PLUS = ADD // technically redundant, but ADD looks funny with MINUS + val PLUSPLUS = encode("++") + val SUB = MINUS // ... as does SUB with PLUS + val XOR = encode("^") + val ZAND = encode("&&") + val ZOR = encode("||") // unary operators val UNARY_~ = encode("unary_~") diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala index 3166eb7a99..798c7adf2e 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala @@ -229,13 +229,13 @@ trait MethodConstruction { self: QuasiquoteProperties => property("splice type name into annotation") = test { val name = TypeName("annot") - assertSameAnnots(q"@$name def foo", List(annot(name))) + assertSameAnnots(q"@$name def foo", List(q"new $name")) } property("splice ident into annotation") = test { val name = TypeName("annot") val ident = Ident(name) - assertSameAnnots(q"@$ident def foo", List(annot(name))) + assertSameAnnots(q"@$ident def foo", List(q"new $name")) } property("splice idents into annotation") = test { @@ -245,36 +245,36 @@ trait MethodConstruction { self: QuasiquoteProperties => } property("splice constructor calls into annotation") = test { - val ctorcalls = List(annot("a1"), annot("a2")) + val ctorcalls = List(q"new a1", q"new a2") assertSameAnnots(q"@..$ctorcalls def foo", ctorcalls) } property("splice multiple annotations (1)") = test { - val annot1 = annot("a1") - val annot2 = annot("a2") + val annot1 = q"new a1" + val annot2 = q"new a2" val res = q"@$annot1 @$annot2 def foo" assertSameAnnots(res, List(annot1, annot2)) } property("splice multiple annotations (2)") = test { - val annot1 = annot("a1") - val annots = List(annot("a2"), annot("a3")) + val annot1 = q"new a1" + val annots = List(q"new a2", q"new a3") val res = q"@$annot1 @..$annots def foo" assertSameAnnots(res, annot1 :: annots) } property("splice annotations with arguments (1)") = test { - val a = annot("a", List(q"x")) + val a = q"new a(x)" assertSameAnnots(q"@$a def foo", q"@a(x) def foo") } property("splice annotations with arguments (2)") = test { - val a = newTypeName("a") + val a = TypeName("a") assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") } property("splice annotations with arguments (3") = test { - val a = Ident(newTypeName("a")) + val a = Ident(TypeName("a")) assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") } @@ -286,7 +286,7 @@ trait MethodConstruction { self: QuasiquoteProperties => } property("can't splice annotations with arguments specificed twice") = test { - val a = annot("a", List(q"x")) + val a = q"new a(x)" assertThrows[IllegalArgumentException] { q"@$a(y) def foo" } diff --git a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala index 209fe9bbeb..88e00c734b 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala @@ -125,18 +125,28 @@ trait ModsDeconstruction { self: QuasiquoteProperties => } property("@..$annots def foo") = test { - val a = annot("a") - val b = annot("b") + val a = q"new a" + val b = q"new b" val q"@..$annots def foo" = q"@$a @$b def foo" annots ≈ List(a, b) } property("@$annot @..$annots def foo") = test { - val a = annot("a") - val b = annot("b") - val c = annot("c") + val a = q"new a" + val b = q"new b" + val c = q"new c" val q"@$first @..$rest def foo" = q"@$a @$b @$c def foo" - first ≈ a && rest ≈ List(b, c) + assert(first ≈ a) + assert(rest ≈ List(b, c)) + } + + property("@..$anots @$annot def foo") = test { + val a = q"new a" + val b = q"new b" + val c = q"new c" + val q"@..$init @$last def foo" = q"@$a @$b @$c def foo" + assert(init ≈ List(a, b)) + assert(last ≈ c) } } diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala index 3a66574c7d..1ba9bba381 100644 --- a/test/files/scalacheck/quasiquotes/ErrorProps.scala +++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala @@ -32,12 +32,6 @@ object ErrorProps extends QuasiquoteProperties("errors") { q"@...$annots def foo" """) - property("@..$first @$rest def foo") = fails( - "Can't extract with .. here", - """ - q"@a @b @c def foo" match { case q"@..$first @$rest def foo" => } - """) - property("only literal string arguments") = fails( "Quasiquotes can only be used with literal strings", """ @@ -140,12 +134,6 @@ object ErrorProps extends QuasiquoteProperties("errors") { q"$m1 $m2 def foo" """) - property("can't extract with .. card here") = fails( - "Can't extract with .. here", - """ - val q"f(..$xs, $y)" = EmptyTree - """) - property("can't extract mods with annots") = fails( "Can't extract modifiers together with annotations, consider extracting just modifiers", """ diff --git a/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala index cccf8095db..c8e66c7ef5 100644 --- a/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala @@ -22,8 +22,18 @@ object PatternDeconstructionProps extends QuasiquoteProperties("pattern deconstr pat0 ≈ pat && subpat0 ≈ subpat } + property("extract apply many") = forAll { (pat: Tree, subpats: List[Tree]) => + val pq"$pat0(..$subpats0)" = pq"$pat(..$subpats)" + pat0 ≈ pat && subpats0 ≈ subpats + } + + property("extract apply last") = forAll { (pat: Tree, subpats: List[Tree], subpatlast: Tree) => + val pq"$pat0(..$subpats0, $subpatlast0)" = pq"$pat(..$subpats, $subpatlast)" + pat0 ≈ pat && subpats0 ≈ subpats && subpatlast0 ≈ subpatlast + } + property("extract casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) => val cq"$pat0 if $cond0 => $body0" = cq"$pat if $cond => $body" pat0 ≈ pat && cond0 ≈ cond && body0 ≈ body } -}
\ No newline at end of file +} diff --git a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala index e4ee5dfcae..589b8d4d72 100644 --- a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala +++ b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala @@ -116,10 +116,5 @@ trait Helpers { } } - def annot(name: String): Tree = annot(TypeName(name), Nil) - 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)" - val scalapkg = build.setSymbol(Ident(TermName("scala")), definitions.ScalaPackage) } diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala index 54187d68c2..145e51ab68 100644 --- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala @@ -291,4 +291,9 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { val stats2 = List.empty[Tree] assert(q"{ ..$stats2 }" ≈ q"") } + + property("consistent variable order") = test { + val q"$a = $b = $c = $d = $e = $f = $g = $h = $k = $l" = q"a = b = c = d = e = f = g = h = k = l" + assert(a ≈ q"a" && b ≈ q"b" && c ≈ q"c" && d ≈ q"d" && e ≈ q"e" && g ≈ q"g" && h ≈ q"h" && k ≈ q"k" && l ≈ q"l") + } } diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala index 8d1ada342a..148bb383b0 100644 --- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala @@ -29,14 +29,34 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction y1 ≈ x1 && y2 ≈ x2 && ys ≈ List(x3) } + property("f(y1, ..ys, yn)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) => + val q"f($y1, ..$ys, $yn)" = q"f($x1, $x2, $x3, $x4)" + y1 ≈ x1 && ys ≈ List(x2, x3) && yn ≈ x4 + } + + property("f(..ys, y_{n-1}, y_n)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) => + val q"f(..$ys, $yn1, $yn)" = q"f($x1, $x2, $x3, $x4)" + ys ≈ List(x1, x2) && yn1 ≈ x3 && yn ≈ x4 + } + property("f(...xss)") = forAll { (x1: Tree, x2: Tree) => - val q"f(...$argss)" = q"f($x1)($x2)" - argss ≈ List(List(x1), List(x2)) + val q"f(...$xss)" = q"f($x1)($x2)" + xss ≈ List(List(x1), List(x2)) + } + + property("f(...$xss)(..$last)") = forAll { (x1: Tree, x2: Tree, x3: Tree) => + val q"f(...$xss)(..$last)" = q"f($x1)($x2)($x3)" + xss ≈ List(List(x1), List(x2)) && last ≈ List(x3) + } + + property("f(...$xss)(..$lastinit, $lastlast)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) => + val q"f(...$xss)(..$lastinit, $lastlast)" = q"f($x1)($x2, $x3, $x4)" + xss ≈ List(List(x1)) && lastinit ≈ List(x2, x3) && lastlast ≈ x4 } property("f(...xss) = f") = forAll { (x1: Tree, x2: Tree) => - val q"f(...$argss)" = q"f" - argss ≈ List() + val q"f(...$xss)" = q"f" + xss ≈ List() } property("deconstruct unit as tuple") = test { @@ -51,12 +71,27 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction property("deconstruct tuple mixed") = test { val q"($first, ..$rest)" = q"(a, b, c)" - assert(first ≈ q"a" && rest ≈ List(q"b", q"c")) + assert(first ≈ q"a") + assert(rest ≈ List(q"b", q"c")) + } + + property("deconstruct tuple last element") = test { + val q"($first, ..$rest, $last)" = q"(a, b, c, d)" + assert(first ≈ q"a") + assert(rest ≈ List(q"b", q"c")) + assert(last ≈ q"d") } property("deconstruct cases") = test { val q"$x match { case ..$cases }" = q"x match { case 1 => case 2 => }" - x ≈ q"x" && cases ≈ List(cq"1 =>", cq"2 =>") + assert(x ≈ q"x") + assert(cases ≈ List(cq"1 =>", cq"2 =>")) + } + + property("deconstruct splitting last case") = test { + val q"$_ match { case ..$cases case $last }" = q"x match { case 1 => case 2 => case 3 => }" + assert(cases ≈ List(cq"1 =>", cq"2 =>")) + assert(last ≈ cq"3 =>") } property("deconstruct block") = test { @@ -64,6 +99,12 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction assert(xs ≈ List(q"x1", q"x2", q"x3")) } + property("deconstruct last element of a block") = test { + val q"{ ..$xs; $x }" = q"x1; x2; x3; x4" + assert(xs ≈ List(q"x1", q"x2", q"x3")) + assert(x ≈ q"x4") + } + property("exhaustive function matcher") = test { def matches(line: String) { val q"(..$args) => $body" = parse(line) } matches("() => bippy") diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala index 499f5d6d8e..44f110a3d5 100644 --- a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala @@ -13,23 +13,43 @@ object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction a ≈ Ident(name1) && b ≈ Ident(name2) } - property("tuple type") = test { + property("tuple type (1)") = test { val tq"(..$empty)" = tq"_root_.scala.Unit" assert(empty.isEmpty) + } + + property("tuple type (2)") = test { val tq"(..$ts)" = tq"(t1, t2)" assert(ts ≈ List(tq"t1", tq"t2")) + } + + property("tuple type (3)") = test { val tq"($head, ..$tail)" = tq"(t0, t1, t2)" - assert(head ≈ tq"t0" && tail ≈ List(tq"t1", tq"t2")) + assert(head ≈ tq"t0") + assert(tail ≈ List(tq"t1", tq"t2")) + } + + property("tuple type (4)") = test { + val tq"(..$init, $last)" = tq"(t0, t1, t2)" + assert(init ≈ List(tq"t0", tq"t1")) + assert(last ≈ tq"t2") } property("refined type") = test { val tq"T { ..$stats }" = tq"T { def foo; val x: Int; type Y = String }" - assert(stats ≈ (q"def foo" :: q"val x: Int" :: q"type Y = String" :: Nil)) + assert(stats ≈ List(q"def foo", q"val x: Int", q"type Y = String")) } - property("function type") = test { + property("function type (1)") = test { val tq"..$argtpes => $restpe" = tq"(A, B) => C" - assert(argtpes ≈ (tq"A" :: tq"B" :: Nil)) + assert(argtpes ≈ List(tq"A", tq"B")) assert(restpe ≈ tq"C") } -}
\ No newline at end of file + + property("function type (2)") = test { + val tq"(..$argtpes, $arglast) => $restpe" = tq"(A, B, C) => D" + assert(argtpes ≈ List(tq"A", tq"B")) + assert(arglast ≈ tq"C") + assert(restpe ≈ tq"D") + } +} diff --git a/test/osgi/src/BasicReflection.scala b/test/osgi/src/BasicReflection.scala index 68fedb7c83..d601f04f89 100644 --- a/test/osgi/src/BasicReflection.scala +++ b/test/osgi/src/BasicReflection.scala @@ -2,6 +2,8 @@ package tools.test.osgi package reflection package basic +import scala.language.higherKinds + import org.junit.Assert._ import org.ops4j.pax.exam.CoreOptions._ diff --git a/test/osgi/src/ScalaOsgiHelper.scala b/test/osgi/src/ScalaOsgiHelper.scala index 7b14cf20e8..084afe8643 100644 --- a/test/osgi/src/ScalaOsgiHelper.scala +++ b/test/osgi/src/ScalaOsgiHelper.scala @@ -1,5 +1,5 @@ package tools.test.osgi - + import org.ops4j.pax.exam.CoreOptions._ import org.ops4j.pax.exam import java.io.File @@ -12,7 +12,7 @@ trait ScalaOsgiHelper { } private def filteredBundleFiles(names: String*): Array[exam.Option] = - for(bundle <- allBundleFiles; if names exists (bundle.getName contains)) + for(bundle <- allBundleFiles; if names exists (bundle.getName contains _)) yield makeBundle(bundle) private def makeBundle(file: File): exam.Option = @@ -34,5 +34,5 @@ trait ScalaOsgiHelper { val bundles = filteredBundleFiles("scala-library") bundles ++ Array[exam.Option](felix(), equinox(), junitBundles()) } - + } |