summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-04-07 07:31:02 +0000
committerPaul Phillips <paulp@improving.org>2011-04-07 07:31:02 +0000
commitf8f09796e884e62a5562efcf8c1e0f49eaa97c49 (patch)
tree937edee858dc437aee7b1a0400a6d922658894ae /src/compiler
parent6a204df670a118be6a31676ed26a20a6408e2ab6 (diff)
downloadscala-f8f09796e884e62a5562efcf8c1e0f49eaa97c49.tar.gz
scala-f8f09796e884e62a5562efcf8c1e0f49eaa97c49.tar.bz2
scala-f8f09796e884e62a5562efcf8c1e0f49eaa97c49.zip
Deleted SourcelessComments.
Nothing and Null with improved documentation of their particulars and convinced scaladoc to parse them without leaving scalac institutionalized. Now rather than seeing our hardcoded documentation strings bitrot in a shadowy flight from classes which do not exist, we are championing the cause of the innocent and powerless. Nothing and Null aren't above the law! So now any responsible party can fire up their text editor and go to town on Nothing.scala. As I'm sure they will. Review by malayeri.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/ant/Scaladoc.scala9
-rw-r--r--src/compiler/scala/tools/nsc/ScalaDoc.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala112
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocParser.scala74
-rw-r--r--src/compiler/scala/tools/nsc/doc/Settings.scala15
-rw-r--r--src/compiler/scala/tools/nsc/doc/SourcelessComments.scala216
-rw-r--r--src/compiler/scala/tools/nsc/doc/Uncompilable.scala48
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala12
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala36
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
11 files changed, 245 insertions, 283 deletions
diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala
index 727b8db0cc..419f60af21 100644
--- a/src/compiler/scala/tools/ant/Scaladoc.scala
+++ b/src/compiler/scala/tools/ant/Scaladoc.scala
@@ -112,6 +112,9 @@ class Scaladoc extends ScalaMatchingTask {
/** Instruct the compiler to generate links to sources */
private var docsourceurl: Option[String] = None
+ /** Point scaladoc at uncompilable sources. */
+ private var docUncompilable: Option[String] = None
+
/** Instruct the compiler to use additional parameters */
private var addParams: String = ""
@@ -331,6 +334,10 @@ class Scaladoc extends ScalaMatchingTask {
buildError("Unknown unchecked flag '" + input + "'")
}
+ def setDocUncompilable(input: String) {
+ docUncompilable = Some(input)
+ }
+
/*============================================================================*\
** Properties getters **
\*============================================================================*/
@@ -518,6 +525,8 @@ class Scaladoc extends ScalaMatchingTask {
if (!doctitle.isEmpty) docSettings.doctitle.value = decodeEscapes(doctitle.get)
if (!docversion.isEmpty) docSettings.docversion.value = decodeEscapes(docversion.get)
if (!docsourceurl.isEmpty) docSettings.docsourceurl.value =decodeEscapes(docsourceurl.get)
+ if (!docUncompilable.isEmpty) docSettings.docUncompilable.value = decodeEscapes(docUncompilable.get)
+
docSettings.deprecation.value = deprecation
docSettings.unchecked.value = unchecked
if (!docgenerator.isEmpty) docSettings.docgenerator.value = docgenerator.get
diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala
index da31ca833d..a9330b053b 100644
--- a/src/compiler/scala/tools/nsc/ScalaDoc.scala
+++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala
@@ -27,6 +27,7 @@ class ScalaDoc {
override def hasErrors = false
}
val command = new ScalaDoc.Command(args.toList, docSettings)
+ def hasFiles = command.files.nonEmpty || docSettings.uncompilableFiles.nonEmpty
if (docSettings.version.value)
reporter.info(null, versionMsg, true)
@@ -38,7 +39,7 @@ class ScalaDoc {
reporter.warning(null, "Plugins are not available when using Scaladoc")
else if (docSettings.showPhases.value)
reporter.warning(null, "Phases are restricted when using Scaladoc")
- else if (docSettings.help.value || command.files.isEmpty)
+ else if (docSettings.help.value || !hasFiles)
reporter.info(null, command.usageMsg, true)
else try {
if (docSettings.target.value == "msil")
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index c8a6e279ff..71ee6dfcb8 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -3,9 +3,11 @@
package scala.tools.nsc
package doc
+import scala.util.control.ControlThrowable
import reporters.Reporter
-import java.lang.ClassNotFoundException
-import util.{Position, NoPosition}
+import util.NoPosition
+import io.{ File, Directory }
+import DocParser.Parsed
/** A documentation processor controls the process of generating Scala documentation, which is as follows.
*
@@ -25,7 +27,6 @@ import util.{Position, NoPosition}
*
* @author Gilles Dubochet */
class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor =>
-
/** The unique compiler instance used by this processor and constructed from its `settings`. */
object compiler extends Global(settings, reporter) with interactive.RangePositions {
override protected def computeInternalPhases() {
@@ -38,64 +39,89 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
phasesSet += refchecks
}
override def forScaladoc = true
- lazy val addSourceless = {
- val sless = new SourcelessComments { val global = compiler }
- docComments ++= sless.comments
- }
}
/** Creates a scaladoc site for all symbols defined in this call's `files`, as well as those defined in `files` of
* previous calls to the same processor.
* @param files The list of paths (relative to the compiler's source path, or absolute) of files to document. */
def makeUniverse(files: List[String]): Option[Universe] = {
- (new compiler.Run()) compile files
- compiler.addSourceless
assert(settings.docformat.value == "html")
- if (!reporter.hasErrors) {
- val modelFactory = (new model.ModelFactory(compiler, settings) with model.comment.CommentFactory with model.TreeFactory)
- modelFactory.makeModel match {
- case Some(madeModel) =>
- println("model contains " + modelFactory.templatesCount + " documentable templates")
- Some(madeModel)
- case None =>
- println("no documentable class found in compilation units")
- None
+ new compiler.Run() compile files
+ if (reporter.hasErrors)
+ return None
+
+ val extraTemplatesToDocument: Set[compiler.Symbol] = {
+ if (settings.docUncompilable.isDefault) Set()
+ else {
+ val uncompilable = new {
+ val global: compiler.type = compiler
+ val settings = processor.settings
+ } with Uncompilable { }
+
+ compiler.docComments ++= uncompilable.comments
+ docdbg("" + uncompilable)
+
+ uncompilable.templates
}
}
- else None
+
+ val modelFactory = (
+ new { override val global: compiler.type = compiler }
+ with model.ModelFactory(compiler, settings)
+ with model.comment.CommentFactory
+ with model.TreeFactory {
+ override def templateShouldDocument(sym: compiler.Symbol) =
+ extraTemplatesToDocument(sym) || super.templateShouldDocument(sym)
+ }
+ )
+
+ modelFactory.makeModel match {
+ case Some(madeModel) =>
+ println("model contains " + modelFactory.templatesCount + " documentable templates")
+ Some(madeModel)
+ case None =>
+ println("no documentable class found in compilation units")
+ None
+ }
+
+ }
+
+ object NoCompilerRunException extends ControlThrowable { }
+
+ val documentError: PartialFunction[Throwable, Unit] = {
+ case NoCompilerRunException =>
+ reporter.info(NoPosition, "No documentation generated with unsucessful compiler run", false)
+ case _: ClassNotFoundException =>
+ ()
}
/** Generate document(s) for all `files` containing scaladoc documenataion.
* @param files The list of paths (relative to the compiler's source path, or absolute) of files to document. */
def document(files: List[String]): Unit = {
+ def generate() = {
+ import doclet._
+ val docletClass = Class.forName(settings.docgenerator.value) // default is html.Doclet
+ val docletInstance = docletClass.newInstance().asInstanceOf[Generator]
- class NoCompilerRunException extends Exception
-
- try {
- val docletClass = Class.forName(settings.docgenerator.value) // default is html.Doclet
- val docletInstance = docletClass.newInstance().asInstanceOf[doclet.Generator]
- if (docletInstance.isInstanceOf[doclet.Universer]) {
- makeUniverse(files) match {
- case Some(universe) =>
- docletClass.getMethod("setUniverse", classOf[Universe]).invoke(docletInstance, universe)
- if (docletInstance.isInstanceOf[doclet.Indexer]) {
- val index = model.IndexModelFactory.makeIndex(universe)
- docletClass.getMethod("setIndex", classOf[Index]).invoke(docletInstance, index)
- }
- case None =>
- throw new NoCompilerRunException()
- }
+ docletInstance match {
+ case universer: Universer =>
+ val universe = makeUniverse(files) getOrElse { throw NoCompilerRunException }
+ universer setUniverse universe
+
+ docletInstance match {
+ case indexer: Indexer => indexer setIndex model.IndexModelFactory.makeIndex(universe)
+ case _ => ()
+ }
+ case _ => ()
}
docletInstance.generate
}
- catch {
- case e: ClassNotFoundException =>
- case e: NoCompilerRunException =>
- reporter.info(NoPosition, "No documentation generated with unsucessful compiler run", false)
- }
-
-
+ try generate()
+ catch documentError
+ }
+ private[doc] def docdbg(msg: String) {
+ if (settings.Ydocdebug.value)
+ println(msg)
}
-
}
diff --git a/src/compiler/scala/tools/nsc/doc/DocParser.scala b/src/compiler/scala/tools/nsc/doc/DocParser.scala
new file mode 100644
index 0000000000..1e45079c48
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/DocParser.scala
@@ -0,0 +1,74 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package nsc
+package doc
+
+import reporters._
+import util._
+import interactive.RangePositions
+import DocParser.Parsed
+
+/** A very minimal global customized for extracting DocDefs. It stops
+ * right after parsing so it can read DocDefs from source code which would
+ * otherwise cause the compiler to go haywire.
+ */
+class DocParser(settings: nsc.Settings, reporter: Reporter)
+ extends Global(settings, reporter)
+ with RangePositions {
+
+ def this(settings: Settings) = this(settings, new ConsoleReporter(settings))
+ def this() = this(new Settings(Console println _))
+
+ // the usual global initialization
+ locally { new Run() }
+
+ override def forScaladoc = true
+ override protected def computeInternalPhases() {
+ phasesSet += syntaxAnalyzer
+ }
+
+ /** Returns a list of DocParser.Parseds, which hold the DocDefs found in the
+ * given code along with the surrounding trees.
+ */
+ def docDefs(code: String) = {
+ def loop(enclosing: List[Tree], tree: Tree): List[Parsed] = tree match {
+ case x: PackageDef => x.stats flatMap (t => loop(enclosing :+ x, t))
+ case x: DocDef => new Parsed(enclosing, x) :: loop(enclosing :+ x.definition, x.definition)
+ case x => x.children flatMap (t => loop(enclosing, t))
+ }
+ loop(Nil, docUnit(code))
+ }
+
+ /** A compilation unit containing parsed source.
+ */
+ def docUnit(code: String) = {
+ val unit = new CompilationUnit(new BatchSourceFile("<console>", code))
+ val scanner = new syntaxAnalyzer.UnitParser(unit)
+
+ scanner.compilationUnit()
+ }
+}
+
+/** Since the DocParser's whole reason for existing involves trashing a
+ * global, it is designed to bottle up general Global#Tree types rather
+ * than path dependent ones. The recipient will have to deal.
+ */
+object DocParser {
+ type Tree = Global#Tree
+ type DefTree = Global#DefTree
+ type DocDef = Global#DocDef
+ type Name = Global#Name
+
+ class Parsed(val enclosing: List[Tree], val docDef: DocDef) {
+ def nameChain: List[Name] = (enclosing :+ docDef.definition) collect { case x: DefTree => x.name }
+ def raw: String = docDef.comment.raw
+
+ override def toString = (
+ nameChain.init.map(x => if (x.isTypeName) x + "#" else x + ".").mkString + nameChain.last
+ )
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala
index bcbdd64e62..292eca91e3 100644
--- a/src/compiler/scala/tools/nsc/doc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/doc/Settings.scala
@@ -41,6 +41,17 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
""
)
+ val docUncompilable = StringSetting (
+ "-doc-no-compile",
+ "path",
+ "A directory containing sources which should be parsed, no more (e.g. AnyRef.scala)",
+ ""
+ )
+ lazy val uncompilableFiles = docUncompilable.value match {
+ case "" => Nil
+ case path => io.Directory(path).deepFiles filter (_ hasExtension "scala") toList
+ }
+
/** A setting that defines a URL to be concatenated with source locations and show a link to source files.
* If needed the sourcepath option can be used to exclude undesired initial part of the link to sources */
val docsourceurl = StringSetting (
@@ -62,8 +73,6 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
"scala.tools.nsc.doc.html.Doclet"
)
- // TODO: add a new setting for whether or not to document sourceless entities (e.g., Any, Unit, etc)
-
// Somewhere slightly before r18708 scaladoc stopped building unless the
// self-type check was suppressed. I hijacked the slotted-for-removal-anyway
// suppress-vt-warnings option and renamed it for this purpose.
@@ -71,7 +80,7 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
// For improved help output.
def scaladocSpecific = Set[Settings#Setting](
- docformat, doctitle, docversion, docsourceurl, docgenerator
+ docformat, doctitle, docversion, docUncompilable, docsourceurl, docgenerator
)
val isScaladocSpecific: String => Boolean = scaladocSpecific map (_.name)
}
diff --git a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala b/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
deleted file mode 100644
index 6b6886a599..0000000000
--- a/src/compiler/scala/tools/nsc/doc/SourcelessComments.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-/* NSC -- new Scala compiler -- Copyright 2007-2011 LAMP/EPFL */
-
-package scala.tools.nsc
-package doc
-
-import scala.collection._
-
-/**
- * A class that provides comments for all symbols which pre-exist in Scala (Any, Nothing, ...)
- * It also contains a HashSet of the given symbols
- * The comments are to be added to a HashMap called comments, which resides in the Global.scala file
- * @author Manohar Jonnalagedda, Stephane Micheloud, Sean McDirmid, Geoffrey Washburn
- * @version 1.0 */
-abstract class SourcelessComments {
-
- val global: Global
-
- import global._
- import definitions._
-
- lazy val comments = {
-
- val comment = mutable.HashMap.empty[Symbol, DocComment]
-
- comment(NothingClass) = new DocComment("""
- /** Class `Nothing` is - together with class [[scala.Null]] - at the bottom of Scala's type hierarchy.
- *
- * Type `Nothing` is a subtype of every other type (including [[scala.Null]]); there exist ''no instances'' of
- * this type. Even though type `Nothing` is empty, it is nevertheless useful as a type parameter. For instance,
- * the Scala library defines a value [[scala.collection.immutable.Nil]] of type `List[Nothing]`. Because lists
- * are covariant in Scala, this makes [[scala.collection.immutable.Nil]] an instance of `List[T]`, for any
- * element of type `T`. */
- """)
-
- comment(NullClass) = new DocComment("""
- /** Class `Null` is - together with class [[scala.Nothing]] - at the bottom of the Scala type hierarchy.
- *
- * Type `Null` is a subtype of all reference types; its only instance is the `null` reference. Since `Null` is
- * not a subtype of value types, `null` is not a member of any such type. For instance, it is not possible to
- * assign `null` to a variable of type [[scala.Int]]. */
- """)
-
- /*******************************************************************/
- /* Documentation for Any */
-
- comment(AnyClass) = new DocComment("""
- /** Class `Any` is the root of the Scala class hierarchy. Every class in a Scala execution environment inherits
- * directly or indirectly from this class. Class `Any` has two direct subclasses: [[scala.AnyRef]] and
- * [[scala.AnyVal]]. */
- """)
-
- comment(Any_equals) = new DocComment("""
- /** This method is used to compare the receiver object (`this`) with the argument object (`arg0`) for equivalence.
- *
- * The default implementations of this method is an [[http://en.wikipedia.org/wiki/Equivalence_relation equivalence
- * relation]]:
- * - It is reflexive: for any instance `x` of type `Any`, `x.equals(x)` should return `true`.
- * - It is symmetric: for any instances `x` and `y` of type `Any`, `x.equals(y)` should return `true` if and
- * only if `y.equals(x)` returns `true`.
- * - It is transitive: for any instances `x`, `y`, and `z` of type `AnyRef` if `x.equals(y)` returns `true` and
- * `y.equals(z)` returns `true`, then `x.equals(z)` should return `true`.
- *
- * If you override this method, you should verify that your implementation remains an equivalence relation.
- * Additionally, when overriding this method it is often necessary to override `hashCode` to ensure that objects
- * that are "equal" (`o1.equals(o2)` returns `true`) hash to the same [[scala.Int]]
- * (`o1.hashCode.equals(o2.hashCode)`).
- *
- * @param arg0 the object to compare against this object for equality.
- * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. */
- """)
-
- comment(Any_==) = new DocComment("""
- /** `o == arg0` is the same as `o.equals(arg0)`.
- *
- * @param arg0 the object to compare against this object for equality.
- * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. */
- """)
-
- comment(Any_!=) = new DocComment("""
- /** `o != arg0` is the same as `!(o == (arg0))`.
- *
- * @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. */
- """)
-
- comment(Any_toString) = new DocComment("""
- /** Returns a string representation of the object.
- *
- * The default representation is platform dependent.
- *
- * @return a string representation of the object. */
- """)
-
- comment(Any_asInstanceOf) = new DocComment("""
- /** This method is used to cast the receiver object to be of type `T0`.
- *
- * Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression
- * `1.asInstanceOf[String]` will throw a `ClassCastException` at runtime, while the expression
- * `List(1).asInstanceOf[List[String]]` will not. In the latter example, because the type argument is erased as
- * part of compilation it is not possible to check whether the contents of the list are of the requested typed.
- *
- * @throws ClassCastException if the receiver object is not an instance of erasure of type `T0`.
- * @return the receiver object. */
- """)
-
- comment(Any_isInstanceOf) = new DocComment("""
- /** This method is used to test whether the dynamic type of the receiver object is `T0`.
- *
- * Note that the test result of the test is modulo Scala's erasure semantics. Therefore the expression
- * `1.isInstanceOf[String]` will return `false`, while the expression `List(1).isInstanceOf[List[String]]` will
- * return `true`. In the latter example, because the type argument is erased as part of compilation it is not
- * possible to check whether the contents of the list are of the requested typed.
- *
- * @return `true` if the receiver object is an instance of erasure of type `T0`; `false` otherwise. */
- """)
-
- comment(Any_hashCode) = new DocComment("""
- /** Returns a hash code value for the object.
- *
- * The default hashing algorithm is platform dependent.
- *
- * Note that it is allowed for two objects to have identical hash codes (`o1.hashCode.equals(o2.hashCode)`) yet
- * not be equal (`o1.equals(o2)` returns `false`). A degenerate implementation could always return `0`.
- * However, it is required that if two objects are equal (`o1.equals(o2)` returns `true`) that they have
- * identical hash codes (`o1.hashCode.equals(o2.hashCode)`). Therefore, when overriding this method, be sure
- * to verify that the behavior is consistent with the `equals` method.
- *
- * @return the hash code value for the object. */
- """)
-
- /*******************************************************************/
- /* Documentation for AnyRef */
-
- comment(AnyRefClass) = new DocComment("""
- /** Class `AnyRef` is the root class of all ''reference types''. */
- """)
-
- comment(Object_==) = new DocComment("""
- /** `o == arg0` is the same as `if (o eq null) arg0 eq null else o.equals(arg0)`.
- *
- * @param arg0 the object to compare against this object for equality.
- * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. */
- """)
-
- comment(Object_ne) = new DocComment("""
- /** `o.ne(arg0)` is the same as `!(o.eq(arg0))`.
- *
- * @param arg0 the object to compare against this object for reference dis-equality.
- * @return `false` if the argument is not a reference to the receiver object; `true` otherwise. */
- """)
-
-
- 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.
- *
- * The details of when and if the `finalize` method are invoked, as well as the interaction between `finalize`
- * and non-local returns and exceptions, are all platform dependent. */
- """)
-
- comment(Object_clone) = new DocComment("""
- /** This method creates and returns a copy of the receiver object.
- *
- * The default implementation of the `clone` method is platform dependent.
- *
- * @return a copy of the receiver object. */
- """)
-
- comment(Object_getClass) = new DocComment("""
- /** Returns a representation that corresponds to the dynamic class of the receiver object.
- *
- * The nature of the representation is platform dependent.
- *
- * @return a representation that corresponds to the dynamic class of the receiver object. */
- """)
-
- comment(Object_notify) = new DocComment("""
- /** Wakes up a single thread that is waiting on the receiver object's monitor. */
- """)
-
- comment(Object_notifyAll) = new DocComment("""
- /** Wakes up all threads that are waiting on the receiver object's monitor. */
- """)
-
- comment(Object_eq) = new DocComment("""
- /** This method is used to test whether the argument (`arg0`) is a reference to the
- * receiver object (`this`).
- *
- * The `eq` method implements an [[http://en.wikipedia.org/wiki/Equivalence_relation equivalence relation]] on
- * non-null instances of `AnyRef`:
- * - It is reflexive: for any non-null instance `x` of type `AnyRef`, `x.eq(x)` returns `true`.
- * - It is symmetric: for any non-null instances `x` and `y` of type `AnyRef`, `x.eq(y)` returns `true` if and
- * only if `y.eq(x)` returns `true`.
- * - It is transitive: for any non-null instances `x`, `y`, and `z` of type `AnyRef` if `x.eq(y)` returns `true`
- * and `y.eq(z)` returns `true`, then `x.eq(z)` returns `true`.
- *
- * Additionally, the `eq` method has three other properties.
- * - It is consistent: for any non-null instances `x` and `y` of type `AnyRef`, multiple invocations of
- * `x.eq(y)` consistently returns `true` or consistently returns `false`.
- * - For any non-null instance `x` of type `AnyRef`, `x.eq(null)` and `null.eq(x)` returns `false`.
- * - `null.eq(null)` returns `true`.
- *
- * When overriding the `equals` or `hashCode` methods, it is important to ensure that their behavior is
- * consistent with reference equality. Therefore, if two objects are references to each other (`o1 eq o2`), they
- * should be equal to each other (`o1 == o2`) and they should hash to the same value (`o1.hashCode == o2.hashCode`).
- *
- * @param arg0 the object to compare against this object for reference equality.
- * @return `true` if the argument is a reference to the receiver object; `false` otherwise. */
- """)
-
- /*******************************************************************/
-
- comment
- }
-
-}
diff --git a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala
new file mode 100644
index 0000000000..1f0c85361e
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package doc
+
+/** Some glue between DocParser (which reads source files which can't be compiled)
+ * and the scaladoc model.
+ */
+trait Uncompilable {
+ val global: Global
+ val settings: Settings
+
+ import global.{ reporter, inform, warning, newTypeName, newTermName, Symbol, Name, DocComment }
+ import global.definitions.RootClass
+
+ private implicit def translateName(name: Global#Name) =
+ if (name.isTypeName) newTypeName("" + name) else newTermName("" + name)
+
+ def docSymbol(p: DocParser.Parsed) = p.nameChain.foldLeft(RootClass: Symbol)(_.tpe member _)
+ def docDefs(code: String) = new DocParser(settings, reporter) docDefs code
+ def docPairs(code: String) = docDefs(code) map (p => (docSymbol(p), new DocComment(p.raw)))
+
+ lazy val pairs = files flatMap { f =>
+ val comments = docPairs(f.slurp())
+ if (settings.verbose.value)
+ inform("Found %d doc comments in parse-only file %s: %s".format(comments.size, f, comments.map(_._1).mkString(", ")))
+
+ comments
+ }
+ def files = settings.uncompilableFiles
+ def symbols = pairs map (_._1)
+ def templates = symbols filter (x => x.isClass || x.isTrait) toSet
+ def comments = {
+ if (settings.debug.value || settings.verbose.value)
+ inform("Found %d uncompilable files: %s".format(files.size, files mkString ", "))
+
+ if (pairs.isEmpty)
+ warning("no doc comments read from " + settings.docUncompilable.value)
+
+ pairs
+ }
+ override def toString = pairs.size + " uncompilable symbols:\n" + (
+ symbols map (x => " " + x.owner.fullName + " " + x.defString) mkString "\n"
+ )
+}
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
index 33f81fef1c..f6dc58617e 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -8,7 +8,6 @@ package doc
package html
import model._
-
import java.io.{ File => JFile }
import io.{ Streamable, Directory }
import scala.collection._
@@ -17,7 +16,6 @@ import scala.collection._
* @author David Bernard
* @author Gilles Dubochet */
class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
-
/** The character encoding to be used for generated Scaladoc sites. This value is currently always UTF-8. */
def encoding: String = "UTF-8"
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 88d3e61263..bc35e4835a 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -390,7 +390,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
val linearization =
mbr match {
- case dtpl: DocTemplateEntity if (isSelf && !isReduced && (!dtpl.linearizationTemplates.isEmpty || !dtpl.subClasses.isEmpty)) =>
+ case dtpl: DocTemplateEntity if isSelf && !isReduced && (dtpl.linearizationTemplates.nonEmpty || dtpl.subClasses.nonEmpty) =>
val linearSupertypes: Seq[scala.xml.Node] =
if (dtpl.linearizationTemplates.isEmpty) NodeSeq.Empty
else {
@@ -523,18 +523,18 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
}
}{ if (isReduced) NodeSeq.Empty else {
mbr match {
- case tpl: DocTemplateEntity if (!tpl.isPackage) =>
- tpl.parentType match {
- case Some(st) => <span class="result"> extends { typeToHtml(st, hasLinks) }</span>
- case None =>NodeSeq.Empty
- }
+ case tpl: DocTemplateEntity if tpl.parentType.isDefined =>
+ <span class="result"> extends { typeToHtml(tpl.parentType.get, hasLinks) }</span>
+
case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isLazyVal || tme.isVar) =>
<span class="result">: { typeToHtml(tme.resultType, hasLinks) }</span>
+
case abt: AbstractType =>
val b2s = boundsToHtml(abt.hi, abt.lo, hasLinks)
if (b2s != NodeSeq.Empty)
<span class="result">{ b2s }</span>
else NodeSeq.Empty
+
case alt: AliasType =>
<span class="result"> = { typeToHtml(alt.alias, hasLinks) }</span>
case _ => NodeSeq.Empty
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 4edfa83a0d..405da29a57 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -17,7 +17,7 @@ import model.{ RootPackage => RootPackageEntity }
class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory: ModelFactory with CommentFactory with TreeFactory =>
import global._
- import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyRefClass }
+ import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyValClass, AnyRefClass }
private var droppedPackages = 0
def templatesCount = templatesCache.size - droppedPackages
@@ -25,6 +25,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
private var modelFinished = false
private var universe: Universe = null
+ private lazy val noSubclassCache = Set(AnyClass, AnyRefClass, ObjectClass, ScalaObjectClass)
+
/** */
def makeModel: Option[Universe] = {
val universe = new Universe { thisUniverse =>
@@ -160,6 +162,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
* * All non-package members (including other templates, as full templates). */
abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
//if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > "))
+ if (settings.verbose.value)
+ inform("Creating doc template for " + sym)
+
templatesCache += (sym -> this)
lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot
@@ -192,33 +197,40 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
else None
}
def parentType = {
- if (sym.isPackage) None else {
+ if (sym.isPackage || sym == AnyClass) None else {
val tps =
(sym.tpe.parents filter (_ != ScalaObjectClass.tpe)) map { _.asSeenFrom(sym.thisType, sym) }
Some(makeType(RefinedType(tps, EmptyScope), inTpl))
}
}
val linearization: List[(TemplateEntity, TypeEntity)] = {
- val acs = sym.ancestors filter { _ != ScalaObjectClass }
- val tps = acs map { cls => makeType(sym.info.baseType(cls), this) }
- val tpls = acs map { makeTemplate(_) }
- tpls map {
- case dtpl: DocTemplateImpl => dtpl.registerSubClass(this)
- case _ =>
+ val acs = sym.ancestors filterNot (_ == ScalaObjectClass)
+ val tps = acs map (cls => makeType(sym.info.baseType(cls), this))
+ val tpls = acs map makeTemplate
+
+ tpls foreach {
+ case dtpl: DocTemplateImpl => dtpl.registerSubClass(this)
+ case _ =>
}
tpls zip tps
}
def linearizationTemplates = linearization map { _._1 }
def linearizationTypes = linearization map { _._2 }
- private lazy val subClassesCache = mutable.Buffer.empty[DocTemplateEntity]
+
+ private lazy val subClassesCache = (
+ if (noSubclassCache(sym)) null
+ else mutable.ListBuffer[DocTemplateEntity]()
+ )
def registerSubClass(sc: DocTemplateEntity): Unit = {
- assert(subClassesCache != null)
- subClassesCache += sc
+ if (subClassesCache != null)
+ subClassesCache += sc
}
- def subClasses = subClassesCache.toList
+ def subClasses = if (subClassesCache == null) Nil else subClassesCache.toList
+
protected lazy val memberSyms =
// Only this class's constructors are part of its members, inherited constructors are not.
sym.info.members.filter(s => localShouldDocument(s) && (!s.isConstructor || s.owner == sym))
+
val members = memberSyms flatMap (makeMember(_, this))
val templates = members collect { case c: DocTemplateEntity => c }
val methods = members collect { case d: Def => d }
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index f0d819538e..2de5ce82ce 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -146,6 +146,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") .
withPostSetHook(set => interpreter.isReplDebug = true)
val Ycompletion = BooleanSetting ("-Ycompletion-debug", "Trace all tab completion activity.")
+ val Ydocdebug = BooleanSetting ("-Ydoc-debug", "Trace all scaladoc activity.")
val Ypmatnaive = BooleanSetting ("-Ypmat-naive", "Desugar matches as naively as possible.")
val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
val YdepMethTpes = BooleanSetting ("-Ydependent-method-types", "Allow dependent method types.")