Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scaladoc diagrams (again) #816

Merged
merged 7 commits into from
Jul 7, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2064,6 +2064,9 @@ DOCUMENTATION
<!-- Compute the URL and show it -->
<property name="scaladoc.url" value="https://github.com/scala/scala/tree/${scaladoc.git.commit}/src"/>
<echo message="Scaladoc will point to ${scaladoc.url} for source files."/>

<!-- Unless set with -Dscaladoc.raw.output, it won't be activated -->
<property name="scaladoc.raw.output" value="no"/>
</target>

<target name="docs.pre-lib" depends="docs.start">
Expand Down Expand Up @@ -2091,7 +2094,7 @@ DOCUMENTATION
classpathref="pack.classpath"
addparams="${scalac.args.all}"
docRootContent="${src.dir}/library/rootdoc.txt"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<src>
<files includes="${src.dir}/actors-migration"/>
<files includes="${src.dir}/actors"/>
Expand Down Expand Up @@ -2175,7 +2178,7 @@ DOCUMENTATION
srcdir="${src.dir}/compiler"
docRootContent="${src.dir}/compiler/rootdoc.txt"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/compiler.complete" verbose="no"/>
Expand All @@ -2197,7 +2200,7 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/jline/src/main/java"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
<include name="**/*.java"/>
</scaladoc>
Expand All @@ -2221,7 +2224,7 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/scalap"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/scalap.complete" verbose="no"/>
Expand All @@ -2243,7 +2246,7 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/partest"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/partest.complete" verbose="no"/>
Expand All @@ -2265,7 +2268,7 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/continuations/plugin"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/continuations-plugin.complete" verbose="no"/>
Expand All @@ -2287,7 +2290,7 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/actors-migration"
addparams="${scalac.args.all}"
implicits="on" diagrams="on">
implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/actors-migration.complete" verbose="no"/>
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/scala/tools/ant/Scaladoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ class Scaladoc extends ScalaMatchingTask {
/** Instruct the scaladoc tool to use the binary given to create diagrams */
private var docDiagramsDotPath: Option[String] = None

/** Instruct the scaladoc to produce textual ouput from html pages, for easy diff-ing */
private var docRawOutput: Boolean = false


/*============================================================================*\
** Properties setters **
Expand Down Expand Up @@ -419,6 +422,11 @@ class Scaladoc extends ScalaMatchingTask {
def setDiagramsDotPath(input: String) =
docDiagramsDotPath = Some(input)

/** Set the `rawOutput` bit so Scaladoc also outputs text from each html file
* @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
def setRawOutput(input: String) =
docRawOutput = Flag.getBooleanValue(input, "rawOutput")

/*============================================================================*\
** Properties getters **
\*============================================================================*/
Expand Down Expand Up @@ -616,6 +624,7 @@ class Scaladoc extends ScalaMatchingTask {
docSettings.docImplicitsShowAll.value = docImplicitsShowAll
docSettings.docDiagrams.value = docDiagrams
docSettings.docDiagramsDebug.value = docDiagramsDebug
docSettings.docRawOutput.value = docRawOutput
if(!docDiagramsDotPath.isEmpty) docSettings.docDiagramsDotPath.value = docDiagramsDotPath.get

if (!docgenerator.isEmpty) docSettings.docgenerator.value = docgenerator.get
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/ScalaDoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class ScalaDoc {

def process(args: Array[String]): Boolean = {
var reporter: ConsoleReporter = null
val docSettings = new doc.Settings(msg => reporter.error(FakePos("scaladoc"), msg + "\n scaladoc -help gives more information"))
val docSettings = new doc.Settings(msg => reporter.error(FakePos("scaladoc"), msg + "\n scaladoc -help gives more information"),
msg => reporter.printMessage(msg))
reporter = new ConsoleReporter(docSettings) {
// need to do this so that the Global instance doesn't trash all the
// symbols just because there was an error
Expand Down
10 changes: 6 additions & 4 deletions src/compiler/scala/tools/nsc/doc/DocFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,22 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
new { override val global: compiler.type = compiler }
with model.ModelFactory(compiler, settings)
with model.ModelFactoryImplicitSupport
with model.diagram.DiagramFactory
with model.comment.CommentFactory
with model.TreeFactory {
override def templateShouldDocument(sym: compiler.Symbol) =
extraTemplatesToDocument(sym) || super.templateShouldDocument(sym)
override def templateShouldDocument(sym: compiler.Symbol, inTpl: TemplateImpl) =
extraTemplatesToDocument(sym) || super.templateShouldDocument(sym, inTpl)
}
)

modelFactory.makeModel match {
case Some(madeModel) =>
if (settings.reportModel)
if (!settings.scaladocQuietRun)
println("model contains " + modelFactory.templatesCount + " documentable templates")
Some(madeModel)
case None =>
println("no documentable class found in compilation units")
if (!settings.scaladocQuietRun)
println("no documentable class found in compilation units")
None
}

Expand Down
82 changes: 66 additions & 16 deletions src/compiler/scala/tools/nsc/doc/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import java.lang.System
import language.postfixOps

/** An extended version of compiler settings, with additional Scaladoc-specific options.
* @param error A function that prints a string to the appropriate error stream. */
class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
* @param error A function that prints a string to the appropriate error stream
* @param print A function that prints the string, without any extra boilerplate of error */
class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) extends scala.tools.nsc.Settings(error) {

/** A setting that defines in which format the documentation is output. ''Note:'' this setting is currently always
* `html`. */
Expand Down Expand Up @@ -104,6 +105,12 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
"(for example conversions that require Numeric[String] to be in scope)"
)

val docImplicitsSoundShadowing = BooleanSetting (
"-implicits-sound-shadowing",
"Use a sound implicit shadowing calculation. Note: this interacts badly with usecases, so " +
"only use it if you haven't defined usecase for implicitly inherited members."
)

val docDiagrams = BooleanSetting (
"-diagrams",
"Create inheritance diagrams for classes, traits and packages."
Expand All @@ -116,10 +123,49 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {

val docDiagramsDotPath = PathSetting (
"-diagrams-dot-path",
"The path to the dot executable used to generate the inheritance diagrams. Ex: /usr/bin/dot",
"The path to the dot executable used to generate the inheritance diagrams. Eg: /usr/bin/dot",
"dot" // by default, just pick up the system-wide dot
)

/** The maxium nuber of normal classes to show in the diagram */
val docDiagramsMaxNormalClasses = IntSetting(
"-diagrams-max-classes",
"The maximum number of superclasses or subclasses to show in a diagram",
15,
None,
_ => None
)

/** The maxium nuber of implcit classes to show in the diagram */
val docDiagramsMaxImplicitClasses = IntSetting(
"-diagrams-max-implicits",
"The maximum number of implicitly converted classes to show in a diagram",
10,
None,
_ => None
)

val docDiagramsDotTimeout = IntSetting(
"-diagrams-dot-timeout",
"The timeout before the graphviz dot util is forecefully closed, in seconds (default: 10)",
10,
None,
_ => None
)

val docDiagramsDotRestart = IntSetting(
"-diagrams-dot-restart",
"The number of times to restart a malfunctioning dot process before disabling diagrams (default: 5)",
5,
None,
_ => None
)

val docRawOutput = BooleanSetting (
"-raw-output",
"For each html file, create another .html.raw file containing only the text. (can be used for quickly diffing two scaladoc outputs)"
)

// 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.
Expand All @@ -129,14 +175,16 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
def scaladocSpecific = Set[Settings#Setting](
docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator, docRootContent, useStupidTypes,
docDiagrams, docDiagramsDebug, docDiagramsDotPath,
docImplicits, docImplicitsDebug, docImplicitsShowAll
docDiagramsDotTimeout, docDiagramsDotRestart,
docImplicits, docImplicitsDebug, docImplicitsShowAll,
docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses
)
val isScaladocSpecific: String => Boolean = scaladocSpecific map (_.name)

override def isScaladoc = true

// unset by the testsuite, we don't need to count the entities in the model
var reportModel = true
// set by the testsuite, when checking test output
var scaladocQuietRun = false

/**
* This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty,
Expand All @@ -150,15 +198,16 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
* the function result should be a humanly-understandable description of the type class
*/
val knownTypeClasses: Map[String, String => String] = Map() +
("<root>.scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
("<root>.scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
("<root>.scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
("<root>.scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
("<root>.scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
("<root>.scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
("<root>.scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
("<root>.scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
("<root>.scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))
// TODO: Bring up to date and test these
("scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
("scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
("scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
("scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))

/**
* Set of classes to exclude from index and diagrams
Expand All @@ -182,7 +231,8 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
"scala.Predef.any2stringfmt",
"scala.Predef.any2stringadd",
"scala.Predef.any2ArrowAssoc",
"scala.Predef.any2Ensuring")
"scala.Predef.any2Ensuring",
"scala.collection.TraversableOnce.alternateImplicit")

/** There's a reason all these are specialized by hand but documenting each of them is beyond the point */
val arraySkipConversions = List(
Expand Down
16 changes: 15 additions & 1 deletion src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import model._
import java.io.{ File => JFile }
import io.{ Streamable, Directory }
import scala.collection._
import page.diagram._

import html.page.diagram.DiagramGenerator

/** A class that can generate Scaladoc sites to some fixed root folder.
* @author David Bernard
Expand All @@ -29,21 +32,27 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
"jquery.js",
"jquery.layout.js",
"scheduler.js",
"diagrams.js",
"template.js",
"tools.tooltip.js",
"modernizr.custom.js",

"index.css",
"ref-index.css",
"template.css",
"diagrams.css",

"class.png",
"class_big.png",
"class_diagram.png",
"object.png",
"object_big.png",
"object_diagram.png",
"package.png",
"package_big.png",
"trait.png",
"trait_big.png",
"trait_diagram.png",

"class_to_object_big.png",
"object_to_class_big.png",
Expand Down Expand Up @@ -105,6 +114,8 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
finally out.close()
}

DiagramGenerator.initialize(universe.settings)

libResources foreach (s => copyResource("lib/" + s))

new page.Index(universe, index) writeFor this
Expand All @@ -115,14 +126,17 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
for (letter <- index.firstLetterIndex) {
new html.page.ReferenceIndex(letter._1, index, universe) writeFor this
}

DiagramGenerator.cleanup()
}

def writeTemplates(writeForThis: HtmlPage => Unit) {
val written = mutable.HashSet.empty[DocTemplateEntity]
val diagramGenerator: DiagramGenerator = new DotDiagramGenerator(universe.settings)

def writeTemplate(tpl: DocTemplateEntity) {
if (!(written contains tpl)) {
writeForThis(new page.Template(universe, tpl))
writeForThis(new page.Template(universe, diagramGenerator, tpl))
written += tpl
tpl.templates map writeTemplate
}
Expand Down
Loading