summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-12-07 17:31:49 +0000
committerMartin Odersky <odersky@gmail.com>2009-12-07 17:31:49 +0000
commit1e88594f358d08b5e9b22ba87280003a581359e4 (patch)
treee68b6d1095ff1b1345e86d8a67c1f874849a31ff
parentde1d172a15e20ec7e96d96d5cea5cb41162b9f75 (diff)
downloadscala-1e88594f358d08b5e9b22ba87280003a581359e4.tar.gz
scala-1e88594f358d08b5e9b22ba87280003a581359e4.tar.bz2
scala-1e88594f358d08b5e9b22ba87280003a581359e4.zip
new doc comment generation, including some new ...
new doc comment generation, including some new style doc comments in collection classes.
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala35
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala365
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala10
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/SourcelessComments.scala94
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/reporters/Reporter.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala63
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala5
-rw-r--r--src/library/scala/collection/IndexedSeqLike.scala13
-rw-r--r--src/library/scala/collection/IterableLike.scala333
-rw-r--r--src/library/scala/collection/Iterator.scala15
-rw-r--r--src/library/scala/collection/LinearSeqLike.scala12
-rw-r--r--src/library/scala/collection/MapLike.scala40
-rw-r--r--src/library/scala/collection/SeqLike.scala325
-rw-r--r--src/library/scala/collection/TraversableLike.scala150
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala9
-rwxr-xr-xtest/files/pos/t2683.scala7
-rw-r--r--test/files/run/sequenceComparisons.scala8
26 files changed, 1085 insertions, 450 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 6b2f3101a6..645eb1ecf6 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -115,31 +115,6 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val treeBrowser = treeBrowsers.create()
-
-// val copy = new LazyTreeCopier()
-
- /** A map of all doc comments, indexed by symbols.
- * Only active in onlyPresentation mode
- */
- val comments =
- if (onlyPresentation) new HashMap[Symbol,String]
- else null
-
- /** A map of all doc comments source file offsets,
- * indexed by symbols.
- * Only active in onlyPresentation mode
- */
- val commentOffsets =
- if (onlyPresentation) new HashMap[Symbol,Int]
- else null
-
- /** A map of argument names for methods
- * !!! can be dropped once named method arguments are in !!!
- */
- val methodArgumentNames =
- if (onlyPresentation) new HashMap[Symbol,List[List[Symbol]]]
- else null
-
// ------------ Hooks for interactive mode-------------------------
/** Called every time an AST node is succesfully typedchecked in typerPhase.
@@ -302,8 +277,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val unit0 = currentRun.currentUnit
try {
currentRun.currentUnit = unit
- reporter.setSource(unit.source)
- if (!cancelled(unit)) apply(unit)
+ if (!cancelled(unit))
+ reporter.withSource(unit.source) { apply(unit) }
currentRun.advanceUnit
} finally {
//assert(currentRun.currentUnit == unit)
@@ -889,11 +864,11 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
var localPhase = firstPhase.asInstanceOf[GlobalPhase]
while (localPhase != null && (localPhase.id < globalPhase.id || localPhase.id <= namerPhase.id)/* && !reporter.hasErrors*/) {
val oldSource = reporter.getSource
- reporter.setSource(unit.source)
- atPhase(localPhase)(localPhase.applyPhase(unit))
+ reporter.withSource(unit.source) {
+ atPhase(localPhase)(localPhase.applyPhase(unit))
+ }
val newLocalPhase = localPhase.next.asInstanceOf[GlobalPhase]
localPhase = if (localPhase == newLocalPhase) null else newLocalPhase
- reporter.setSource(oldSource)
}
refreshProgress
}
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
new file mode 100755
index 0000000000..d754f12dee
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -0,0 +1,365 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2009 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: Unapplies.scala 19206 2009-10-21 20:57:27Z extempore $
+
+package scala.tools.nsc
+package ast
+
+import symtab._
+import util.{Position, NoPosition}
+import scala.collection.mutable.{HashMap, ListBuffer, StringBuilder}
+
+/*
+ * @author Martin Odersky
+ * @version 1.0
+ */
+trait DocComments { self: SymbolTable =>
+
+ val docComments = new HashMap[Symbol, DocComment] // !!! todo: inherit from comment?
+
+ private val defs = new HashMap[Symbol, Map[String, String]] {
+ override def default(key: Symbol) = Map()
+ }
+
+ def getDocComment(sym: Symbol): Option[DocComment] = {
+ docComments get sym match {
+ case None =>
+ mapFind(sym.allOverriddenSymbols)(docComments.get)
+ case someSym =>
+ someSym
+ }
+ }
+
+ private def mapFind[A, B](xs: Iterable[A])(f: A => Option[B]): Option[B] = {
+ var res: Option[B] = None
+ val it = xs.iterator
+ while (res.isEmpty && it.hasNext) {
+ res = f(it.next())
+ }
+ res
+ }
+
+ /** The raw doc comment of symbol `sym`, as it appears in the source text, "" if missing.
+ */
+ def rawDocComment(sym: Symbol): String = getDocComment(sym) map (_.raw) getOrElse ""
+
+ /** The processed doc comment of symbol `sym`, where
+ * Wiki syntax is expanded and @usecase or @define parts are removed.
+ * No variables are expanded yet. "" if missing.
+ */
+ def templateDocComment(sym: Symbol): String = getDocComment(sym) map (_.template) getOrElse ""
+
+ /** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
+ * @param sym The symbol for which doc comment is returned
+ * @param site The class for which doc comments are generated
+ */
+ def cookedDocComment(sym: Symbol, site: Symbol): String =
+ getDocComment(sym) map (_.expanded(site)) getOrElse ""
+
+ /** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
+ * @param sym The symbol for which doc comment is returned (site is always the containing class)
+ */
+ def cookedDocComment(sym: Symbol): String = cookedDocComment(sym, sym.owner)
+
+ /** The position of the doc comment of symbol `sym`, or NoPosition if missing */
+ def docCommentPos(sym: Symbol): Position = getDocComment(sym) map (_.pos) getOrElse NoPosition
+
+ def useCases(sym: Symbol, site: Symbol): List[(Symbol, String)] = {
+ def getUseCases(dc: DocComment) = {
+ for (uc <- dc.useCases; defn <- uc.expandedDefs(site)) yield
+ (defn, uc.comment.expanded(site))
+ }
+ getDocComment(sym) map getUseCases getOrElse List()
+ }
+
+ def useCases(sym: Symbol): List[(Symbol, String)] = useCases(sym, sym.owner)
+
+ private val usecasePrefix = "@usecase "
+ private val definePrefix = "@define "
+
+ /** Returns index of string `str` after `in` skipping longest
+ * sequence of space and tab characters.
+ */
+ private def skipWhitespace(str: String, in: Int): Int = {
+ var idx = in
+ do {
+ idx += 1
+ } while (idx < str.length && (str charAt idx) == ' ' || (str charAt idx) == '\t')
+ idx
+ }
+
+ /** Returns index of string `str` after `in` skipping longest
+ * sequence of space and tab characters, possibly also containing
+ * a single `*' character.
+ */
+ private def skipLineLead(str: String, in: Int, end: Int): Int = {
+ val idx = skipWhitespace(str, in)
+ if (idx < end && (str charAt idx) == '*') skipWhitespace(str, idx)
+ else idx
+ }
+
+ /** Extracts variable name from a string, stripping any pair of surrounding braces */
+ private def variableName(str: String): String =
+ if (str.length >= 2 && (str charAt 0) == '{' && (str charAt (str.length - 1)) == '}')
+ str.substring(1, str.length - 1)
+ else
+ str
+
+ private def isVarPart(ch: Char) =
+ '0' <= ch && ch <= '9' || 'A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z'
+
+ /** Returns index following variable, or start index if no variable was recognized
+ */
+ private def skipVariable(str: String, start: Int): Int = {
+ var idx = start
+ if (idx < str.length && (str charAt idx) == '{') {
+ do idx += 1
+ while (idx < str.length && (str charAt idx) != '}')
+ if (idx < str.length) idx + 1 else start
+ } else {
+ while (idx < str.length && isVarPart(str charAt idx))
+ idx += 1
+ idx
+ }
+ }
+
+ private val wikiReplacements = List(
+ ("""(\n\s*\*?)(\s*\n)""" .r, """$1 <p>$2"""),
+ ("""\{\{\{(.*(?:\n.*)*)\}\}\}""".r, """<pre>$1</pre>"""),
+ ("""`([^`]*)`""" .r, """<code>$1</code>"""),
+ ("""__([^_]*)__""" .r, """<u>$1</u>"""),
+ ("""''([^']*)''""" .r, """<i>$1</i>"""),
+ ("""'''([^']*)'''""" .r, """<b>$1</b>"""),
+ ("""\^([^^]*)\^""" .r, """<sup>$1</sup>"""),
+ (""",,([^,]*),,""" .r, """<sub>$1</sub>"""))
+ private def expandWiki(str: String): String =
+ (str /: wikiReplacements) { (str1, regexRepl) => regexRepl._1 replaceAllIn(str1, regexRepl._2) }
+
+ /** Lookup definition of variable.
+ *
+ * @param vble The variable for which a definition is searched
+ * @param owner The current owner in which variable definitions are searched.
+ * @param site The class for which doc comments are generated
+ */
+ def lookupVariable(vble: String, site: Symbol): Option[String] =
+ if (site == NoSymbol)
+ None
+ else
+ mapFind(site.info.baseClasses)(defs(_).get(vble)) match {
+ case None => lookupVariable(vble, site.owner)
+ case someStr => someStr
+ }
+
+ private var expandCount = 0
+ private final val expandLimit = 10
+
+ /** Expand variable occurrences in string `str', until a fix point is reached or
+ * a expandLimit is exceeded.
+ *
+ * @param str The string to be expanded
+ * @param site The class for which doc comments are generated
+ * @return Expanded string
+ */
+ private def expandVariables(str: String, site: Symbol): String =
+ if (expandCount < expandLimit) {
+ try {
+ val out = new StringBuilder
+ var start = 0
+ var idx = 0
+ while (idx < str.length) {
+ if ((str charAt idx) == '$') {
+ val vstart = idx
+ idx = skipVariable(str, idx + 1)
+ val vname = variableName(str.substring(vstart + 1, idx))
+ if (vname.length > 0) {
+ lookupVariable(vname, site) match {
+ case Some(replacement) =>
+ out append str.substring(start, vstart)
+ out append replacement
+ start = idx
+ case None =>
+ println("no replacement for "+vname) // !!!
+ }
+ } else {
+ idx += 1
+ }
+ } else {
+ idx += 1
+ }
+ }
+ if (out.length == 0) str
+ else {
+ out append str.substring(start)
+ expandVariables(out.toString, site)
+ }
+ } finally {
+ expandCount -= 1
+ }
+ } else throw new ExpansionLimitExceeded(str)
+
+ case class DocComment(raw: String, pos: Position = NoPosition) {
+
+ lazy val (template, defines, useCases) = {
+ val parts = decompose(raw)
+ val (defines, usecases) = parts.tail partition (_._1 startsWith definePrefix)
+ val templ = expandWiki(parts.head._1)
+ (templ,
+ defines map (d => expandWiki(d._1)),
+ usecases map (decomposeUseCase(_, templ)))
+ }
+
+ def expanded(site: Symbol): String =
+ expandVariables(template, site)
+/*
+ expansions get site match {
+ case Some(str) => str
+ case None => val str =
+ expandVariables(template, sym, site)
+ expansions += (site -> str)
+ str
+ }
+ private var expansions: Map[Symbol, String] = Map()
+*/
+
+
+ /** Decomposes a comment string into
+ * an initial comment and a list of @define and @usecase clauses, each with starting index
+ */
+ private def decompose(str: String): List[(String, Int)] = {
+ val out = new ListBuffer[(String, Int)]
+ var segstart = 0
+ var idx = 3 // skip initial "/**"
+ val end = str.length - 2 // stop before final "*/"
+ var eolIdx = idx
+ while (idx < end) {
+ if ((str charAt idx) == '\n') {
+ eolIdx = idx
+ idx = skipLineLead(str, idx, end)
+ if ((str charAt idx) == '@' &&
+ (str.startsWith(definePrefix, idx) || str.startsWith(usecasePrefix, idx))) {
+ var segment = str.substring(segstart, eolIdx)
+ if (segstart == 0) segment += "*/"
+ out += ((segment, segstart))
+ segstart = idx
+ }
+ } else idx += 1
+ }
+ if (segstart == 0)
+ List((str, 0))
+ else {
+ out += ((str.substring(segstart, eolIdx), segstart))
+ out.toList
+ }
+ }
+
+ def subPos(start: Int, end: Int) =
+ if (pos == NoPosition) NoPosition
+ else {
+ val start1 = pos.start + start
+ val end1 = pos.end + end
+ pos withStart start1 withPoint start1 withEnd end1
+ }
+
+ def decomposeUseCase(stroff: (String, Int), mainComment: String): UseCase = {
+ val str = stroff._1
+ val offset = stroff._2
+ val start = usecasePrefix.length
+ var idx = start
+ while (idx < str.length && (str charAt idx) != '\n') idx += 1
+ val code = str.substring(start, idx)
+ val codePos = subPos(offset + usecasePrefix.length, offset + idx)
+ var firstParBreak = mainComment indexOf "<p>"
+ if (firstParBreak == -1) firstParBreak = mainComment.length - 2
+ val comment = mainComment.substring(0, firstParBreak)+"<p>"+
+ str.substring(skipLineLead(str, idx, str.length))+"*/"
+ val commentPos = subPos(offset + idx, offset + str.length)
+ UseCase(DocComment(comment, commentPos), code, codePos)
+ }
+
+ def defineVariables(sym: Symbol) {
+ for (str <- defines) {
+ val start = definePrefix.length
+ var idx = skipVariable(str, start)
+ val vble = variableName(str.substring(start, idx))
+ if (idx < str.length && (str charAt idx) == ' ') idx += 1
+ defs(sym) += vble -> str.substring(idx)
+ }
+ if (defs(sym).nonEmpty) println("vars of "+sym+" = "+defs(sym)) // !!!
+ }
+ }
+
+ case class UseCase(comment: DocComment, body: String, pos: Position) {
+ var defined: List[Symbol] = List()
+ var aliases: List[Symbol] = List()
+
+ def expandedDefs(site: Symbol): List[Symbol] = {
+
+ def select(site: Type, name: Name, orElse: => Type): Type = {
+ val member = site.nonPrivateMember(name)
+ if (member.isTerm) SingleType(site, member)
+ else if (member.isType) site.memberType(member)
+ else orElse
+ }
+
+ def getSite(name: Name): Type = {
+ if (name == nme.this_) site.thisType
+ else {
+ def findIn(sites: List[Symbol]): Type = sites match {
+ case List() => NoType
+ case site :: sites1 => select(site.thisType, name, findIn(sites1))
+ }
+ val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass)
+ findIn(classes ::: List(pkgs.head, definitions.RootClass))
+ }
+ }
+
+ def getType(str: String): Type = {
+ val parts = str.split("""\.""").toList
+ val partnames = (parts.init map newTermName) ::: List(newTypeName(parts.last))
+ (getSite(partnames.head) /: partnames.tail)(select(_, _, NoType))
+ }
+
+ val aliasExpansions: List[Type] =
+ for (alias <- aliases) yield
+ lookupVariable(alias.name.toString.substring(1), site) match {
+ case Some(repl) =>
+ val tpe = getType(repl)
+ if (tpe != NoType) tpe
+ else {
+ val alias1 = alias.cloneSymbol(definitions.RootClass)
+ alias1.name = repl.toTypeName
+ TypeRef(NoPrefix, alias1, List())
+ }
+ case None =>
+ TypeRef(NoPrefix, alias, List())
+ }
+
+ def subst(sym: Symbol, from: List[Symbol], to: List[Type]): Type =
+ if (from.isEmpty) sym.tpe
+ else if (from.head == sym) to.head
+ else subst(sym, from.tail, to.tail)
+
+ val substAliases = new TypeMap {
+ def apply(tp: Type) = mapOver(tp) match {
+ case tp1 @ TypeRef(pre, sym, args) if (sym.name.length > 1 && sym.name(0) == '$') =>
+ subst(sym, aliases, aliasExpansions) match {
+ case TypeRef(pre, sym1, _) =>
+ TypeRef(pre, sym1, args)
+ case _ =>
+ tp1
+ }
+ case tp1 =>
+ tp1
+ }
+ }
+
+ for (defn <- defined) yield
+ defn.cloneSymbol(site).setInfo(
+ substAliases(defn.info).asSeenFrom(site.thisType, defn.owner))
+ }
+ }
+
+ class ExpansionLimitExceeded(str: String) extends Exception
+}
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index d18ecbbd37..4ba5f17a40 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -215,7 +215,7 @@ abstract class TreePrinters {
}
case DocDef(comment, definition) =>
- print(comment); println; print(definition)
+ print(comment.raw); println; print(definition)
case Template(parents, self, body) =>
val currentOwner1 = currentOwner
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 6c6311f143..3af729d4d7 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -570,7 +570,7 @@ trait Trees {
// It's used primarily as a marker to check that the import has been typechecked.
/** Documented definition, eliminated by analyzer */
- case class DocDef(comment: String, definition: Tree)
+ case class DocDef(comment: DocComment, definition: Tree)
extends Tree {
override def symbol: Symbol = definition.symbol
override def symbol_=(sym: Symbol) { definition.symbol = sym }
@@ -1072,7 +1072,7 @@ trait Trees {
def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
- def DocDef(tree: Tree, comment: String, definition: Tree): DocDef
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
@@ -1127,7 +1127,7 @@ trait Trees {
new LabelDef(name, params, rhs).copyAttrs(tree)
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) =
new Import(expr, selectors).copyAttrs(tree)
- def DocDef(tree: Tree, comment: String, definition: Tree) =
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) =
new DocDef(comment, definition).copyAttrs(tree)
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) =
new Template(parents, self, body).copyAttrs(tree)
@@ -1244,7 +1244,7 @@ trait Trees {
if (expr0 == expr) && (selectors0 == selectors) => t
case _ => treeCopy.Import(tree, expr, selectors)
}
- def DocDef(tree: Tree, comment: String, definition: Tree) = tree match {
+ def DocDef(tree: Tree, comment: DocComment, definition: Tree) = tree match {
case t @ DocDef(comment0, definition0)
if (comment0 == comment) && (definition0 == definition) => t
case _ => treeCopy.DocDef(tree, comment, definition)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index de71ba30ab..c4c26e54b3 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -420,13 +420,13 @@ self =>
*/
def joinComment(trees: => List[Tree]): List[Tree] = {
val doc = in.flushDoc
- if ((doc ne null) && doc._1.length > 0) {
+ if ((doc ne null) && doc.raw.length > 0) {
val ts = trees
val main = ts.find(_.pos.isOpaqueRange)
ts map {
t =>
- val dd = DocDef(doc._1, t)
- val pos = doc._2.withEnd(t.pos.endOrPoint)
+ val dd = DocDef(doc, t)
+ val pos = doc.pos.withEnd(t.pos.endOrPoint)
dd setPos (if (t eq main) pos else pos.makeTransparent)
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 62c47e8606..3de13ed877 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -103,11 +103,11 @@ trait Scanners {
/** buffer for the documentation comment
*/
var docBuffer: StringBuilder = null
- var docOffset: Position = null
+ var docPos: Position = null
/** Return current docBuffer and set docBuffer to null */
- def flushDoc = {
- val ret = if (docBuffer != null) (docBuffer.toString, docOffset) else null
+ def flushDoc: DocComment = {
+ val ret = if (docBuffer != null) DocComment(docBuffer.toString, docPos) else null
docBuffer = null
ret
}
@@ -1091,8 +1091,8 @@ trait Scanners {
}
override def foundDocComment(value: String, start: Int, end: Int) {
- docOffset = new RangePosition(unit.source, start, start, end)
- unit.comment(docOffset, value)
+ docPos = new RangePosition(unit.source, start, start, end)
+ unit.comment(docPos, value)
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index 240ba17d51..3c969c41f8 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -39,7 +39,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
override def onlyPresentation = true
lazy val addSourceless = {
val sless = new SourcelessComments { val global = compiler }
- comments ++= sless.comments
+ docComments ++= sless.comments
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala b/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
index 50888ba27c..9216fa6f23 100644
--- a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
+++ b/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
@@ -21,9 +21,9 @@ abstract class SourcelessComments {
lazy val comments = {
- val comment = mutable.HashMap.empty[Symbol, String]
+ val comment = mutable.HashMap.empty[Symbol, DocComment]
- comment(NothingClass) = """
+ comment(NothingClass) = new DocComment("""
/** <p>
* Class <code>Nothing</code> is - together with class <a href="Null.html">
* <code>Null</code></a> - at the bottom of the
@@ -44,9 +44,9 @@ abstract class SourcelessComments {
* instance of <code><a href="List.html">List</a>[T]</code>, for
* any element type <code>T</code>.
* </p> */
- """
+ """)
- comment(NullClass) = """
+ comment(NullClass) = new DocComment("""
/** <p>
* Class <code>Null</code> is - together with class <a href="Nothing.html">
* <code>Nothing</code> - at the bottom of the
@@ -61,12 +61,12 @@ abstract class SourcelessComments {
* it is not possible to assign <code>null</code> to a variable of
* type <a href="Int.html"><code>Int</code></a>.
* </p> */
- """
+ """)
/*******************************************************************/
/* Documentation for Any */
- comment(AnyClass) = """
+ comment(AnyClass) = new DocComment("""
/** <p>
* Class <code>Any</code> is the root of the <a
* href="http://scala-lang.org/"
@@ -77,9 +77,9 @@ abstract class SourcelessComments {
* <a href="AnyRef.html"><code>AnyRef</code></a> and
* <a href="AnyVal.html"><code>AnyVal</code></a>.
* </p> */
- """
+ """)
- comment(Any_equals) = """
+ comment(Any_equals) = new DocComment("""
/** This method is used to compare the receiver object (<code>this</code>)
* with the argument object (<code>arg0</code>) for equivalence.
*
@@ -113,34 +113,34 @@ abstract class SourcelessComments {
* @param arg0 the object to compare against this object for equality.
* @return <code>true</code> if the receiver object is equivalent to the argument; <code>false</code> otherwise.
* </p> */
- """
+ """)
- comment(Any_==) = """
+ comment(Any_==) = new DocComment("""
/** `o == arg0` is the same as `o.equals(arg0)`.
* <p>
* @param arg0 the object to compare against this object for equality.
* @return `true` if the receiver object is equivalent to the argument; `false` otherwise.
* </p> */
- """
+ """)
- comment(Any_!=) = """
+ comment(Any_!=) = new DocComment("""
/** `o != arg0` is the same as `!(o == (arg0))`.
* <p>
* @param arg0 the object to compare against this object for dis-equality.
* @return `false` if the receiver object is equivalent to the argument; `true` otherwise.
* </p> */
- """
+ """)
- comment(Any_toString) = """
+ comment(Any_toString) = new DocComment("""
/** Returns a string representation of the object.
* <p>
* The default representation is platform dependent.
*
* @return a string representation of the object.
* </p>*/
- """
+ """)
- comment(Any_asInstanceOf) = """
+ comment(Any_asInstanceOf) = new DocComment("""
/**This method is used to cast the receiver object to be of type <code>T0</code>.
*
* <p>Note that the success of a cast at runtime is modulo Scala's
@@ -156,9 +156,9 @@ abstract class SourcelessComments {
* instance of erasure of type <code>T0</code>.
* @return the receiver object.
* </p> */
- """
+ """)
- comment(Any_isInstanceOf) = """
+ comment(Any_isInstanceOf) = new DocComment("""
/** This method is used to test whether the dynamic type of the receiver object is <code>T0</code>.
*
* <p>Note that the test result of the test is modulo Scala's erasure
@@ -172,9 +172,9 @@ abstract class SourcelessComments {
*
* @return <code>true</code> if the receiver object is an
* instance of erasure of type <code>T0</code>; <code>false</code> otherwise. */
- """
+ """)
- comment(Any_hashCode) = """
+ comment(Any_hashCode) = new DocComment("""
/** Returns a hash code value for the object.
*
* <p>
@@ -195,36 +195,36 @@ abstract class SourcelessComments {
* <p>
* @return the hash code value for the object.
* </p> */
- """
+ """)
/*******************************************************************/
/* Documentation for AnyRef */
- comment(AnyRefClass) = """
+ comment(AnyRefClass) = new DocComment("""
/** <p>
* Class <code>AnyRef</code> is the root class of all
* <em>reference types</em>.
* </p> */
- """
+ """)
- comment(Object_==) = """
+ comment(Object_==) = new DocComment("""
/** <code>o == arg0</code> is the same as <code>if (o eq null) arg0 eq null else o.equals(arg0)</code>.
* <p>
* @param arg0 the object to compare against this object for equality.
* @return <code>true</code> if the receiver object is equivalent to the argument; <code>false</code> otherwise.
* </p> */
- """
+ """)
- comment(Object_ne) = """
+ comment(Object_ne) = new DocComment("""
/** <code>o.ne(arg0)</code> is the same as <code>!(o.eq(arg0))</code>.
* <p>
* @param arg0 the object to compare against this object for reference dis-equality.
* @return <code>false</code> if the argument is not a reference to the receiver object; <code>true</code> otherwise.
* </p> */
- """
+ """)
- comment(Object_finalize) = """
+ comment(Object_finalize) = new DocComment("""
/** This method is called by the garbage collector on the receiver object when garbage
* collection determines that there are no more references to the object.
* <p>
@@ -232,9 +232,9 @@ abstract class SourcelessComments {
* invoked, as well as the interaction between <code>finalize</code>
* and non-local returns and exceptions, are all platform dependent.
* </p> */
- """
+ """)
- comment(Object_clone) = """
+ comment(Object_clone) = new DocComment("""
/** This method creates and returns a copy of the receiver object.
*
* <p>
@@ -242,9 +242,9 @@ abstract class SourcelessComments {
*
* @return a copy of the receiver object.
* </p> */
- """
+ """)
- comment(Object_getClass) = """
+ comment(Object_getClass) = new DocComment("""
/** Returns a representation that corresponds to the dynamic class of the receiver object.
*
* <p>
@@ -252,17 +252,17 @@ abstract class SourcelessComments {
*
* @return a representation that corresponds to the dynamic class of the receiver object.
* </p> */
- """
+ """)
- comment(Object_notify) = """
+ comment(Object_notify) = new DocComment("""
/** Wakes up a single thread that is waiting on the receiver object's monitor. */
- """
+ """)
- comment(Object_notifyAll) = """
+ comment(Object_notifyAll) = new DocComment("""
/** Wakes up all threads that are waiting on the receiver object's monitor. */
- """
+ """)
- comment(Object_eq) = """
+ comment(Object_eq) = new DocComment("""
/** This method is used to test whether the argument (<code>arg0</code>) is a reference to the
* receiver object (<code>this</code>).
*
@@ -304,11 +304,11 @@ abstract class SourcelessComments {
* @param arg0 the object to compare against this object for reference equality.
* @return <code>true</code> if the argument is a reference to the receiver object; <code>false</code> otherwise.
* </p> */
- """
+ """)
/*******************************************************************/
- comment(AnyValClass) = """
+ comment(AnyValClass) = new DocComment("""
/** <p>
* Class <code>AnyVal</code> is the root class of all
* <em>value types</em>.
@@ -338,25 +338,25 @@ abstract class SourcelessComments {
* <a href="Double.html"><code>Double</code></a> are called
* <em>floating point types</em>.
* </p> */
- """
+ """)
- comment(BooleanClass) = """
+ comment(BooleanClass) = new DocComment("""
/** <p>
* Class <code>Boolean</code> has only two values: <code>true</code>
* and <code>false</code>.
* </p> */
- """
+ """)
- comment(UnitClass) = """
+ comment(UnitClass) = new DocComment("""
/** <p>
* Class <code>Unit</code> has only one value: <code>()</code>.
* </p> */
- """
+ """)
List(ByteClass, CharClass, DoubleClass, LongClass, FloatClass, IntClass, ShortClass) foreach { sym =>
val maxValue = "MAX_" + sym.name.toString().toUpperCase()
val minValue = "MIN_" + sym.name.toString().toUpperCase()
- comment(sym) = """
+ comment(sym) = new DocComment("""
/** <p>
* Class <code>""" + sym.name + """</code> belongs to the value
* classes whose instances are not represented as objects by the
@@ -370,7 +370,7 @@ abstract class SourcelessComments {
* Values <code>""" + maxValue + """</code> and <code>""" + minValue + """</code>
* are in defined in object <a href="Math$object.html">scala.Math</a>.
* </p> */
- """
+ """)
}
comment
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index b8a219fb4d..35d212071e 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -512,11 +512,8 @@ self =>
*/
private def applyPhase(phase: Phase, unit: CompilationUnit) {
val oldSource = reporter.getSource
- try {
- reporter.setSource(unit.source)
+ reporter.withSource(unit.source) {
atPhase(phase) { phase.asInstanceOf[GlobalPhase] applyPhase unit }
- } finally {
- reporter setSource oldSource
}
}
}
diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
index b00590d501..99292f2338 100644
--- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
@@ -41,6 +41,15 @@ abstract class Reporter {
private var source: SourceFile = _
def setSource(source: SourceFile) { this.source = source }
def getSource: SourceFile = source
+ def withSource[A](src: SourceFile)(op: => A) = {
+ val oldSource = source
+ try {
+ source = src
+ op
+ } finally {
+ source = oldSource
+ }
+ }
def info(pos: Position, msg: String, force: Boolean) { info0(pos, msg, INFO, force) }
def warning(pos: Position, msg: String ) { info0(pos, msg, WARNING, false) }
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index da0d237567..2a70c55cd6 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc
package symtab
-import ast.Trees
+import ast.{Trees, DocComments}
import util._
@@ -23,6 +23,7 @@ abstract class SymbolTable extends Names
with AnnotationCheckers
with Trees
with Positions
+ with DocComments
{
def settings: Settings
def rootLoader: LazyType
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 8d3d0bbf2a..ee0576d654 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -538,7 +538,7 @@ abstract class UnPickler {
case other => errorBadSignature("Document comment not a string (" + other + ")")
}
val definition = readTreeRef()
- DocDef(comment, definition)
+ DocDef(DocComment(comment, NoPosition), definition)
case TEMPLATEtree =>
setSym()
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 1e8b93bf5d..2132be4d50 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -758,9 +758,6 @@ trait Namers { self: Analyzer =>
tpt setPos meth.pos.focus
}
- if (onlyPresentation && methodArgumentNames != null)
- methodArgumentNames(meth) = vparamss.map(_.map(_.symbol));
-
def convertToDeBruijn(vparams: List[Symbol], level: Int): TypeMap = new TypeMap {
def debruijnFor(param: Symbol) =
DeBruijnIndex(level, vparams indexOf param)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 682a7db991..a18fbe70d1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -151,6 +151,17 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
decls.enter(s)
}
}
+ if (settings.verbose.value && onlyPresentation && !sym.isAnonymousClass) {
+ println("========== scaladoc of "+sym+" =============================")
+ for (member <- sym.info.members) {
+ println(member+":"+sym.thisType.memberInfo(member)+"\n"+
+ cookedDocComment(member, sym))
+ for ((useCase, comment) <- useCases(member, sym)) {
+ println("usecase "+useCase+":"+useCase.info)
+ println(comment)
+ }
+ }
+ }
super.transform(tree)
case ModuleDef(_, _, _) =>
checkCompanionNameClashes(sym)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 7e4d6b7d7d..a610f85104 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -15,7 +15,7 @@ import scala.collection.mutable.{HashMap, ListBuffer}
import scala.util.control.ControlException
import scala.compat.Platform.currentTime
import scala.tools.nsc.interactive.RangePositions
-import scala.tools.nsc.util.{ Position, Set, NoPosition, SourceFile }
+import scala.tools.nsc.util.{ Position, Set, NoPosition, SourceFile, BatchSourceFile }
import symtab.Flags._
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
@@ -689,8 +689,8 @@ trait Typers { self: Analyzer =>
else qual.tpe.nonLocalMember(name)
}
- def silent(op: Typer => Tree): AnyRef /* in fact, TypeError or Tree */ = {
- val start = System.nanoTime()
+ def silent[T](op: Typer => T): Any /* in fact, TypeError or T */ = {
+// val start = System.nanoTime()
try {
if (context.reportGeneralErrors) {
val context1 = context.makeSilent(context.reportAmbiguousErrors)
@@ -709,7 +709,7 @@ trait Typers { self: Analyzer =>
} catch {
case ex: CyclicReference => throw ex
case ex: TypeError =>
- failedSilent += System.nanoTime() - start
+// failedSilent += System.nanoTime() - start
ex
}}
@@ -1709,6 +1709,45 @@ trait Typers { self: Analyzer =>
}
}
+ def typedUseCase(useCase: UseCase) {
+ def stringParser(str: String): syntaxAnalyzer.Parser = {
+ val file = new BatchSourceFile(context.unit.source.file, str) {
+ override def positionInUltimateSource(pos: Position) = {
+ pos.withSource(context.unit.source, useCase.pos.start)
+ }
+ }
+ val unit = new CompilationUnit(file)
+ new syntaxAnalyzer.UnitParser(unit)
+ }
+ val trees = stringParser(useCase.body+";").nonLocalDefOrDcl
+ val enclClass = context.enclClass.owner
+ def defineAlias(name: Name) =
+ if (context.scope.lookup(name) == NoSymbol) {
+ lookupVariable(name.toString.substring(1), enclClass) match {
+ case Some(repl) =>
+ silent(_.typedTypeConstructor(stringParser(repl).typ())) match {
+ case tpt: Tree =>
+ val alias = enclClass.newAliasType(useCase.pos, name)
+ val tparams = cloneSymbols(tpt.tpe.typeSymbol.typeParams, alias)
+ alias setInfo polyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
+ context.scope.enter(alias)
+ case _ =>
+ }
+ case _ =>
+ }
+ }
+ for (tree <- trees; t <- tree)
+ t match {
+ case Ident(name) if (name.length > 0 && name(0) == '$') => defineAlias(name)
+ case _ =>
+ }
+ useCase.aliases = context.scope.toList
+ namer.enterSyms(trees)
+ typedStats(trees, NoSymbol)
+ useCase.defined = context.scope.toList -- useCase.aliases
+// println("defined use cases: "+(useCase.defined map (sym => sym+":"+sym.tpe)))
+ }
+
/**
* @param ddef ...
* @return ...
@@ -3701,12 +3740,18 @@ trait Typers { self: Analyzer =>
labelTyper(ldef).typedLabelDef(ldef)
case ddef @ DocDef(comment, defn) =>
- val ret = typed(defn, mode, pt)
- if ((comments ne null) && (defn.symbol ne null) && (defn.symbol ne NoSymbol)) {
- comments(defn.symbol) = comment
- commentOffsets(defn.symbol) = ddef.pos.startOrPoint
+ if (onlyPresentation && (sym ne null) && (sym ne NoSymbol)) {
+ docComments(sym) = comment
+ comment.defineVariables(sym)
+ val typer1 = newTyper(context.makeNewScope(tree, context.owner))
+ for (useCase <- comment.useCases)
+ typer1.silent(_.typedUseCase(useCase)) match {
+ case ex: TypeError =>
+ unit.warning(useCase.pos, ex.msg)
+ case _ =>
+ }
}
- ret
+ typed(defn, mode, pt)
case Annotated(constr, arg) =>
typedAnnotated(constr, typed(arg, mode, pt))
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index 999dca3927..806c885291 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -109,6 +109,9 @@ trait Position {
/** The same position with a different point value (if a range or offset) */
def withPoint(off: Int) = this
+ /** The same position with a different source value, and its values shifted by given offset */
+ def withSource(source: SourceFile, shift: Int) = this
+
/** If this is a range, the union with the other range, with the point of this position.
* Otherwise, this position
*/
@@ -200,6 +203,7 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e
override def isDefined = true
override def pointOrElse(default: Int): Int = point
override def withPoint(off: Int) = new OffsetPosition(source, off)
+ override def withSource(source: SourceFile, shift: Int) = new OffsetPosition(source, point + shift)
override def line: Int = source.offsetToLine(point) + 1
@@ -240,6 +244,7 @@ extends OffsetPosition(source, point) {
override def withStart(off: Int) = new RangePosition(source, off, point, end)
override def withEnd(off: Int) = new RangePosition(source, start, point, off)
override def withPoint(off: Int) = new RangePosition(source, start, off, end)
+ override def withSource(source: SourceFile, shift: Int) = new RangePosition(source, start + shift, point + shift, end + shift)
override def focusStart = new OffsetPosition(source, start)
override def focus = {
if (focusCache eq NoPosition) focusCache = new OffsetPosition(source, point)
diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala
index 68862e4aed..7041078229 100644
--- a/src/library/scala/collection/IndexedSeqLike.scala
+++ b/src/library/scala/collection/IndexedSeqLike.scala
@@ -77,7 +77,18 @@ trait IndexedSeqLike[+A, +Repr] extends SeqLike[A, Repr] { self =>
val i = prefixLength(!p(_))
if (i < length) Some(this(i)) else None
}
-
+/*
+ override def mapFind[B](f: A => Option[B]): Option[B] = {
+ var i = 0
+ var res: Option[B] = None
+ val len = length
+ while (res.isEmpty && i < len) {
+ res = f(this(i))
+ i += 1
+ }
+ res
+ }
+*/
@tailrec
private def foldl[B](start: Int, end: Int, z: B, op: (B, A) => B): B =
if (start == end) z
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index f1401f1221..66f63dd2f5 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -14,7 +14,7 @@ import immutable.{List, Stream}
import annotation.unchecked.uncheckedVariance
/** <p>
- * A template trait for iterable collections.
+ * A template trait for iterable collections of type `Iterable[A]`.
* </p>
* <p>
* Collection classes mixing in this trait provide a method
@@ -36,11 +36,27 @@ import annotation.unchecked.uncheckedVariance
* <code>Iterable</code></a>.
* </p>
*
- * @note This trait replaces every method that uses breaks in the original by an iterator version.
+ * Note: This trait replaces every method that uses breaks in the original by an iterator version.
+ *
+ * @see Iterable
*
* @author Martin Odersky
* @version 2.8
* @since 2.8
+ *
+ * @tparam A the element type of the collection
+ * @tparam Repr the type of the actual collection containing the elements.
+ *
+ * @define Coll Iterable
+ * @define coll iterable collection
+ * @define zipthatinfo the class of the returned collection. Where possible, `That` is
+ * the same class as the current collection class `Repr`, but this
+ * depends on the element type `(A1, B)` being admissible for that class,
+ * which means that an implicit instance of type `CanBuildFrom[Repr, (A1, B), That]`.
+ * is found.
+ * @define zipbfinfo an implicit value of class `CanBuildFrom` which determines the
+ * result class `That` from the current representation type `Repr`
+ * and the new element type `(A1, B)`.
*/
trait IterableLike[+A, +Repr] extends Equals with TraversableLike[A, Repr] {
self =>
@@ -58,102 +74,50 @@ self =>
@deprecated("use `iterator' instead")
def elements = iterator
- /** Apply a function <code>f</code> to all elements of this
- * iterable object.
- *
- * @param f A function that is applied for its side-effect to every element.
- * The result (of arbitrary type U) of function `f` is discarded.
- *
- * @note This method underlies the implementation of most other bulk operations.
- * Implementing `foreach` with `iterator` is often suboptimal.
- * So `foreach` should be overridden in concrete collection classes if a more
- * efficient implementation is available.
- */
- def foreach[U](f: A => U): Unit = iterator.foreach(f)
-
-
- /** Return true iff the given predicate `p` yields true for all elements
- * of this iterable.
- *
- * @note May not terminate for infinite-sized collections.
- * @param p the predicate
- */
- override def forall(p: A => Boolean): Boolean = iterator.forall(p)
-
- /** Return true iff there is an element in this iterable for which the
- * given predicate `p` yields true.
- *
- * @note May not terminate for infinite-sized collections.
- * @param p the predicate
- */
- override def exists(p: A => Boolean): Boolean = iterator.exists(p)
-
- /** Find and return the first element of the iterable object satisfying a
- * predicate, if any.
+ /** Applies a function `f` to all elements of this $coll.
*
- * @note may not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered.
- * @param p the predicate
- * @return an option containing the first element in the iterable object
- * satisfying <code>p</code>, or <code>None</code> if none exists.
- */
- override def find(p: A => Boolean): Option[A] = iterator.find(p)
-
- /** Does this iterable contain no elements?
- */
- override def isEmpty: Boolean = !this.iterator.hasNext
-
- /** Combines the elements of this iterable together using the binary
- * function <code>f</code>, from right to left, and starting with
- * the value <code>z</code>.
+ * Note: this method underlies the implementation of most other bulk operations.
+ * Subclasses should re-implement this method if a more efficient implementation exists.
*
- * @note Will not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered, or
- * the operator is associative and commutative.
- * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
- * if the iterable is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
- */
- override def foldRight[B](z: B)(op: (A, B) => B): B =
- this.iterator.foldRight(z)(op)
-
- /** Combines the elements of this iterable object together using the binary
- * operator <code>op</code>, from right to left
- * @note Will not terminate for infinite-sized collections.
- * @note Might return different results for different runs, unless this iterable is ordered, or
- * the operator is associative and commutative.
- * @param op The operator to apply
+ * @param f the function that is applied for its side-effect to every element.
+ * The result of function `f` is discarded.
*
- * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
- * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
- * a<sub>n</sub></code>.
+ * @tparam U the type parameter describing the result of function `f`.
+ * This result will always be ignored. Typically `U` is `Unit`,
+ * but this is not necessary.
*
- * @throws Predef.UnsupportedOperationException if the iterator is empty.
- */
- override def reduceRight[B >: A](op: (A, B) => B): B =
- this.iterator.reduceRight(op)
-
- /** The iterable itself */
- override def toIterable: Iterable[A] = thisCollection
-
- /** The first element of this iterable.
+ * @usecase def foreach(f: A => Unit): Unit
*
- * @note Might return different results for different runs, unless this iterable is ordered
- * @throws Predef.NoSuchElementException if the iterable is empty.
+ * @param f the function that is applied for its side-effect to every element.
+ * The result of function `f` is discarded.
*/
- override def head: A =
- if (isEmpty)
- throw new NoSuchElementException
- else
- this.iterator.next
-
- /** Return an iterable consisting only of the first <code>n</code>
- * elements of this iterable, or else the whole iterable, if it has less
- * than <code>n</code> elements.
- *
- * @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def take(n: Int): Repr = {
+ def foreach[U](f: A => U): Unit =
+ iterator.foreach(f)
+
+ override /*TraversableLike*/ def forall(p: A => Boolean): Boolean =
+ iterator.forall(p)
+ override /*TraversableLike*/ def exists(p: A => Boolean): Boolean =
+ iterator.exists(p)
+ override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
+ iterator.find(p)
+/*
+ override /*TraversableLike*/ def mapFind[B](f: A => Option[B]): Option[B] =
+ iterator.mapFind(f)
+*/
+ override /*TraversableLike*/ def isEmpty: Boolean =
+ !iterator.hasNext
+ override /*TraversableLike*/ def foldRight[B](z: B)(op: (A, B) => B): B =
+ iterator.foldRight(z)(op)
+ override /*TraversableLike*/ def reduceRight[B >: A](op: (A, B) => B): B =
+ iterator.reduceRight(op)
+ override /*TraversableLike*/ def toIterable: Iterable[A] =
+ thisCollection
+
+ override /*TraversableLike*/ def head: A =
+ if (isEmpty) throw new NoSuchElementException
+ else iterator.next
+
+ override /*TraversableLike*/ def take(n: Int): Repr = {
val b = newBuilder
var i = 0
val it = iterator
@@ -164,17 +128,7 @@ self =>
b.result
}
- /** A sub-iterable starting at index `from`
- * and extending up to (but not including) index `until`.
- *
- * @note c.slice(from, to) is equivalent to (but possibly more efficient than)
- * c.drop(from).take(to - from)
- *
- * @param from The index of the first element of the returned subsequence
- * @param until The index of the element following the returned subsequence
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def slice(from: Int, until: Int): Repr = {
+ override /*TraversableLike*/ def slice(from: Int, until: Int): Repr = {
val b = newBuilder
var i = from
val it = iterator drop from
@@ -185,13 +139,7 @@ self =>
b.result
}
- /** Returns the longest prefix of this iterable whose elements satisfy
- * the predicate <code>p</code>.
- *
- * @param p the test predicate.
- * @note Might return different results for different runs, unless this iterable is ordered
- */
- override def takeWhile(p: A => Boolean): Repr = {
+ override /*TraversableLike*/ def takeWhile(p: A => Boolean): Repr = {
val b = newBuilder
val it = iterator
while (it.hasNext) {
@@ -202,10 +150,12 @@ self =>
b.result
}
- /** Returns the rightmost <code>n</code> elements from this iterable.
+ /** Selects last ''n'' elements.
+ * $orderDependent
*
* @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @return a $coll consisting only of the last `n` elements of this $coll, or else the
+ * whole $coll, if it has less than `n` elements.
*/
def takeRight(n: Int): Repr = {
val b = newBuilder
@@ -219,10 +169,12 @@ self =>
b.result
}
- /** Returns the iterable wihtout its rightmost <code>n</code> elements.
+ /** Selects all elements except first ''n'' ones.
+ * $orderDependent
*
- * @param n the number of elements to take
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @param n The number of elements to take
+ * @return a $coll consisting of all elements of this $coll except the first `n` ones, or else the
+ * empty $coll, if this $coll has less than `n` elements.
*/
def dropRight(n: Int): Repr = {
val b = newBuilder
@@ -235,17 +187,7 @@ self =>
b.result
}
- /** Fills the given array <code>xs</code> with at most `len` elements of
- * this iterable starting at position `start`.
- * Copying will stop once either the end of the current iterable is reached or
- * `len` elements have been copied or the end of the array is reached.
- *
- * @note Will not terminate for infinite-sized collections.
- * @param xs the array to fill.
- * @param start starting index.
- * @param len number of elements to copy
- */
- override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ override /*TraversableLike*/ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
var i = start
val end = (start + len) min xs.length
val it = iterator
@@ -255,10 +197,29 @@ self =>
}
}
- /** Returns an iterable formed from this iterable and another iterable
+ /** Returns a $coll formed from this $coll and another iterable collection
* by combining corresponding elements in pairs.
- * If one of the two iterables is longer than the other, its remaining elements are ignored.
+ * If one of the two collections is longer than the other, its remaining elements are ignored.
+ *
+ * $orderDependent
+ *
* @param that The iterable providing the second half of each result pair
+ * @tparam A1 the type of the first half of the returned pairs (this is always a supertype
+ * of the collection's element type `A`).
+ * @tparam B the type of the second half of the returned pairs
+ * @tparam That $zipthatinfo
+ * @param bf $zipbfinfo
+ * @return a new collection of type `That` containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the minimum of the lengths of this $coll$ and `that`.
+ *
+ * @usecase def zip[B](that: Iterable[B]): $Coll[(A, B)]
+ *
+ * @param that The iterable providing the second half of each result pair
+ * @tparam B the type of the second half of the returned pairs
+ * @return a new $coll containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the minimum of the lengths of this $coll$ and `that`.
*/
def zip[A1 >: A, B, That](that: Iterable[B])(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = {
val b = bf(repr)
@@ -269,25 +230,33 @@ self =>
b.result
}
- /** Returns an iterable formed from this iterable and the specified iterable
- * <code>that</code> by associating each element of the former with
- * the element at the same position in the latter.
+ /** Returns a $coll formed from this $coll and another iterable collection
+ * by combining corresponding elements in pairs.
+ * If one of the two collections is shorter than the other,
+ * placeholder elements are used to extend the collection to the longer length.
*
- * @param that iterable <code>that</code> may have a different length
- * as the self iterable.
- * @param thisElem element <code>thisElem</code> is used to fill up the
- * resulting iterable if the self iterable is shorter than
- * <code>that</code>
- * @param thatElem element <code>thatElem</code> is used to fill up the
- * resulting iterable if <code>that</code> is shorter than
- * the self iterable
- * @return <code>Sequence((a<sub>0</sub>,b<sub>0</sub>), ...,
- * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
- * ..., {elem,b<sub>m</sub>})</code>
- * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
- * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
- * invoked where <code>m &gt; n</code>.
+ * $orderDependent
*
+ * @param that the iterable providing the second half of each result pair
+ * @param thisElem the element to be used to fill up the result if this $coll is shorter than `that`.
+ * @param thatElem the element to be used to fill up the result if `that` is shorter than this $coll.
+ * @return a new collection of type `That` containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the maximum of the lengths of this $coll$ and `that`.
+ * If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
+ * If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
+ *
+ * @usecase def zipAll[B](that: Iterable[B], thisElem: A, thatElem: B): $Coll[(A, B)]
+ *
+ * @param that The iterable providing the second half of each result pair
+ * @param thisElem the element to be used to fill up the result if this $coll is shorter than `that`.
+ * @param thatElem the element to be used to fill up the result if `that` is shorter than this $coll.
+ * @tparam B the type of the second half of the returned pairs
+ * @return a new $coll containing pairs consisting of
+ * corresponding elements of this $coll and `that`. The length
+ * of the returned collection is the maximum of the lengths of this $coll$ and `that`.
+ * If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
+ * If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
*/
def zipAll[B, A1 >: A, That](that: Iterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = {
val b = bf(repr)
@@ -302,7 +271,30 @@ self =>
b.result
}
- /** Zips this iterable with its indices (startiong from 0).
+ /** Zips this $coll with its indices.
+ *
+ * $orderDependent
+ *
+ * @tparam A1 the type of the first half of the returned pairs (this is always a supertype
+ * of the collection's element type `A`).
+ * @tparam That the class of the returned collection. Where possible, `That` is
+ * the same class as the current collection class `Repr`, but this
+ * depends on the element type `(A1, Int)` being admissible for that class,
+ * which means that an implicit instance of type `CanBuildFrom[Repr, (A1, Int), That]`.
+ * is found.
+ * @tparam bf an implicit value of class `CanBuildFrom` which determines the
+ * result class `That` from the current representation type `Repr`
+ * and the new element type `(A1, Int)`.
+ * @return A new collection of type `That` containing pairs consisting of all elements of this
+ * $coll paired with their index. Indices start at `0`.
+ *
+ * @usecase def zipWithIndex: $Coll[(A, Int)]
+ *
+ * @return A new $coll containing pairs consisting of all elements of this
+ * $coll paired with their index. Indices start at `0`.
+ * @example
+ * `List("a", "b", "c").zipWithIndex = List(("a", 0), ("b", 1), ("c", 2))`
+ *
*/
def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = {
val b = bf(repr)
@@ -314,12 +306,19 @@ self =>
b.result
}
- /** Checks if the other iterable object contains the same elements as this one.
+ /** Checks if the other iterable collection contains the same elements in the same order as this $coll.
+ *
+ * $orderDependent
+ * $willNotTerminateInf
+ *
+ * @param that the collection to compare with.
+ * @tparam B the type of the elements of collection `that`.
+ * @return `true`, if both collections contain the same elements in the same order, `false` otherwise.
*
- * @note will not terminate for infinite-sized iterables.
- * @param that the other iterable
- * @return true, iff both iterables contain the same elements in the same order.
- * @note Might return different results for different runs, unless this iterable is ordered
+ * @usecase def sameElements(that: Iterable[A]): Boolean
+ *
+ * @param that the collection to compare with.
+ * @return `true`, if both collections contain the same elements in the same order, `false` otherwise.
*/
def sameElements[B >: A](that: Iterable[B]): Boolean = {
val these = this.iterator
@@ -331,44 +330,36 @@ self =>
!these.hasNext && !those.hasNext
}
- /** Returns a stream with all elements in this iterable object.
- */
- override def toStream: Stream[A] = iterator.toStream
+ override /*TraversableLike*/ def toStream: Stream[A] = iterator.toStream
/** Method called from equality methods, so that user-defined subclasses can
* refuse to be equal to other collections of the same kind.
+ * @param that The object with which this $coll should be compared
+ * @return `true`, if this $coll can possibly equal `that`, `false` otherwise. The test
+ * takes into consideration only the run-time types of objects but ignores their elements.
*/
- override def canEqual(that: Any) = true
+ override /*TraversableLike*/ def canEqual(that: Any) = true
- /** Creates a view of this iterable @see IterableView
- */
- override def view = new IterableView[A, Repr] {
+ override /*TraversableLike*/ def view = new IterableView[A, Repr] {
protected lazy val underlying = self.repr
override def iterator = self.iterator
}
- /** A sub-iterable view starting at index `from`
- * and extending up to (but not including) index `until`.
- *
- * @param from The index of the first element of the slice
- * @param until The index of the element following the slice
- * @note The difference between `view` and `slice` is that `view` produces
- * a view of the current iterable, whereas `slice` produces a new iterable.
- *
- * @note Might return different results for different runs, unless this iterable is ordered
- * @note view(from, to) is equivalent to view.slice(from, to)
- */
- override def view(from: Int, until: Int) = view.slice(from, until)
+ override /*TraversableLike*/ def view(from: Int, until: Int) = view.slice(from, until)
+ /** @deprecated use `head' instead. */
@deprecated("use `head' instead") def first: A = head
- /** <code>None</code> if iterable is empty. */
+ /** <code>None</code> if iterable is empty.
+ * @deprecated "use `headOption' instead"
+ */
@deprecated("use `headOption' instead") def firstOption: Option[A] = headOption
/**
* returns a projection that can be used to call non-strict <code>filter</code>,
* <code>map</code>, and <code>flatMap</code> methods that build projections
* of the collection.
+ * @deprecated "use `view' instead"
*/
@deprecated("use `view' instead")
def projection = view
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index fa5c2d3597..ac6cb890c4 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -636,6 +636,21 @@ trait Iterator[+A] { self =>
res
}
+ /** Applies option-valued function to successive elements of this iterator
+ * until a defined value is found.
+ *
+ * @param f the function to be applied to successive elements.
+ * @return an option value containing the first defined result of
+ * `f`, or `None` if `f` returns `None` for all all elements.
+ def mapFind[B](f: A => Option[B]): Option[B] = {
+ var res: Option[B] = None
+ while (res.isEmpty && hasNext) {
+ res = f(next())
+ }
+ res
+ }
+ */
+
/** Returns index of the first element satisfying a predicate, or -1.
*
* @note may not terminate for infinite-sized collections.
diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala
index 4fb9b4ad79..08bb071da9 100644
--- a/src/library/scala/collection/LinearSeqLike.scala
+++ b/src/library/scala/collection/LinearSeqLike.scala
@@ -152,7 +152,17 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr
}
None
}
-
+/*
+ override def mapFind[B](f: A => Option[B]): Option[B] = {
+ var res: Option[B] = None
+ var these = this
+ while (res.isEmpty && !these.isEmpty) {
+ res = f(these.head)
+ these = these.tail
+ }
+ res
+ }
+*/
/** Combines the elements of this list together using the binary
* function <code>f</code>, from left to right, and starting with
* the value <code>z</code>.
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala
index a1ea657553..a9ea82b2f9 100644
--- a/src/library/scala/collection/MapLike.scala
+++ b/src/library/scala/collection/MapLike.scala
@@ -14,28 +14,30 @@ import generic._
import mutable.{Builder, StringBuilder, MapBuilder}
import PartialFunction._
-/** <p>
- * A generic template for maps from keys of type <code>A</code> to values
- * of type <code>B</code>.<br/>
- * To implement a concrete map, you need to provide implementations of the
- * following methods (where <code>This</code> is the type of the map in
+/**
+ * A generic template for maps from keys of type `A` to values
+ * of type `B`.
+ *
+ * To implement a concrete map, 'you' need to provide implementations of the
+ * following methods (where `This` is the type of the map in
* question):
- * </p>
- * <pre>
- * <b>def</b> get(key: A): Option[B]
- * <b>def</b> iterator: Iterator[(A, B)]
- * <b>def</b> + [B1 >: B](kv: (A, B1)): This
- * <b>def</b> -(key: A): This</pre>
- * <p>
+ * {{{
+ * def get(key: A): Option[B]
+ *
+ * def iterator: Iterator[(A, B)]
+ *
+ * def + [B1 >: B](kv: (A, B1)): This
+ *
+ * def -(key: A): This</pre>
+ * }}}
* If you wish that methods <code>like</code>, <code>take</code>, <code>drop</code>,
* <code>filter</code> return the same kind of map, you should also override:
- * </p>
- * <pre>
- * <b>def</b> empty: This</pre>
- * <p>
- * It is also good idea to override methods <code>foreach</code> and
- * <code>size</code> for efficiency.
- * </p>
+ * {{{
+ * def empty: This
+ * }}}
+ *
+ * It is also good idea to override methods `foreach` and
+ * `size` for efficiency.
*
* @author Martin Odersky
* @version 2.8
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 4d096a88c6..5e7ea8ebfa 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -10,20 +10,19 @@
package scala.collection
-import generic._
+
import mutable.{ListBuffer, HashMap, GenericArray}
import immutable.{List, Range}
-
-// import immutable.{List, Nil, ::}
import generic._
-/** Contains a KMP implementation, based on the undoubtedly reliable wikipedia entry.
- *
- * @author paulp
- * @since 2.8
+/** The companion object for trait `SeqLike`.
*/
object SeqLike {
+ /** A KMP implementation, based on the undoubtedly reliable wikipedia entry.
+ * @author paulp
+ * @since 2.8
+ */
private def KMP[B](S: Seq[B], W: Seq[B]): Option[Int] = {
// trivial cases
if (W.isEmpty) return Some(0)
@@ -73,6 +72,8 @@ object SeqLike {
None
}
+ /** Waiting for a doc comment from Paul
+ */
def indexOf[B](
source: Seq[B], sourceOffset: Int, sourceCount: Int,
target: Seq[B], targetOffset: Int, targetCount: Int,
@@ -82,6 +83,8 @@ object SeqLike {
case Some(x) => x + fromIndex
}
+ /** Waiting for a doc comment from Paul
+ */
def lastIndexOf[B](
source: Seq[B], sourceOffset: Int, sourceCount: Int,
target: Seq[B], targetOffset: Int, targetCount: Int,
@@ -96,41 +99,89 @@ object SeqLike {
}
}
-/** Class <code>Seq[A]</code> represents sequences of elements
- * of type <code>A</code>.
- * It adds the following methods to class Iterable:
- * `length`, `lengthCompare`, `apply`, `isDefinedAt`, `segmentLength`, `prefixLength`,
- * `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, `reverse`, `reverseIterator`,
- * `startsWith`, `endsWith`, `indexOfSlice`, , `zip`, `zipAll`, `zipWithIndex`.
+/** A template trait for sequences of type `Seq[A]`, representing
+ * sequences of elements of type <code>A</code>.
+ *
+ * Sequences are special cases of iterable collections of class `Iterable`.
+ * Unlike iterables, sequences always have a defined order of elements.
+ * Sequences provide a method `apply` for indexing. Indices range from `0` up the the `length` of
+ * a sequence. Sequences support a number to find occurrences of elements or subsequences, including
+ * `segmentLength`, `prefixLength`, `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`,
+ * `startsWith`, `endsWith`, `indexOfSlice`.
*
+ * Another way to see a sequence is as a `PartialFunction` from `Int` values
+ * to the element type of the sequence. The `isDefinedAt` method of a sequence
+ * returns `true` for the interval from `0` until `length`.
+ *
+ * Sequences can be accessed in reverse order of their elements, using methods
+ * `reverse` and `reverseIterator`.
+ *
+ * Sequences have two principle subtraits, `IndexedSeq` and `LinearSeq`, which give different guarantees for performance.
+ * An `IndexedSeq` provides fast random-access of elements and a fast `length` operation.
+ * A `LinearSeq` provides fast access only to the first element via `head`, but also
+ * has a fast `tail` operation.
*
* @author Martin Odersky
* @author Matthias Zenger
* @version 1.0, 16/07/2003
* @since 2.8
+ *
+ * @tparam A the element type of the collection
+ * @tparam Repr the type of the actual collection containing the elements.
+ *
+ * @define Coll Seq
+ * @define coll sequence
+ * @define thatinfo the class of the returned collection. Where possible, `That` is
+ * the same class as the current collection class `Repr`, but this
+ * depends on the element type `B` being admissible for that class,
+ * which means that an implicit instance of type `CanBuildFrom[Repr, B, That]`
+ * is found.
+ * @define bfinfo an implicit value of class `CanBuildFrom` which determines the
+ * result class `That` from the current representation type `Repr`
+ * and the new element type `B`.
+ * @define orderDependent
+ * @define orderDependentFold
+ * @define mayNotTerminateInf
+ *
+ * Note: may not terminate for infinite-sized collections.
+ * @define willNotTerminateInf
+ *
+ * Note: will not terminate for infinite-sized collections.
*/
trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
override protected[this] def thisCollection: Seq[A] = this.asInstanceOf[Seq[A]]
override protected[this] def toCollection(repr: Repr): Seq[A] = repr.asInstanceOf[Seq[A]]
- /** Returns the length of the sequence.
+ /** The length of the $coll.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.length` and `xs.size` yield the same result.
+ *
+ * @return the number of elements in this $coll.
*/
def length: Int
- /** Returns the elements at position `idx`
+ /** Selects an element by its index in the $coll
+ *
+ * @param idx The index to select
+ * @return the element of tyh
*/
def apply(idx: Int): A
- /** Result of comparing <code>length</code> with operand <code>len</code>.
- * returns <code>x</code> where
- * <code>x &lt; 0</code> iff <code>this.length &lt; len</code>
- * <code>x == 0</code> iff <code>this.length == len</code>
- * <code>x &gt; 0</code> iff <code>this.length &gt; len</code>.
+ /** Compares the length of this $coll to a test value.
*
- * The method as implemented here does not call length directly; its running time
- * is O(length min len) instead of O(length). The method should be overwritten
- * if computing length is cheap.
+ * @param len the test value that gets compared with the length.
+ * @return A value `x` where
+ * {{{
+ * x < 0 if this.length < len
+ * x == 0 if this.length == len
+ * x > 0 if this.length > len
+ * }}}
+ * The method as implemented here does not call `length` directly; its running time
+ * is `O(length min len)` instead of `O(length)`. The method should be overwritten
+ * if computing `length` is cheap.
*/
def lengthCompare(len: Int): Int = {
var i = 0
@@ -142,18 +193,32 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i - len
}
- /** Should always be <code>length</code> */
+ /** The size of this $coll, equivalent to `length`.
+ *
+ * $willNotTerminateInf
+ *
+ * @return the number of elements in this $coll.
+ */
override def size = length
- /** Is this partial function defined for the index <code>x</code>?
+ /** Tests whether this $coll contains given index.
+ *
+ * The implementations of methods `apply` and `isDefinedAt` turn a `Seq[A]` into
+ * a `PartialFunction[Int, A]`.
+ *
+ * @param idx the index to test
+ * @return `true` if this $coll contains an element at position `idx`, `false` otherwise.
*/
- def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length)
+ def isDefinedAt(idx: Int): Boolean = (idx >= 0) && (idx < length)
- /** Returns length of longest segment starting from a start index `from`
- * such that every element of the segment satisfies predicate `p`.
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
- * @param from the start index
+ /** Computes length of longest segment whose elements all satisfy some preficate.
+ *
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @param from the index where the search starts.
+ * @return the length of the longest segment of this $coll starting from index `from`
+ * such that every element of the segment satisfies the predicate `p`.
*/
def segmentLength(p: A => Boolean, from: Int): Int = {
var i = 0
@@ -163,26 +228,34 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i
}
- /** Returns length of longest prefix of this seqence
- * such that every element of the prefix satisfies predicate `p`.
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
+ /** Returns the length of the longest prefix whose elements all satisfy some preficate.
+ *
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @return the length of the longest prefix of this $coll
+ * such that every element of the segment satisfies the predicate `p`.
*/
def prefixLength(p: A => Boolean) = segmentLength(p, 0)
- /** Returns index of the first element satisfying a predicate, or -1, if none exists.
+ /** Finds index of first element satisfying some predicate.
*
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
+ * $mayNotTerminateInf
+ *
+ * @param p the predicate used to test elements.
+ * @return the index of the first element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def indexWhere(p: A => Boolean): Int = indexWhere(p, 0)
- /** Returns index of the first element starting from a start index
- * satisying a predicate, or -1, if none exists.
+ /** Finds index of the first element satisfying some predicate after or at some start index.
+ *
+ * $mayNotTerminateInf
*
- * @note may not terminate for infinite-sized collections.
- * @param p the predicate
- * @param from the start index
+ * @param p the predicate used to test elements.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def indexWhere(p: A => Boolean, from: Int): Int = {
var i = from
@@ -192,63 +265,95 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
if (it.hasNext) i else -1
}
- /** Returns index of the first element satisying a predicate, or -1. */
- @deprecated("Use `indexWhere' instead")
+ /** Returns index of the first element satisying a predicate, or `-1`.
+ * @deprecated "Use `indexWhere` instead"
+ */
def findIndexOf(p: A => Boolean): Int = indexWhere(p)
- /** Returns the index of the first occurence of the specified
- * object in this sequence.
+ /** Finds index of first occurrence of some value in this $coll.
*
- * @note may not terminate for infinite-sized collections.
- * @param elem element to search for.
- * @return the index in this sequence of the first occurence of the
- * specified element, or -1 if the sequence does not contain
- * this element.
+ * $mayNotTerminateInf
+ *
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @return the index of the first element of this $coll that is equal (wrt `==`)
+ * tp `elem`, or `-1`, if none exists.
+ *
+ * @usecase def indexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index of the first element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def indexOf[B >: A](elem: B): Int = indexOf(elem, 0)
- /** Returns the index of the first occurence of the specified
- * object in this sequence, starting from a start index, or
- * -1, if none exists.
+ /** Finds index of first occurrence of some value in this $coll after or at some start index.
+ *
+ * $mayNotTerminateInf
*
- * @note may not terminate for infinite-sized collections.
- * @param elem element to search for.
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that is equal (wrt `==`)
+ * tp `elem`, or `-1`, if none exists.
+ *
+ * @usecase def indexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @param from the start index
+ * @return the index `>= from` of the first element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem ==, from)
- /** Returns the index of the last occurence of the specified element
- * in this sequence, or -1 if the sequence does not contain this element.
+ /** Finds index of last occurrence of some value in this $coll.
+ *
+ * $willNotTerminateInf
+ *
+ * @param elem the element value to search for.
+ * @tparam B the type of the element `elem`.
+ * @return the index of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*
- * @param elem element to search for.
- * @return the index in this sequence of the last occurence of the
- * specified element, or -1 if the sequence does not contain
- * this element.
+ * @usecase def lastIndexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
*/
def lastIndexOf[B >: A](elem: B): Int = lastIndexWhere(elem ==)
- /** Returns the index of the last
- * occurence of the specified element in this sequence
- * before or at a given end index,
- * or -1 if the sequence does not contain this element.
- *
- * @param elem element to search for.
- * @param end the end index
- */
+ /** Finds index of last occurrence of some value in this $coll before or at a given end index.
+ *
+ * @param elem the element value to search for.
+ * @param end the end index.
+ * @tparam B the type of the element `elem`.
+ * @return the index `<= end` of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
+ *
+ * @usecase def lastIndexOf(elem: A): Int
+ *
+ * @param elem the element value to search for.
+ * @return the index `<= end` of the last element of this $coll that is equal (wrt `==`)
+ * to `elem`, or `-1`, if none exists.
+ */
def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end)
- /** Returns index of the last element satisying a predicate, or -1, if none exists.
+ /** Finds index of last element satisfying some predicate.
+ *
+ * $willNotTerminateInf
*
- * @param p the predicate
- * @return the index of the last element satisfying <code>p</code>,
- * or -1 if such an element does not exist
+ * @param p the predicate used to test elements.
+ * @return the index of the last element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def lastIndexWhere(p: A => Boolean): Int = lastIndexWhere(p, length - 1)
- /** Returns index of the last element not exceeding a given end index
- * and satisying a predicate, or -1 if none exists.
+ /** Finds index of last element satisfying some predicate before or at given end index.
*
- * @param end the end index
- * @param p the predicate
+ * @param p the predicate used to test elements.
+ * @return the index `<= end` of the last element of this $coll that satisfies the predicate `p`,
+ * or `-1`, if none exists.
*/
def lastIndexWhere(p: A => Boolean, end: Int): Int = {
var i = length - 1
@@ -257,8 +362,11 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
i
}
- /** A sequence of type <code>C</code> consisting of all elements of
- * this sequence in reverse order.
+ /** Returns new $coll wih elements in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * @return A new $coll with all elements of this $coll in reversed order.
*/
def reverse: Repr = {
var xs: List[A] = List()
@@ -270,18 +378,34 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
b.result
}
- /** Apply a function to all the elements of the sequence, and return the
- * reversed sequence of results. This is equivalent to a call to <code>reverse</code>
- * followed by a call to <code>map</code>, but more efficient.
+ /**
+ * Builds a new collection by applying a function to all elements of this $coll and
+ * collecting the results in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.reverseMap(f)` is the same as `xs.reverse.map(f)` but might be more efficient.
+ *
+ * @param f the function to apply to each element.
+ * @tparam B the element type of the returned collection.
+ * @tparam That $thatinfo
+ * @param bf $bfinfo
+ * @return a new collection of type `That` resulting from applying the given function
+ * `f` to each element of this $coll and collecting the results in reversed order.
+ *
+ * @usecase def reverseMap[B](f: A => B): $Coll[B]
+ *
+ * Note: `xs.reverseMap(f)` is the same as `xs.reverse.map(f)` but might be more efficient.
*
- * @param f the function to apply to each elements.
- * @return the reversed seq of results.
+ * @param f the function to apply to each element.
+ * @tparam B the element type of the returned collection.
+ * @return a new $coll resulting from applying the given function
+ * `f` to each element of this $coll and collecting the results in reversed order.
*/
def reverseMap[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
var xs: List[A] = List()
for (x <- this)
xs = x :: xs
-
val b = bf(repr)
for (x <- xs)
b += f(x)
@@ -289,25 +413,30 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
b.result
}
- /** The elements of this sequence in reversed order
+ /** An iterator yielding elements in reversed order.
+ *
+ * $willNotTerminateInf
+ *
+ * Note: `xs.reverseIterator` is the same as `xs.reverse.iterator` but might be more efficient.
+ *
+ * @return an iterator yielding the elements of this $coll in reversed order
*/
def reverseIterator: Iterator[A] = toCollection(reverse).iterator
+ /** @deprecated use `reverseIterator` instead */
@deprecated("use `reverseIterator' instead")
def reversedElements = reverseIterator
- /**
- * Checks whether the argument sequence is contained at the
- * specified index within the receiver object.
+ /** Checks whether this $coll contains the given sequence at a given index.
*
* If the both the receiver object, <code>this</code> and
* the argument, <code>that</code> are infinite sequences
* this method may not terminate.
*
- * @return true if <code>that</code> is contained in
- * <code>this</code>, at the specified index, otherwise false
- *
- * @see String.startsWith
+ * @param that the candidate sequence
+ * @param offset the index where the sequence is searched.
+ * @return `true` if the sequence `that` is contained in this $coll at index `offset`,
+ * otherwise `false`.
*/
def startsWith[B](that: Seq[B], offset: Int): Boolean = {
val i = this.iterator drop offset
@@ -319,10 +448,10 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
!j.hasNext
}
- /**
- * Check whether the receiver object starts with the argument sequence.
+ /** Checks whether this $coll starts with the given sequence.
*
- * @return true if <code>that</code> is a prefix of <code>this</code>,
+ * @param that the candidate sequence
+ * @return `true` if this collection has `that` as a prefix, `false` otherwise.
* otherwise false
*/
def startsWith[B](that: Seq[B]): Boolean = startsWith(that, 0)
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 44cb7ced63..0ff6227a3a 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -63,14 +63,12 @@ import immutable.{List, Stream, Nil, ::}
*
* @define Coll Traversable
* @define coll traversable collection
- * @define thatinfo
- * the class of the returned collection. Where possible, `That` is
+ * @define thatinfo the class of the returned collection. Where possible, `That` is
* the same class as the current collection class `Repr`, but this
* depends on the element type `B` being admissible for that class,
* which means that an implicit instance of type `CanBuildFrom[Repr, B, That]`
* is found.
- * @define bfinfo
- * an implicit value of class `CanBuildFrom` which determines the
+ * @define bfinfo an implicit value of class `CanBuildFrom` which determines the
* result class `That` from the current representation type `Repr`
* and the new element type `B`.
* @define orderDependent
@@ -100,12 +98,13 @@ self =>
*/
def repr: Repr = this.asInstanceOf[Repr]
- /** The underlying collection seen as an instance of `Traversable`.
- * By default this is implemented as the `TraversableLike` object itself, but this can be overridden.
+ /** The underlying collection seen as an instance of `$Coll`.
+ * By default this is implemented as the current collection object itself,
+ * but this can be overridden.
*/
protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
- /** A conversion from collections of type `Repr` to `Traversable` objects.
+ /** A conversion from collections of type `Repr` to `$Coll` objects.
* By default this is implemented as just a cast, but this can be overridden.
*/
protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
@@ -116,8 +115,9 @@ self =>
/** Applies a function `f` to all elements of this $coll.
*
- * Note: this method underlies the implementation of most other bulk operations.
- * It's important to implement this method in an efficient way.
+ * Note: this method underlies the implementation of most other bulk operations.
+ * It's important to implement this method in an efficient way.
+ *
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
@@ -126,7 +126,7 @@ self =>
* This result will always be ignored. Typically `U` is `Unit`,
* but this is not necessary.
*
- * @usage def foreach(f: A => Unit): Unit
+ * @usecase def foreach(f: A => Unit): Unit
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
@@ -184,7 +184,7 @@ self =>
* @return a new collection of type `That` which contains all elements of this $coll
* followed by all elements of `that`.
*
- * @usage def ++(that: Traversable[A]): $Coll[A]
+ * @usecase def ++(that: Traversable[A]): $Coll[A]
*
* @param that the traversable to append.
* @return a new $coll which contains all elements of this $coll
@@ -206,7 +206,7 @@ self =>
* @return a new collection of type `That` which contains all elements of this $coll
* followed by all elements of `that`.
*
- * @usage def ++(that: Iterator[A]): $Coll[A]
+ * @usecase def ++(that: Iterator[A]): $Coll[A]
*
* @param that the iterator to append.
* @return a new $coll which contains all elements of this $coll
@@ -228,7 +228,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given function
* `f` to each element of this $coll and collecting the results.
*
- * @usage def map[B](f: A => B): $Coll[B]
+ * @usecase def map[B](f: A => B): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -251,7 +251,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given collection-valued function
* `f` to each element of this $coll and concatenating the results.
*
- * @usage def flatMap[B](f: A => Traversable[B]): $Coll[B]
+ * @usecase def flatMap[B](f: A => Traversable[B]): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -266,7 +266,7 @@ self =>
/** Selects all elements of this $coll which satisfy a predicate.
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return a new $coll consisting of all elements of this $coll that satisfy the given
* predicate `p`. The order of the elements is preserved.
*/
@@ -296,7 +296,7 @@ self =>
* `pf` to each element on which it is defined and collecting the results.
* The order of the elements is preserved.
*
- * @usage def partialMap[B](pf: PartialFunction[Any, B]): $Coll[B]
+ * @usecase def partialMap[B](pf: PartialFunction[Any, B]): $Coll[B]
*
* @param pf the partial function which filters and maps the $coll.
* @return a new $coll resulting from applying the given partial function
@@ -309,6 +309,34 @@ self =>
b.result
}
+ /** Builds a new collection by applying an option-valued function to all elements of this $coll
+ * on which the function is defined.
+ *
+ * @param f the option-valued function which filters and maps the $coll.
+ * @tparam B the element type of the returned collection.
+ * @tparam That $thatinfo
+ * @param bf $bfinfo
+ * @return a new collection of type `That` resulting from applying the option-valued function
+ * `f` to each element and collecting all defined results.
+ * The order of the elements is preserved.
+ *
+ * @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
+ *
+ * @param pf the partial function which filters and maps the $coll.
+ * @return a new $coll resulting from applying the given option-valued function
+ * `f` to each element and collecting all defined results.
+ * The order of the elements is preserved.
+ def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
+ val b = bf(repr)
+ for (x <- this)
+ f(x) match {
+ case Some(y) => b += y
+ case _ =>
+ }
+ b.result
+ }
+ */
+
/** Partitions this $coll in two ${coll}s according to a predicate.
*
* @param p the predicate on which to partition.
@@ -356,7 +384,7 @@ self =>
*
* $mayNotTerminateInf
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return `true` if the given predicate `p` holds for all elements
* of this $coll, otherwise `false`.
*/
@@ -373,7 +401,7 @@ self =>
*
* $mayNotTerminateInf
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return `true` if the given predicate `p` holds for some of the elements
* of this $coll, otherwise `false`.
*/
@@ -388,7 +416,7 @@ self =>
/** Counts the number of elements in the $coll which satisfy a predicate.
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return the number of elements satisfying the predicate `p`.
*
*
@@ -406,7 +434,7 @@ self =>
* $mayNotTerminateInf
* $orderDependent
*
- * @param p the predicate used used to test elements.
+ * @param p the predicate used to test elements.
* @return an option value containing the first element in the $coll
* that satisfies `p`, or `None` if none exists.
*/
@@ -419,6 +447,28 @@ self =>
result
}
+ /** Applies option-valued function to successive elements of this $coll
+ * until a defined value is found.
+ *
+ * $mayNotTerminateInf
+ * $orderDependent
+ *
+ * @param f the function to be applied to successive elements.
+ * @return an option value containing the first defined result of
+ * `f`, or `None` if `f` returns `None` for all all elements.
+ def mapFind[B](f: A => Option[B]): Option[B] = {
+ var result: Option[B] = None
+ breakable {
+ for (x <- this)
+ f(x) match {
+ case s @ Some(_) => result = s; break
+ case _ =>
+ }
+ }
+ result
+ }
+ */
+
/** Applies a binary operator to a start value and all elements of this $coll, going left to right.
*
* $willNotTerminateInf
@@ -430,9 +480,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right with the start value `z` on the left:
* {{{
- * op(...op(z, x_1), x_2, ..., x_n)
+ * op(...op(z, x,,1,,), x,,2,,, ..., x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*
*/
def foldLeft[B](z: B)(op: (B, A) => B): B = {
@@ -454,9 +504,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right with the start value `z` on the left:
* {{{
- * op(...op(op(z, x_1), x_2), ..., x_n)
+ * op(...op(op(z, x,,1,,), x,,2,,), ..., x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*/
def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
@@ -467,9 +517,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left with the start value `z` on the right:
* {{{
- * op(x_1, op(x_2, ... op(x_n, z)...))
+ * op(x,,1,,, op(x,,2,,, ... op(x,,n,,, z)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*
* $willNotTerminateInf
* $orderDependentFold
@@ -492,9 +542,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left with the start value `z` on the right:
* {{{
- * op(x_1, op(x_2, ... op(x_n, z)...))
+ * op(x,,1,,, op(x,,2,,, ... op(x,,n,,, z)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
*/
def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
@@ -507,9 +557,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going left to right:
* {{{
- * op(...(op(x_1, x_2), ... ) , x_n)
+ * op(...(op(x,,1,,, x,,2,,), ... ) , x,,n,,)
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
* @throws `UnsupportedOperationException` if this $coll is empty.
*/
def reduceLeft[B >: A](op: (B, A) => B): B = {
@@ -544,9 +594,9 @@ self =>
* @return the result of inserting `op` between consecutive elements of this $coll$,
* going right to left:
* {{{
- * op(x_1, op(x_2, ..., op(x_(n-1), x_n)...))
+ * op(x,,1,,, op(x,,2,,, ..., op(x,,n-1,,, x,,n,,)...))
* }}}
- * where `x_1, ..., x_n` are the elements of this $coll.
+ * where `x,,1,,, ..., x,,n,,` are the elements of this $coll.
* @throws `UnsupportedOperationException` if this $coll is empty.
*/
def reduceRight[B >: A](op: (A, B) => B): B = {
@@ -576,9 +626,13 @@ self =>
* @tparam B the result type of the `+` operator.
* @return the sum of all elements of this $coll with respect to the `+` operator in `num`.
*
- * @usage sum: Num
- * @return the sum of all elements in this $coll of numbers of type `Num`.
- * `Num` must be a numeric type such as `Int`, `Double`, `BigDecimal`.
+ * @usecase def sum: Int
+ *
+ * @return the sum of all elements in this $coll of numbers of type `Int`.
+ * Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
+ * can be used as element type of the $coll and as result type of `sum`.
+ * Examples of such types are: `Long`, `Float`, `Double`, `BigInt`.
+ *
*/
def sum[B >: A](implicit num: Numeric[B]): B = {
var acc = num.zero
@@ -593,9 +647,12 @@ self =>
* @tparam B the result type of the `*` operator.
* @return the product of all elements of this $coll with respect to the `*` operator in `num`.
*
- * @usage product: Num
- * @return the product of all elements in this $coll of numbers of type `Num`.
- * `Num` must be a numeric type such as `Int`, `Double`, `BigDecimal`.
+ * @usecase def product: Int
+ *
+ * @return the product of all elements in this $coll of numbers of type `Int`.
+ * Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
+ * can be used as element type of the $coll and as result type of `product`.
+ * Examples of such types are: `Long`, `Float`, `Double`, `BigInt`.
*/
def product[B >: A](implicit num: Numeric[B]): B = {
var acc = num.one
@@ -609,7 +666,7 @@ self =>
* @tparam B The type over which the ordering is defined.
* @return the smallest element of this $coll with respect to the ordering `cmp`.
*
- * @usage min: A
+ * @usecase def min: A
* @return the smallest element of this $coll
*/
def min[B >: A](implicit cmp: Ordering[B]): A = {
@@ -626,7 +683,7 @@ self =>
* @tparam B The type over which the ordering is defined.
* @return the largest element of this $coll with respect to the ordering `cmp`.
*
- * @usage min: A
+ * @usecase def min: A
* @return the largest element of this $coll.
*/
def max[B >: A](implicit cmp: Ordering[B]): A = {
@@ -861,7 +918,7 @@ self =>
* @tparam B the type of the elements of the array.
*
*
- * @usage copyToArray(xs: Array[A], start: Int, len: Int): Unit
+ * @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
*
* @param xs the array to fill.
* @param start the starting index.
@@ -891,7 +948,7 @@ self =>
* @param start the starting index.
* @tparam B the type of the elements of the array.
*
- * @usage def copyToArray(xs: Array[A], start: Int): Unit
+ * @usecase def copyToArray(xs: Array[A], start: Int): Unit
*
* @param xs the array to fill.
* @param start the starting index.
@@ -907,7 +964,7 @@ self =>
* be available.
* @return an array containing all elements of this $coll.
*
- * @usage toArray: Array[A]
+ * @usecase def toArray: Array[A]
* @return an array containing all elements of this $coll.
* A `ClassManifest` must be available for the element type of this $coll.
*/
@@ -1054,7 +1111,6 @@ self =>
/** Creates a non-strict view of this $coll.
*
* @return a non-strict view of this $coll.
- * @see TraversableView
*/
def view = new TraversableView[A, Repr] {
protected lazy val underlying = self.repr
@@ -1107,7 +1163,7 @@ self =>
* `f` to each element of the outer $coll that satisfies predicate `p`
* and collecting the results.
*
- * @usage def map[B](f: A => B): $Coll[B]
+ * @usecase def map[B](f: A => B): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -1132,7 +1188,7 @@ self =>
* @return a new collection of type `That` resulting from applying the given collection-valued function
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
*
- * @usage def flatMap[B](f: A => Traversable[B]): $Coll[B]
+ * @usecase def flatMap[B](f: A => Traversable[B]): $Coll[B]
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -1156,7 +1212,7 @@ self =>
* This result will always be ignored. Typically `U` is `Unit`,
* but this is not necessary.
*
- * @usage def foreach(f: A => Unit): Unit
+ * @usecase def foreach(f: A => Unit): Unit
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index d03858a68f..92f1b5bba6 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -103,6 +103,15 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*/
override def updated[B1 >: B](key: A, value: B1): mutable.Map[A, B1] = this + ((key, value))
+ /** If given key is already in this map, returns associated value
+ * Otherwise, computes value from given expression `op`, stores with key
+ * in map and returns that value.
+ */
+ def cached(key: A, op: => B) = get(key) match {
+ case Some(v) => v
+ case None => val v = op; update(key, v); v
+ }
+
/** Add a new key/value mapping and return the map itself.
*
* @param kv the key/value mapping to be added
diff --git a/test/files/pos/t2683.scala b/test/files/pos/t2683.scala
new file mode 100755
index 0000000000..4ba34b554a
--- /dev/null
+++ b/test/files/pos/t2683.scala
@@ -0,0 +1,7 @@
+class A
+class B extends A
+
+object Test {
+ val c: Class[_ <: A] = Class.forName("B").asSubclass(classOf[A])
+ val x: Option[Class[_ <: A]] = Some(3).map { case _ => c }
+}
diff --git a/test/files/run/sequenceComparisons.scala b/test/files/run/sequenceComparisons.scala
index 4f110eddce..e674d55bf7 100644
--- a/test/files/run/sequenceComparisons.scala
+++ b/test/files/run/sequenceComparisons.scala
@@ -52,14 +52,14 @@ object Test {
val endsWithInputs: Inputs
lazy val endsWith = Method(_ endsWith _, endsWithInputs, "%s endsWith %s")
- val indexOfSeqInputs: Inputs
+ val indexOfSliceInputs: Inputs
private def subseqTest(s1: Seq[T], s2: Seq[T]) = (s1 indexOfSlice s2) != -1
- lazy val indexOfSeq = Method(subseqTest _, indexOfSeqInputs, "(%s indexOfSeq %s) != -1")
+ lazy val indexOfSlice = Method(subseqTest _, indexOfSliceInputs, "(%s indexOfSlice %s) != -1")
val sameElementsInputs: Inputs
lazy val sameElements = Method(_ sameElements _, sameElementsInputs, "%s sameElements %s")
- def methodList = List(eqeq, startsWith, endsWith, indexOfSeq, sameElements)
+ def methodList = List(eqeq, startsWith, endsWith, indexOfSlice, sameElements)
}
object test1 extends Data[Int] {
@@ -75,7 +75,7 @@ object Test {
List(0 :: seq, List(5,2,3,4,5), List(3,4), List(5,6))
)
- val indexOfSeqInputs = (
+ val indexOfSliceInputs = (
List(Nil, List(1), List(3), List(5), List(1,2), List(2,3,4), List(4,5), seq),
List(List(1,2,3,5), List(6), List(5,4,3,2,1), List(2,1))
)