summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-03-18 10:42:20 -0700
committerPaul Phillips <paulp@improving.org>2012-03-18 10:42:20 -0700
commit513232f251f1e1ce89adbde53fa1ccec67bda24d (patch)
tree7792247e953f37dc6c05fe64baeb0841811f31cd /src
parentf90efea9600cd9bd39537b256e371a093aa994cd (diff)
parentb3efb3d493605d1c7e106e5f0a697b52ebb3d97c (diff)
downloadscala-513232f251f1e1ce89adbde53fa1ccec67bda24d.tar.gz
scala-513232f251f1e1ce89adbde53fa1ccec67bda24d.tar.bz2
scala-513232f251f1e1ce89adbde53fa1ccec67bda24d.zip
Merge remote-tracking branches 'axel22/feature/checkinit-transient' and 'jsuereth/mirrored-seq-extractors' into develop
Diffstat (limited to 'src')
-rw-r--r--src/build/maven/maven-deploy.xml38
-rw-r--r--src/build/pack.xml2
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala15
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala51
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala17
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala122
-rwxr-xr-x[-rw-r--r--]src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala33
-rwxr-xr-x[-rw-r--r--]src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala22
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala88
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
-rwxr-xr-xsrc/compiler/scala/tools/nsc/util/DocStrings.scala87
-rw-r--r--src/library/scala/collection/SeqExtractors.scala21
-rw-r--r--src/library/scala/collection/mutable/ConcurrentTrieMap.scala (renamed from src/library/scala/collection/mutable/Ctrie.scala)100
-rw-r--r--src/library/scala/collection/parallel/mutable/ParConcurrentTrieMap.scala (renamed from src/library/scala/collection/parallel/mutable/ParCtrie.scala)54
-rw-r--r--src/library/scala/package.scala3
-rw-r--r--src/library/scala/reflect/api/Modifier.scala2
-rw-r--r--src/library/scala/util/Properties.scala24
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/Elem.scala35
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/Node.scala2
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/PrettyPrinter.scala2
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/Utility.scala63
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/XML.scala19
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/factory/Binder.scala10
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/parsing/ConstructingHandler.scala4
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/parsing/DefaultMarkupHandler.scala2
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/parsing/MarkupHandler.scala3
-rwxr-xr-x[-rw-r--r--]src/library/scala/xml/parsing/MarkupParser.scala2
-rwxr-xr-xsrc/library/scala/xml/pull/XMLEventReader.scala2
-rw-r--r--src/partest/scala/tools/partest/CompilerTest.scala35
-rw-r--r--src/partest/scala/tools/partest/DirectTest.scala2
34 files changed, 565 insertions, 318 deletions
diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml
index 2e490163e0..e0f31a5db2 100644
--- a/src/build/maven/maven-deploy.xml
+++ b/src/build/maven/maven-deploy.xml
@@ -16,10 +16,15 @@
<property name="local.release.repository" value="${user.home}/.m2/repository" />
<property name="repository.credentials.id" value="sonatype-nexus" />
<property name="settings.file" value="${user.home}/.m2/settings.xml" />
-
+ <condition property="version.is.snapshot">
+ <contains string="${maven.version.number}" substring="-SNAPSHOT"/>
+ </condition>
+
<echo>Using server[${repository.credentials.id}] for maven repository credentials.
Please make sure that your ~/.m2/settings.xml has the needed username/password for this server id
</echo>
+
+
</target>
<target name="init.maven" depends="init.properties">
@@ -241,28 +246,31 @@
</target>
<!-- Local Targets -->
- <target name="deploy.snapshot.local" depends="deploy.local.init" description="Deploys the bundled snapshot of the Scala Lanaguage to a local maven repository">
- <deploy-local-all version="${maven.snapshot.version.number}" repository="${local.snapshot.repository}" />
+ <target name="deploy.snapshot.local" depends="deploy.local.init" if="version.is.snapshot" description="Deploys the bundled snapshot of the Scala Lanaguage to a local maven repository">
+ <deploy-local-all version="${maven.version.number}" repository="${local.snapshot.repository}" />
</target>
- <target name="deploy.release.local" depends="deploy.local.init" description="Deploys the bundled files as a release into the local Maven repository">
- <deploy-local-all version="${version.number}" repository="${local.release.repository}" />
+ <target name="deploy.release.local" depends="deploy.local.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the local Maven repository">
+ <deploy-local-all version="${maven.version.number}" repository="${local.release.repository}" />
</target>
+ <target name="deploy.local" depends="deploy.snapshot.local, deploy.release.local" description="Deploys the bundle files to the local maven repo."/>
- <!-- Remote Targets -->
- <target name="deploy.signed.snapshot" depends="deploy.remote.init" description="Deploys the bundled files as a snapshot into the desired remote Maven repository">
- <deploy-remote-signed-all version="${maven.snapshot.version.number}" repository="${remote.snapshot.repository}" />
+ <!-- Remote Signed Targets -->
+ <target name="deploy.signed.snapshot" depends="deploy.remote.init" if="version.is.snapshot" description="Deploys the bundled files as a snapshot into the desired remote Maven repository">
+ <deploy-remote-signed-all version="${maven.version.number}" repository="${remote.snapshot.repository}" />
</target>
- <target name="deploy.signed.release" depends="deploy.remote.init" description="Deploys the bundled files as a release into the desired remote Maven repository">
- <deploy-remote-signed-all version="${version.number}" repository="${remote.release.repository}" />
+ <target name="deploy.signed.release" depends="deploy.remote.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the desired remote Maven repository">
+ <deploy-remote-signed-all version="${maven.version.number}" repository="${remote.release.repository}" />
</target>
-
- <target name="deploy.snapshot" depends="deploy.remote.init" description="Deploys the bundled files as a snapshot into the desired remote Maven repository">
- <deploy-remote-all version="${maven.snapshot.version.number}" repository="${remote.snapshot.repository}" />
+ <target name="deploy.signed" depends="deploy.signed.release, deploy.signed.snapshot" description="Deploys signed bundles to remote repo"/>
+ <!-- Remote unsigned targets -->
+ <target name="deploy.snapshot" depends="deploy.remote.init" if="version.is.snapshot" description="Deploys the bundled files as a snapshot into the desired remote Maven repository">
+ <deploy-remote-all version="${maven.version.number}" repository="${remote.snapshot.repository}" />
</target>
- <target name="deploy.release" depends="deploy.remote.init" description="Deploys the bundled files as a release into the desired remote Maven repository">
- <deploy-remote-all version="${version.number}" repository="${remote.release.repository}" />
+ <target name="deploy.release" depends="deploy.remote.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the desired remote Maven repository">
+ <deploy-remote-all version="${maven.version.number}" repository="${remote.release.repository}" />
</target>
+ <target name="deploy" depends="deploy.snapshot, deploy.release" description="Deploys unsigned artifacts to the maven repo."/>
</project>
diff --git a/src/build/pack.xml b/src/build/pack.xml
index 1b0cf19151..e79895e3a8 100644
--- a/src/build/pack.xml
+++ b/src/build/pack.xml
@@ -315,8 +315,6 @@ MAIN DISTRIBUTION SBAZ
<copy tofile="${dists.dir}/maven/${version.number}/build.xml"
file="${src.dir}/build/maven/maven-deploy.xml"/>
<!-- export properties for use when deploying -->
- <property name="maven.snapshot.version.number"
- value="${version.major}.${version.minor}.${version.patch}-SNAPSHOT"/>
<echoproperties destfile="${dists.dir}/maven/${version.number}/build.properties"/>
</target>
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 1d53b83b75..bd823c3128 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -904,6 +904,20 @@ trait Definitions extends reflect.api.StandardDefinitions {
def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name))
def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name))
+ def findMemberFromRoot(fullName: Name): Symbol = {
+ val segs = nme.segments(fullName.toString, fullName.isTermName)
+ if (segs.isEmpty) NoSymbol
+ else findNamedMember(segs.tail, definitions.RootClass.info member segs.head)
+ }
+ def findNamedMember(fullName: Name, root: Symbol): Symbol = {
+ val segs = nme.segments(fullName.toString, fullName.isTermName)
+ if (segs.isEmpty || segs.head != root.simpleName) NoSymbol
+ else findNamedMember(segs.tail, root)
+ }
+ def findNamedMember(segs: List[Name], root: Symbol): Symbol =
+ if (segs.isEmpty) root
+ else findNamedMember(segs.tail, root.info member segs.head)
+
def getMember(owner: Symbol, name: Name): Symbol = {
if (owner == NoSymbol) NoSymbol
else owner.info.nonPrivateMember(name) match {
@@ -911,6 +925,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
case result => result
}
}
+
def packageExists(packageName: String): Boolean =
getModuleIfDefined(packageName).isPackage
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index 270491d078..8aae80eed4 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -468,33 +468,34 @@ class Flags extends ModifierFlags {
protected final val rawFlagPickledOrder: Array[Long] = pickledListOrder.toArray
def flagOfModifier(mod: Modifier): Long = mod match {
- case Modifier.`protected` => PROTECTED
- case Modifier.`private` => PRIVATE
- case Modifier.`override` => OVERRIDE
- case Modifier.`abstract` => ABSTRACT
- case Modifier.`final`=> FINAL
- case Modifier.`sealed`=> SEALED
- case Modifier.`implicit`=> IMPLICIT
- case Modifier.`lazy`=> LAZY
- case Modifier.`case`=> CASE
- case Modifier.`trait`=> TRAIT
- case Modifier.deferred => DEFERRED
- case Modifier.interface => INTERFACE
- case Modifier.mutable => MUTABLE
- case Modifier.parameter => PARAM
- case Modifier.`macro` => MACRO
- case Modifier.covariant => COVARIANT
- case Modifier.contravariant => CONTRAVARIANT
- case Modifier.preSuper => PRESUPER
+ case Modifier.`protected` => PROTECTED
+ case Modifier.`private` => PRIVATE
+ case Modifier.`override` => OVERRIDE
+ case Modifier.`abstract` => ABSTRACT
+ case Modifier.`final` => FINAL
+ case Modifier.`sealed` => SEALED
+ case Modifier.`implicit` => IMPLICIT
+ case Modifier.`lazy` => LAZY
+ case Modifier.`case` => CASE
+ case Modifier.`trait` => TRAIT
+ case Modifier.deferred => DEFERRED
+ case Modifier.interface => INTERFACE
+ case Modifier.mutable => MUTABLE
+ case Modifier.parameter => PARAM
+ case Modifier.`macro` => MACRO
+ case Modifier.covariant => COVARIANT
+ case Modifier.contravariant => CONTRAVARIANT
+ case Modifier.preSuper => PRESUPER
case Modifier.abstractOverride => ABSOVERRIDE
- case Modifier.local => LOCAL
- case Modifier.java => JAVA
- case Modifier.static => STATIC
- case Modifier.caseAccessor => CASEACCESSOR
+ case Modifier.local => LOCAL
+ case Modifier.java => JAVA
+ case Modifier.static => STATIC
+ case Modifier.caseAccessor => CASEACCESSOR
case Modifier.defaultParameter => DEFAULTPARAM
- case Modifier.defaultInit => DEFAULTINIT
- case Modifier.paramAccessor => PARAMACCESSOR
- case Modifier.bynameParameter => BYNAMEPARAM
+ case Modifier.defaultInit => DEFAULTINIT
+ case Modifier.paramAccessor => PARAMACCESSOR
+ case Modifier.bynameParameter => BYNAMEPARAM
+ case _ => 0
}
def flagsOfModifiers(mods: List[Modifier]): Long =
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index bc2cc8191c..9ccd0c28db 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -44,6 +44,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
with symtab.Positions {
override def settings = currentSettings
+
+ import definitions.{ findNamedMember, findMemberFromRoot }
// alternate constructors ------------------------------------------
@@ -1494,21 +1496,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
afterPhase(phase) { currentRun.units foreach (treePrinter.print(_)) }
}
- private def findMemberFromRoot(fullName: Name): Symbol = {
- val segs = nme.segments(fullName.toString, fullName.isTermName)
- if (segs.isEmpty) NoSymbol
- else findNamedMember(segs.tail, definitions.RootClass.info member segs.head)
- }
-
- private def findNamedMember(fullName: Name, root: Symbol): Symbol = {
- val segs = nme.segments(fullName.toString, fullName.isTermName)
- if (segs.isEmpty || segs.head != root.simpleName) NoSymbol
- else findNamedMember(segs.tail, root)
- }
- private def findNamedMember(segs: List[Name], root: Symbol): Symbol =
- if (segs.isEmpty) root
- else findNamedMember(segs.tail, root.info member segs.head)
-
/** We resolve the class/object ambiguity by passing a type/term name.
*/
def showDef(fullName: Name, declsOnly: Boolean, ph: Phase) = {
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index 6a6379cca2..678f7b3028 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -19,6 +19,8 @@ import scala.collection.mutable
*/
trait DocComments { self: Global =>
+ var cookedDocComments = Map[Symbol, String]()
+
def reporter: Reporter
/** The raw doc comment map */
@@ -50,21 +52,29 @@ trait DocComments { self: Global =>
else sym.owner.ancestors map (sym overriddenSymbol _) filter (_ != NoSymbol)
}
- /** The raw doc comment of symbol `sym`, minus @usecase and @define sections, augmented by
+ /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by
* missing sections of an inherited doc comment.
* If a symbol does not have a doc comment but some overridden version of it does,
* the doc comment of the overridden version is copied instead.
*/
- def cookedDocComment(sym: Symbol, docStr: String = ""): String = {
- val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
- else DocComment(docStr).template
- superComment(sym) match {
- case None =>
- ownComment
- case Some(sc) =>
- if (ownComment == "") sc
- else merge(sc, ownComment, sym)
- }
+ def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.get(sym) match {
+ case Some(comment) =>
+ comment
+ case None =>
+ val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
+ else DocComment(docStr).template
+ val comment = superComment(sym) match {
+ case None =>
+ if (ownComment.indexOf("@inheritdoc") != -1)
+ reporter.warning(sym.pos, "The comment for " + sym +
+ " contains @inheritdoc, but no parent comment is available to inherit from.")
+ ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
+ case Some(sc) =>
+ if (ownComment == "") sc
+ else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
+ }
+ cookedDocComments += (sym -> comment)
+ comment
}
/** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
@@ -99,10 +109,18 @@ trait DocComments { self: Global =>
*/
def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = {
def getUseCases(dc: DocComment) = {
- for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield
- (defn,
- expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site),
- uc.pos)
+ val fullSigComment = cookedDocComment(sym)
+ for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield {
+ // use cases comments go through a series of transformations:
+ // 1 - filling in missing sections from the full signature
+ // 2 - expanding explicit inheritance @inheritdoc tags
+ // 3 - expanding variables like $COLL
+ val useCaseCommentRaw = uc.comment.raw
+ val useCaseCommentMerged = merge(fullSigComment, useCaseCommentRaw, defn)
+ val useCaseCommentInheritdoc = expandInheritdoc(fullSigComment, useCaseCommentMerged, sym)
+ val useCaseCommentVariables = expandVariables(useCaseCommentInheritdoc, sym, site)
+ (defn, useCaseCommentVariables, uc.pos)
+ }
}
getDocComment(sym) map getUseCases getOrElse List()
}
@@ -201,6 +219,80 @@ trait DocComments { self: Global =>
}
}
+ /**
+ * Expand inheritdoc tags
+ * - for the main comment we transform the inheritdoc into the super variable,
+ * and the variable expansion can expand it further
+ * - for the param, tparam and throws sections we must replace comments on the spot
+ *
+ * This is done separately, for two reasons:
+ * 1. It takes longer to run compared to merge
+ * 2. The inheritdoc annotation should not be used very often, as building the comment from pieces severely
+ * impacts performance
+ */
+ def expandInheritdoc(src: String, dst: String, sym: Symbol): String =
+ if (dst.indexOf("@inheritdoc") == -1)
+ dst
+ else {
+ val srcSections = tagIndex(src)
+ val dstSections = tagIndex(dst)
+ val srcTagMap = sectionTagMap(src, srcSections)
+ val srcNamedParams = Map() +
+ ("@param" -> paramDocs(src, "@param", srcSections)) +
+ ("@tparam" -> paramDocs(src, "@tparam", srcSections)) +
+ ("@throws" -> paramDocs(src, "@throws", srcSections))
+
+ val out = new StringBuilder
+
+ def replaceInheritdoc(src: String, dst: String) =
+ if (dst.indexOf("@inheritdoc") == -1)
+ dst
+ else
+ dst.replaceAllLiterally("@inheritdoc", src)
+
+ def getSourceSection(section: (Int, Int)): String = {
+
+ def getSectionHeader = extractSectionTag(dst, section) match {
+ case param@("@param"|"@tparam"|"@throws") => param + " " + extractSectionParam(dst, section)
+ case other => other
+ }
+
+ def sectionString(param: String, paramMap: Map[String, (Int, Int)]): String =
+ paramMap.get(param) match {
+ case Some(section) =>
+ // Cleanup the section tag and parameter
+ val sectionTextBounds = extractSectionText(src, section)
+ cleanupSectionText(src.substring(sectionTextBounds._1, sectionTextBounds._2))
+ case None =>
+ reporter.info(sym.pos, "The \"" + getSectionHeader + "\" annotation of the " + sym +
+ " comment contains @inheritdoc, but the corresponding section in the parent is not defined.", true)
+ "<invalid inheritdoc annotation>"
+ }
+
+ dst.substring(section._1, section._1 + 7) match {
+ case param@("@param "|"@tparam"|"@throws") => sectionString(extractSectionParam(dst, section), srcNamedParams(param.trim))
+ case _ => sectionString(extractSectionTag(dst, section), srcTagMap)
+ }
+ }
+
+ def mainComment(str: String, sections: List[(Int, Int)]): String =
+ if (str.trim.length > 3)
+ str.trim.substring(3, startTag(str, sections))
+ else
+ ""
+
+ // Append main comment
+ out.append("/**")
+ out.append(replaceInheritdoc(mainComment(src, srcSections), mainComment(dst, dstSections)))
+
+ // Append sections
+ for (section <- dstSections)
+ out.append(replaceInheritdoc(getSourceSection(section), dst.substring(section._1, section._2)))
+
+ out.append("*/")
+ out.toString
+ }
+
/** Maps symbols to the variable -> replacement maps that are defined
* in their doc comments
*/
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 46ade7d889..93fa9a60f6 100644..100755
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -267,7 +267,7 @@ trait MarkupParsers {
val (qname, attrMap) = xTag(())
if (ch == '/') { // empty element
xToken("/>")
- handle.element(r2p(start, start, curOffset), qname, attrMap, new ListBuffer[Tree])
+ handle.element(r2p(start, start, curOffset), qname, attrMap, true, new ListBuffer[Tree])
}
else { // handle content
xToken('>')
@@ -281,7 +281,7 @@ trait MarkupParsers {
val pos = r2p(start, start, curOffset)
qname match {
case "xml:group" => handle.group(pos, ts)
- case _ => handle.element(pos, qname, attrMap, ts)
+ case _ => handle.element(pos, qname, attrMap, false, ts)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index cd64c49b47..ccebcfa54d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -126,7 +126,7 @@ self =>
val global: Global
import global._
- case class OpInfo(operand: Tree, operator: Name, targs: List[Tree], offset: Offset)
+ case class OpInfo(operand: Tree, operator: Name, offset: Offset)
class SourceFileParser(val source: SourceFile) extends Parser {
@@ -789,7 +789,7 @@ self =>
val rPos = top.pos
val end = if (rPos.isDefined) rPos.endOrPoint else opPos.endOrPoint
top = atPos(start, opinfo.offset, end) {
- makeBinop(isExpr, opinfo.operand, opinfo.operator, top, opPos, opinfo.targs)
+ makeBinop(isExpr, opinfo.operand, opinfo.operator, top, opPos)
}
}
top
@@ -1440,17 +1440,6 @@ self =>
}
}
- def advanceStack(base: List[OpInfo], top: Tree): Tree = {
- val newTop = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
- val op = in.name
- val pos = in.offset
- ident()
- val targs = if (in.token == LBRACKET) exprTypeArgs() else Nil
- opstack ::= OpInfo(newTop, op, targs, pos)
-
- newTop
- }
-
/** {{{
* PostfixExpr ::= InfixExpr [Id [nl]]
* InfixExpr ::= PrefixExpr
@@ -1462,21 +1451,22 @@ self =>
var top = prefixExpr()
while (isIdent) {
- top = advanceStack(base, top)
+ top = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ val op = in.name
+ opstack = OpInfo(top, op, in.offset) :: opstack
+ ident()
newLineOptWhenFollowing(isExprIntroToken)
-
if (isExprIntro) {
val next = prefixExpr()
if (next == EmptyTree)
return reduceStack(true, base, top, 0, true)
top = next
- }
- else {
+ } else {
val topinfo = opstack.head
opstack = opstack.tail
val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
return atPos(od.pos.startOrPoint, topinfo.offset) {
- applyTypeArgs(Select(od, topinfo.operator.encode), topinfo.targs)
+ Select(od, topinfo.operator.encode)
}
}
}
@@ -1816,7 +1806,7 @@ self =>
top = reduceStack(
false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
val op = in.name
- opstack = OpInfo(top, op, Nil, in.offset) :: opstack
+ opstack = OpInfo(top, op, in.offset) :: opstack
ident()
top = simplePattern()
}
@@ -1906,11 +1896,6 @@ self =>
def exprTypeArgs() = outPattern.typeArgs()
def exprSimpleType() = outPattern.simpleType()
- def applyTypeArgs(sel: Tree, targs: List[Tree]): Tree = (
- if (targs.isEmpty) sel
- else atPos(sel.pos)(TypeApply(sel, targs))
- )
-
/** Default entry points into some pattern contexts. */
def pattern(): Tree = noSeq.pattern()
def patterns(): List[Tree] = noSeq.patterns()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index ffe65aec63..849437e4ff 100644..100755
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -101,7 +101,8 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
pre: Tree,
label: Tree,
attrs: Tree,
- scope:Tree,
+ scope: Tree,
+ empty: Boolean,
children: Seq[Tree]): Tree =
{
def starArgs =
@@ -109,7 +110,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
else List(Typed(makeXMLseq(pos, children), wildStar))
def pat = Apply(_scala_xml__Elem, List(pre, label, wild, wild) ::: convertToTextPat(children))
- def nonpat = New(_scala_xml_Elem, List(List(pre, label, attrs, scope) ::: starArgs))
+ def nonpat = New(_scala_xml_Elem, List(List(pre, label, attrs, scope, if (empty) Literal(Constant(true)) else Literal(Constant(false))) ::: starArgs))
atPos(pos) { if (isPattern) pat else nonpat }
}
@@ -140,7 +141,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
case (Some(pre), rest) => (const(pre), const(rest))
case _ => (wild, const(n))
}
- mkXML(pos, true, prepat, labpat, null, null, args)
+ mkXML(pos, true, prepat, labpat, null, null, false, args)
}
protected def convertToTextPat(t: Tree): Tree = t match {
@@ -188,7 +189,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
def unparsed(pos: Position, str: String): Tree =
atPos(pos)( New(_scala_xml_Unparsed, LL(const(str))) )
- def element(pos: Position, qname: String, attrMap: mutable.Map[String, Tree], args: Seq[Tree]): Tree = {
+ def element(pos: Position, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = {
def handleNamespaceBinding(pre: String, z: String): Tree = {
def mkAssign(t: Tree): Tree = Assign(
Ident(_tmpscope),
@@ -259,6 +260,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
const(newlabel),
makeSymbolicAttrs,
Ident(_scope),
+ empty,
args
)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 87251b4cc9..0d2fbc5372 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -174,14 +174,7 @@ abstract class TreeBuilder {
}
/** Create tree representing (unencoded) binary operation expression or pattern. */
- def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = {
- require(isExpr || targs.isEmpty, ((left, op, targs, right)))
-
- def mkSel(t: Tree) = {
- val sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode))
- if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs))
- }
-
+ def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = {
def mkNamed(args: List[Tree]) =
if (isExpr) args map {
case a @ Assign(id @ Ident(name), rhs) =>
@@ -194,17 +187,14 @@ abstract class TreeBuilder {
}
if (isExpr) {
if (treeInfo.isLeftAssoc(op)) {
- Apply(mkSel(left), arguments)
- }
- else {
+ Apply(atPos(opPos union left.pos) { Select(stripParens(left), op.encode) }, arguments)
+ } else {
val x = freshTermName()
Block(
List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))),
- Apply(mkSel(right), List(Ident(x)))
- )
+ Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x))))
}
- }
- else {
+ } else {
Apply(Ident(op.encode), stripParens(left) :: arguments)
}
}
@@ -216,7 +206,7 @@ abstract class TreeBuilder {
def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]],
npos: Position, cpos: Position): Tree =
if (parents.isEmpty)
- makeNew(List(atPos(npos union cpos)(scalaAnyRefConstr)), self, stats, argss, npos, cpos)
+ makeNew(List(scalaAnyRefConstr), self, stats, argss, npos, cpos)
else if (parents.tail.isEmpty && stats.isEmpty)
atPos(npos union cpos) { New(parents.head, argss) }
else {
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 5e5320ca9a..e35286b281 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -438,7 +438,9 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
if(!comment.throws.isEmpty) {
<dt>Exceptions thrown</dt>
<dd>{
- val exceptionsXml: Iterable[scala.xml.NodeSeq] = (for(exception <- comment.throws ) yield <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span> )
+ val exceptionsXml: Iterable[scala.xml.NodeSeq] =
+ for(exception <- comment.throws.toList.sortBy(_._1) ) yield
+ <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span>
exceptionsXml.reduceLeft(_ ++ Text("") ++ _)
}</dd>
} else NodeSeq.Empty
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index efa524503c..b088c643cb 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -38,7 +38,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
val key = (sym, inTpl)
if (commentCache isDefinedAt key)
Some(commentCache(key))
- else { // not reached for use-case comments
+ else {
val c = defineComment(sym, inTpl)
if (c isDefined) commentCache += (sym, inTpl) -> c.get
c
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 8ed44b5a31..b21fa4bc83 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -165,24 +165,19 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
varSym
}
- def addStaticMethodToClass(forName: String, forArgsTypes: List[Type], forResultType: Type)
- (forBody: Pair[Symbol, List[Symbol]] => Tree): Symbol = {
+ def addStaticMethodToClass(forBody: (Symbol, Symbol) => Tree): Symbol = {
+ val methSym = currentClass.newMethod(mkTerm(nme.reflMethodName), ad.pos, STATIC | SYNTHETIC)
+ val params = methSym.newSyntheticValueParams(List(ClassClass.tpe))
+ methSym setInfoAndEnter MethodType(params, MethodClass.tpe)
- val methSym = currentClass.newMethod(mkTerm(forName), ad.pos, STATIC | SYNTHETIC)
- val params = methSym.newSyntheticValueParams(forArgsTypes)
- methSym setInfoAndEnter MethodType(params, forResultType)
-
- val methDef = typedPos( DefDef(methSym, forBody(methSym -> params)) )
+ val methDef = typedPos(DefDef(methSym, forBody(methSym, params.head)))
newStaticMembers append transform(methDef)
-
methSym
}
def fromTypesToClassArrayLiteral(paramTypes: List[Type]): Tree =
ArrayValue(TypeTree(ClassClass.tpe), paramTypes map LIT)
- def theTypeClassArray = arrayType(ClassClass.tpe)
-
/* ... */
def reflectiveMethodCache(method: String, paramTypes: List[Type]): Symbol = dispatchType match {
case NO_CACHE =>
@@ -197,12 +192,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
*/
val reflParamsCacheSym: Symbol =
- addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true)
+ addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true)
- addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) {
- case Pair(reflMethodSym, List(forReceiverSym)) =>
- (REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))
- }
+ addStaticMethodToClass((_, forReceiverSym) =>
+ gen.mkMethodCall(REF(forReceiverSym), Class_getMethod, Nil, List(LIT(method), safeREF(reflParamsCacheSym)))
+ )
case MONO_CACHE =>
@@ -226,7 +220,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
*/
val reflParamsCacheSym: Symbol =
- addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true)
+ addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true)
val reflMethodCacheSym: Symbol =
addStaticVariableToClass(nme.reflMethodCacheName, MethodClass.tpe, NULL, false)
@@ -237,17 +231,16 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
def isCacheEmpty(receiver: Symbol): Tree =
reflClassCacheSym.IS_NULL() OR (reflClassCacheSym.GET() OBJ_NE REF(receiver))
- addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) {
- case Pair(reflMethodSym, List(forReceiverSym)) =>
- BLOCK(
- IF (isCacheEmpty(forReceiverSym)) THEN BLOCK(
- safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) ,
- safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)),
- UNIT
- ) ENDIF,
- safeREF(reflMethodCacheSym)
- )
- }
+ addStaticMethodToClass((_, forReceiverSym) =>
+ BLOCK(
+ IF (isCacheEmpty(forReceiverSym)) THEN BLOCK(
+ safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) ,
+ safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)),
+ UNIT
+ ) ENDIF,
+ safeREF(reflMethodCacheSym)
+ )
+ )
case POLY_CACHE =>
@@ -273,7 +266,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
*/
val reflParamsCacheSym: Symbol =
- addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true)
+ addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true)
def mkNewPolyCache = gen.mkSoftRef(NEW(TypeTree(EmptyMethodCacheClass.tpe)))
val reflPolyCacheSym: Symbol = (
@@ -281,26 +274,25 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
)
def getPolyCache = gen.mkCast(fn(safeREF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe)
- addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe)
- { case Pair(reflMethodSym, List(forReceiverSym)) =>
- val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe
-
- BLOCK(
- IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF,
- VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) ,
- IF (REF(methodSym) OBJ_!= NULL) .
- THEN (Return(REF(methodSym)))
- ELSE {
- def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym)))
- def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym)))
- BLOCK(
- REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)),
- safeREF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS),
- Return(REF(methodSym))
- )
- }
- )
- }
+ addStaticMethodToClass((reflMethodSym, forReceiverSym) => {
+ val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe
+
+ BLOCK(
+ IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF,
+ VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) ,
+ IF (REF(methodSym) OBJ_!= NULL) .
+ THEN (Return(REF(methodSym)))
+ ELSE {
+ def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym)))
+ def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym)))
+ BLOCK(
+ REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)),
+ safeREF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS),
+ Return(REF(methodSym))
+ )
+ }
+ )
+ })
}
/* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 973e26af41..25f3e7af5c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1295,7 +1295,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def parentTypes(templ: Template): List[Tree] =
- if (templ.parents.isEmpty) List(atPos(templ.pos.focus)(TypeTree(AnyRefClass.tpe)))
+ if (templ.parents.isEmpty) List(atPos(templ.pos)(TypeTree(AnyRefClass.tpe)))
else try {
val clazz = context.owner
// Normalize supertype and mixins so that supertype is always a class, not a trait.
@@ -3630,7 +3630,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val Select(qual, name) = fun
tryTypedArgs(args, forArgMode(fun, mode)) match {
case Some(args1) =>
- assert((args1.length == 0) || !args1.head.tpe.isErroneous, "try typed args is ok")
val qual1 =
if (!pt.isError) adaptToArguments(qual, name, args1, pt, true, true)
else qual
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index fbe92e5d84..f4ce6d6ef1 100755
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
@@ -26,6 +26,14 @@ object DocStrings {
if (start < str.length && isIdentifierPart(str charAt start)) skipIdent(str, start + 1)
else start
+ /** Returns index of string `str` following `start` skipping
+ * sequence of identifier characters.
+ */
+ def skipTag(str: String, start: Int): Int =
+ if (start < str.length && (str charAt start) == '@') skipIdent(str, start + 1)
+ else start
+
+
/** Returns index of string `str` after `start` skipping longest
* sequence of space and tab characters, possibly also containing
* a single `*` character or the `/``**` sequence.
@@ -68,38 +76,46 @@ object DocStrings {
/** Produces a string index, which is a list of ``sections'', i.e
* pairs of start/end positions of all tagged sections in the string.
- * Every section starts with a `@` and extends to the next `@`, or
- * to the end of the comment string, but excluding the final two
+ * Every section starts with an at sign and extends to the next at sign,
+ * or to the end of the comment string, but excluding the final two
* characters which terminate the comment.
*
* Also take usecases into account - they need to expand until the next
* usecase or the end of the string, as they might include other sections
* of their own
*/
- def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] =
- findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match {
+ def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] = {
+ var indices = findAll(str, 0) (idx => str(idx) == '@' && p(idx))
+ indices = mergeUsecaseSections(str, indices)
+ indices = mergeInheritdocSections(str, indices)
+
+ indices match {
case List() => List()
- case idxs => {
- val idxs2 = mergeUsecaseSections(str, idxs)
- idxs2 zip (idxs2.tail ::: List(str.length - 2))
- }
+ case idxs => idxs zip (idxs.tail ::: List(str.length - 2))
}
+ }
/**
* Merge sections following an usecase into the usecase comment, so they
* can override the parent symbol's sections
*/
def mergeUsecaseSections(str: String, idxs: List[Int]): List[Int] = {
- idxs.find(str.substring(_).startsWith("@usecase")) match {
- case Some(firstUC) =>
- val commentSections = idxs.take(idxs.indexOf(firstUC))
- val usecaseSections = idxs.drop(idxs.indexOf(firstUC)).filter(str.substring(_).startsWith("@usecase"))
+ idxs.indexWhere(str.substring(_).startsWith("@usecase")) match {
+ case firstUCIndex if firstUCIndex != -1 =>
+ val commentSections = idxs.take(firstUCIndex)
+ val usecaseSections = idxs.drop(firstUCIndex).filter(str.substring(_).startsWith("@usecase"))
commentSections ::: usecaseSections
- case None =>
+ case _ =>
idxs
}
}
+ /**
+ * Merge the inheritdoc sections, as they never make sense on their own
+ */
+ def mergeInheritdocSections(str: String, idxs: List[Int]): List[Int] =
+ idxs.filterNot(str.substring(_).startsWith("@inheritdoc"))
+
/** Does interval `iv` start with given `tag`?
*/
def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean =
@@ -108,12 +124,11 @@ object DocStrings {
def startsWithTag(str: String, start: Int, tag: String): Boolean =
str.startsWith(tag, start) && !isIdentifierPart(str charAt (start + tag.length))
-
/** The first start tag of a list of tag intervals,
* or the end of the whole comment string - 2 if list is empty
*/
def startTag(str: String, sections: List[(Int, Int)]) = sections match {
- case List() => str.length - 2
+ case Nil => str.length - 2
case (start, _) :: _ => start
}
@@ -155,4 +170,46 @@ object DocStrings {
idx
}
}
+
+ /** A map from the section tag to section parameters */
+ def sectionTagMap(str: String, sections: List[(Int, Int)]): Map[String, (Int, Int)] =
+ Map() ++ {
+ for (section <- sections) yield
+ extractSectionTag(str, section) -> section
+ }
+
+ /** Extract the section tag, treating the section tag as an indentifier */
+ def extractSectionTag(str: String, section: (Int, Int)): String =
+ str.substring(section._1, skipTag(str, section._1))
+
+ /** Extract the section parameter */
+ def extractSectionParam(str: String, section: (Int, Int)): String = {
+ assert(str.substring(section._1).startsWith("@param") ||
+ str.substring(section._1).startsWith("@tparam") ||
+ str.substring(section._1).startsWith("@throws"))
+
+ val start = skipWhitespace(str, skipTag(str, section._1))
+ val finish = skipIdent(str, start)
+
+ str.substring(start, finish)
+ }
+
+ /** Extract the section text, except for the tag and comment newlines */
+ def extractSectionText(str: String, section: (Int, Int)): (Int, Int) = {
+ if (str.substring(section._1).startsWith("@param") ||
+ str.substring(section._1).startsWith("@tparam") ||
+ str.substring(section._1).startsWith("@throws"))
+ (skipWhitespace(str, skipIdent(str, skipWhitespace(str, skipTag(str, section._1)))), section._2)
+ else
+ (skipWhitespace(str, skipTag(str, section._1)), section._2)
+ }
+
+ /** Cleanup section text */
+ def cleanupSectionText(str: String) = {
+ var result = str.trim.replaceAll("\n\\s+\\*\\s+", " \n")
+ while (result.endsWith("\n"))
+ result = result.substring(0, str.length - 1)
+ result
+ }
+
}
diff --git a/src/library/scala/collection/SeqExtractors.scala b/src/library/scala/collection/SeqExtractors.scala
new file mode 100644
index 0000000000..cb3cb27f18
--- /dev/null
+++ b/src/library/scala/collection/SeqExtractors.scala
@@ -0,0 +1,21 @@
+package scala.collection
+
+/** An extractor used to head/tail deconstruct sequences. */
+object +: {
+ def unapply[T,Coll <: SeqLike[T, Coll]](
+ t: Coll with SeqLike[T, Coll]): Option[(T, Coll)] =
+ if(t.isEmpty) None
+ else Some(t.head -> t.tail)
+}
+
+/** An extractor used to init/last deconstruct sequences. */
+object :+ {
+ /** Splits a sequence into init :+ tail.
+ * @returns Some(init, tail) if sequence is non-empty.
+ * None otherwise.
+ */
+ def unapply[T,Coll <: SeqLike[T, Coll]](
+ t: Coll with SeqLike[T, Coll]): Option[(Coll, T)] =
+ if(t.isEmpty) None
+ else Some(t.init -> t.last)
+}
diff --git a/src/library/scala/collection/mutable/Ctrie.scala b/src/library/scala/collection/mutable/ConcurrentTrieMap.scala
index cbec118aa9..1a44c8e423 100644
--- a/src/library/scala/collection/mutable/Ctrie.scala
+++ b/src/library/scala/collection/mutable/ConcurrentTrieMap.scala
@@ -13,7 +13,7 @@ package mutable
import java.util.concurrent.atomic._
import collection.immutable.{ ListMap => ImmutableListMap }
-import collection.parallel.mutable.ParCtrie
+import collection.parallel.mutable.ParConcurrentTrieMap
import generic._
import annotation.tailrec
import annotation.switch
@@ -31,16 +31,16 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
@inline final def CAS(old: MainNode[K, V], n: MainNode[K, V]) = INodeBase.updater.compareAndSet(this, old, n)
- final def gcasRead(ct: Ctrie[K, V]): MainNode[K, V] = GCAS_READ(ct)
+ final def gcasRead(ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = GCAS_READ(ct)
- @inline final def GCAS_READ(ct: Ctrie[K, V]): MainNode[K, V] = {
+ @inline final def GCAS_READ(ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = {
val m = /*READ*/mainnode
val prevval = /*READ*/m.prev
if (prevval eq null) m
else GCAS_Complete(m, ct)
}
- @tailrec private def GCAS_Complete(m: MainNode[K, V], ct: Ctrie[K, V]): MainNode[K, V] = if (m eq null) null else {
+ @tailrec private def GCAS_Complete(m: MainNode[K, V], ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = if (m eq null) null else {
// complete the GCAS
val prev = /*READ*/m.prev
val ctr = ct.readRoot(true)
@@ -72,7 +72,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
}
}
- @inline final def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: Ctrie[K, V]): Boolean = {
+ @inline final def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: ConcurrentTrieMap[K, V]): Boolean = {
n.WRITE_PREV(old)
if (CAS(old, n)) {
GCAS_Complete(n, ct)
@@ -86,7 +86,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
nin
}
- final def copyToGen(ngen: Gen, ct: Ctrie[K, V]) = {
+ final def copyToGen(ngen: Gen, ct: ConcurrentTrieMap[K, V]) = {
val nin = new INode[K, V](ngen)
val main = GCAS_READ(ct)
nin.WRITE(main)
@@ -97,7 +97,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
*
* @return true if successful, false otherwise
*/
- @tailrec final def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Boolean = {
+ @tailrec final def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Boolean = {
val m = GCAS_READ(ct) // use -Yinline!
m match {
@@ -143,7 +143,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
* @param cond null - don't care if the key was there; KEY_ABSENT - key wasn't there; KEY_PRESENT - key was there; other value `v` - key must be bound to `v`
* @return null if unsuccessful, Option[V] otherwise (indicating previous value bound to the key)
*/
- @tailrec final def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Option[V] = {
+ @tailrec final def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Option[V] = {
val m = GCAS_READ(ct) // use -Yinline!
m match {
@@ -233,7 +233,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
*
* @return null if no value has been found, RESTART if the operation wasn't successful, or any other value otherwise
*/
- @tailrec final def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): AnyRef = {
+ @tailrec final def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): AnyRef = {
val m = GCAS_READ(ct) // use -Yinline!
m match {
@@ -276,7 +276,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
* @param v if null, will remove the key irregardless of the value; otherwise removes only if binding contains that exact key and value
* @return null if not successful, an Option[V] indicating the previous value otherwise
*/
- final def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Option[V] = {
+ final def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Option[V] = {
val m = GCAS_READ(ct) // use -Yinline!
m match {
@@ -352,7 +352,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
}
}
- private def clean(nd: INode[K, V], ct: Ctrie[K, V], lev: Int) {
+ private def clean(nd: INode[K, V], ct: ConcurrentTrieMap[K, V], lev: Int) {
val m = nd.GCAS_READ(ct)
m match {
case cn: CNode[K, V] => nd.GCAS(cn, cn.toCompressed(ct, lev, gen), ct)
@@ -360,9 +360,9 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
}
}
- final def isNullInode(ct: Ctrie[K, V]) = GCAS_READ(ct) eq null
+ final def isNullInode(ct: ConcurrentTrieMap[K, V]) = GCAS_READ(ct) eq null
- final def cachedSize(ct: Ctrie[K, V]): Int = {
+ final def cachedSize(ct: ConcurrentTrieMap[K, V]): Int = {
val m = GCAS_READ(ct)
m.cachedSize(ct)
}
@@ -438,7 +438,7 @@ extends MainNode[K, V] {
if (updmap.size > 1) new LNode(updmap)
else {
val (k, v) = updmap.iterator.next
- new TNode(k, v, Ctrie.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses
+ new TNode(k, v, ConcurrentTrieMap.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses
}
}
def get(k: K) = listmap.get(k)
@@ -455,7 +455,7 @@ extends CNodeBase[K, V] {
val currsz = READ_SIZE()
if (currsz != -1) currsz
else {
- val sz = computeSize(ct.asInstanceOf[Ctrie[K, V]])
+ val sz = computeSize(ct.asInstanceOf[ConcurrentTrieMap[K, V]])
while (READ_SIZE() == -1) CAS_SIZE(-1, sz)
READ_SIZE()
}
@@ -466,7 +466,7 @@ extends CNodeBase[K, V] {
// => if there are concurrent size computations, they start
// at different positions, so they are more likely to
// to be independent
- private def computeSize(ct: Ctrie[K, V]): Int = {
+ private def computeSize(ct: ConcurrentTrieMap[K, V]): Int = {
var i = 0
var sz = 0
val offset = math.abs(util.Random.nextInt()) % array.length
@@ -511,7 +511,7 @@ extends CNodeBase[K, V] {
/** Returns a copy of this cnode such that all the i-nodes below it are copied
* to the specified generation `ngen`.
*/
- final def renewed(ngen: Gen, ct: Ctrie[K, V]) = {
+ final def renewed(ngen: Gen, ct: ConcurrentTrieMap[K, V]) = {
var i = 0
val arr = array
val len = arr.length
@@ -542,7 +542,7 @@ extends CNodeBase[K, V] {
// returns the version of this node with at least some null-inodes
// removed (those existing when the op began)
// - if there are only null-i-nodes below, returns null
- final def toCompressed(ct: Ctrie[K, V], lev: Int, gen: Gen) = {
+ final def toCompressed(ct: ConcurrentTrieMap[K, V], lev: Int, gen: Gen) = {
var bmp = bitmap
var i = 0
val arr = array
@@ -594,7 +594,7 @@ private[mutable] object CNode {
val yidx = (yhc >>> lev) & 0x1f
val bmp = (1 << xidx) | (1 << yidx)
if (xidx == yidx) {
- val subinode = new INode[K, V](gen)//(Ctrie.inodeupdater)
+ val subinode = new INode[K, V](gen)//(ConcurrentTrieMap.inodeupdater)
subinode.mainnode = dual(x, xhc, y, yhc, lev + 5, gen)
new CNode(bmp, Array(subinode), gen)
} else {
@@ -613,7 +613,7 @@ private[mutable] case class RDCSS_Descriptor[K, V](old: INode[K, V], expectedmai
}
-/** A concurrent hash-trie or Ctrie is a concurrent thread-safe lock-free
+/** A concurrent hash-trie or ConcurrentTrieMap is a concurrent thread-safe lock-free
* implementation of a hash array mapped trie. It is used to implement the
* concurrent map abstraction. It has particularly scalable concurrent insert
* and remove operations and is memory-efficient. It supports O(1), atomic,
@@ -627,20 +627,20 @@ private[mutable] case class RDCSS_Descriptor[K, V](old: INode[K, V], expectedmai
* @since 2.10
*/
@SerialVersionUID(0L - 6402774413839597105L)
-final class Ctrie[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[Ctrie[K, V], AnyRef])
+final class ConcurrentTrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[ConcurrentTrieMap[K, V], AnyRef])
extends ConcurrentMap[K, V]
- with MapLike[K, V, Ctrie[K, V]]
- with CustomParallelizable[(K, V), ParCtrie[K, V]]
+ with MapLike[K, V, ConcurrentTrieMap[K, V]]
+ with CustomParallelizable[(K, V), ParConcurrentTrieMap[K, V]]
with Serializable
{
- import Ctrie.computeHash
+ import ConcurrentTrieMap.computeHash
private var rootupdater = rtupd
@volatile var root = r
def this() = this(
INode.newRootNode,
- AtomicReferenceFieldUpdater.newUpdater(classOf[Ctrie[K, V]], classOf[AnyRef], "root")
+ AtomicReferenceFieldUpdater.newUpdater(classOf[ConcurrentTrieMap[K, V]], classOf[AnyRef], "root")
)
/* internal methods */
@@ -652,22 +652,22 @@ extends ConcurrentMap[K, V]
out.writeObject(k)
out.writeObject(v)
}
- out.writeObject(CtrieSerializationEnd)
+ out.writeObject(ConcurrentTrieMapSerializationEnd)
}
private def readObject(in: java.io.ObjectInputStream) {
root = INode.newRootNode
- rootupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[Ctrie[K, V]], classOf[AnyRef], "root")
+ rootupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[ConcurrentTrieMap[K, V]], classOf[AnyRef], "root")
var obj: AnyRef = null
do {
obj = in.readObject()
- if (obj != CtrieSerializationEnd) {
+ if (obj != ConcurrentTrieMapSerializationEnd) {
val k = obj.asInstanceOf[K]
val v = in.readObject().asInstanceOf[V]
update(k, v)
}
- } while (obj != CtrieSerializationEnd)
+ } while (obj != ConcurrentTrieMapSerializationEnd)
}
@inline final def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv)
@@ -760,37 +760,37 @@ extends ConcurrentMap[K, V]
override def seq = this
- override def par = new ParCtrie(this)
+ override def par = new ParConcurrentTrieMap(this)
- override def empty: Ctrie[K, V] = new Ctrie[K, V]
+ override def empty: ConcurrentTrieMap[K, V] = new ConcurrentTrieMap[K, V]
final def isReadOnly = rootupdater eq null
final def nonReadOnly = rootupdater ne null
- /** Returns a snapshot of this Ctrie.
+ /** Returns a snapshot of this ConcurrentTrieMap.
* This operation is lock-free and linearizable.
*
* The snapshot is lazily updated - the first time some branch
- * in the snapshot or this Ctrie are accessed, they are rewritten.
+ * in the snapshot or this ConcurrentTrieMap are accessed, they are rewritten.
* This means that the work of rebuilding both the snapshot and this
- * Ctrie is distributed across all the threads doing updates or accesses
+ * ConcurrentTrieMap is distributed across all the threads doing updates or accesses
* subsequent to the snapshot creation.
*/
- @tailrec final def snapshot(): Ctrie[K, V] = {
+ @tailrec final def snapshot(): ConcurrentTrieMap[K, V] = {
val r = RDCSS_READ_ROOT()
val expmain = r.gcasRead(this)
- if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new Ctrie(r.copyToGen(new Gen, this), rootupdater)
+ if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new ConcurrentTrieMap(r.copyToGen(new Gen, this), rootupdater)
else snapshot()
}
- /** Returns a read-only snapshot of this Ctrie.
+ /** Returns a read-only snapshot of this ConcurrentTrieMap.
* This operation is lock-free and linearizable.
*
* The snapshot is lazily updated - the first time some branch
- * of this Ctrie are accessed, it is rewritten. The work of creating
+ * of this ConcurrentTrieMap are accessed, it is rewritten. The work of creating
* the snapshot is thus distributed across subsequent updates
- * and accesses on this Ctrie by all threads.
+ * and accesses on this ConcurrentTrieMap by all threads.
* Note that the snapshot itself is never rewritten unlike when calling
* the `snapshot` method, but the obtained snapshot cannot be modified.
*
@@ -799,7 +799,7 @@ extends ConcurrentMap[K, V]
@tailrec final def readOnlySnapshot(): collection.Map[K, V] = {
val r = RDCSS_READ_ROOT()
val expmain = r.gcasRead(this)
- if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new Ctrie(r, null)
+ if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new ConcurrentTrieMap(r, null)
else readOnlySnapshot()
}
@@ -872,7 +872,7 @@ extends ConcurrentMap[K, V]
def iterator: Iterator[(K, V)] =
if (nonReadOnly) readOnlySnapshot().iterator
- else new CtrieIterator(0, this)
+ else new ConcurrentTrieMapIterator(0, this)
private def cachedSize() = {
val r = RDCSS_READ_ROOT()
@@ -883,17 +883,17 @@ extends ConcurrentMap[K, V]
if (nonReadOnly) readOnlySnapshot().size
else cachedSize()
- override def stringPrefix = "Ctrie"
+ override def stringPrefix = "ConcurrentTrieMap"
}
-object Ctrie extends MutableMapFactory[Ctrie] {
+object ConcurrentTrieMap extends MutableMapFactory[ConcurrentTrieMap] {
val inodeupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[INodeBase[_, _]], classOf[MainNode[_, _]], "mainnode")
- implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Ctrie[K, V]] = new MapCanBuildFrom[K, V]
+ implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), ConcurrentTrieMap[K, V]] = new MapCanBuildFrom[K, V]
- def empty[K, V]: Ctrie[K, V] = new Ctrie[K, V]
+ def empty[K, V]: ConcurrentTrieMap[K, V] = new ConcurrentTrieMap[K, V]
@inline final def computeHash[K](k: K): Int = {
var hcode = k.hashCode
@@ -905,7 +905,7 @@ object Ctrie extends MutableMapFactory[Ctrie] {
}
-private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ctrie[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] {
+private[collection] class ConcurrentTrieMapIterator[K, V](var level: Int, private var ct: ConcurrentTrieMap[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] {
var stack = new Array[Array[BasicNode]](7)
var stackpos = new Array[Int](7)
var depth = -1
@@ -971,9 +971,9 @@ private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ct
}
} else current = null
- protected def newIterator(_lev: Int, _ct: Ctrie[K, V], _mustInit: Boolean) = new CtrieIterator[K, V](_lev, _ct, _mustInit)
+ protected def newIterator(_lev: Int, _ct: ConcurrentTrieMap[K, V], _mustInit: Boolean) = new ConcurrentTrieMapIterator[K, V](_lev, _ct, _mustInit)
- protected def dupTo(it: CtrieIterator[K, V]) = {
+ protected def dupTo(it: ConcurrentTrieMapIterator[K, V]) = {
it.level = this.level
it.ct = this.ct
it.depth = this.depth
@@ -993,7 +993,7 @@ private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ct
}
/** Returns a sequence of iterators over subsets of this iterator.
- * It's used to ease the implementation of splitters for a parallel version of the Ctrie.
+ * It's used to ease the implementation of splitters for a parallel version of the ConcurrentTrieMap.
*/
protected def subdivide(): Seq[Iterator[(K, V)]] = if (subiter ne null) {
// the case where an LNode is being iterated
@@ -1043,7 +1043,7 @@ private[mutable] object RestartException extends util.control.ControlThrowable
/** Only used for ctrie serialization. */
@SerialVersionUID(0L - 7237891413820527142L)
-private[mutable] case object CtrieSerializationEnd
+private[mutable] case object ConcurrentTrieMapSerializationEnd
private[mutable] object Debug {
diff --git a/src/library/scala/collection/parallel/mutable/ParCtrie.scala b/src/library/scala/collection/parallel/mutable/ParConcurrentTrieMap.scala
index 470972adad..a6495161ea 100644
--- a/src/library/scala/collection/parallel/mutable/ParCtrie.scala
+++ b/src/library/scala/collection/parallel/mutable/ParConcurrentTrieMap.scala
@@ -20,12 +20,12 @@ import scala.collection.mutable.LNode
import scala.collection.mutable.CNode
import scala.collection.mutable.SNode
import scala.collection.mutable.INode
-import scala.collection.mutable.Ctrie
-import scala.collection.mutable.CtrieIterator
+import scala.collection.mutable.ConcurrentTrieMap
+import scala.collection.mutable.ConcurrentTrieMapIterator
-/** Parallel Ctrie collection.
+/** Parallel ConcurrentTrieMap collection.
*
* It has its bulk operations parallelized, but uses the snapshot operation
* to create the splitter. This means that parallel bulk operations can be
@@ -34,24 +34,24 @@ import scala.collection.mutable.CtrieIterator
* @author Aleksandar Prokopec
* @since 2.10
*/
-final class ParCtrie[K, V] private[collection] (private val ctrie: Ctrie[K, V])
+final class ParConcurrentTrieMap[K, V] private[collection] (private val ctrie: ConcurrentTrieMap[K, V])
extends ParMap[K, V]
- with GenericParMapTemplate[K, V, ParCtrie]
- with ParMapLike[K, V, ParCtrie[K, V], Ctrie[K, V]]
- with ParCtrieCombiner[K, V]
+ with GenericParMapTemplate[K, V, ParConcurrentTrieMap]
+ with ParMapLike[K, V, ParConcurrentTrieMap[K, V], ConcurrentTrieMap[K, V]]
+ with ParConcurrentTrieMapCombiner[K, V]
with Serializable
{
- def this() = this(new Ctrie)
+ def this() = this(new ConcurrentTrieMap)
- override def mapCompanion: GenericParMapCompanion[ParCtrie] = ParCtrie
+ override def mapCompanion: GenericParMapCompanion[ParConcurrentTrieMap] = ParConcurrentTrieMap
- override def empty: ParCtrie[K, V] = ParCtrie.empty
+ override def empty: ParConcurrentTrieMap[K, V] = ParConcurrentTrieMap.empty
- protected[this] override def newCombiner = ParCtrie.newCombiner
+ protected[this] override def newCombiner = ParConcurrentTrieMap.newCombiner
override def seq = ctrie
- def splitter = new ParCtrieSplitter(0, ctrie.readOnlySnapshot().asInstanceOf[Ctrie[K, V]], true)
+ def splitter = new ParConcurrentTrieMapSplitter(0, ctrie.readOnlySnapshot().asInstanceOf[ConcurrentTrieMap[K, V]], true)
override def clear() = ctrie.clear()
@@ -87,11 +87,11 @@ extends ParMap[K, V]
}
}
- override def stringPrefix = "ParCtrie"
+ override def stringPrefix = "ParConcurrentTrieMap"
/* tasks */
- /** Computes Ctrie size in parallel. */
+ /** Computes ConcurrentTrieMap size in parallel. */
class Size(offset: Int, howmany: Int, array: Array[BasicNode]) extends Task[Int, Size] {
var result = -1
def leaf(prev: Option[Int]) = {
@@ -118,15 +118,15 @@ extends ParMap[K, V]
}
-private[collection] class ParCtrieSplitter[K, V](lev: Int, ct: Ctrie[K, V], mustInit: Boolean)
-extends CtrieIterator[K, V](lev, ct, mustInit)
+private[collection] class ParConcurrentTrieMapSplitter[K, V](lev: Int, ct: ConcurrentTrieMap[K, V], mustInit: Boolean)
+extends ConcurrentTrieMapIterator[K, V](lev, ct, mustInit)
with IterableSplitter[(K, V)]
{
// only evaluated if `remaining` is invoked (which is not used by most tasks)
lazy val totalsize = ct.par.size
var iterated = 0
- protected override def newIterator(_lev: Int, _ct: Ctrie[K, V], _mustInit: Boolean) = new ParCtrieSplitter[K, V](_lev, _ct, _mustInit)
+ protected override def newIterator(_lev: Int, _ct: ConcurrentTrieMap[K, V], _mustInit: Boolean) = new ParConcurrentTrieMapSplitter[K, V](_lev, _ct, _mustInit)
override def shouldSplitFurther[S](coll: collection.parallel.ParIterable[S], parallelismLevel: Int) = {
val maxsplits = 3 + Integer.highestOneBit(parallelismLevel)
@@ -153,15 +153,15 @@ extends CtrieIterator[K, V](lev, ct, mustInit)
}
-/** Only used within the `ParCtrie`. */
-private[mutable] trait ParCtrieCombiner[K, V] extends Combiner[(K, V), ParCtrie[K, V]] {
+/** Only used within the `ParConcurrentTrieMap`. */
+private[mutable] trait ParConcurrentTrieMapCombiner[K, V] extends Combiner[(K, V), ParConcurrentTrieMap[K, V]] {
- def combine[N <: (K, V), NewTo >: ParCtrie[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else {
+ def combine[N <: (K, V), NewTo >: ParConcurrentTrieMap[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else {
throw new UnsupportedOperationException("This shouldn't have been called in the first place.")
- val thiz = this.asInstanceOf[ParCtrie[K, V]]
- val that = other.asInstanceOf[ParCtrie[K, V]]
- val result = new ParCtrie[K, V]
+ val thiz = this.asInstanceOf[ParConcurrentTrieMap[K, V]]
+ val that = other.asInstanceOf[ParConcurrentTrieMap[K, V]]
+ val result = new ParConcurrentTrieMap[K, V]
result ++= thiz.iterator
result ++= that.iterator
@@ -174,13 +174,13 @@ private[mutable] trait ParCtrieCombiner[K, V] extends Combiner[(K, V), ParCtrie[
}
-object ParCtrie extends ParMapFactory[ParCtrie] {
+object ParConcurrentTrieMap extends ParMapFactory[ParConcurrentTrieMap] {
- def empty[K, V]: ParCtrie[K, V] = new ParCtrie[K, V]
+ def empty[K, V]: ParConcurrentTrieMap[K, V] = new ParConcurrentTrieMap[K, V]
- def newCombiner[K, V]: Combiner[(K, V), ParCtrie[K, V]] = new ParCtrie[K, V]
+ def newCombiner[K, V]: Combiner[(K, V), ParConcurrentTrieMap[K, V]] = new ParConcurrentTrieMap[K, V]
- implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParCtrie[K, V]] = new CanCombineFromMap[K, V]
+ implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParConcurrentTrieMap[K, V]] = new CanCombineFromMap[K, V]
}
diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala
index 366af34ee9..1ef1911fd3 100644
--- a/src/library/scala/package.scala
+++ b/src/library/scala/package.scala
@@ -64,6 +64,9 @@ package object scala {
type ::[A] = scala.collection.immutable.::[A]
val :: = scala.collection.immutable.::
+ val +: = scala.collection.+:
+ val :+ = scala.collection.:+
+
type Stream[+A] = scala.collection.immutable.Stream[A]
val Stream = scala.collection.immutable.Stream
val #:: = scala.collection.immutable.Stream.#::
diff --git a/src/library/scala/reflect/api/Modifier.scala b/src/library/scala/reflect/api/Modifier.scala
index cbfe91e59b..1b67929e15 100644
--- a/src/library/scala/reflect/api/Modifier.scala
+++ b/src/library/scala/reflect/api/Modifier.scala
@@ -2,7 +2,7 @@ package scala.reflect.api
import collection.{ immutable, mutable }
-sealed abstract class Modifier {
+abstract class Modifier private[api] () {
def name: String
def isKeyword: Boolean
def sourceString: String = if (isKeyword) "`" + name + "`" else name
diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala
index 0c7772cd07..38ca89b98b 100644
--- a/src/library/scala/util/Properties.scala
+++ b/src/library/scala/util/Properties.scala
@@ -72,10 +72,11 @@ private[scala] trait PropertiesTrait {
* it is an RC, Beta, etc. or was built from source, or if the version
* cannot be read.
*/
- val releaseVersion = scalaPropOrNone("version.number") flatMap { s =>
- val segments = s split '.'
- if (segments.size == 4 && segments.last == "final") Some(segments take 3 mkString ".") else None
- }
+ val releaseVersion =
+ for {
+ v <- scalaPropOrNone("maven.version.number")
+ if !(v endsWith "-SNAPSHOT")
+ } yield v
/** The development Scala version, if this is not a final release.
* The precise contents are not guaranteed, but it aims to provide a
@@ -85,15 +86,12 @@ private[scala] trait PropertiesTrait {
* @return Some(version) if this is a non-final version, None if this
* is a final release or the version cannot be read.
*/
- val developmentVersion = scalaPropOrNone("version.number") flatMap { s =>
- val segments = s split '.'
- if (segments.isEmpty || segments.last == "final")
- None
- else if (segments.last startsWith "r")
- Some(s takeWhile (ch => ch != '-')) // Cutting e.g. 2.10.0.r24774-b20110417125606 to 2.10.0.r24774
- else
- Some(s)
- }
+ val developmentVersion =
+ for {
+ v <- scalaPropOrNone("maven.version.number")
+ if v endsWith "-SNAPSHOT"
+ ov <- scalaPropOrNone("version.number")
+ } yield ov
/** Either the development or release version if known, otherwise
* the empty string.
diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
index df52b34f87..cc244a5b88 100644..100755
--- a/src/library/scala/xml/Elem.scala
+++ b/src/library/scala/xml/Elem.scala
@@ -17,8 +17,18 @@ package scala.xml
* @author Burak Emir <bqe@google.com>
*/
object Elem {
- def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) =
- new Elem(prefix, label, attributes, scope, child:_*)
+ /** Build an Elem, setting its minimizeEmpty property to <code>true</code> if it has no children. Note that this
+ * default may not be exactly what you want, as some XML dialects don't permit some elements to be minimized.
+ *
+ * @deprecated This factory method is retained for backward compatibility; please use the other one, with which you
+ * can specify your own preference for minimizeEmpty.
+ */
+ @deprecated
+ def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*): Elem =
+ apply(prefix, label, attributes, scope, child.isEmpty, child: _*)
+
+ def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, child: Node*): Elem =
+ new Elem(prefix,label,attributes,scope, minimizeEmpty, child:_*)
def unapplySeq(n: Node) = n match {
case _: SpecialNode | _: Group => None
@@ -29,11 +39,13 @@ object Elem {
/** The case class `Elem` extends the `Node` class,
* providing an immutable data object representing an XML element.
*
- * @param prefix namespace prefix (may be null, but not the empty string)
- * @param label the element name
- * @param attribute the attribute map
- * @param scope the scope containing the namespace bindings
- * @param child the children of this node
+ * @param prefix namespace prefix (may be null, but not the empty string)
+ * @param label the element name
+ * @param attributes1 the attribute map
+ * @param scope the scope containing the namespace bindings
+ * @param minimizeEmpty `true` if this element should be serialized as minimized (i.e. "&lt;el/&gt;") when
+ * empty; `false` if it should be written out in long form.
+ * @param child the children of this node
*
* Copyright 2008 Google Inc. All Rights Reserved.
* @author Burak Emir <bqe@google.com>
@@ -43,9 +55,15 @@ class Elem(
val label: String,
attributes1: MetaData,
override val scope: NamespaceBinding,
+ val minimizeEmpty: Boolean,
val child: Node*)
extends Node with Serializable
{
+ @deprecated("This constructor is retained for backward compatibility. Please use the primary constructor, which lets you specify your own preference for `minimizeEmpty`.", "2.10")
+ def this(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = {
+ this(prefix, label, attributes, scope, child.isEmpty, child: _*)
+ }
+
final override def doCollectNamespaces = true
final override def doTransform = true
@@ -83,8 +101,9 @@ extends Node with Serializable
label: String = this.label,
attributes: MetaData = this.attributes,
scope: NamespaceBinding = this.scope,
+ minimizeEmpty: Boolean = this.minimizeEmpty,
child: Seq[Node] = this.child.toSeq
- ): Elem = Elem(prefix, label, attributes, scope, child: _*)
+ ): Elem = Elem(prefix, label, attributes, scope, minimizeEmpty, child: _*)
/** Returns concatenation of `text(n)` for each child `n`.
*/
diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala
index 2ead18fe08..02e34e1bdc 100644..100755
--- a/src/library/scala/xml/Node.scala
+++ b/src/library/scala/xml/Node.scala
@@ -159,7 +159,7 @@ abstract class Node extends NodeSeq {
* @return ...
*/
def buildString(stripComments: Boolean): String =
- Utility.toXML(this, stripComments = stripComments).toString
+ Utility.serialize(this, stripComments = stripComments).toString
/**
* Same as `toString('''false''')`.
diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala
index ea39b51352..64dbd00f2f 100644..100755
--- a/src/library/scala/xml/PrettyPrinter.scala
+++ b/src/library/scala/xml/PrettyPrinter.scala
@@ -161,7 +161,7 @@ class PrettyPrinter(width: Int, step: Int) {
case _ =>
val test = {
val sb = new StringBuilder()
- Utility.toXML(node, pscope, sb, false)
+ Utility.serialize(node, pscope, sb, false)
if (doPreserve(node)) sb.toString
else TextBuffer.fromString(sb.toString).toText(0).data
}
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index fc20b892b9..9f944c0e92 100644..100755
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -181,6 +181,13 @@ object Utility extends AnyRef with parsing.TokenTests {
// sb.toString()
// }
+ /**
+ * Serialize the provided Node to the provided StringBuilder.
+ * <p/>
+ * Note that calling this source-compatible method will result in the same old, arguably almost universally unwanted,
+ * behaviour.
+ */
+ @deprecated("Please use `serialize` instead and specify a `minimizeTags` parameter", "2.10")
def toXML(
x: Node,
pscope: NamespaceBinding = TopScope,
@@ -190,29 +197,51 @@ object Utility extends AnyRef with parsing.TokenTests {
preserveWhitespace: Boolean = false,
minimizeTags: Boolean = false): StringBuilder =
{
+ serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, if (minimizeTags) MinimizeMode.Always else MinimizeMode.Never)
+ }
+
+ /**
+ * Serialize an XML Node to a StringBuilder.
+ *
+ * This is essentially a minor rework of `toXML` that can't have the same name due to an unfortunate
+ * combination of named/default arguments and overloading.
+ *
+ * @todo use a Writer instead
+ */
+ def serialize(
+ x: Node,
+ pscope: NamespaceBinding = TopScope,
+ sb: StringBuilder = new StringBuilder,
+ stripComments: Boolean = false,
+ decodeEntities: Boolean = true,
+ preserveWhitespace: Boolean = false,
+ minimizeTags: MinimizeMode.Value = MinimizeMode.Default): StringBuilder =
+ {
x match {
- case c: Comment => if (!stripComments) c buildString sb else sb
- case x: SpecialNode => x buildString sb
- case g: Group =>
- g.nodes foreach {toXML(_, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)}
- sb
- case _ =>
+ case c: Comment if !stripComments => c buildString sb
+ case s: SpecialNode => s buildString sb
+ case g: Group => for (c <- g.nodes) serialize(c, g.scope, sb, minimizeTags = minimizeTags) ; sb
+ case el: Elem =>
// print tag with namespace declarations
sb.append('<')
- x.nameToString(sb)
- if (x.attributes ne null) x.attributes.buildString(sb)
- x.scope.buildString(sb, pscope)
- if (x.child.isEmpty && minimizeTags) {
+ el.nameToString(sb)
+ if (el.attributes ne null) el.attributes.buildString(sb)
+ el.scope.buildString(sb, pscope)
+ if (el.child.isEmpty &&
+ (minimizeTags == MinimizeMode.Always ||
+ (minimizeTags == MinimizeMode.Default && el.minimizeEmpty)))
+ {
// no children, so use short form: <xyz .../>
- sb.append(" />")
+ sb.append("/>")
} else {
// children, so use long form: <xyz ...>...</xyz>
sb.append('>')
- sequenceToXML(x.child, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
+ sequenceToXML(el.child, el.scope, sb, stripComments)
sb.append("</")
- x.nameToString(sb)
+ el.nameToString(sb)
sb.append('>')
}
+ case _ => throw new IllegalArgumentException("Don't know how to serialize a " + x.getClass.getName)
}
}
@@ -223,20 +252,20 @@ object Utility extends AnyRef with parsing.TokenTests {
stripComments: Boolean = false,
decodeEntities: Boolean = true,
preserveWhitespace: Boolean = false,
- minimizeTags: Boolean = false): Unit =
+ minimizeTags: MinimizeMode.Value = MinimizeMode.Default): Unit =
{
if (children.isEmpty) return
else if (children forall isAtomAndNotText) { // add space
val it = children.iterator
val f = it.next
- toXML(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
+ serialize(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
while (it.hasNext) {
val x = it.next
sb.append(' ')
- toXML(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
+ serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
}
}
- else children foreach { toXML(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) }
+ else children foreach { serialize(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) }
}
/**
diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala
index bc3033d081..4beba91899 100644..100755
--- a/src/library/scala/xml/XML.scala
+++ b/src/library/scala/xml/XML.scala
@@ -26,6 +26,21 @@ object Source
def fromSysId(sysID: String) = new InputSource(sysID)
def fromString(string: String) = fromReader(new StringReader(string))
}
+
+/**
+ * Governs how empty elements (i.e. those without child elements) should be serialized.
+ */
+object MinimizeMode extends Enumeration {
+ /** Minimize empty tags if they were originally empty when parsed, or if they were constructed with [[scala.xml.Elem]]`#minimizeEmpty` == true */
+ val Default = Value
+
+ /** Always minimize empty tags. Note that this may be problematic for XHTML, in which case [[scala.xml.Xhtml]]`#toXhtml` should be used instead. */
+ val Always = Value
+
+ /** Never minimize empty tags. */
+ val Never = Value
+}
+
import Source._
/** The object `XML` provides constants, and functions to load
@@ -83,10 +98,10 @@ object XML extends XMLLoader[Elem]
* @param xmlDecl if true, write xml declaration
* @param doctype if not null, write doctype declaration
*/
- final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) {
+ final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType, minimizeTags: MinimizeMode.Value = MinimizeMode.Default) {
/* TODO: optimize by giving writer parameter to toXML*/
if (xmlDecl) w.write("<?xml version='1.0' encoding='" + enc + "'?>\n")
if (doctype ne null) w.write( doctype.toString() + "\n")
- w.write(Utility.toXML(node).toString)
+ w.write(Utility.serialize(node, minimizeTags = minimizeTags).toString)
}
}
diff --git a/src/library/scala/xml/factory/Binder.scala b/src/library/scala/xml/factory/Binder.scala
index a8b0ed585b..b4fe153bd8 100644..100755
--- a/src/library/scala/xml/factory/Binder.scala
+++ b/src/library/scala/xml/factory/Binder.scala
@@ -43,13 +43,13 @@ abstract class Binder(val preserveWS: Boolean) extends ValidatingMarkupHandler {
result &+ text(0, x.data)
case x:EntityRef =>
result &+ entityRef(0, x.entityName)
- case _ =>
- elemStart(0, n.prefix, n.label, n.attributes, n.scope)
+ case x:Elem =>
+ elemStart(0, x.prefix, x.label, x.attributes, x.scope)
val old = result
result = new NodeBuffer()
- for (m <- n.child) traverse(m)
- result = old &+ elem(0, n.prefix, n.label, n.attributes, n.scope, NodeSeq.fromSeq(result)).toList;
- elemEnd(0, n.prefix, n.label)
+ for (m <- x.child) traverse(m)
+ result = old &+ elem(0, x.prefix, x.label, x.attributes, x.scope, x.minimizeEmpty, NodeSeq.fromSeq(result)).toList;
+ elemEnd(0, x.prefix, x.label)
}
final def validate(n: Node): Node = {
diff --git a/src/library/scala/xml/parsing/ConstructingHandler.scala b/src/library/scala/xml/parsing/ConstructingHandler.scala
index 60c19138c3..7e61674682 100644..100755
--- a/src/library/scala/xml/parsing/ConstructingHandler.scala
+++ b/src/library/scala/xml/parsing/ConstructingHandler.scala
@@ -21,8 +21,8 @@ abstract class ConstructingHandler extends MarkupHandler
val preserveWS: Boolean
def elem(pos: Int, pre: String, label: String, attrs: MetaData,
- pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq =
- Elem(pre, label, attrs, pscope, nodes:_*)
+ pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq =
+ Elem(pre, label, attrs, pscope, empty, nodes:_*)
def procInstr(pos: Int, target: String, txt: String) =
ProcInstr(target, txt)
diff --git a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala
index 699c5b2b5f..e0258ba781 100644..100755
--- a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala
+++ b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala
@@ -16,7 +16,7 @@ package parsing
abstract class DefaultMarkupHandler extends MarkupHandler {
def elem(pos: Int, pre: String, label: String, attrs: MetaData,
- scope:NamespaceBinding, args: NodeSeq) = NodeSeq.Empty
+ scope:NamespaceBinding, empty: Boolean, args: NodeSeq) = NodeSeq.Empty
def procInstr(pos: Int, target: String, txt: String) = NodeSeq.Empty
diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala
index 87e785a98f..83db2f177d 100644..100755
--- a/src/library/scala/xml/parsing/MarkupHandler.scala
+++ b/src/library/scala/xml/parsing/MarkupHandler.scala
@@ -75,10 +75,11 @@ abstract class MarkupHandler extends Logged
* @param pre the prefix
* @param label the local name
* @param attrs the attributes (metadata)
+ * @param empty `true` if the element was previously empty; `false` otherwise.
* @param args the children of this element
* @return ...
*/
- def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, args: NodeSeq): NodeSeq
+ def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, empty: Boolean, args: NodeSeq): NodeSeq
/** callback method invoked by MarkupParser after parsing PI.
*/
diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala
index 1de08b3025..32feaa2209 100644..100755
--- a/src/library/scala/xml/parsing/MarkupParser.scala
+++ b/src/library/scala/xml/parsing/MarkupParser.scala
@@ -569,7 +569,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests
tmp
}
}
- val res = handle.elem(pos, pre, local, aMap, scope, ts)
+ val res = handle.elem(pos, pre, local, aMap, scope, ts == NodeSeq.Empty, ts)
handle.elemEnd(pos, pre, local)
res
}
diff --git a/src/library/scala/xml/pull/XMLEventReader.scala b/src/library/scala/xml/pull/XMLEventReader.scala
index f84d91d138..c764d042c8 100755
--- a/src/library/scala/xml/pull/XMLEventReader.scala
+++ b/src/library/scala/xml/pull/XMLEventReader.scala
@@ -81,7 +81,7 @@ extends collection.AbstractIterator[XMLEvent]
// memory usage optimization return one <ignore/> for top level to satisfy
// MarkupParser.document() otherwise NodeSeq.Empty
private var ignoreWritten = false
- final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq =
+ final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq =
if (level == 1 && !ignoreWritten) {ignoreWritten = true; <ignore/> } else NodeSeq.Empty
def procInstr(pos: Int, target: String, txt: String) = setEvent(EvProcInstr(target, txt))
diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala
index 1cb09b433a..994928c0f6 100644
--- a/src/partest/scala/tools/partest/CompilerTest.scala
+++ b/src/partest/scala/tools/partest/CompilerTest.scala
@@ -19,9 +19,42 @@ abstract class CompilerTest extends DirectTest {
lazy val global: Global = newCompiler()
lazy val units = compilationUnits(global)(sources: _ *)
+ import global._
+ import definitions._
override def extraSettings = "-usejavacp -d " + testOutput.path
- def sources: List[String] = List(code)
def show() = (sources, units).zipped foreach check
+
+ // Override at least one of these...
+ def code = ""
+ def sources: List[String] = List(code)
+
+ // Utility functions
+
+ class MkType(sym: Symbol) {
+ def apply[M](implicit m1: Manifest[M]): Type =
+ if (sym eq NoSymbol) NoType
+ else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x)))
+ }
+ implicit def mkMkType(sym: Symbol) = new MkType(sym)
+
+ def allMembers(root: Symbol): List[Symbol] = {
+ def loop(seen: Set[Symbol], roots: List[Symbol]): List[Symbol] = {
+ val latest = roots flatMap (_.info.members) filterNot (seen contains _)
+ if (latest.isEmpty) seen.toList.sortWith(_ isLess _)
+ else loop(seen ++ latest, latest)
+ }
+ loop(Set(), List(root))
+ }
+
+ class SymsInPackage(pkgName: String) {
+ def pkg = getRequiredModule(pkgName)
+ def classes = allMembers(pkg) filter (_.isClass)
+ def modules = allMembers(pkg) filter (_.isModule)
+ def symbols = classes ++ terms filterNot (_ eq NoSymbol)
+ def terms = allMembers(pkg) filter (s => s.isTerm && !s.isConstructor)
+ def tparams = classes flatMap (_.info.typeParams)
+ def tpes = symbols map (_.tpe) distinct
+ }
}
diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala
index 07444f8d4b..4e7f36bdc9 100644
--- a/src/partest/scala/tools/partest/DirectTest.scala
+++ b/src/partest/scala/tools/partest/DirectTest.scala
@@ -69,7 +69,7 @@ abstract class DirectTest extends App {
/** Constructor/main body **/
try show()
- catch { case t => println(t) ; sys.exit(1) }
+ catch { case t => println(t) ; t.printStackTrace ; sys.exit(1) }
/** Debugger interest only below this line **/
protected def isDebug = (sys.props contains "partest.debug") || (sys.env contains "PARTEST_DEBUG")