diff options
20 files changed, 527 insertions, 133 deletions
diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index d0a5b452a8..7944ab3fd3 100755 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -108,8 +108,22 @@ rm -rf $baseDir/resolutionScratch_ mkdir -p $baseDir/resolutionScratch_ # repo used to publish "locker" scala to (to start the bootstrap) -privateCred="private-repo" -privateRepo="http://private-repo.typesafe.com/typesafe/scala-release-temp/" +releaseTempRepoCred="private-repo" +releaseTempRepoUrl=${releaseTempRepoUrl-"http://private-repo.typesafe.com/typesafe/scala-release-temp/"} + +# Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs, +# so we need to configure SBT to use these rather than its default, Maven Central. +# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html +sbtRepositoryConfig="$scriptsDir/repositories-scala-release" +cat > "$sbtRepositoryConfig" << EOF +[repositories] + plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] + private-repo: $releaseTempRepoUrl + typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly + sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] + maven-central + local +EOF ##### git gfxd() { @@ -158,7 +172,7 @@ function st_stagingRepoClose() { # the old version (on jenkins, and I don't want to upgrade for risk of breaking other builds) honors -sbt-dir # the new version of sbt-extras ignores sbt-dir, so we pass it in as -Dsbt.global.base # need to set sbt-dir to one that has the gpg.sbt plugin config -sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$scriptsDir/repositories-scala-release -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13" +sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13" sbtBuild() { echo "### sbtBuild: "$sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" @@ -457,8 +471,8 @@ bootstrap() { # in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler ant -Dmaven.version.number=$SCALA_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$privateRepo\ - -Drepository.credentials.id=$privateCred\ + -Dremote.release.repository=$releaseTempRepoUrl\ + -Drepository.credentials.id=$releaseTempRepoCred\ -Dscalac.args.optimise=-optimise\ -Ddocs.skip=1\ -Dlocker.skip=1\ @@ -471,7 +485,7 @@ bootstrap() { # publish to our internal repo (so we can resolve the modules in the scala build below) # we only need to build the modules necessary to build Scala itself # since the version of locker and quick are the same - publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$privateRepo\")") + publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$releaseTempRepoUrl\")") buildTasks=($publishPrivateTask) buildModules @@ -496,14 +510,14 @@ bootstrap() { # which is fully cross-versioned (for $SCALA_VER, the version we're releasing) ant -Dstarr.version=$SCALA_VER\ -Dscala.full.version=$SCALA_VER\ - -Dextra.repo.url=$privateRepo\ + -Dextra.repo.url=$releaseTempRepoUrl\ -Dmaven.version.suffix=$SCALA_VER_SUFFIX\ ${updatedModuleVersions[@]} \ -Dupdate.versions=1\ -Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$privateRepo\ - -Drepository.credentials.id=$privateCred\ + -Dremote.release.repository=$releaseTempRepoUrl\ + -Drepository.credentials.id=$releaseTempRepoCred\ -Dscalac.args.optimise=-optimise\ $antBuildTask $publishPrivateTask diff --git a/scripts/repositories-scala-release b/scripts/repositories-scala-release deleted file mode 100644 index 00538a08ff..0000000000 --- a/scripts/repositories-scala-release +++ /dev/null @@ -1,7 +0,0 @@ -[repositories] - plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] - private-repo: http://private-repo.typesafe.com/typesafe/scala-release-temp/ - typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly - sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] - maven-central - local
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index 99399e363f..67241ef639 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -126,10 +126,9 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { def makeTextPat(txt: Tree) = Apply(_scala_xml__Text, List(txt)) def makeText1(txt: Tree) = New(_scala_xml_Text, LL(txt)) def comment(pos: Position, text: String) = atPos(pos)( Comment(const(text)) ) - def charData(pos: Position, txt: String) = atPos(pos) { - val t = if (isPattern) Apply(_scala_xml(xmlterms._PCData), List(const(txt))) - else New(_scala_xml(_PCData), LL(const(txt))) - if (coalescing) t updateAttachment TextAttache(pos, txt) else t + def charData(pos: Position, txt: String) = if (coalescing) text(pos, txt) else atPos(pos) { + if (isPattern) Apply(_scala_xml(xmlterms._PCData), List(const(txt))) + else New(_scala_xml(_PCData), LL(const(txt))) } def procInstr(pos: Position, target: String, txt: String) = diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index f217d21c35..630276e412 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -142,7 +142,7 @@ trait ScalaSettings extends AbsScalaSettings // XML parsing options object XxmlSettings extends MultiChoiceEnumeration { val coalescing = Choice("coalescing", "Convert PCData to Text and coalesce sibling nodes") - def isCoalescing = Xxml contains coalescing + def isCoalescing = (Xxml contains coalescing) || (!isScala212 && !Xxml.isSetByUser) } val Xxml = MultiChoiceSetting( name = "-Xxml", diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 994bcd8359..a59b9d3f48 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1141,16 +1141,12 @@ abstract class ClassfileParser { private def innerSymbol(entry: InnerClassEntry): Symbol = { val name = entry.originalName.toTypeName val enclosing = entry.enclosing - def getMember = ( + val member = ( if (enclosing == clazz) entry.scope lookup name else lookupMemberAtTyperPhaseIfPossible(enclosing, name) ) - getMember - /* There used to be an assertion that this result is not NoSymbol; changing it to an error - * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable - * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who - * thought it wasn't triggering, I removed it entirely. - */ + def newStub = enclosing.newStubSymbol(name, s"Unable to locate class corresponding to inner class entry for $name in owner ${entry.outerName}") + member.orElse(newStub) } } diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 94e88589f5..2d33b35241 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -15,13 +15,12 @@ import scala.collection.mutable.LinkedHashMap * Currently Uncurry is responsible for that transformation. * * From a lambda, Delambdafy will create - * 1) a static forwarder at the top level of the class that contained the lambda - * 2) a new top level class that + * 1) a new top level class that a) has fields and a constructor taking the captured environment (including possibly the "this" * reference) - * b) an apply method that calls the static forwarder + * b) an apply method that calls the target method * c) if needed a bridge method for the apply method - * 3) an instantiation of the newly created class which replaces the lambda + * 2) an instantiation of the newly created class which replaces the lambda * * TODO the main work left to be done is to plug into specialization. Primarily that means choosing a * specialized FunctionN trait instead of the generic FunctionN trait as a parent and creating the @@ -76,36 +75,25 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre referrers } - val accessorMethods = mutable.ArrayBuffer[Tree]() - - // the result of the transformFunction method. A class definition for the lambda, an expression - // insantiating the lambda class, and an accessor method for the lambda class to be able to - // call the implementation - case class TransformedFunction(lambdaClassDef: ClassDef, newExpr: Tree, accessorMethod: Tree) + // the result of the transformFunction method. + sealed abstract class TransformedFunction + // A class definition for the lambda, an expression insantiating the lambda class + case class DelambdafyAnonClass(lambdaClassDef: ClassDef, newExpr: Tree) extends TransformedFunction // here's the main entry point of the transform override def transform(tree: Tree): Tree = tree match { // the main thing we care about is lambdas case fun @ Function(_, _) => - // a lambda beccomes a new class, an instantiation expression, and an - // accessor method - val TransformedFunction(lambdaClassDef, newExpr, accessorMethod) = transformFunction(fun) - // we'll add accessor methods to the current template later - accessorMethods += accessorMethod - val pkg = lambdaClassDef.symbol.owner - - // we'll add the lambda class to the package later - lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg) - - super.transform(newExpr) - // when we encounter a template (basically the thing that holds body of a class/trait) - // we need to updated it to include newly created accessor methods after transforming it - case Template(_, _, _) => - try { - // during this call accessorMethods will be populated from the Function case - val Template(parents, self, body) = super.transform(tree) - Template(parents, self, body ++ accessorMethods) - } finally accessorMethods.clear() + transformFunction(fun) match { + case DelambdafyAnonClass(lambdaClassDef, newExpr) => + // a lambda beccomes a new class, an instantiation expression + val pkg = lambdaClassDef.symbol.owner + + // we'll add the lambda class to the package later + lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg) + + super.transform(newExpr) + } case _ => super.transform(tree) } @@ -120,8 +108,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre private def optionSymbol(sym: Symbol): Option[Symbol] = if (sym.exists) Some(sym) else None - // turns a lambda into a new class def, a New expression instantiating that class, and an - // accessor method fo the body of the lambda + // turns a lambda into a new class def, a New expression instantiating that class private def transformFunction(originalFunction: Function): TransformedFunction = { val functionTpe = originalFunction.tpe val targs = functionTpe.typeArgs @@ -132,46 +119,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // passed into the constructor of the anonymous function class val captures = FreeVarTraverser.freeVarsOf(originalFunction) - /** - * Creates the apply method for the anonymous subclass of FunctionN - */ - def createAccessorMethod(thisProxy: Symbol, fun: Function): DefDef = { - val target = targetMethod(fun) - if (!thisProxy.exists) { - target setFlag STATIC - } - val params = ((optionSymbol(thisProxy) map {proxy:Symbol => ValDef(proxy)}) ++ (target.paramss.flatten map ValDef.apply)).toList - - val methSym = oldClass.newMethod(unit.freshTermName(nme.accessor.toString() + "$"), target.pos, FINAL | BRIDGE | SYNTHETIC | PROTECTED | STATIC) + val target = targetMethod(originalFunction) + target.makeNotPrivate(target.owner) + if (!thisReferringMethods.contains(target)) + target setFlag STATIC - val paramSyms = params map {param => methSym.newSyntheticValueParam(param.symbol.tpe, param.name) } - - params zip paramSyms foreach { case (valdef, sym) => valdef.symbol = sym } - params foreach (_.symbol.owner = methSym) - - val methodType = MethodType(paramSyms, restpe) - methSym setInfo methodType - - oldClass.info.decls enter methSym - - val body = localTyper.typed { - val newTarget = Select(if (thisProxy.exists) gen.mkAttributedRef(paramSyms(0)) else gen.mkAttributedThis(oldClass), target) - val newParams = paramSyms drop (if (thisProxy.exists) 1 else 0) map Ident - Apply(newTarget, newParams) - } setPos fun.pos - val methDef = DefDef(methSym, List(params), body) - - // Have to repack the type to avoid mismatches when existentials - // appear in the result - see SI-4869. - // TODO probably don't need packedType - methDef.tpt setType localTyper.packedType(body, methSym) - methDef - } /** * Creates the apply method for the anonymous subclass of FunctionN */ - def createApplyMethod(newClass: Symbol, fun: Function, accessor: DefDef, thisProxy: Symbol): DefDef = { + def createApplyMethod(newClass: Symbol, fun: Function, thisProxy: Symbol): DefDef = { val methSym = newClass.newMethod(nme.apply, fun.pos, FINAL | SYNTHETIC) val params = fun.vparams map (_.duplicate) @@ -187,8 +144,12 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre newClass.info.decls enter methSym val Apply(_, oldParams) = fun.body + val qual = if (thisProxy.exists) + Select(gen.mkAttributedThis(newClass), thisProxy) + else + gen.mkAttributedThis(oldClass) // sort of a lie, EmptyTree.<static method> would be more honest, but the backend chokes on that. - val body = localTyper typed Apply(Select(gen.mkAttributedThis(oldClass), accessor.symbol), (optionSymbol(thisProxy) map {tp => Select(gen.mkAttributedThis(newClass), tp)}).toList ++ oldParams) + val body = localTyper typed Apply(Select(qual, target), oldParams) body.substituteSymbols(fun.vparams map (_.symbol), params map (_.symbol)) body changeOwner (fun.symbol -> methSym) @@ -271,18 +232,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // the Optional proxy that will hold a reference to the 'this' // object used by the lambda, if any. NoSymbol if there is no this proxy val thisProxy = { - val target = targetMethod(originalFunction) - if (thisReferringMethods contains target) { + if (target.hasFlag(STATIC)) + NoSymbol + else { val sym = lambdaClass.newVariable(nme.FAKE_LOCAL_THIS, originalFunction.pos, SYNTHETIC) - sym.info = oldClass.tpe - sym - } else NoSymbol + sym.setInfo(oldClass.tpe) + } } val decapturify = new DeCapturifyTransformer(captureProxies2, unit, oldClass, lambdaClass, originalFunction.symbol.pos, thisProxy) - val accessorMethod = createAccessorMethod(thisProxy, originalFunction) - val decapturedFunction = decapturify.transform(originalFunction).asInstanceOf[Function] val members = (optionSymbol(thisProxy).toList ++ (captureProxies2 map (_._2))) map {member => @@ -294,7 +253,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val constr = createConstructor(lambdaClass, members) // apply method with same arguments and return type as original lambda. - val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, accessorMethod, thisProxy) + val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, thisProxy) val bridgeMethod = createBridgeMethod(lambdaClass, originalFunction, applyMethodDef) @@ -312,10 +271,10 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod // TODO if member fields are private this complains that they're not accessible - (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy, accessorMethod) + (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy) } - val (anonymousClassDef, thisProxy, accessorMethod) = makeAnonymousClass + val (anonymousClassDef, thisProxy) = makeAnonymousClass pkg.info.decls enter anonymousClassDef.symbol @@ -327,7 +286,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val typedNewStat = localTyper.typedPos(originalFunction.pos)(newStat) - TransformedFunction(anonymousClassDef, typedNewStat, accessorMethod) + DelambdafyAnonClass(anonymousClassDef, typedNewStat) } /** diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index eaae05bed5..554b43afaf 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -3,7 +3,7 @@ package api trait Quasiquotes { self: Universe => - /** Implicit class that introduces `q`, `tq`, `cq,` `p` and `fq` string interpolators + /** Implicit class that introduces `q`, `tq`, `cq,` `pq` and `fq` string interpolators * that are also known as quasiquotes. With their help you can easily manipulate * Scala reflection ASTs. * diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala index c80b94bf89..1ccade2172 100644 --- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala +++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala @@ -8,6 +8,7 @@ package tools.nsc package interpreter import java.lang.{ ClassLoader => JavaClassLoader, Iterable => JIterable } +import scala.tools.asm.Opcodes import scala.tools.nsc.util.ScalaClassLoader import java.io.{ ByteArrayInputStream, CharArrayWriter, FileNotFoundException, PrintWriter, StringWriter, Writer } import java.util.{ Locale } @@ -758,32 +759,19 @@ object JavapClass { import scala.tools.asm.ClassReader import scala.tools.asm.Opcodes.INVOKESTATIC import scala.tools.asm.tree.{ ClassNode, MethodInsnNode } - // the accessor methods invoked statically by the apply of the given closure class - def accesses(s: String): Seq[(String, String)] = { - val accessor = """accessor\$\d+""".r + def callees(s: String): List[(String, String)] = { loader classReader s withMethods { ms => - ms filter (_.name == "apply") flatMap (_.instructions.toArray.collect { - case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && when(i.name) { case accessor(_*) => true } => (i.owner, i.name) - }) + val nonBridgeApplyMethods = ms filter (_.name == "apply") filter (n => (n.access & Opcodes.ACC_BRIDGE) == 0) + val instructions = nonBridgeApplyMethods flatMap (_.instructions.toArray) + instructions.collect { + case i: MethodInsnNode => (i.owner, i.name) + }.toList } } - // get the k.$anonfun for the accessor k.m - def anonOf(k: String, m: String): String = { - val res = - loader classReader k withMethods { ms => - ms filter (_.name == m) flatMap (_.instructions.toArray.collect { - case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && i.name.startsWith("$anonfun") => i.name - }) - } - assert(res.size == 1) - res.head - } - // the lambdas invoke accessors that call the anonfuns of interest. Filter k on the k#$anonfuns. - val ack = accesses(lambda) - assert(ack.size == 1) // There can be only one. - ack.head match { - case (k, _) if target.isModule && !(k endsWith "$") => None - case (k, m) => Some(s"${k}#${anonOf(k, m)}") + callees(lambda) match { + case (k, _) :: Nil if target.isModule && !(k endsWith "$") => None + case (k, m) :: _ => Some(s"${k}#${m}") + case _ => None } } /** Translate the supplied targets to patterns for anonfuns. diff --git a/test/files/run/repl-javap-lambdas.scala b/test/files/run/repl-javap-lambdas.scala index c503c99d66..76a6ec8450 100644 --- a/test/files/run/repl-javap-lambdas.scala +++ b/test/files/run/repl-javap-lambdas.scala @@ -16,7 +16,7 @@ object Test extends JavapTest { // three anonfuns of Betty#g override def yah(res: Seq[String]) = { import PartialFunction.{ cond => when } - val r = """\s*private static final .* \$anonfun\$\d+\(.*""".r + val r = """.*final .* .*\$anonfun\$\d+\(.*""".r def filtered = res filter (when(_) { case r(_*) => true }) 3 == filtered.size } diff --git a/test/files/run/t3368-b.check b/test/files/run/t3368-b.check new file mode 100644 index 0000000000..4cbe98c577 --- /dev/null +++ b/test/files/run/t3368-b.check @@ -0,0 +1,89 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("start")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuff")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.PCData("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("x")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-b.scala b/test/files/run/t3368-b.scala new file mode 100644 index 0000000000..108cb9a5ee --- /dev/null +++ b/test/files/run/t3368-b.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // not coalescing + override def extraSettings = s"${super.extraSettings} -Xxml:-coalescing" +} diff --git a/test/files/run/t3368-c.check b/test/files/run/t3368-c.check new file mode 100644 index 0000000000..e0c10cc0dd --- /dev/null +++ b/test/files/run/t3368-c.check @@ -0,0 +1,85 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.Text("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.Text("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-c.scala b/test/files/run/t3368-c.scala new file mode 100644 index 0000000000..5121794463 --- /dev/null +++ b/test/files/run/t3368-c.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // default coalescing behavior, whatever that is today. + //override def extraSettings = s"${super.extraSettings} -Xxml:coalescing" +} diff --git a/test/files/run/t3368-d.check b/test/files/run/t3368-d.check new file mode 100644 index 0000000000..4cbe98c577 --- /dev/null +++ b/test/files/run/t3368-d.check @@ -0,0 +1,89 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("start")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuff")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + }: _*)) + } + } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.PCData("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("x")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368-d.scala b/test/files/run/t3368-d.scala new file mode 100644 index 0000000000..5777c1a81e --- /dev/null +++ b/test/files/run/t3368-d.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } + """ + + // default under 2.12 is not coalescing + override def extraSettings = s"${super.extraSettings} -Xsource:212" +} diff --git a/test/files/run/t3368.check b/test/files/run/t3368.check index 1d9dd677f6..e0c10cc0dd 100644 --- a/test/files/run/t3368.check +++ b/test/files/run/t3368.check @@ -6,8 +6,8 @@ package <empty> { }; def x = { val $buf = new _root_.scala.xml.NodeBuffer(); - $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); - $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.Text("red & black")); $buf } }; @@ -41,6 +41,45 @@ package <empty> { }: _*)) } } + }; + abstract trait Z extends scala.AnyRef { + def $init$() = { + () + }; + def d = new _root_.scala.xml.Text("hello, world"); + def e = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }; + def f = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world")); + $buf + }: _*)) + } + }; + def g = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, world")); + $buf + }: _*)) + } + }; + def h = { + { + new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world")); + $buf + }: _*)) + } + } } } diff --git a/test/files/run/t3368.scala b/test/files/run/t3368.scala index 15acba5099..284fed0784 100644 --- a/test/files/run/t3368.scala +++ b/test/files/run/t3368.scala @@ -12,7 +12,15 @@ object Test extends ParserTest { trait Y { def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> } + trait Z { + def d = <![CDATA[hello, world]]> + def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced + def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text + def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing + def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo> + } """ + // coalescing override def extraSettings = s"${super.extraSettings} -Xxml:coalescing" } diff --git a/test/files/run/t9268.check b/test/files/run/t9268.check new file mode 100644 index 0000000000..90ef940eb3 --- /dev/null +++ b/test/files/run/t9268.check @@ -0,0 +1,5 @@ +Compiling Client1 +pos: NoPosition Class Waiter not found - continuing with a stub. WARNING +Compiling Client2 +pos: NoPosition Class Waiter not found - continuing with a stub. WARNING +pos: NoPosition Unable to locate class corresponding to inner class entry for Predicate in owner Waiter ERROR diff --git a/test/files/run/t9268/Java.java b/test/files/run/t9268/Java.java new file mode 100644 index 0000000000..c9a0bec3ff --- /dev/null +++ b/test/files/run/t9268/Java.java @@ -0,0 +1,12 @@ +public class Java { +} + +class Partial { + public <E extends java.lang.Exception> long waitFor(long l, Waiter.Predicate<E> pred) throws E { + return 0L; + } +} + +class Waiter { + interface Predicate<E> {} +} diff --git a/test/files/run/t9268/Test.scala b/test/files/run/t9268/Test.scala new file mode 100644 index 0000000000..813cbe7b60 --- /dev/null +++ b/test/files/run/t9268/Test.scala @@ -0,0 +1,40 @@ +import scala.tools.partest._ +import java.io.File + +object Test extends StoreReporterDirectTest { + def code = ??? + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } + + def client1 = """ + class Client1 { def p(p: Partial) = p.toString } + """ + + def client2 = """ + class Client2 { def p(p: Partial) = p.waitFor() } + """ + + def deleteClass(s: String) = { + val f = new File(testOutput.path, s + ".class") + assert(f.exists) + f.delete() + } + + def show(): Unit = { + deleteClass("Waiter") + deleteClass("Waiter$Predicate") + + // Used to crash in Java Generic Signature parsing + println("Compiling Client1") + compileCode(client1) + println(storeReporter.infos.mkString("\n")) + storeReporter.reset() + println("Compiling Client2") + compileCode(client2) + println(storeReporter.infos.mkString("\n")) + } +} + |