Scaladoc 2.
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@19844 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
14
build.xml
|
@ -334,6 +334,10 @@ LOCAL REFERENCE BUILD (LOCKER)
|
||||||
<include name="**/*.xml"/>
|
<include name="**/*.xml"/>
|
||||||
<include name="**/*.js"/>
|
<include name="**/*.js"/>
|
||||||
<include name="**/*.css"/>
|
<include name="**/*.css"/>
|
||||||
|
<include name="**/*.properties"/>
|
||||||
|
<include name="**/*.swf"/>
|
||||||
|
<include name="**/*.png"/>
|
||||||
|
|
||||||
</fileset>
|
</fileset>
|
||||||
</copy>
|
</copy>
|
||||||
<touch file="${build-locker.dir}/compiler.complete" verbose="no"/>
|
<touch file="${build-locker.dir}/compiler.complete" verbose="no"/>
|
||||||
|
@ -547,6 +551,9 @@ QUICK BUILD (QUICK)
|
||||||
<include name="**/*.xml"/>
|
<include name="**/*.xml"/>
|
||||||
<include name="**/*.js"/>
|
<include name="**/*.js"/>
|
||||||
<include name="**/*.css"/>
|
<include name="**/*.css"/>
|
||||||
|
<include name="**/*.properties"/>
|
||||||
|
<include name="**/*.swf"/>
|
||||||
|
<include name="**/*.png"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</copy>
|
</copy>
|
||||||
<touch file="${build-quick.dir}/compiler.complete" verbose="no"/>
|
<touch file="${build-quick.dir}/compiler.complete" verbose="no"/>
|
||||||
|
@ -976,7 +983,10 @@ BOOTSTRAPPING BUILD (STRAP)
|
||||||
<include name="**/*.xml"/>
|
<include name="**/*.xml"/>
|
||||||
<include name="**/*.js"/>
|
<include name="**/*.js"/>
|
||||||
<include name="**/*.css"/>
|
<include name="**/*.css"/>
|
||||||
</fileset>
|
<include name="**/*.properties"/>
|
||||||
|
<include name="**/*.swf"/>
|
||||||
|
<include name="**/*.png"/>
|
||||||
|
</fileset>
|
||||||
</copy>
|
</copy>
|
||||||
<touch file="${build-strap.dir}/compiler.complete" verbose="no"/>
|
<touch file="${build-strap.dir}/compiler.complete" verbose="no"/>
|
||||||
<stopwatch name="strap.comp.timer" action="total"/>
|
<stopwatch name="strap.comp.timer" action="total"/>
|
||||||
|
@ -1186,7 +1196,6 @@ DOCUMENTATION
|
||||||
<mkdir dir="${build-docs.dir}/library"/>
|
<mkdir dir="${build-docs.dir}/library"/>
|
||||||
<scaladoc
|
<scaladoc
|
||||||
destdir="${build-docs.dir}/library"
|
destdir="${build-docs.dir}/library"
|
||||||
windowtitle="Scala Library"
|
|
||||||
doctitle="Scala ${version.number} API"
|
doctitle="Scala ${version.number} API"
|
||||||
classpathref="pack.classpath">
|
classpathref="pack.classpath">
|
||||||
<src>
|
<src>
|
||||||
|
@ -1269,7 +1278,6 @@ DOCUMENTATION
|
||||||
<mkdir dir="${build-docs.dir}/compiler"/>
|
<mkdir dir="${build-docs.dir}/compiler"/>
|
||||||
<scaladoc
|
<scaladoc
|
||||||
destdir="${build-docs.dir}/compiler"
|
destdir="${build-docs.dir}/compiler"
|
||||||
windowtitle="Scala Compiler"
|
|
||||||
doctitle="Scala Compiler ${version.number} API"
|
doctitle="Scala Compiler ${version.number} API"
|
||||||
classpathref="pack.classpath"
|
classpathref="pack.classpath"
|
||||||
srcdir="${src.dir}/compiler">
|
srcdir="${src.dir}/compiler">
|
||||||
|
|
|
@ -17,8 +17,8 @@ import org.apache.tools.ant.taskdefs.MatchingTask
|
||||||
import org.apache.tools.ant.types.{Path, Reference}
|
import org.apache.tools.ant.types.{Path, Reference}
|
||||||
import org.apache.tools.ant.util.{FileUtils, GlobPatternMapper}
|
import org.apache.tools.ant.util.{FileUtils, GlobPatternMapper}
|
||||||
|
|
||||||
import scala.tools.nsc.{Global, Settings}
|
import scala.tools.nsc.Global
|
||||||
import scala.tools.nsc.doc.DefaultDocDriver
|
import scala.tools.nsc.doc.Settings
|
||||||
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
||||||
|
|
||||||
/** <p>
|
/** <p>
|
||||||
|
@ -40,9 +40,7 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
||||||
* <li>extdirs,</li>
|
* <li>extdirs,</li>
|
||||||
* <li>extdirsref,</li>
|
* <li>extdirsref,</li>
|
||||||
* <li>encoding,</li>
|
* <li>encoding,</li>
|
||||||
* <li>windowtitle,</li>
|
|
||||||
* <li>doctitle,</li>
|
* <li>doctitle,</li>
|
||||||
* <li>stylesheetfile,</li>
|
|
||||||
* <li>header,</li>
|
* <li>header,</li>
|
||||||
* <li>footer,</li>
|
* <li>footer,</li>
|
||||||
* <li>top,</li>
|
* <li>top,</li>
|
||||||
|
@ -103,21 +101,9 @@ class Scaladoc extends MatchingTask {
|
||||||
/** The character encoding of the files to compile. */
|
/** The character encoding of the files to compile. */
|
||||||
private var encoding: Option[String] = None
|
private var encoding: Option[String] = None
|
||||||
|
|
||||||
/** The window title of the generated HTML documentation. */
|
|
||||||
private var windowtitle: Option[String] = None
|
|
||||||
|
|
||||||
/** The document title of the generated HTML documentation. */
|
/** The document title of the generated HTML documentation. */
|
||||||
private var doctitle: Option[String] = None
|
private var doctitle: Option[String] = None
|
||||||
|
|
||||||
/** The user-specified stylesheet file. */
|
|
||||||
private var stylesheetfile: Option[String] = None
|
|
||||||
|
|
||||||
/** The user-specified header/footer and top/bottom texts. */
|
|
||||||
private var pageheader: Option[String] = None
|
|
||||||
private var pagefooter: Option[String] = None
|
|
||||||
private var pagetop : Option[String] = None
|
|
||||||
private var pagebottom: Option[String] = None
|
|
||||||
|
|
||||||
/** Instruct the compiler to use additional parameters */
|
/** Instruct the compiler to use additional parameters */
|
||||||
private var addParams: String = ""
|
private var addParams: String = ""
|
||||||
|
|
||||||
|
@ -275,14 +261,6 @@ class Scaladoc extends MatchingTask {
|
||||||
encoding = Some(input)
|
encoding = Some(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the <code>windowtitle</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>windowtitle</code>.
|
|
||||||
*/
|
|
||||||
def setWindowtitle(input: String) {
|
|
||||||
windowtitle = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the <code>doctitle</code> attribute.
|
/** Sets the <code>doctitle</code> attribute.
|
||||||
*
|
*
|
||||||
* @param input The value of <code>doctitle</code>.
|
* @param input The value of <code>doctitle</code>.
|
||||||
|
@ -291,46 +269,6 @@ class Scaladoc extends MatchingTask {
|
||||||
doctitle = Some(input)
|
doctitle = Some(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the <code>stylesheetfile</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>stylesheetfile</code>.
|
|
||||||
*/
|
|
||||||
def setStylesheetfile(input: String) {
|
|
||||||
stylesheetfile = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the <code>header</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>header</code>.
|
|
||||||
*/
|
|
||||||
def setHeader(input: String) {
|
|
||||||
pageheader = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the <code>footer</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>footer</code>.
|
|
||||||
*/
|
|
||||||
def setFooter(input: String) {
|
|
||||||
pagefooter = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the <code>top</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>top</code>.
|
|
||||||
*/
|
|
||||||
def setTop(input: String) {
|
|
||||||
pagetop = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the <code>bottom</code> attribute.
|
|
||||||
*
|
|
||||||
* @param input The value of <code>bottom</code>.
|
|
||||||
*/
|
|
||||||
def setBottom(input: String) {
|
|
||||||
pagebottom = Some(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the <code>addparams</code> info attribute.
|
/** Set the <code>addparams</code> info attribute.
|
||||||
*
|
*
|
||||||
* @param input The value for <code>addparams</code>.
|
* @param input The value for <code>addparams</code>.
|
||||||
|
@ -492,7 +430,7 @@ class Scaladoc extends MatchingTask {
|
||||||
\*============================================================================*/
|
\*============================================================================*/
|
||||||
|
|
||||||
/** Initializes settings and source files */
|
/** Initializes settings and source files */
|
||||||
protected def initialize: Pair[scala.tools.nsc.doc.Settings, List[File]] = {
|
protected def initialize: Pair[Settings, List[File]] = {
|
||||||
// Tests if all mandatory attributes are set and valid.
|
// Tests if all mandatory attributes are set and valid.
|
||||||
if (origin.isEmpty) error("Attribute 'srcdir' is not set.")
|
if (origin.isEmpty) error("Attribute 'srcdir' is not set.")
|
||||||
if (getOrigin.isEmpty) error("Attribute 'srcdir' is not set.")
|
if (getOrigin.isEmpty) error("Attribute 'srcdir' is not set.")
|
||||||
|
@ -542,7 +480,7 @@ class Scaladoc extends MatchingTask {
|
||||||
|
|
||||||
// Builds-up the compilation settings for Scalac with the existing Ant
|
// Builds-up the compilation settings for Scalac with the existing Ant
|
||||||
// parameters.
|
// parameters.
|
||||||
val docSettings = new scala.tools.nsc.doc.Settings(error)
|
val docSettings = new Settings(error)
|
||||||
docSettings.outdir.value = asString(destination.get)
|
docSettings.outdir.value = asString(destination.get)
|
||||||
if (!classpath.isEmpty)
|
if (!classpath.isEmpty)
|
||||||
docSettings.classpath.value = asString(getClasspath)
|
docSettings.classpath.value = asString(getClasspath)
|
||||||
|
@ -554,13 +492,7 @@ class Scaladoc extends MatchingTask {
|
||||||
docSettings.bootclasspath.value = asString(getBootclasspath)
|
docSettings.bootclasspath.value = asString(getBootclasspath)
|
||||||
if (!extdirs.isEmpty) docSettings.extdirs.value = asString(getExtdirs)
|
if (!extdirs.isEmpty) docSettings.extdirs.value = asString(getExtdirs)
|
||||||
if (!encoding.isEmpty) docSettings.encoding.value = encoding.get
|
if (!encoding.isEmpty) docSettings.encoding.value = encoding.get
|
||||||
if (!windowtitle.isEmpty) docSettings.windowtitle.value = windowtitle.get
|
|
||||||
if (!doctitle.isEmpty) docSettings.doctitle.value = decodeEscapes(doctitle.get)
|
if (!doctitle.isEmpty) docSettings.doctitle.value = decodeEscapes(doctitle.get)
|
||||||
if (!stylesheetfile.isEmpty) docSettings.stylesheetfile.value = stylesheetfile.get
|
|
||||||
if (!pageheader.isEmpty) docSettings.pageheader.value = decodeEscapes(pageheader.get)
|
|
||||||
if (!pagefooter.isEmpty) docSettings.pagefooter.value = decodeEscapes(pagefooter.get)
|
|
||||||
if (!pagetop.isEmpty) docSettings.pagetop.value = decodeEscapes(pagetop.get)
|
|
||||||
if (!pagebottom.isEmpty) docSettings.pagebottom.value = decodeEscapes(pagebottom.get)
|
|
||||||
docSettings.deprecation.value = deprecation
|
docSettings.deprecation.value = deprecation
|
||||||
docSettings.unchecked.value = unchecked
|
docSettings.unchecked.value = unchecked
|
||||||
log("Scaladoc params = '" + addParams + "'", Project.MSG_DEBUG)
|
log("Scaladoc params = '" + addParams + "'", Project.MSG_DEBUG)
|
||||||
|
@ -583,26 +515,11 @@ class Scaladoc extends MatchingTask {
|
||||||
|
|
||||||
/** Performs the compilation. */
|
/** Performs the compilation. */
|
||||||
override def execute() = {
|
override def execute() = {
|
||||||
val Pair(commandSettings, sourceFiles) = initialize
|
val Pair(docSettings, sourceFiles) = initialize
|
||||||
val reporter = new ConsoleReporter(commandSettings)
|
val reporter = new ConsoleReporter(docSettings)
|
||||||
|
|
||||||
// Compiles the actual code
|
|
||||||
val compiler = new Global(commandSettings, reporter) {
|
|
||||||
override protected def computeInternalPhases() {
|
|
||||||
phasesSet += syntaxAnalyzer
|
|
||||||
phasesSet += analyzer.namerFactory
|
|
||||||
phasesSet += analyzer.typerFactory
|
|
||||||
}
|
|
||||||
override def onlyPresentation = true
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
val run = new compiler.Run
|
val docProcessor = new scala.tools.nsc.doc.Processor(reporter, docSettings)
|
||||||
run.compile(sourceFiles.map (_.toString))
|
docProcessor.document(sourceFiles.map (_.toString))
|
||||||
object generator extends DefaultDocDriver {
|
|
||||||
lazy val global: compiler.type = compiler
|
|
||||||
lazy val settings = commandSettings
|
|
||||||
}
|
|
||||||
generator.process(run.units)
|
|
||||||
if (reporter.ERROR.count > 0)
|
if (reporter.ERROR.count > 0)
|
||||||
error(
|
error(
|
||||||
"Document failed with " +
|
"Document failed with " +
|
||||||
|
|
|
@ -9,7 +9,6 @@ package scala.tools.nsc
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
import scala.tools.nsc.doc.DefaultDocDriver
|
|
||||||
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
||||||
import scala.tools.nsc.util.FakePos //{Position}
|
import scala.tools.nsc.util.FakePos //{Position}
|
||||||
|
|
||||||
|
@ -19,78 +18,69 @@ import scala.tools.nsc.util.FakePos //{Position}
|
||||||
*/
|
*/
|
||||||
object ScalaDoc {
|
object ScalaDoc {
|
||||||
|
|
||||||
val versionMsg = "Scala documentation generator " +
|
val versionMsg: String =
|
||||||
|
"Scaladoc " +
|
||||||
Properties.versionString + " -- " +
|
Properties.versionString + " -- " +
|
||||||
Properties.copyrightString
|
Properties.copyrightString
|
||||||
|
|
||||||
var reporter: ConsoleReporter = _
|
var reporter: ConsoleReporter = _
|
||||||
|
|
||||||
def error(msg: String) {
|
def error(msg: String): Unit = {
|
||||||
reporter.error(/*new Position */FakePos("scalac"),
|
reporter.error(FakePos("scalac"), msg + "\n scalac -help gives more information")
|
||||||
msg + "\n scalac -help gives more information")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def process(args: Array[String]) {
|
def process(args: Array[String]): Unit = {
|
||||||
val docSettings : doc.Settings = new doc.Settings(error)
|
|
||||||
|
val docSettings: doc.Settings =
|
||||||
|
new doc.Settings(error)
|
||||||
|
|
||||||
reporter = new ConsoleReporter(docSettings)
|
reporter = new ConsoleReporter(docSettings)
|
||||||
val command = new CompilerCommand(args.toList, docSettings, error, false)
|
|
||||||
if (command.settings.version.value)
|
val command =
|
||||||
reporter.info(null, versionMsg, true)
|
new CompilerCommand(args.toList, docSettings, error, false)
|
||||||
else {
|
|
||||||
if (command.settings.target.value == "msil") {
|
if (!reporter.hasErrors) { // No need to continue if reading the command generated errors
|
||||||
val libpath = System.getProperty("msil.libpath")
|
|
||||||
if (libpath != null)
|
if (docSettings.version.value)
|
||||||
command.settings.assemrefs.value =
|
reporter.info(null, versionMsg, true)
|
||||||
command.settings.assemrefs.value + File.pathSeparator + libpath
|
else if (docSettings.help.value) {
|
||||||
|
reporter.info(null, command.usageMsg, true)
|
||||||
}
|
}
|
||||||
try {
|
else if (docSettings.Xhelp.value)
|
||||||
object compiler extends Global(command.settings, reporter) {
|
reporter.info(null, command.xusageMsg, true)
|
||||||
override protected def computeInternalPhases() {
|
else if (docSettings.Yhelp.value)
|
||||||
phasesSet += syntaxAnalyzer
|
reporter.info(null, command.yusageMsg, true)
|
||||||
phasesSet += analyzer.namerFactory
|
else if (docSettings.showPlugins.value)
|
||||||
phasesSet += analyzer.typerFactory
|
reporter.warning(null, "Plugins are not available when using Scaladoc")
|
||||||
}
|
else if (docSettings.showPhases.value)
|
||||||
override def onlyPresentation = true
|
reporter.warning(null, "Phases are restricted when using Scaladoc")
|
||||||
}
|
else try {
|
||||||
if (reporter.hasErrors) {
|
|
||||||
reporter.flush()
|
if (docSettings.target.value == "msil") {
|
||||||
return
|
val libpath = System.getProperty("msil.libpath")
|
||||||
|
if (libpath != null)
|
||||||
|
docSettings.assemrefs.value = docSettings.assemrefs.value + File.pathSeparator + libpath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.settings.help.value || command.settings.Xhelp.value || command.settings.Yhelp.value) {
|
val docProcessor = new scala.tools.nsc.doc.Processor(reporter, docSettings)
|
||||||
if (command.settings.help.value) {
|
docProcessor.document(command.files)
|
||||||
reporter.info(null, command.usageMsg, true)
|
|
||||||
reporter.info(null, compiler.pluginOptionsHelp, true)
|
}
|
||||||
}
|
catch {
|
||||||
if (command.settings.Xhelp.value)
|
|
||||||
reporter.info(null, command.xusageMsg, true)
|
|
||||||
if (command.settings.Yhelp.value)
|
|
||||||
reporter.info(null, command.yusageMsg, true)
|
|
||||||
} else if (command.settings.showPlugins.value)
|
|
||||||
reporter.info(null, compiler.pluginDescriptions, true)
|
|
||||||
else if (command.settings.showPhases.value)
|
|
||||||
reporter.info(null, compiler.phaseDescriptions, true)
|
|
||||||
else {
|
|
||||||
val run = new compiler.Run()
|
|
||||||
run compile command.files
|
|
||||||
val generator = new DefaultDocDriver {
|
|
||||||
lazy val global: compiler.type = compiler
|
|
||||||
lazy val settings = docSettings
|
|
||||||
}
|
|
||||||
generator.process(run.units)
|
|
||||||
reporter.printSummary()
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
case ex @ FatalError(msg) =>
|
case ex @ FatalError(msg) =>
|
||||||
if (command.settings.debug.value)
|
if (docSettings.debug.value) ex.printStackTrace();
|
||||||
ex.printStackTrace();
|
reporter.error(null, "fatal error: " + msg)
|
||||||
reporter.error(null, "fatal error: " + msg)
|
}
|
||||||
|
finally {
|
||||||
|
reporter.printSummary()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]): Unit = {
|
||||||
process(args)
|
process(args)
|
||||||
exit(if (reporter.hasErrors) 1 else 0)
|
exit(if (reporter.hasErrors) 1 else 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,307 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2007-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import java.util.zip.ZipFile
|
|
||||||
|
|
||||||
import symtab.Flags._
|
|
||||||
import scala.xml._
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
abstract class DefaultDocDriver extends DocDriver with ModelFrames with ModelToXML {
|
|
||||||
import global._
|
|
||||||
import definitions.{AnyClass, AnyRefClass}
|
|
||||||
|
|
||||||
lazy val additions = new mutable.LinkedHashSet[Symbol]
|
|
||||||
lazy val additions0 = new ModelAdditions(global) {
|
|
||||||
override def addition(sym: global.Symbol) = {
|
|
||||||
super.addition(sym)
|
|
||||||
sym match {
|
|
||||||
case sym : global.ClassSymbol => additions += sym.asInstanceOf[Symbol]
|
|
||||||
case sym : global.ModuleSymbol => additions += sym.asInstanceOf[Symbol]
|
|
||||||
case sym : global.TypeSymbol => additions += sym.asInstanceOf[Symbol]
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def init {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add all top-level entities in ModelAdditions to allClasses */
|
|
||||||
def addAdditionsToClasses() {
|
|
||||||
additions0.init
|
|
||||||
for (sym <- additions) {
|
|
||||||
val packSym = sym.enclosingPackage
|
|
||||||
if (packSym != NoSymbol) {
|
|
||||||
val pack = Package(packSym)
|
|
||||||
if (!(allClasses contains pack)) {
|
|
||||||
// don't emit an addition unless its package
|
|
||||||
// is already being scaladoced
|
|
||||||
} else {
|
|
||||||
val addition: Option[ClassOrObject] =
|
|
||||||
if (sym.isClass)
|
|
||||||
Some(new TopLevelClass(sym))
|
|
||||||
else if (sym.isModule)
|
|
||||||
Some(new TopLevelObject(sym))
|
|
||||||
else if (sym == definitions.AnyRefClass) {
|
|
||||||
// AnyRef is the only top-level type alias, so handle
|
|
||||||
// it specially instead of introducing general support for
|
|
||||||
// top-level aliases
|
|
||||||
Some(new TopLevelClass(sym))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
None
|
|
||||||
|
|
||||||
addition match {
|
|
||||||
case None =>
|
|
||||||
//println("skipping: " + sym) //DEBUG
|
|
||||||
case Some(addition) =>
|
|
||||||
allClasses(pack) += addition
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//println("no package found for: "+sym) //DEBUG
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def process(units: Iterator[CompilationUnit]) {
|
|
||||||
|
|
||||||
assert(global.definitions != null)
|
|
||||||
|
|
||||||
def g(pkg: Package, clazz: ClassOrObject) {
|
|
||||||
if (isAccessible(clazz.sym)) {
|
|
||||||
allClasses(pkg) += clazz
|
|
||||||
clazz.decls.map(_._2).foreach {
|
|
||||||
case clazz : ClassOrObject => g(pkg, clazz)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def f(pkg: Package, tree: Tree) {
|
|
||||||
if (tree != EmptyTree && tree.hasSymbol) {
|
|
||||||
val sym = tree.symbol
|
|
||||||
if (sym != NoSymbol && !sym.hasFlag(symtab.Flags.PRIVATE)) tree match {
|
|
||||||
case tree : PackageDef =>
|
|
||||||
val pkg1 = new Package(sym.asInstanceOf[ModuleSymbol])
|
|
||||||
tree.stats.foreach(stat => f(pkg1, stat))
|
|
||||||
case tree : ClassDef =>
|
|
||||||
assert(pkg != null)
|
|
||||||
g(pkg, new TopLevelClass(sym.asInstanceOf[ClassSymbol]))
|
|
||||||
case tree : ModuleDef =>
|
|
||||||
assert(pkg != null)
|
|
||||||
g(pkg, new TopLevelObject(sym.asInstanceOf[ModuleSymbol]))
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
units.foreach(unit => f(null, unit.body))
|
|
||||||
addAdditionsToClasses()
|
|
||||||
|
|
||||||
for (p <- allClasses; d <- p._2) {
|
|
||||||
symbols += d.sym
|
|
||||||
for (pp <- d.sym.tpe.parents) subClasses(pp.typeSymbol) += d
|
|
||||||
}
|
|
||||||
copyResources
|
|
||||||
lazy val packages0 = sort(allClasses.keySet)
|
|
||||||
new AllPackagesFrame with Frame { def packages = packages0 }
|
|
||||||
new PackagesContentFrame with Frame { def packages = packages0 }
|
|
||||||
new NavigationFrame with Frame { }
|
|
||||||
new ListClassFrame with Frame {
|
|
||||||
def classes = for (p <- allClasses; d <- p._2) yield d
|
|
||||||
object organized extends mutable.LinkedHashMap[(List[String],Boolean),List[ClassOrObject]] {
|
|
||||||
override def default(key : (List[String],Boolean)) = Nil;
|
|
||||||
classes.foreach(cls => {
|
|
||||||
val path = cls.path.map(_.name);
|
|
||||||
this((path,cls.isInstanceOf[Clazz])) = cls :: this((path,cls.isInstanceOf[Clazz]));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
def title = "List of all classes and objects"
|
|
||||||
def path = "all-classes"
|
|
||||||
def navLabel = null // "root-page"
|
|
||||||
// override protected def navSuffix = ".html";
|
|
||||||
override def optional(cls: ClassOrObject): NodeSeq = {
|
|
||||||
val path = cls.path.map(_.name)
|
|
||||||
val key = (cls.path.map(_.name), cls.isInstanceOf[Clazz])
|
|
||||||
assert(!organized(key).isEmpty);
|
|
||||||
|
|
||||||
((if (!organized(key).tail.isEmpty) Text(" (" +{
|
|
||||||
//Console.println("CONFLICT: " + path + " " + organized(key));
|
|
||||||
val str = cls.path(0).sym.owner.fullNameString('.');
|
|
||||||
val idx = str.lastIndexOf('.');
|
|
||||||
if (idx == -1) str;
|
|
||||||
else str.substring(idx + 1);
|
|
||||||
}+ ")");
|
|
||||||
else NodeSeq.Empty) ++ super.optional(cls))//(NodeSeq.builderFactory)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for ((pkg0, classes0) <- allClasses) {
|
|
||||||
new ListClassFrame with Frame {
|
|
||||||
def title =
|
|
||||||
"List of classes and objects in package " + pkg0.fullName('.')
|
|
||||||
def classes = classes0
|
|
||||||
def path = pkgPath(pkg0.sym) + NAME_SUFFIX_PACKAGE
|
|
||||||
def navLabel = pkg0.fullName('.')
|
|
||||||
}
|
|
||||||
new PackageContentFrame with Frame {
|
|
||||||
def classes = classes0
|
|
||||||
def pkg = pkg0
|
|
||||||
}
|
|
||||||
for (clazz0 <- classes0) {
|
|
||||||
new ClassContentFrame with Frame {
|
|
||||||
def clazz = clazz0
|
|
||||||
def title =
|
|
||||||
clazz0.kind + " " + clazz0.name + " in " + (clazz0.sym.owner.fullNameString('.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new RootFrame with Frame
|
|
||||||
}
|
|
||||||
override def longList(entity: ClassOrObject, category: Category)(implicit from: Frame) : NodeSeq = category match {
|
|
||||||
case Classes | Objects => NodeSeq.Empty
|
|
||||||
case _ => super.longList(entity, category)
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Frame extends super.Frame {
|
|
||||||
def longHeader(entity : Entity) = DefaultDocDriver.this.longHeader(entity)(this)
|
|
||||||
def shortHeader(entity : Entity) = DefaultDocDriver.this.shortHeader(entity)(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
import DocUtil._
|
|
||||||
override def classBody(entity: ClassOrObject)(implicit from: Frame): NodeSeq =
|
|
||||||
(((subClasses.get(entity.sym) match {
|
|
||||||
case Some(symbols) =>
|
|
||||||
(<dl>
|
|
||||||
<dt style="margin:10px 0 0 20px;"><b>Direct Known Subclasses:</b></dt>
|
|
||||||
<dd>{symbols.mkXML("",", ","")(cls => {
|
|
||||||
aref(urlFor(cls.sym), cls.path.map(_.name).mkString("",".",""));
|
|
||||||
})}</dd>
|
|
||||||
</dl><hr/>);
|
|
||||||
case None =>
|
|
||||||
NodeSeq.Empty
|
|
||||||
}): NodeSeq)++super.classBody(entity))//(NodeSeq.builderFactory)
|
|
||||||
|
|
||||||
protected def urlFor(sym: Symbol)(implicit frame: Frame) = frame.urlFor(sym)
|
|
||||||
|
|
||||||
override protected def decodeTag(tag: String): String = tag match {
|
|
||||||
case "exception" => "Throws"
|
|
||||||
case "ex" => "Examples"
|
|
||||||
case "param" => "Parameters"
|
|
||||||
case "pre" => "Precondition"
|
|
||||||
case "return" => "Returns"
|
|
||||||
case "note" => "Notes"
|
|
||||||
case "see" => "See Also"
|
|
||||||
case tag => super.decodeTag(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
override protected def decodeOption(tag: String, option: String): NodeSeq = tag match {
|
|
||||||
case "throws" if additions0.exceptions.contains(option) =>
|
|
||||||
val (sym, s) = additions0.exceptions(option)
|
|
||||||
val path = "../" //todo: fix path
|
|
||||||
val href = path + sym.fullNameString('/') +
|
|
||||||
(if (sym.isModule || sym.isModuleClass) NAME_SUFFIX_OBJECT else "") +
|
|
||||||
"#" + s
|
|
||||||
(<a href={href}>{option}</a>) ++ {Text(" - ")};
|
|
||||||
case _ =>
|
|
||||||
super.decodeOption(tag,option)
|
|
||||||
}
|
|
||||||
|
|
||||||
object roots extends mutable.LinkedHashMap[String,String];
|
|
||||||
roots("classes") = "http://java.sun.com/j2se/1.5.0/docs/api";
|
|
||||||
roots("rt") = roots("classes");
|
|
||||||
private val SCALA_API_ROOT = "http://www.scala-lang.org/docu/files/api/";
|
|
||||||
roots("scala-library") = SCALA_API_ROOT;
|
|
||||||
|
|
||||||
private def keyFor(file: ZipFile): String = {
|
|
||||||
var name = file.getName
|
|
||||||
var idx = name.lastIndexOf(java.io.File.pathSeparator)
|
|
||||||
if (idx == -1) idx = name.lastIndexOf('/')
|
|
||||||
if (idx != -1) name = name.substring(idx + 1)
|
|
||||||
if (name endsWith ".jar") name.substring(0, name.length - (".jar").length)
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
|
|
||||||
// <code>{Text(string + " - ")}</code>;
|
|
||||||
override def hasLink0(sym: Symbol): Boolean = {
|
|
||||||
if (sym == NoSymbol) return false;
|
|
||||||
if (sym == AnyRefClass) {
|
|
||||||
// AnyRefClass is a type alias, so the following logic
|
|
||||||
// does not work. AnyClass should have a link in
|
|
||||||
// the same cases as AnyRefClass, so test it instead.
|
|
||||||
return hasLink(AnyClass)
|
|
||||||
}
|
|
||||||
if (super.hasLink0(sym) && symbols.contains(sym))
|
|
||||||
return true;
|
|
||||||
if (SyntheticClasses contains sym)
|
|
||||||
return true;
|
|
||||||
if (sym.toplevelClass == NoSymbol) return false;
|
|
||||||
val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol];
|
|
||||||
import scala.tools.nsc.io._;
|
|
||||||
clazz.classFile match {
|
|
||||||
case file : ZipArchive#FileEntry =>
|
|
||||||
val key = keyFor(file.archive);
|
|
||||||
if (key != null && roots.contains(key)) return true;
|
|
||||||
case null =>
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
def aref(href: String, label: String)(implicit frame: Frame) =
|
|
||||||
frame.aref(href, "_self", label)
|
|
||||||
|
|
||||||
protected def anchor(entity: Symbol)(implicit frame: Frame): NodeSeq =
|
|
||||||
(<a name={Text(frame.docName(entity))}></a>)
|
|
||||||
|
|
||||||
object symbols extends mutable.LinkedHashSet[Symbol]
|
|
||||||
|
|
||||||
object allClasses extends mutable.LinkedHashMap[Package, mutable.LinkedHashSet[ClassOrObject]] {
|
|
||||||
override def default(pkg: Package): mutable.LinkedHashSet[ClassOrObject] = {
|
|
||||||
object ret extends mutable.LinkedHashSet[ClassOrObject]
|
|
||||||
this(pkg) = ret
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object subClasses extends mutable.LinkedHashMap[Symbol, mutable.LinkedHashSet[ClassOrObject]] {
|
|
||||||
override def default(key: Symbol) = {
|
|
||||||
val ret = new mutable.LinkedHashSet[ClassOrObject]
|
|
||||||
this(key) = ret
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def rootFor(sym: Symbol): String = {
|
|
||||||
assert(sym != NoSymbol)
|
|
||||||
if (sym == definitions.AnyRefClass) {
|
|
||||||
// AnyRefClass is a type alias, so the following logic
|
|
||||||
// does not work. AnyClass should have the same root,
|
|
||||||
// so use it instead.
|
|
||||||
return rootFor(definitions.AnyClass)
|
|
||||||
}
|
|
||||||
if (sym.toplevelClass == NoSymbol) return super.rootFor(sym)
|
|
||||||
if (symbols.contains(sym.toplevelClass)) return super.rootFor(sym)
|
|
||||||
if (SyntheticClasses contains sym)
|
|
||||||
return SCALA_API_ROOT
|
|
||||||
val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol]
|
|
||||||
import scala.tools.nsc.io._;
|
|
||||||
clazz.classFile match {
|
|
||||||
case file : ZipArchive#FileEntry =>
|
|
||||||
val key = keyFor(file.archive)
|
|
||||||
if (key != null && roots.contains(key)) {
|
|
||||||
return roots(key) + '/'
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
super.rootFor(sym)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2007-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an abstract class for documentation plugins.
|
|
||||||
*
|
|
||||||
* @author Geoffrey Washburn
|
|
||||||
*/
|
|
||||||
abstract class DocDriver {
|
|
||||||
val global: Global
|
|
||||||
import global._
|
|
||||||
def settings: doc.Settings
|
|
||||||
|
|
||||||
def process(units: Iterator[CompilationUnit]): Unit
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2005-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
import java.io.StringReader
|
|
||||||
import org.xml.sax.InputSource
|
|
||||||
|
|
||||||
import scala.collection.immutable.{ListMap, TreeSet}
|
|
||||||
import scala.xml._
|
|
||||||
|
|
||||||
object DocUtil
|
|
||||||
{
|
|
||||||
def load(str: String): NodeSeq =
|
|
||||||
if ((str == null) || (str.length == 0))
|
|
||||||
NodeSeq.Empty
|
|
||||||
else {
|
|
||||||
val xmlSrc =
|
|
||||||
if (str.matches("^(<!--.*-->)*<[^>]+>.*<[^>]+>(<!--.*-->)*$")) str
|
|
||||||
else "<div>" + str + "</div>"
|
|
||||||
XML.load(new StringReader(xmlSrc))
|
|
||||||
}
|
|
||||||
|
|
||||||
def br(nodes: NodeSeq): NodeSeq = nodes ++ (<br/>)
|
|
||||||
def hr(nodes: NodeSeq): NodeSeq = nodes ++ (<hr/>)
|
|
||||||
|
|
||||||
trait UrlContext {
|
|
||||||
def relative: String
|
|
||||||
|
|
||||||
def aref(href0: String, target: String, text: String): NodeSeq = {
|
|
||||||
if (href0 == null) return Text(text);
|
|
||||||
|
|
||||||
val href = {
|
|
||||||
if (href0.startsWith("http:") || href0.startsWith("file:")) "";
|
|
||||||
else relative
|
|
||||||
} + Utility.escape(href0)
|
|
||||||
if ((target ne null) && target.indexOf('<') != -1) throw new Error(target)
|
|
||||||
|
|
||||||
val t0 = Text(text)
|
|
||||||
if (target ne null)
|
|
||||||
(<a href={href} target={target}>{t0}</a>);
|
|
||||||
else
|
|
||||||
(<a href={href}>{t0}</a>);
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't use platform default here or the generated XML may end up all MacRoman
|
|
||||||
val encoding = Properties.sourceEncoding
|
|
||||||
val generator = System.getProperty("doc.generator", "scaladoc (" + Properties.versionString + ")")
|
|
||||||
val header =
|
|
||||||
(<meta http-equiv="content-type" content={"text/html; charset=" + encoding}/>
|
|
||||||
<meta name="generator" content={generator}/>
|
|
||||||
<link rel="stylesheet" type="text/css" href={ relative + "style.css"}/>
|
|
||||||
<script type="text/javascript" src={relative + "script.js"}></script>);
|
|
||||||
|
|
||||||
def body0(hasBody: Boolean, nodes: NodeSeq): NodeSeq =
|
|
||||||
if (!hasBody) nodes else (<body onload="init()">{nodes}</body>);
|
|
||||||
|
|
||||||
val dtype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
|
|
||||||
|
|
||||||
def page(title: String, body: NodeSeq, hasBody: Boolean): NodeSeq =
|
|
||||||
(<html>
|
|
||||||
<head><title>{Text(if (title eq null) "null title" else title)}</title>
|
|
||||||
{header}
|
|
||||||
</head>
|
|
||||||
{body0(hasBody, body)}
|
|
||||||
</html>)
|
|
||||||
} // UrlContext
|
|
||||||
|
|
||||||
def div0(title: String): NodeSeq =
|
|
||||||
(<div class="doctitle-larger">{Text(title)}</div>);
|
|
||||||
|
|
||||||
def merge[T](ts0: TreeSet[T], ts1: TreeSet[T]): TreeSet[T] = ts0 ++ ts1
|
|
||||||
|
|
||||||
def merge[T,S](ts0: ListMap[T,TreeSet[S]], ts1: ListMap[T,TreeSet[S]]): ListMap[T,TreeSet[S]] = {
|
|
||||||
(ts1 foldLeft ts0) { case (xs, (k, v)) =>
|
|
||||||
if (xs contains k) xs.updated(k, xs(k) ++ v)
|
|
||||||
else xs.updated(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implicit def coerceIterable[T](list : Iterable[T]) = NodeWrapper(list.iterator)
|
|
||||||
implicit def coerceIterator[T](list : Iterator[T]) = NodeWrapper(list)
|
|
||||||
|
|
||||||
case class NodeWrapper[T](list: Iterator[T]) {
|
|
||||||
def interleave(xs: Seq[NodeSeq], sep: NodeSeq): NodeSeq =
|
|
||||||
if (xs.isEmpty) NodeSeq.Empty
|
|
||||||
else if (xs.size == 1) xs.head
|
|
||||||
else xs.head ++ sep ++ interleave(xs.tail, sep)
|
|
||||||
|
|
||||||
def mkXML(begin: NodeSeq, separator: NodeSeq, end: NodeSeq)(f: T => NodeSeq): NodeSeq =
|
|
||||||
begin ++ interleave(list.toSeq map f, separator) ++ end
|
|
||||||
|
|
||||||
def mkXML(begin: String, separator: String, end: String)(f: T => NodeSeq): NodeSeq =
|
|
||||||
this.mkXML(Text(begin), Text(separator), Text(end))(f)
|
|
||||||
|
|
||||||
def surround(open: String, close: String)(f: T => NodeSeq) =
|
|
||||||
if (list.hasNext) mkXML(open, ", ", close)(f)
|
|
||||||
else NodeSeq.Empty
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,412 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2007-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Stephane Micheloud, Sean McDirmid, Geoffrey Washburn
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
class ModelAdditions(val global: Global) {
|
|
||||||
import global._
|
|
||||||
import definitions._
|
|
||||||
def addition(sym: global.Symbol) {}
|
|
||||||
|
|
||||||
addition(NothingClass);
|
|
||||||
comments(NothingClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>Nothing</code> is - together with class <a href="Null.html">
|
|
||||||
<code>Null</code></a> - at the bottom of the
|
|
||||||
<a href="http://scala-lang.org" target="_top">Scala</a> type
|
|
||||||
hierarchy.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Type <code>Nothing</code> is a subtype of every other type
|
|
||||||
(including <a href="Null.html"><code>Null</code></a>); there
|
|
||||||
exist <em>no instances</em> of this type. Even though type
|
|
||||||
<code>Nothing</code> is empty, it is nevertheless useful as a
|
|
||||||
type parameter. For instance, the <a href="http://scala-lang.org"
|
|
||||||
target="_top">Scala</a> library defines a value
|
|
||||||
<a href="Nil$object.html"><code>Nil</code></a> of type
|
|
||||||
<code><a href="List.html">List</a>[Nothing]</code>. Because lists
|
|
||||||
are covariant in <a href="http://scala-lang.org" target="_top">Scala</a>,
|
|
||||||
this makes <a href="Nil$object.html"><code>Nil</code></a> an
|
|
||||||
instance of <code><a href="List.html">List</a>[T]</code>, for
|
|
||||||
any element type <code>T</code>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
addition(NullClass);
|
|
||||||
comments(NullClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>Null</code> is - together with class <a href="Nothing.html">
|
|
||||||
<code>Nothing</code> - at the bottom of the
|
|
||||||
<a href="http://scala-lang.org" target="_top">Scala</a> type
|
|
||||||
hierarchy.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Type <code>Null</code> is a subtype of all reference types; its
|
|
||||||
only instance is the <code>null</code> reference.
|
|
||||||
Since <code>Null</code> is not a subtype of value types,
|
|
||||||
<code>null</code> is not a member of any such type. For instance,
|
|
||||||
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 */
|
|
||||||
|
|
||||||
addition(AnyClass);
|
|
||||||
comments(AnyClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>Any</code> is the root of the <a
|
|
||||||
href="http://scala-lang.org/"
|
|
||||||
target="_top">Scala</a> class hierarchy. Every class in a
|
|
||||||
<a href="http://scala-lang.org/" target="_top">Scala</a> execution
|
|
||||||
environment inherits directly or indirectly from this class.
|
|
||||||
Class <code>Any</code> has two direct subclasses:
|
|
||||||
<a href="AnyRef.html"><code>AnyRef</code></a> and
|
|
||||||
<a href="AnyVal.html"><code>AnyVal</code></a>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
addition(Any_equals);
|
|
||||||
comments(Any_equals) = """
|
|
||||||
This method is used to compare the receiver object (<code>this</code>)
|
|
||||||
with the argument object (<code>arg0</code>) for equivalence.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The default implementations of this method is an <a
|
|
||||||
href="http://en.wikipedia.org/wiki/Equivalence_relation">equivalence
|
|
||||||
relation</a>:
|
|
||||||
<ul>
|
|
||||||
<li>It is reflexive: for any instance <code>x</code> of type <code>Any</code>,
|
|
||||||
<code>x.equals(x)</code> should return <code>true</code>.</li>
|
|
||||||
<li>It is symmetric: for any instances <code>x</code> and <code>y</code> of type
|
|
||||||
<code>Any</code>, <code>x.equals(y)</code> should return <code>true</code> if and only
|
|
||||||
if <code>y.equals(x)</code> returns <code>true</code>.</li>
|
|
||||||
<li>It is transitive: for any instances
|
|
||||||
<code>x</code>, <code>y</code>, and <code>z</code> of type <code>AnyRef</code>
|
|
||||||
if <code>x.equals(y)</code> returns <code>true</code> and
|
|
||||||
<code>y.equals(z)</code> returns
|
|
||||||
<code>true</code>, then <code>x.equals(z)</code> should return <code>true</code>.</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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 <code>hashCode</code> to ensure that objects that are
|
|
||||||
"equal" (<code>o1.equals(o2)</code> returns <code>true</code>)
|
|
||||||
hash to the same <a href="Int.html"><code>Int</code></a>
|
|
||||||
(<code>o1.hashCode.equals(o2.hashCode)</code>).
|
|
||||||
|
|
||||||
@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>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Any_==);
|
|
||||||
comments(Any_==) = """
|
|
||||||
<code>o == arg0</code> is the same as <code>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>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Any_!=);
|
|
||||||
comments(Any_!=) = """
|
|
||||||
<code>o != arg0</code> is the same as <code>!(o == (arg0))</code>.
|
|
||||||
<p>
|
|
||||||
@param arg0 the object to compare against this object for dis-equality.
|
|
||||||
@return <code>false</code> if the receiver object is equivalent to the argument; <code>true</code> otherwise.
|
|
||||||
</p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Any_toString);
|
|
||||||
comments(Any_toString) = """
|
|
||||||
Returns a string representation of the object.
|
|
||||||
<p>
|
|
||||||
The default representation is platform dependent.
|
|
||||||
|
|
||||||
@return a string representation of the object.
|
|
||||||
</p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Any_asInstanceOf);
|
|
||||||
comments(Any_asInstanceOf) = """
|
|
||||||
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
|
|
||||||
erasure semantics. Therefore the expression
|
|
||||||
<code>1.asInstanceOf[String]</code> will throw a
|
|
||||||
<code>ClassCastException</code> at runtime, while the expression
|
|
||||||
<code>List(1).asInstanceOf[List[String]]</code> 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 <code>T0</code>.
|
|
||||||
@return the receiver object.
|
|
||||||
</p> """
|
|
||||||
|
|
||||||
addition(Any_isInstanceOf);
|
|
||||||
comments(Any_isInstanceOf) = """
|
|
||||||
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
|
|
||||||
semantics. Therefore the expression
|
|
||||||
<code>1.isInstanceOf[String]</code> will return
|
|
||||||
<code>false</code>, while the expression
|
|
||||||
<code>List(1).isInstanceOf[List[String]]</code> will return
|
|
||||||
<code>true</code>. 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 <code>true</code> if the receiver object is an
|
|
||||||
instance of erasure of type <code>T0</code>; <code>false</code> otherwise.
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Any_hashCode);
|
|
||||||
comments(Any_hashCode) = """
|
|
||||||
Returns a hash code value for the object.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The default hashing algorithm is platform dependent.
|
|
||||||
|
|
||||||
Note that it is allowed for two objects to have identical hash
|
|
||||||
codes (<code>o1.hashCode.equals(o2.hashCode)</code>) yet not be
|
|
||||||
equal (<code>o1.equals(o2)</code> returns <code>false</code>). A
|
|
||||||
degenerate implementation could always return <code>0</code>.
|
|
||||||
However, it is required that if two objects are equal
|
|
||||||
(<code>o1.equals(o2)</code> returns <code>true</code>) that they
|
|
||||||
have identical hash codes
|
|
||||||
(<code>o1.hashCode.equals(o2.hashCode)</code>). Therefore, when
|
|
||||||
overriding this method, be sure to verify that the behavior is
|
|
||||||
consistent with the <code>equals</code> method.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
@return the hash code value for the object.
|
|
||||||
</p> """
|
|
||||||
|
|
||||||
/*******************************************************************/
|
|
||||||
/* Documentation for AnyRef */
|
|
||||||
|
|
||||||
addition(AnyRefClass);
|
|
||||||
comments(AnyRefClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>AnyRef</code> is the root class of all
|
|
||||||
<em>reference types</em>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
addition(Object_==);
|
|
||||||
comments(Object_==) = """
|
|
||||||
<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>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_ne);
|
|
||||||
comments(Object_ne) = """
|
|
||||||
<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>
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
addition(Object_finalize);
|
|
||||||
comments(Object_finalize) = """
|
|
||||||
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>
|
|
||||||
The details of when and if the <code>finalize</code> method are
|
|
||||||
invoked, as well as the interaction between <code>finalize</code>
|
|
||||||
and non-local returns and exceptions, are all platform dependent.
|
|
||||||
</p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_clone);
|
|
||||||
comments(Object_clone) = """
|
|
||||||
This method creates and returns a copy of the receiver object.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The default implementation of the <code>clone</code> method is platform dependent.
|
|
||||||
|
|
||||||
@return a copy of the receiver object.
|
|
||||||
</p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_getClass);
|
|
||||||
comments(Object_getClass) = """
|
|
||||||
Returns a representation that corresponds to the dynamic class of the receiver object.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The nature of the representation is platform dependent.
|
|
||||||
|
|
||||||
@return a representation that corresponds to the dynamic class of the receiver object.
|
|
||||||
</p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_notify);
|
|
||||||
comments(Object_notify) = """
|
|
||||||
Wakes up a single thread that is waiting on the receiver object's monitor.
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_notifyAll);
|
|
||||||
comments(Object_notifyAll) = """
|
|
||||||
Wakes up all threads that are waiting on the receiver object's monitor.
|
|
||||||
"""
|
|
||||||
|
|
||||||
addition(Object_eq);
|
|
||||||
comments(Object_eq) = """
|
|
||||||
This method is used to test whether the argument (<code>arg0</code>) is a reference to the
|
|
||||||
receiver object (<code>this</code>).
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The <code>eq</code> method implements an
|
|
||||||
<a href="http://en.wikipedia.org/wiki/Equivalence_relation">equivalence relation</a> on non-null instances of
|
|
||||||
<code>AnyRef</code>:
|
|
||||||
<ul>
|
|
||||||
<li>It is reflexive: for any non-null instance <code>x</code> of type <code>AnyRef</code>,
|
|
||||||
<code>x.eq(x)</code> returns <code>true</code>.</li>
|
|
||||||
<li>It is symmetric: for any non-null instances <code>x</code> and <code>y</code> of type
|
|
||||||
<code>AnyRef</code>, <code>x.eq(y)</code> returns <code>true</code> if and only
|
|
||||||
if <code>y.eq(x)</code> returns <code>true</code>.</li>
|
|
||||||
<li>It is transitive: for any non-null instances
|
|
||||||
<code>x</code>, <code>y</code>, and <code>z</code> of type <code>AnyRef</code>
|
|
||||||
if <code>x.eq(y)</code> returns <code>true</code> and
|
|
||||||
<code>y.eq(z)</code> returns
|
|
||||||
<code>true</code>, then <code>x.eq(z)</code> returns <code>true</code>.</li>
|
|
||||||
</ul>
|
|
||||||
Additionally, the <code>eq</code> method has three other properties.
|
|
||||||
<ul>
|
|
||||||
<li>It is consistent: for any non-null instances <code>x</code> and <code>y</code> of type <code>AnyRef</code>,
|
|
||||||
multiple invocations of <code>x.eq(y)</code> consistently returns <code>true</code>
|
|
||||||
or consistently returns <code>false</code>.</li>
|
|
||||||
<li>For any non-null instance <code>x</code> of type <code>AnyRef</code>,
|
|
||||||
<code>x.eq(null)</code> and <code>null.eq(x)</code> returns <code>false</code>.</li>
|
|
||||||
<li><code>null.eq(null)</code> returns <code>true</code>.</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> When overriding the <code>equals</code> or
|
|
||||||
<code>hashCode</code> methods, it is important to ensure that
|
|
||||||
their behavior is consistent with reference equality. Therefore,
|
|
||||||
if two objects are references to each other (<code>o1 eq
|
|
||||||
o2</code>), they should be equal to each other (<code>o1 ==
|
|
||||||
o2</code>) and they should hash to the same value
|
|
||||||
(<code>o1.hashCode == o2.hashCode</code>).</p>
|
|
||||||
|
|
||||||
@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>
|
|
||||||
"""
|
|
||||||
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
addition(AnyValClass);
|
|
||||||
comments(AnyValClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>AnyVal</code> is the root class of all
|
|
||||||
<em>value types</em>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<code>AnyVal</code> has a fixed number subclasses, which
|
|
||||||
describe values which are not implemented as objects in the
|
|
||||||
underlying host system.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Classes <a href="Double.html"><code>Double</code></a>,
|
|
||||||
<a href="Float.html"><code>Float</code></a>,
|
|
||||||
<a href="Long.html"><code>Long</code></a>,
|
|
||||||
<a href="Int.html"><code>Int</code></a>,
|
|
||||||
<a href="Char.html"><code>Char</code></a>,
|
|
||||||
<a href="Short.html"><code>Short</code></a>, and
|
|
||||||
<a href="Byte.html"><code>Byte</code></a> are together called
|
|
||||||
<em>numeric value types</em>.
|
|
||||||
Classes <a href="Byte.html"><code>Byte</code></a>,
|
|
||||||
<a href="Short.html"><code>Short</code></a>, or
|
|
||||||
<a href="Char.html"><code>Char</code></a>
|
|
||||||
are called <em>subrange types</em>. Subrange types, as well as
|
|
||||||
<a href="Int.html"><code>Int</code></a> and
|
|
||||||
<a href="Long.html"><code>Long</code></a> are called
|
|
||||||
<em>integer types</em>, whereas
|
|
||||||
<a href="Float.html"><code>Float</code></a> and
|
|
||||||
<a href="Double.html"><code>Double</code></a> are called
|
|
||||||
<em>floating point types</em>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
addition(BooleanClass)
|
|
||||||
comments(BooleanClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>Boolean</code> has only two values: <code>true</code>
|
|
||||||
and <code>false</code>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
def numericValDescr(sym: Symbol) = {
|
|
||||||
val maxValue = "MAX_" + sym.name.toString().toUpperCase()
|
|
||||||
val minValue = "MIN_" + sym.name.toString().toUpperCase()
|
|
||||||
addition(sym)
|
|
||||||
comments(sym) = """
|
|
||||||
<p>
|
|
||||||
Class <code>""" + sym.name + """</code> belongs to the value
|
|
||||||
classes whose instances are not represented as objects by the
|
|
||||||
underlying host system. There is an implicit conversion from
|
|
||||||
instances of <code>""" + sym.name + """</code> to instances of
|
|
||||||
<a href="runtime/Rich""" + sym.name + """.html"><code>runtime.Rich""" + sym.name + """</code></a> which
|
|
||||||
provides useful non-primitive operations. All value classes inherit
|
|
||||||
from class <a href="AnyVal.html"><code>AnyVal</code></a>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Values <code>""" + maxValue + """</code> and <code>""" + minValue + """</code>
|
|
||||||
are in defined in object <a href="Math$object.html">scala.Math</a>.
|
|
||||||
</p>"""
|
|
||||||
}
|
|
||||||
(ByteClass :: CharClass :: DoubleClass :: LongClass ::
|
|
||||||
FloatClass :: IntClass :: ShortClass :: Nil).foreach(numericValDescr);
|
|
||||||
|
|
||||||
addition(UnitClass);
|
|
||||||
comments(UnitClass) = """
|
|
||||||
<p>
|
|
||||||
Class <code>Unit</code> has only one value: <code>()</code>.
|
|
||||||
</p>"""
|
|
||||||
|
|
||||||
addition(UnitClass);
|
|
||||||
/*
|
|
||||||
def boxedValDescr(what: String) = {
|
|
||||||
val sym = definitions.getClass("java.lang." + what)
|
|
||||||
addition(sym)
|
|
||||||
comments(sym) = """
|
|
||||||
<p>
|
|
||||||
Class <code>""" + sym.name + """</code> implements the
|
|
||||||
boxing/unboxing from/to value types.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Boxing and unboxing enable value types to be treated as objects;
|
|
||||||
they provide a unified view of the type system wherein a value
|
|
||||||
of any type can ultimately be treated as an object.
|
|
||||||
</p>"""
|
|
||||||
};
|
|
||||||
//("Float" :: "Long" :: "Number" :: "Integer" :: Nil).foreach(boxedValDescr);
|
|
||||||
*/
|
|
||||||
object exceptions extends collection.JavaConversions.JMapWrapper[String,(Symbol,String)](
|
|
||||||
new java.util.TreeMap()) {
|
|
||||||
def f(name: String) {
|
|
||||||
this("Predef." + name) = (definitions.PredefModule, name)
|
|
||||||
}
|
|
||||||
f("IndexOutOfBoundsException")
|
|
||||||
f("NoSuchElementException")
|
|
||||||
f("NullPointerException")
|
|
||||||
f("UnsupportedOperationException")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,453 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2007-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import compat.Platform.{EOL => LINE_SEPARATOR}
|
|
||||||
|
|
||||||
|
|
||||||
/** This class attempts to reverse engineer source code intent from compiler
|
|
||||||
* symbol objects.
|
|
||||||
*
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
trait ModelExtractor {
|
|
||||||
val global: Global
|
|
||||||
import global._
|
|
||||||
def settings: doc.Settings
|
|
||||||
|
|
||||||
def assert(b: Boolean) {
|
|
||||||
if (!b) throw new Error
|
|
||||||
}
|
|
||||||
|
|
||||||
def assert(b: Boolean, message: Any) {
|
|
||||||
if (!b) throw new Error(message.toString)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class Tag(tag: String, option: String, body: String)
|
|
||||||
|
|
||||||
case class Comment(body: String, attributes: List[Tag]) {
|
|
||||||
def decodeAttributes = {
|
|
||||||
val map = new mutable.LinkedHashMap[String, List[(String, String)]] {
|
|
||||||
override def default(key: String) = Nil
|
|
||||||
}
|
|
||||||
attributes.foreach(a => {
|
|
||||||
map(a.tag) = map(a.tag) ::: List((a.option, a.body))
|
|
||||||
});
|
|
||||||
map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected def decode(sym: Symbol) =
|
|
||||||
if (sym == definitions.ScalaObjectClass || sym == definitions.ObjectClass)
|
|
||||||
definitions.AnyRefClass
|
|
||||||
else sym match {
|
|
||||||
case sym: ModuleClassSymbol => sym.sourceModule
|
|
||||||
case sym => sym
|
|
||||||
}
|
|
||||||
|
|
||||||
protected def decodeComment(comment0: String): Comment = {
|
|
||||||
val comment = { // discard outmost comment delimiters if present
|
|
||||||
val begin = if (comment0 startsWith "/**") 3 else 0
|
|
||||||
val end = comment0.length - (if (comment0 endsWith "*/") 2 else 0)
|
|
||||||
comment0.substring(begin, end)
|
|
||||||
}
|
|
||||||
val tok = new java.util.StringTokenizer(comment, LINE_SEPARATOR)
|
|
||||||
val buf = new StringBuilder
|
|
||||||
type AttrDescr = (String, String, StringBuilder)
|
|
||||||
val attributes = new collection.mutable.ListBuffer[AttrDescr]
|
|
||||||
var attr: AttrDescr = null
|
|
||||||
while (tok.hasMoreTokens) {
|
|
||||||
val s = tok.nextToken.replaceFirst("\\p{Space}?\\*", "")
|
|
||||||
val mat1 = pat1.matcher(s)
|
|
||||||
if (mat1.matches) {
|
|
||||||
attr = (mat1.group(1), null, new StringBuilder(mat1.group(2)))
|
|
||||||
//if (kind != CONSTRUCTOR)
|
|
||||||
attributes += attr
|
|
||||||
} else {
|
|
||||||
val mat2 = pat2.matcher(s)
|
|
||||||
if (mat2.matches) {
|
|
||||||
attr = (mat2.group(1), mat2.group(2), new StringBuilder(mat2.group(3)))
|
|
||||||
//if (kind != CLASS)
|
|
||||||
attributes += attr
|
|
||||||
} else if (attr ne null)
|
|
||||||
attr._3.append(s + LINE_SEPARATOR)
|
|
||||||
else
|
|
||||||
buf.append(s + LINE_SEPARATOR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Comment(buf.toString, attributes.toList.map({x => Tag(x._1,x._2,x._3.toString)}))
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed abstract class Entity(val sym: Symbol) {
|
|
||||||
private[ModelExtractor] def sym0 = sym
|
|
||||||
|
|
||||||
override def toString = sym.toString
|
|
||||||
def comment: Option[String] = global.comments.get(sym)
|
|
||||||
// comments decoded, now what?
|
|
||||||
def attributes = sym.annotations
|
|
||||||
def decodeComment: Option[Comment] = {
|
|
||||||
val comment0 = this.comment
|
|
||||||
if (comment0.isEmpty) None
|
|
||||||
else Some(ModelExtractor.this.decodeComment(comment0.get.trim))
|
|
||||||
}
|
|
||||||
protected def accessQualified(core: String, qual: String) = core match {
|
|
||||||
case "public" => "" // assert(qual == null); "";
|
|
||||||
case core => core + (if (qual == null) "" else "[" + qual + "]")
|
|
||||||
}
|
|
||||||
|
|
||||||
def flagsString = {
|
|
||||||
import symtab.Flags
|
|
||||||
//val isLocal = sym.hasFlag(Flags.LOCAL)
|
|
||||||
val x =
|
|
||||||
if (sym hasFlag Flags.PRIVATE) "private"
|
|
||||||
else if (sym hasFlag Flags.PROTECTED) "protected"
|
|
||||||
else "public"
|
|
||||||
var string = accessQualified(x,
|
|
||||||
if (sym hasFlag Flags.LOCAL) "this"
|
|
||||||
else if (sym.privateWithin != null && sym.privateWithin != NoSymbol)
|
|
||||||
sym.privateWithin.nameString
|
|
||||||
else null
|
|
||||||
)
|
|
||||||
def f(flag: Int, str: String) {
|
|
||||||
if (sym hasFlag flag) string = string + " " + str
|
|
||||||
}
|
|
||||||
f(Flags.IMPLICIT, "implicit")
|
|
||||||
f(Flags.SEALED, "sealed")
|
|
||||||
f(Flags.OVERRIDE, "override")
|
|
||||||
f(Flags.CASE, "case")
|
|
||||||
if (!sym.isTrait) f(Flags.ABSTRACT, "abstract")
|
|
||||||
if (!sym.isModule) f(Flags.FINAL, "final")
|
|
||||||
if (!sym.isTrait) f(Flags.DEFERRED, "abstract")
|
|
||||||
string.trim
|
|
||||||
}
|
|
||||||
def listName = name
|
|
||||||
def name = sym.nameString
|
|
||||||
def fullName(sep: Char) = sym.fullNameString(sep)
|
|
||||||
def kind: String
|
|
||||||
def header { }
|
|
||||||
def typeParams: List[TypeParam] = Nil
|
|
||||||
def valueParams: List[List[ValueParam]] = Nil
|
|
||||||
def resultType: Option[Type] = None
|
|
||||||
def parents: Iterable[Type] = Nil
|
|
||||||
def lo: Option[Type] = sym.info match {
|
|
||||||
case TypeBounds(lo, hi) if decode(lo.typeSymbol) != definitions.NothingClass => Some(lo)
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
def hi: Option[Type] = sym.info match {
|
|
||||||
case TypeBounds(lo, hi) if decode(hi.typeSymbol) != definitions.AnyClass => Some(hi)
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
def variance = {
|
|
||||||
import symtab.Flags._
|
|
||||||
if (sym hasFlag COVARIANT) "+"
|
|
||||||
else if (sym hasFlag CONTRAVARIANT) "-"
|
|
||||||
else ""
|
|
||||||
}
|
|
||||||
def overridden: Iterable[Symbol] = Nil
|
|
||||||
}
|
|
||||||
|
|
||||||
class ValueParam(sym: Symbol) extends Entity(sym) {
|
|
||||||
override def resultType = Some(sym.tpe)
|
|
||||||
//def kind = if (sym.isPublic) "val" else "";
|
|
||||||
def kind = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConstructorParam(sym: Symbol) extends ValueParam(sym) {
|
|
||||||
override protected def accessQualified(core: String, qual: String) = core match {
|
|
||||||
case "public" => "val"
|
|
||||||
case "protected" => super.accessQualified(core,qual) + " val"
|
|
||||||
case "private" if qual == "this" => ""
|
|
||||||
case core => super.accessQualified(core, qual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def ValueParam(sym: Symbol) = new ValueParam(sym)
|
|
||||||
class TypeParam(sym: Symbol) extends Entity(sym) {
|
|
||||||
def kind = ""
|
|
||||||
}
|
|
||||||
def TypeParam(sym: Symbol) = new TypeParam(sym)
|
|
||||||
|
|
||||||
trait Clazz extends ClassOrObject {
|
|
||||||
private def csym = sym.asInstanceOf[TypeSymbol]
|
|
||||||
override def typeParams = csym.typeParams.map(TypeParam)
|
|
||||||
override def valueParams = {
|
|
||||||
if (constructorArgs.isEmpty) Nil
|
|
||||||
else constructorArgs.valuesIterator.toList :: Nil
|
|
||||||
}
|
|
||||||
def isTrait = csym.isTrait
|
|
||||||
override def kind = if (sym.isTrait) "trait" else "class"
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Object extends ClassOrObject {
|
|
||||||
override def kind = "object"
|
|
||||||
}
|
|
||||||
|
|
||||||
case class Package(override val sym: Symbol) extends Entity(sym) {
|
|
||||||
override def kind = "package"
|
|
||||||
override def name = fullName('.')
|
|
||||||
}
|
|
||||||
|
|
||||||
trait TopLevel extends ClassOrObject
|
|
||||||
class TopLevelClass (sym: Symbol) extends Entity(sym) with TopLevel with Clazz
|
|
||||||
class TopLevelObject(sym: Symbol) extends Entity(sym) with TopLevel with Object {
|
|
||||||
override def attributes = sym.moduleClass.annotations
|
|
||||||
}
|
|
||||||
|
|
||||||
def compare(pathA: List[ClassOrObject], pathB: List[ClassOrObject]): Int = {
|
|
||||||
var pA = pathA
|
|
||||||
var pB = pathB
|
|
||||||
while (true) {
|
|
||||||
if (pA.isEmpty) return -1
|
|
||||||
if (pB.isEmpty) return +1
|
|
||||||
val diff = pA.head.name compare pB.head.name
|
|
||||||
if (diff != 0) return diff
|
|
||||||
pA = pA.tail
|
|
||||||
pB = pB.tail
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
def isAccessible(sym: Symbol): Boolean = {
|
|
||||||
import symtab.Flags._
|
|
||||||
settings.memberaccess.value match {
|
|
||||||
case "private" => sym.isPublic || (sym hasFlag PROTECTED) || (sym hasFlag PRIVATE)
|
|
||||||
case "protected" => sym.isPublic || (sym hasFlag PROTECTED)
|
|
||||||
case "public" => sym.isPublic
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait ClassOrObject extends Entity {
|
|
||||||
def path: List[ClassOrObject] = this :: Nil
|
|
||||||
override def listName = path map (_.name) mkString "."
|
|
||||||
|
|
||||||
object freshParents extends mutable.LinkedHashSet[Type] {
|
|
||||||
this ++= sym.tpe.parents
|
|
||||||
this.toList foreach (this --= _.parents)
|
|
||||||
}
|
|
||||||
object constructorArgs extends mutable.LinkedHashMap[Symbol, ValueParam] {
|
|
||||||
import symtab.Flags._
|
|
||||||
sym.constrParamAccessors.filter(arg => ! (arg hasFlag SYNTHETIC)).foreach(arg => {
|
|
||||||
val str = flagsToString(arg.flags)
|
|
||||||
assert((arg hasFlag PRIVATE) && (arg hasFlag LOCAL), arg)
|
|
||||||
val argName = arg.name.toString.trim
|
|
||||||
val actual = sym.tpe.decls.iterator.find(e => {
|
|
||||||
val eName = e.name.toString.trim;
|
|
||||||
argName == eName && {
|
|
||||||
val str = flagsToString(e.flags);
|
|
||||||
!e.hasFlag(LOCAL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
val param = actual getOrElse arg
|
|
||||||
this(param) = new ConstructorParam(param)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
object decls extends mutable.LinkedHashMap[Symbol, Member] {
|
|
||||||
sym.tpe.decls.iterator.foreach(e => {
|
|
||||||
if (!constructorArgs.contains(e)) {
|
|
||||||
val m = Member(e)
|
|
||||||
if (!m.isEmpty && !this.contains(e)) this.put(e, m.get)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
def members0(f: Symbol => Boolean) = decls.filterKeys(f).valuesIterator.toList
|
|
||||||
def members(c: Category): Iterable[Member] = members0(c.f)
|
|
||||||
object inherited extends mutable.LinkedHashMap[Symbol, List[Member]]() {
|
|
||||||
override def default(tpe: Symbol) = Nil
|
|
||||||
for (m <- sym.tpe.members if !sym.tpe.decls.iterator.contains(m) &&
|
|
||||||
(Values.f(m) || Methods.f(m))) {
|
|
||||||
val o = m.overridingSymbol(sym)
|
|
||||||
if (o == NoSymbol) {
|
|
||||||
val parent = decode(m.enclClass)
|
|
||||||
val mo = Member(m)
|
|
||||||
if (!mo.isEmpty) {
|
|
||||||
this(parent) = mo.get :: this(parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override def parents = freshParents
|
|
||||||
abstract class Member(sym: Symbol) extends Entity(sym) {
|
|
||||||
private def overriding = sym.allOverriddenSymbols
|
|
||||||
override def comment = super.comment match {
|
|
||||||
case ret @ Some(comment) =>
|
|
||||||
ret
|
|
||||||
case None =>
|
|
||||||
val o = overriding.find(comments.contains)
|
|
||||||
o.map(comments.apply)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
abstract class ValDef(sym: Symbol) extends Member(sym) {
|
|
||||||
override def resultType = Some(resultType0)
|
|
||||||
protected def resultType0: Type
|
|
||||||
override def overridden: Iterable[Symbol] = {
|
|
||||||
var ret: mutable.LinkedHashSet[Symbol] = null
|
|
||||||
for (parent <- ClassOrObject.this.parents) {
|
|
||||||
val sym0 = sym.overriddenSymbol(parent.typeSymbol)
|
|
||||||
if (sym0 != NoSymbol) {
|
|
||||||
if (ret == null) ret = new mutable.LinkedHashSet[Symbol];
|
|
||||||
ret += sym0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret == null) Nil else ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case class Def(override val sym : TermSymbol) extends ValDef(sym) {
|
|
||||||
override def resultType0 = sym.tpe.finalResultType
|
|
||||||
override def typeParams = sym.tpe.typeParams.map(TypeParam)
|
|
||||||
override def valueParams = methodArgumentNames.get(sym) match {
|
|
||||||
case Some(argss) if argss.length > 1 || (!argss.isEmpty && !argss(0).isEmpty) =>
|
|
||||||
argss map (_.map(ValueParam))
|
|
||||||
case _ =>
|
|
||||||
var i = 0
|
|
||||||
val ret = for (tpe <- sym.tpe.paramTypes) yield {
|
|
||||||
val ret = sym.newValueParameter(sym.pos, newTermName("arg" + i));
|
|
||||||
ret setInfo tpe
|
|
||||||
i += 1
|
|
||||||
ValueParam(ret)
|
|
||||||
}
|
|
||||||
if (ret.isEmpty) Nil
|
|
||||||
else ret :: Nil
|
|
||||||
}
|
|
||||||
override def kind = "def"
|
|
||||||
}
|
|
||||||
case class Val(override val sym: TermSymbol) extends ValDef(sym) {
|
|
||||||
import symtab.Flags._
|
|
||||||
def resultType0: Type = sym.tpe
|
|
||||||
override def kind: String =
|
|
||||||
if (sym hasFlag ACCESSOR) {
|
|
||||||
val setterName = nme.getterToSetter(sym.name)
|
|
||||||
val setter = sym.owner.info.decl(setterName)
|
|
||||||
val lazyMod = if (sym hasFlag LAZY) "lazy " else ""
|
|
||||||
lazyMod + (if (setter == NoSymbol) "val" else "var")
|
|
||||||
} else {
|
|
||||||
assert(sym hasFlag JAVA)
|
|
||||||
if (sym hasFlag FINAL) "val" else "var"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AbstractType(override val sym: Symbol) extends Member(sym) {
|
|
||||||
override def kind = "type"
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class NestedClassOrObject(override val sym: Symbol) extends Member(sym) with ClassOrObject {
|
|
||||||
override def path: List[ClassOrObject] = ClassOrObject.this.path ::: super.path
|
|
||||||
}
|
|
||||||
|
|
||||||
case class NestedClass(override val sym: ClassSymbol) extends NestedClassOrObject(sym) with Clazz
|
|
||||||
|
|
||||||
case class NestedObject(override val sym: ModuleSymbol) extends NestedClassOrObject(sym) with Object {
|
|
||||||
override def attributes = sym.moduleClass.annotations
|
|
||||||
}
|
|
||||||
|
|
||||||
def isVisible(sym: Symbol): Boolean = {
|
|
||||||
import symtab.Flags._
|
|
||||||
if (sym.isLocalClass) return false
|
|
||||||
if (sym.isLocal) return false
|
|
||||||
if (sym.isPrivateLocal) return false
|
|
||||||
// the next line used to return !inIDE - now it returns true. The underlying
|
|
||||||
// logic being applied here is somewhat mysterious (if PRIVATE return isVisible == true?)
|
|
||||||
// but changing it causes the docgenerator.scala test case to break, so I leave as-is.
|
|
||||||
if (sym hasFlag PRIVATE) return true
|
|
||||||
if (sym hasFlag SYNTHETIC) return false
|
|
||||||
if (sym hasFlag BRIDGE) return false
|
|
||||||
if ((sym.nameString indexOf "$") != -1) return false
|
|
||||||
if ((sym hasFlag CASE) && sym.isMethod) return false
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
def Member(sym: Symbol): Option[Member] = {
|
|
||||||
import global._
|
|
||||||
import symtab.Flags
|
|
||||||
if (!isVisible(sym))
|
|
||||||
None
|
|
||||||
else if (!isAccessible(sym))
|
|
||||||
None
|
|
||||||
else if (sym hasFlag Flags.ACCESSOR) {
|
|
||||||
if (sym.isSetter) return None;
|
|
||||||
assert(sym.isGetter);
|
|
||||||
Some[Member](new Val(sym.asInstanceOf[TermSymbol]))
|
|
||||||
}
|
|
||||||
else if (sym.isValue && !sym.isMethod && !sym.isModule) {
|
|
||||||
if (!sym.hasFlag(Flags.JAVA)) {
|
|
||||||
Console.println("SYM: " + sym + " " + sym.fullNameString('.'))
|
|
||||||
Console.println("FLA: " + Flags.flagsToString(sym.flags))
|
|
||||||
}
|
|
||||||
assert(sym hasFlag Flags.JAVA)
|
|
||||||
Some[Member](new Val(sym.asInstanceOf[TermSymbol]))
|
|
||||||
}
|
|
||||||
else if (sym.isValue && !sym.isModule) {
|
|
||||||
val str = Flags.flagsToString(sym.flags)
|
|
||||||
assert(sym.isMethod)
|
|
||||||
Some[Member](new Def(sym.asInstanceOf[TermSymbol]))
|
|
||||||
}
|
|
||||||
else if (sym.isAliasType || sym.isAbstractType)
|
|
||||||
Some(new AbstractType(sym))
|
|
||||||
else if (sym.isClass)
|
|
||||||
Some(new NestedClass(sym.asInstanceOf[ClassSymbol]))
|
|
||||||
else if (sym.isModule)
|
|
||||||
Some(new NestedObject(sym.asInstanceOf[ModuleSymbol]))
|
|
||||||
else
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
case class Category(label: String)(g: Symbol => Boolean) {
|
|
||||||
val f = g
|
|
||||||
def plural = label + "s"
|
|
||||||
}
|
|
||||||
val Constructors = new Category("Additional Constructor")(e => e.isConstructor && !e.isPrimaryConstructor) {
|
|
||||||
// override def plural = "Additional Constructors";
|
|
||||||
}
|
|
||||||
val Objects = Category("Object")(_.isModule);
|
|
||||||
val Classes = new Category("Class")(sym => sym.isClass || (sym == definitions.AnyRefClass)) {
|
|
||||||
override def plural = "Classes"
|
|
||||||
}
|
|
||||||
val Values = new Category("Value")(e => e.isValue && e.hasFlag(symtab.Flags.ACCESSOR)) {
|
|
||||||
override def plural = "Values and Variables"
|
|
||||||
}
|
|
||||||
val Methods = Category("Method")(e => e.isValue && e.isMethod && !e.isConstructor && !e.hasFlag(symtab.Flags.ACCESSOR));
|
|
||||||
val Types = Category("Type")(e => e.isAliasType || e.isAbstractType);
|
|
||||||
|
|
||||||
val categories = Constructors :: Types :: Values :: Methods :: Classes :: Objects :: Nil;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
// patterns for standard tags with 1 and 2 arguments
|
|
||||||
private val pat1 = Pattern.compile(
|
|
||||||
"[ \t]*@(author|deprecated|owner|pre|return|see|since|todo|version|ex|note)[ \t]*(.*)")
|
|
||||||
private val pat2 = Pattern.compile(
|
|
||||||
"[ \t]*@(exception|param|throws)[ \t]+(\\p{Graph}*)[ \t]*(.*)")
|
|
||||||
|
|
||||||
def sort[E <: Entity](entities: Iterable[E]): Iterable[E] = {
|
|
||||||
val set = new collection.immutable.TreeSet[E]()(new Ordering[E] {
|
|
||||||
def compare(eA : E, eB: E): Int = {
|
|
||||||
if (eA eq eB) return 0;
|
|
||||||
(eA, eB) match {
|
|
||||||
case (eA: ClassOrObject, eB: ClassOrObject) =>
|
|
||||||
val diff = ModelExtractor.this.compare(eA.path, eB.path)
|
|
||||||
if (diff!= 0) return diff
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
if (eA.getClass != eB.getClass) {
|
|
||||||
val diff = eA.getClass.getName.compare(eB.getClass.getName)
|
|
||||||
assert(diff != 0)
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
if (!eA.sym0.isPackage) {
|
|
||||||
val diff = eA.sym0.nameString compare eB.sym0.nameString
|
|
||||||
if (diff != 0) return diff
|
|
||||||
}
|
|
||||||
val diff0 = eA.sym0.fullNameString compare eB.sym0.fullNameString
|
|
||||||
assert(diff0 != 0)
|
|
||||||
diff0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
set ++ entities
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,396 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2005-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
import java.io.{File, FileWriter}
|
|
||||||
import scala.util.NameTransformer
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.compat.Platform.{EOL => LINE_SEPARATOR}
|
|
||||||
import scala.xml.{NodeSeq, Text, Unparsed, Utility}
|
|
||||||
|
|
||||||
/** This class provides HTML document framing functionality.
|
|
||||||
*
|
|
||||||
* @author Sean McDirmid, Stephane Micheloud
|
|
||||||
*/
|
|
||||||
trait ModelFrames extends ModelExtractor {
|
|
||||||
import DocUtil._
|
|
||||||
def settings: doc.Settings
|
|
||||||
import global.definitions.{AnyClass, AnyRefClass}
|
|
||||||
|
|
||||||
val SyntheticClasses = new scala.collection.mutable.HashSet[global.Symbol];
|
|
||||||
{
|
|
||||||
import global.definitions._
|
|
||||||
global.definitions.init
|
|
||||||
SyntheticClasses ++= List(
|
|
||||||
NothingClass, NullClass, AnyClass, AnyRefClass, AnyValClass,
|
|
||||||
//value classes
|
|
||||||
BooleanClass, ByteClass, CharClass, IntClass, LongClass, ShortClass,
|
|
||||||
FloatClass, DoubleClass, UnitClass)
|
|
||||||
}
|
|
||||||
|
|
||||||
val outdir = settings.outdir.value
|
|
||||||
val windowTitle = settings.windowtitle.value
|
|
||||||
val docTitle = load(settings.doctitle.value)
|
|
||||||
|
|
||||||
val stylesheetSetting = settings.stylesheetfile
|
|
||||||
|
|
||||||
def pageHeader = load(settings.pageheader.value)
|
|
||||||
def pageFooter = load(settings.pagefooter.value)
|
|
||||||
def pageTop = load(settings.pagetop.value)
|
|
||||||
def pageBottom = load(settings.pagebottom.value)
|
|
||||||
|
|
||||||
def contentFrame = "contentFrame"
|
|
||||||
def classesFrame = "classesFrame"
|
|
||||||
def modulesFrame = "modulesFrame"
|
|
||||||
|
|
||||||
protected val FILE_EXTENSION_HTML = ".html"
|
|
||||||
protected val NAME_SUFFIX_OBJECT = "$object"
|
|
||||||
protected val NAME_SUFFIX_PACKAGE = "$package"
|
|
||||||
|
|
||||||
def rootTitle = (<div class="page-title">{docTitle}</div>);
|
|
||||||
def rootDesc =
|
|
||||||
(<p>{load("This document is the API specification for " + windowTitle)}</p>);
|
|
||||||
|
|
||||||
final def hasLink(sym: global.Symbol): Boolean =
|
|
||||||
if (sym == global.NoSymbol) false
|
|
||||||
else if (hasLink0(sym)) true
|
|
||||||
else hasLink(decode(sym.owner))
|
|
||||||
|
|
||||||
def hasLink0(sym: global.Symbol): Boolean = true
|
|
||||||
|
|
||||||
abstract class Frame extends UrlContext {
|
|
||||||
{ // just save.
|
|
||||||
save(page(title, body, hasBody));
|
|
||||||
}
|
|
||||||
def path: String // relative to outdir
|
|
||||||
def relative: String = {
|
|
||||||
if (path eq null) return "foo"
|
|
||||||
assert(path ne null)
|
|
||||||
var idx = 0
|
|
||||||
var ct = new StringBuilder
|
|
||||||
while (idx != -1) {
|
|
||||||
idx = path.indexOf('/', idx)
|
|
||||||
//System.err.println(path + " idx=" + idx)
|
|
||||||
ct.append(if (idx != -1) "../" else "")
|
|
||||||
idx += (if (idx == -1) 0 else 1)
|
|
||||||
}
|
|
||||||
ct.toString
|
|
||||||
}
|
|
||||||
def save(nodes: NodeSeq) = {
|
|
||||||
val path = this.path
|
|
||||||
if (path.startsWith("http://")) throw new Error("frame: " + this)
|
|
||||||
val path0 = outdir + File.separator + path + FILE_EXTENSION_HTML
|
|
||||||
//if (settings.debug.value) inform("Writing XML nodes to " + path0)
|
|
||||||
val file = new File(path0)
|
|
||||||
val parent = file.getParentFile()
|
|
||||||
if (!parent.exists()) parent.mkdirs()
|
|
||||||
val writer = new FileWriter(file)
|
|
||||||
val str = dtype + LINE_SEPARATOR + nodes.toString()
|
|
||||||
writer.write(str, 0, str.length())
|
|
||||||
writer.close()
|
|
||||||
}
|
|
||||||
protected def body: NodeSeq
|
|
||||||
protected def title: String
|
|
||||||
protected def hasBody = true
|
|
||||||
|
|
||||||
//def urlFor(entity: Entity, target: String): NodeSeq
|
|
||||||
def urlFor(entity: Entity): String = {
|
|
||||||
val ret = this.urlFor(entity.sym)
|
|
||||||
assert(ret != null);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
def link(entity: Entity, target: String) = aref(urlFor(entity), target, entity.name)
|
|
||||||
protected def shortHeader(entity: Entity): NodeSeq
|
|
||||||
protected def longHeader(entity: Entity): NodeSeq
|
|
||||||
import global._
|
|
||||||
import symtab.Flags
|
|
||||||
|
|
||||||
def urlFor(sym: Symbol): String = sym match {
|
|
||||||
case psym : ModuleSymbol if psym.isPackage =>
|
|
||||||
urlFor0(sym, sym) + FILE_EXTENSION_HTML
|
|
||||||
case sym if !hasLink(sym) =>
|
|
||||||
null
|
|
||||||
case sym if sym == AnyRefClass =>
|
|
||||||
urlFor0(sym, sym) + FILE_EXTENSION_HTML
|
|
||||||
case msym: ModuleSymbol =>
|
|
||||||
urlFor0(sym, sym) + FILE_EXTENSION_HTML
|
|
||||||
case csym: ClassSymbol =>
|
|
||||||
urlFor0(sym, sym) + FILE_EXTENSION_HTML
|
|
||||||
case _ =>
|
|
||||||
val cnt = urlFor(decode(sym.owner))
|
|
||||||
if (cnt == null) null else cnt + "#" + docName(sym)
|
|
||||||
}
|
|
||||||
|
|
||||||
def docName(sym: Symbol): String = {
|
|
||||||
def javaParams(paramTypes: List[Type]): String = {
|
|
||||||
def javaName(pt: Type): String = {
|
|
||||||
val s = pt.toString
|
|
||||||
val matVal = patVal.matcher(s)
|
|
||||||
if (matVal.matches) matVal.group(1).toLowerCase
|
|
||||||
else s.replaceAll("\\$", ".")
|
|
||||||
}
|
|
||||||
paramTypes.map(pt => javaName(pt)).mkString("(", ",", ")")
|
|
||||||
}
|
|
||||||
def scalaParams(paramTypes: List[Type]): String = {
|
|
||||||
def scalaName(pt: Type): String = pt.toString.replaceAll(" ", "")
|
|
||||||
paramTypes.map(pt => scalaName(pt)).mkString("(", ",", ")")
|
|
||||||
}
|
|
||||||
java.net.URLEncoder.encode(sym.nameString +
|
|
||||||
(sym.tpe match {
|
|
||||||
case MethodType(params, _) =>
|
|
||||||
val paramTypes = params map (_.tpe)
|
|
||||||
if (sym hasFlag Flags.JAVA) javaParams(paramTypes)
|
|
||||||
else scalaParams(paramTypes)
|
|
||||||
case PolyType(_, MethodType(params, _)) =>
|
|
||||||
val paramTypes = params map (_.tpe)
|
|
||||||
if (sym hasFlag Flags.JAVA) javaParams(paramTypes)
|
|
||||||
else scalaParams(paramTypes)
|
|
||||||
case _ => ""
|
|
||||||
}), encoding)
|
|
||||||
}
|
|
||||||
|
|
||||||
def urlFor0(sym: Symbol, orig: Symbol): String =
|
|
||||||
(if (sym == NoSymbol) "XXX"
|
|
||||||
else if (sym.owner.isPackageClass) rootFor(sym) + pkgPath(sym)
|
|
||||||
else urlFor0(decode(sym.owner), orig) + "." + NameTransformer.encode(Utility.escape(sym.nameString))
|
|
||||||
) +
|
|
||||||
(sym match {
|
|
||||||
case msym: ModuleSymbol =>
|
|
||||||
if (msym hasFlag Flags.PACKAGE) NAME_SUFFIX_PACKAGE
|
|
||||||
else NAME_SUFFIX_OBJECT
|
|
||||||
case csym: ClassSymbol if csym.isModuleClass =>
|
|
||||||
if (csym hasFlag Flags.PACKAGE) NAME_SUFFIX_PACKAGE
|
|
||||||
else NAME_SUFFIX_OBJECT
|
|
||||||
case _ =>
|
|
||||||
""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
def pkgPath(sym : global.Symbol) = sym.fullNameString('/') match {
|
|
||||||
case "<empty>" => "_empty_"
|
|
||||||
case path => path
|
|
||||||
}
|
|
||||||
|
|
||||||
protected def rootFor(sym: global.Symbol) = ""
|
|
||||||
|
|
||||||
abstract class AllPackagesFrame extends Frame {
|
|
||||||
override lazy val path = "modules"
|
|
||||||
override lazy val title = "List of all packages"
|
|
||||||
def packages: Iterable[Package]
|
|
||||||
override def body: NodeSeq =
|
|
||||||
(<div>
|
|
||||||
<div class="doctitle-larger">{windowTitle}</div>
|
|
||||||
<a href="all-classes.html" target={classesFrame} onclick="resetKind();">{"All objects and classes"}</a>
|
|
||||||
</div>
|
|
||||||
<div class="kinds">Packages</div>
|
|
||||||
<ul class="list">{sort(packages).mkXML("","\n","")(pkg => {
|
|
||||||
(<li><a href={urlFor(pkg)} target={classesFrame} onclick="resetKind();">
|
|
||||||
{pkg.fullName('.')}</a></li>)
|
|
||||||
})}
|
|
||||||
</ul>);
|
|
||||||
}
|
|
||||||
abstract class PackagesContentFrame extends Frame {
|
|
||||||
lazy val path = "root-content"
|
|
||||||
lazy val title = "All Packages"
|
|
||||||
def packages : Iterable[Package]
|
|
||||||
//def modules: TreeMap[String, ModuleClassSymbol]
|
|
||||||
def body: NodeSeq =
|
|
||||||
{rootTitle} ++ {rootDesc} ++ (<hr/>) ++
|
|
||||||
(<table cellpadding="3" class="member" summary="">
|
|
||||||
<tr><td colspan="2" class="title">Package Summary</td></tr>
|
|
||||||
{sort(packages).mkXML("","\n","")(pkg => (<tr><td class="signature">
|
|
||||||
<code>package
|
|
||||||
{aref(pkgPath(pkg.sym) + "$content.html", "_self", pkg.fullName('.'))}
|
|
||||||
</code>
|
|
||||||
</td></tr>))}
|
|
||||||
</table>);
|
|
||||||
}
|
|
||||||
|
|
||||||
val classFrameKinds = Classes :: Objects :: Nil;
|
|
||||||
abstract class ListClassFrame extends Frame {
|
|
||||||
def classes: Iterable[ClassOrObject]
|
|
||||||
def navLabel: String
|
|
||||||
private def navPath = {
|
|
||||||
val p = path;
|
|
||||||
(if (p endsWith NAME_SUFFIX_PACKAGE)
|
|
||||||
p.substring(0, p.length() - NAME_SUFFIX_PACKAGE.length());
|
|
||||||
else p) + navSuffix;
|
|
||||||
}
|
|
||||||
protected def navSuffix = "$content.html"
|
|
||||||
|
|
||||||
def body: NodeSeq = {
|
|
||||||
val nav = if (navLabel == null) NodeSeq.Empty else
|
|
||||||
(<table class="navigation" summary="">
|
|
||||||
<tr><td valign="top" class="navigation-links">
|
|
||||||
{aref(navPath, contentFrame, navLabel)}
|
|
||||||
</td></tr>
|
|
||||||
</table>);
|
|
||||||
val ids = new mutable.LinkedHashSet[String]
|
|
||||||
def idFor(kind: Category, t: Entity)(seq : NodeSeq): NodeSeq = {
|
|
||||||
val ch = t.listName.charAt(0);
|
|
||||||
val id = kind.plural + "_" + ch;
|
|
||||||
if (ids contains id) (<li>{seq}</li>);
|
|
||||||
else {
|
|
||||||
ids += id;
|
|
||||||
(<li id={id}>{seq}</li>)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
val body = (<div>{classFrameKinds.mkXML("","\n","")(kind => {
|
|
||||||
val classes = sort(this.classes.filter(e => kind.f(e.sym)));
|
|
||||||
if (classes.isEmpty) NodeSeq.Empty; else
|
|
||||||
(<div id={kind.plural} class="kinds">{Text(kind.plural)}</div>
|
|
||||||
<ul class="list">
|
|
||||||
{classes.mkXML("","\n","")(cls => {
|
|
||||||
idFor(kind, cls)(
|
|
||||||
aref(urlFor(cls), contentFrame, cls.listName) ++ optional(cls)
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ul>);
|
|
||||||
})}</div>);
|
|
||||||
nav ++ body
|
|
||||||
}
|
|
||||||
def optional(cls: ClassOrObject): NodeSeq = NodeSeq.Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class PackageContentFrame extends Frame {
|
|
||||||
override def path = pkgPath(pkg.sym) + "$content"
|
|
||||||
override def title = "All classes and objects in " + pkg.fullName('.')
|
|
||||||
protected def pkg: Package
|
|
||||||
protected def classes: Iterable[ClassOrObject]
|
|
||||||
def body: NodeSeq =
|
|
||||||
{rootTitle} ++ {rootDesc} ++ {classFrameKinds.mkXML("","\n","")(kind => {
|
|
||||||
val classes = sort(this.classes.filter(e => kind.f(e.sym) && e.isInstanceOf[TopLevel]));
|
|
||||||
if (classes.isEmpty) NodeSeq.Empty else
|
|
||||||
(<table cellpadding="3" class="member" summary="">
|
|
||||||
<tr><td colspan="2" class="title">{kind.label} Summary</td></tr>
|
|
||||||
{classes.mkXML("","\n","")(shortHeader)}
|
|
||||||
</table>)
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ClassContentFrame extends Frame {
|
|
||||||
def clazz: ClassOrObject
|
|
||||||
def body: NodeSeq =
|
|
||||||
(<xml:group>
|
|
||||||
{pageHeader}{navigation}{pageTop}
|
|
||||||
{header0}{longHeader(clazz)}
|
|
||||||
{pageBottom}{navigation}{pageFooter}
|
|
||||||
</xml:group>);
|
|
||||||
final def path = urlFor0(clazz.sym, clazz.sym)
|
|
||||||
private def navigation: NodeSeq =
|
|
||||||
(<table class="navigation" summary="">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" class="navigation-links">
|
|
||||||
<!-- <table><tr></tr></table> -->
|
|
||||||
</td>
|
|
||||||
<td align="right" valign="top" style="white-space:nowrap;" rowspan="2">
|
|
||||||
<div class="doctitle-larger">{windowTitle}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr><td></td></tr>
|
|
||||||
</table>);
|
|
||||||
private def header0: NodeSeq = {
|
|
||||||
val owner = decode(clazz.sym.owner)
|
|
||||||
(<xml:group>
|
|
||||||
<div class="entity">
|
|
||||||
{aref(urlFor(owner), "_self", owner.fullNameString('.'))}
|
|
||||||
<br/>
|
|
||||||
<span class="entity">{Text(clazz.kind)} {Text(clazz.name)}</span>
|
|
||||||
</div><hr/>
|
|
||||||
<div class="source">
|
|
||||||
{
|
|
||||||
if (SyntheticClasses contains clazz.sym)
|
|
||||||
Text("[Source: none]")
|
|
||||||
else {
|
|
||||||
val name = owner.fullNameString('/') + (if (owner.isPackage) "/" + clazz.name else "")
|
|
||||||
Text("[source: ") ++
|
|
||||||
(<a class={name} href=""><code>{name + ".scala"}</code></a>) ++
|
|
||||||
Text("]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div><hr/>
|
|
||||||
</xml:group>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val index =
|
|
||||||
(<frameset cols="25%, 75%">
|
|
||||||
<frameset rows="50%, 28, 50%">
|
|
||||||
<frame src="modules.html" name={modulesFrame}></frame>
|
|
||||||
<frame src="nav-classes.html" name="navigationFrame"></frame>
|
|
||||||
<frame src="all-classes.html" name={classesFrame}></frame>
|
|
||||||
</frameset>
|
|
||||||
<frame src="root-content.html" name={contentFrame}></frame>
|
|
||||||
</frameset>);
|
|
||||||
|
|
||||||
val root = (<b></b>);
|
|
||||||
|
|
||||||
abstract class RootFrame extends Frame {
|
|
||||||
def title = windowTitle
|
|
||||||
def body = index
|
|
||||||
def path = "index"
|
|
||||||
override def hasBody = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val indexChars = 'A' :: 'B' :: 'C' :: 'D' :: 'E' :: 'G' :: 'I' :: 'L' :: 'M' :: 'P' :: 'R' :: 'T' :: 'V' :: 'X' :: Nil;
|
|
||||||
|
|
||||||
abstract class NavigationFrame extends Frame {
|
|
||||||
def title="navigation"
|
|
||||||
def path="nav-classes"
|
|
||||||
override def body0(hasBody: Boolean, nodes: NodeSeq): NodeSeq =
|
|
||||||
if (!hasBody) nodes
|
|
||||||
else (<body style="margin:1px 0 0 1px; padding:1px 0 0 1px;">{nodes}</body>);
|
|
||||||
def body =
|
|
||||||
(<form>
|
|
||||||
<select id="kinds" onchange="gotoKind()">
|
|
||||||
<option value="#Classes" selected="selected">Classes</option>
|
|
||||||
<option value="#Objects">Objects</option>
|
|
||||||
</select>
|
|
||||||
<span id="alphabet" style="font-family:Courier;word-spacing:-8px;">{
|
|
||||||
indexChars.mkXML("","\n","")(c => {
|
|
||||||
(<a href={Unparsed("javascript:gotoName(\'" + c + "\')")}>{c}</a>)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</form>)
|
|
||||||
}
|
|
||||||
|
|
||||||
def copyResources = {
|
|
||||||
import java.io._
|
|
||||||
val loader = this.getClass().getClassLoader()
|
|
||||||
def basename(path: String): String = {
|
|
||||||
val pos = path lastIndexOf System.getProperty("file.separator", "/")
|
|
||||||
if (pos != -1) path.substring(pos + 1) else path
|
|
||||||
}
|
|
||||||
def copyResource(name: String, isFile: Boolean) = try {
|
|
||||||
val (in, outfile) =
|
|
||||||
if (isFile)
|
|
||||||
(new FileInputStream(name), basename(name))
|
|
||||||
else {
|
|
||||||
// The name of a resource is a '/'-separated path name that identifies the resource.
|
|
||||||
(loader.getResourceAsStream("scala/tools/nsc/doc/" + name), name)
|
|
||||||
}
|
|
||||||
val out = new FileOutputStream(new File(outdir + File.separator + outfile))
|
|
||||||
val buf = new Array[Byte](1024)
|
|
||||||
var len = 0
|
|
||||||
while (len != -1) {
|
|
||||||
out.write(buf, 0, len)
|
|
||||||
len = in.read(buf)
|
|
||||||
}
|
|
||||||
in.close()
|
|
||||||
out.close()
|
|
||||||
} catch {
|
|
||||||
case _ =>
|
|
||||||
System.err.println("Resource file '" + name + "' not found")
|
|
||||||
}
|
|
||||||
copyResource(stylesheetSetting.value, !stylesheetSetting.isDefault)
|
|
||||||
copyResource("script.js", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val patVal = java.util.regex.Pattern.compile(
|
|
||||||
"scala\\.(Byte|Boolean|Char|Double|Float|Int|Long|Short)")
|
|
||||||
}
|
|
|
@ -1,368 +0,0 @@
|
||||||
/* NSC -- new Scala compiler
|
|
||||||
* Copyright 2007-2009 LAMP/EPFL
|
|
||||||
* @author Sean McDirmid
|
|
||||||
*/
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
package scala.tools.nsc
|
|
||||||
package doc
|
|
||||||
|
|
||||||
import scala.xml._
|
|
||||||
|
|
||||||
/** This class has functionality to format source code models as XML blocks.
|
|
||||||
*
|
|
||||||
* @author Sean McDirmid, Stephane Micheloud
|
|
||||||
*/
|
|
||||||
trait ModelToXML extends ModelExtractor {
|
|
||||||
import global._
|
|
||||||
import definitions.AnyRefClass
|
|
||||||
import DocUtil._
|
|
||||||
// decode entity into XML.
|
|
||||||
type Frame
|
|
||||||
|
|
||||||
protected def urlFor(sym: Symbol)(implicit frame: Frame): String
|
|
||||||
protected def anchor(sym: Symbol)(implicit frame: Frame): NodeSeq
|
|
||||||
|
|
||||||
def aref(href: String, label: String)(implicit frame: Frame): NodeSeq
|
|
||||||
/*
|
|
||||||
def link(entity: Symbol)(implicit frame: Frame): NodeSeq = {
|
|
||||||
val url = urlFor(entity)
|
|
||||||
// nothing to do but be verbose.
|
|
||||||
if (url == null)
|
|
||||||
Text(entity.owner.fullNameString('.') + '.' + entity.nameString)
|
|
||||||
else
|
|
||||||
aref(url, entity.nameString)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
def link(entity: Symbol, label: String)(implicit frame: Frame): NodeSeq = {
|
|
||||||
val url = urlFor(entity)
|
|
||||||
if (url == null) { // external link (handled by script.js)
|
|
||||||
val (href, attr) =
|
|
||||||
if (entity.isClass || (entity==AnyRefClass))
|
|
||||||
("", entity.owner.fullNameString('/') + '/' + entity.nameString)
|
|
||||||
else
|
|
||||||
("#" + entity.nameString, entity.owner.fullNameString('/'))
|
|
||||||
val name = entity.owner.fullNameString('.') + '.' + entity.nameString
|
|
||||||
<a href={Utility.escape(href)} class={attr} target="contentFrame">{name}</a>;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
aref(url, label)
|
|
||||||
}
|
|
||||||
|
|
||||||
def link(entity: Symbol)(implicit frame: Frame): NodeSeq =
|
|
||||||
link(entity, entity.nameString)
|
|
||||||
|
|
||||||
def link(tpe: Type)(implicit frame: Frame): NodeSeq = {
|
|
||||||
if (!tpe.typeArgs.isEmpty) {
|
|
||||||
if (definitions.isFunctionType(tpe)) {
|
|
||||||
val (args,r) = tpe.normalize.typeArgs.splitAt(tpe.normalize.typeArgs.length - 1);
|
|
||||||
args.mkXML("(", ", ", ")")(link) ++ Text(" => ") ++ link(r.head);
|
|
||||||
} else if (definitions.isRepeatedParamType(tpe)) {
|
|
||||||
assert(tpe.typeArgs.length == 1)
|
|
||||||
link(tpe.typeArgs(0)) ++ Text("*")
|
|
||||||
} else if (tpe.typeSymbol == definitions.ByNameParamClass) {
|
|
||||||
assert(tpe.typeArgs.length == 1)
|
|
||||||
Text("=> ") ++ link(tpe.typeArgs(0))
|
|
||||||
} else if (tpe.typeSymbol.name.toString.startsWith("Tuple") &&
|
|
||||||
tpe.typeSymbol.owner.name == nme.scala_.toTypeName) {
|
|
||||||
tpe.typeArgs.mkXML("(", ", ", ")")(link)
|
|
||||||
} else
|
|
||||||
link(decode(tpe.typeSymbol)) ++ tpe.typeArgs.surround("[", "]")(link)
|
|
||||||
} else tpe match {
|
|
||||||
case PolyType(tparams,result) =>
|
|
||||||
link(result) ++ tparams.surround("[", "]")(link)
|
|
||||||
case RefinedType(parents,_) =>
|
|
||||||
val parents1 =
|
|
||||||
if ((parents.length > 1) &&
|
|
||||||
(parents.head.typeSymbol eq definitions.ObjectClass)) parents.tail;
|
|
||||||
else parents;
|
|
||||||
parents1.mkXML(Text(""), <code> with </code>, Text(""))(link);
|
|
||||||
case _ =>
|
|
||||||
if (tpe.typeSymbol == NoSymbol) {
|
|
||||||
throw new Error(tpe + " has no type class " + tpe.getClass)
|
|
||||||
}
|
|
||||||
link(decode(tpe.typeSymbol))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def printIf[T](what: Option[T], before: String, after: String)(f: T => NodeSeq): NodeSeq =
|
|
||||||
if (what.isEmpty) Text("")
|
|
||||||
else Text(before) ++ f(what.get) ++ Text(after)
|
|
||||||
|
|
||||||
def bodyFor(entity: Entity)(implicit frame: Frame): NodeSeq = try {
|
|
||||||
var seq = {entity.typeParams.surround("[", "]")(e => {
|
|
||||||
Text(e.variance) ++ <em>{e.name}</em> ++
|
|
||||||
{printIf(e.hi, " <: ", "")(link)} ++
|
|
||||||
{printIf(e.lo, " >: ", "")(link)}
|
|
||||||
})} ++ printIf(entity.hi, " <: ", "")(link) ++
|
|
||||||
printIf(entity.lo, " >: ", "")(link);
|
|
||||||
{entity.valueParams.foreach(xs => {
|
|
||||||
seq = seq ++ xs.mkXML("(", ", ", ")")(arg =>
|
|
||||||
{
|
|
||||||
val str = arg.flagsString.trim
|
|
||||||
if (str.length == 0) NodeSeq.Empty
|
|
||||||
else <code>{Text(str)} </code>
|
|
||||||
} ++
|
|
||||||
<em>{arg.name}</em> ++ (try {
|
|
||||||
|
|
||||||
Text(" : ") ++ link(arg.resultType.get)
|
|
||||||
} catch {
|
|
||||||
case e : Throwable => System.err.println("ARG " + arg + " in " + entity); throw e
|
|
||||||
})
|
|
||||||
);
|
|
||||||
seq
|
|
||||||
})};
|
|
||||||
seq ++ {printIf(entity.resultType, " : ", "")(tpe => link(tpe))}
|
|
||||||
} catch {
|
|
||||||
case e => System.err.println("generating for " + entity); throw e
|
|
||||||
}
|
|
||||||
|
|
||||||
def extendsFor(entity: Entity)(implicit frame: Frame): NodeSeq = {
|
|
||||||
if (entity.parents.isEmpty) NodeSeq.Empty
|
|
||||||
else <code> extends </code>++
|
|
||||||
entity.parents.mkXML(Text(""), <code> with </code>, Text(""))(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
def parse(str: String): NodeSeq = {
|
|
||||||
new SpecialNode {
|
|
||||||
def label = "#PCDATA"
|
|
||||||
def buildString(sb: StringBuilder): StringBuilder = {
|
|
||||||
sb.append(str.trim)
|
|
||||||
sb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def longHeader(entity: Entity)(implicit frame: Frame): NodeSeq = Group({
|
|
||||||
anchor(entity.sym) ++ <dl>
|
|
||||||
<dt>
|
|
||||||
{attrsFor(entity)}
|
|
||||||
<code>{Text(entity.flagsString)}</code>
|
|
||||||
<code>{Text(entity.kind)}</code>
|
|
||||||
<em>{entity.sym.nameString}</em>{bodyFor(entity)}
|
|
||||||
</dt>
|
|
||||||
<dd>{extendsFor(entity)}</dd>
|
|
||||||
</dl>;
|
|
||||||
} ++ {
|
|
||||||
val cmnt = entity.decodeComment
|
|
||||||
if (cmnt.isEmpty) NodeSeq.Empty
|
|
||||||
else longComment(entity, cmnt.get)
|
|
||||||
} ++ (entity match {
|
|
||||||
case entity: ClassOrObject => classBody(entity)
|
|
||||||
case _ => NodeSeq.Empty
|
|
||||||
}) ++ {
|
|
||||||
val overridden = entity.overridden
|
|
||||||
if (overridden.isEmpty)
|
|
||||||
NodeSeq.Empty
|
|
||||||
else {
|
|
||||||
<dl>
|
|
||||||
<dt style="margin:10px 0 0 20px;">
|
|
||||||
<b>Overrides</b>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
{ overridden.mkXML("",", ", "")(sym => link(decode(sym.owner)) ++ Text(".") ++ link(sym))
|
|
||||||
}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
}
|
|
||||||
} ++ <hr/>);
|
|
||||||
|
|
||||||
def longComment(entity: Entity, cmnt: Comment)(implicit frame: Frame): NodeSeq = {
|
|
||||||
val attrs = <dl>{
|
|
||||||
var seq: NodeSeq = NodeSeq.Empty
|
|
||||||
cmnt.decodeAttributes.foreach{
|
|
||||||
case (tag, xs) =>
|
|
||||||
seq = seq ++ <dt style="margin:10px 0 0 20px;">
|
|
||||||
<b>{decodeTag(tag)}</b></dt> ++ {xs.flatMap{
|
|
||||||
case (option,body) => <dd>{
|
|
||||||
if (option == null) NodeSeq.Empty;
|
|
||||||
else decodeOption(tag, option);
|
|
||||||
}{ tag match {
|
|
||||||
case "see" => resolveSee(entity.sym, body.trim)
|
|
||||||
case _ => parse(body)
|
|
||||||
}}</dd>
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
seq
|
|
||||||
}</dl>;
|
|
||||||
<xml:group>
|
|
||||||
<dl><dd>{parse(cmnt.body)}</dd></dl>
|
|
||||||
{attrs}
|
|
||||||
</xml:group>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to be smart about @see elements. If the body looks like a link, turn it into
|
|
||||||
* a link. If it can be resolved in the symbol table, turn it into a link to the referenced
|
|
||||||
* entity.
|
|
||||||
*/
|
|
||||||
private def resolveSee(owner: Symbol, body: String)(implicit frame: Frame): NodeSeq = {
|
|
||||||
/** find a class either in the root package, in the current class or in the current package. */
|
|
||||||
def findClass(clsName: String): Symbol = {
|
|
||||||
try { definitions.getClass(clsName) } catch {
|
|
||||||
case f: FatalError =>
|
|
||||||
try { definitions.getMember(owner, clsName.toTypeName) } catch {
|
|
||||||
case f: FatalError =>
|
|
||||||
definitions.getMember(owner.enclosingPackage, clsName.toTypeName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body.startsWith("http://")
|
|
||||||
|| body.startsWith("https://")
|
|
||||||
|| body.startsWith("www")) {
|
|
||||||
// a link
|
|
||||||
body.split(" ") match {
|
|
||||||
case Seq(href, txt, rest @ _*) =>
|
|
||||||
<a href={href}>{txt}{rest}</a>
|
|
||||||
case _ =>
|
|
||||||
<a href={body}>{body}</a>
|
|
||||||
}
|
|
||||||
} else try {
|
|
||||||
// treat it like a class or member reference
|
|
||||||
body.split("#") match {
|
|
||||||
case Seq(clazz, member) =>
|
|
||||||
val clazzSym = if (clazz.length == 0) owner.enclClass else findClass(clazz)
|
|
||||||
link(definitions.getMember(clazzSym, member), body)
|
|
||||||
case Seq(clazz, _*) =>
|
|
||||||
link(findClass(clazz), body)
|
|
||||||
case _ =>
|
|
||||||
parse(body)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
case f: FatalError =>
|
|
||||||
log("Error resolving @see: " + f.toString)
|
|
||||||
parse(body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def classBody(entity: ClassOrObject)(implicit from: Frame): NodeSeq =
|
|
||||||
<xml:group>
|
|
||||||
{categories.mkXML("","\n","")(c => shortList(entity, c)) : NodeSeq}
|
|
||||||
{categories.mkXML("","\n","")(c => longList(entity, c)) : NodeSeq}
|
|
||||||
</xml:group>;
|
|
||||||
|
|
||||||
def longList(entity: ClassOrObject, category: Category)(implicit from: Frame): NodeSeq = {
|
|
||||||
val xs = entity.members(category)
|
|
||||||
if (!xs.iterator.hasNext)
|
|
||||||
NodeSeq.Empty
|
|
||||||
else Group(
|
|
||||||
<table cellpadding="3" class="member-detail" summary="">
|
|
||||||
<tr><td class="title">{Text(category.label)} Details</td></tr>
|
|
||||||
</table>
|
|
||||||
<div>{xs.mkXML("","\n","")(m => longHeader(m))}</div>)
|
|
||||||
}
|
|
||||||
|
|
||||||
def shortList(entity: ClassOrObject, category: Category)(implicit from: Frame): NodeSeq = {
|
|
||||||
val xs = entity.members(category)
|
|
||||||
var seq: NodeSeq = NodeSeq.Empty
|
|
||||||
if (xs.iterator.hasNext) {
|
|
||||||
// alphabetic
|
|
||||||
val set = new scala.collection.immutable.TreeSet[entity.Member]()(new Ordering[entity.Member] {
|
|
||||||
def compare(mA : entity.Member, mB: entity.Member): Int =
|
|
||||||
if (mA eq mB) 0
|
|
||||||
else {
|
|
||||||
val diff = mA.name compare mB.name
|
|
||||||
if (diff != 0) diff
|
|
||||||
else {
|
|
||||||
val diff0 = mA.hashCode - mB.hashCode
|
|
||||||
assert(diff0 != 0, mA.name)
|
|
||||||
diff0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})++xs
|
|
||||||
seq = seq ++ <table cellpadding="3" class="member" summary="">
|
|
||||||
<tr><td colspan="2" class="title">{Text(category.label + " Summary")}</td></tr>
|
|
||||||
{set.mkXML("","\n","")(mmbr => shortHeader(mmbr))}
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
// list inherited members...if any.
|
|
||||||
for ((tpe,members) <- entity.inherited) {
|
|
||||||
val members0 = members.filter(m => category.f(m.sym));
|
|
||||||
if (!members0.isEmpty) seq = seq ++ <table cellpadding="3" class="inherited" summary="">
|
|
||||||
<tr><td colspan="2" class="title">
|
|
||||||
{Text(category.plural + " inherited from ") ++ link(tpe)}
|
|
||||||
</td></tr>
|
|
||||||
<tr><td colspan="2" class="signature">
|
|
||||||
{members0.mkXML((""), (", "), (""))(m => {
|
|
||||||
link(decode(m.sym)) ++
|
|
||||||
(if (m.sym.hasFlag(symtab.Flags.ABSTRACT) || m.sym.hasFlag(symtab.Flags.DEFERRED)) {
|
|
||||||
Text(" (abstract)");
|
|
||||||
} else NodeSeq.Empty);
|
|
||||||
})}
|
|
||||||
</td></tr>
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected def decodeOption(tag: String, string: String): NodeSeq =
|
|
||||||
<code>{Text(string + " - ")}</code>;
|
|
||||||
|
|
||||||
protected def decodeTag(tag: String): String = tag.capitalize
|
|
||||||
|
|
||||||
def shortHeader(entity: Entity)(implicit from: Frame): NodeSeq =
|
|
||||||
<tr>
|
|
||||||
<td valign="top" class="modifiers">
|
|
||||||
<code>{Text(entity.flagsString)} {Text(entity.kind)}</code>
|
|
||||||
</td>
|
|
||||||
<td class="signature">
|
|
||||||
<em>{link(decode(entity.sym))}</em>
|
|
||||||
{bodyFor(entity) ++ extendsFor(entity)}
|
|
||||||
{
|
|
||||||
entity.resultType match {
|
|
||||||
case Some(PolyType(_, ConstantType(v))) => Text(" = " + v.escapedStringValue)
|
|
||||||
case _ => NodeSeq.Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
val cmnt = entity.decodeComment
|
|
||||||
if (cmnt.isEmpty) NodeSeq.Empty
|
|
||||||
else shortComment(cmnt.get)
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
// pattern detecting first line of comment (see ticket #224)
|
|
||||||
private val pat = Pattern.compile("[ \t]*(/\\*)[ \t]*")
|
|
||||||
|
|
||||||
/** Ticket #224
|
|
||||||
* Write the first sentence as a short summary of the method, as scaladoc
|
|
||||||
* automatically places it in the method summary table (and index).
|
|
||||||
* (see http://java.sun.com/j2se/javadoc/writingdoccomments/)
|
|
||||||
*/
|
|
||||||
def shortComment(cmnt: Comment): NodeSeq = {
|
|
||||||
val lines = cmnt.body split "<p>"
|
|
||||||
val first =
|
|
||||||
if (lines.length < 2)
|
|
||||||
lines(0)
|
|
||||||
else {
|
|
||||||
val line0 = lines(0)
|
|
||||||
val mat = pat matcher line0
|
|
||||||
if (mat.matches()) line0 + lines(1)
|
|
||||||
else line0
|
|
||||||
}
|
|
||||||
<div>{parse(first/*cmnt.body*/)}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
def attrsFor(entity: Entity)(implicit from: Frame): NodeSeq = {
|
|
||||||
def attrFor(attr: AnnotationInfo): Node = {
|
|
||||||
val buf = new StringBuilder
|
|
||||||
val AnnotationInfo(tpe, args, nvPairs) = attr
|
|
||||||
val name = link(decode(tpe.typeSymbol))
|
|
||||||
if (!args.isEmpty)
|
|
||||||
buf.append(args.mkString("(", ",", ")"))
|
|
||||||
if (!nvPairs.isEmpty)
|
|
||||||
for (((name, value), index) <- nvPairs.zipWithIndex) {
|
|
||||||
if (index > 0)
|
|
||||||
buf.append(", ")
|
|
||||||
buf.append(name).append(" = ").append(value)
|
|
||||||
}
|
|
||||||
Group(name ++ Text(buf.toString))
|
|
||||||
}
|
|
||||||
def toGroup(x: AnnotationInfo): Node = Group(Text("@") ++ attrFor(x) ++ <br/>)
|
|
||||||
if (entity.sym.hasFlag(symtab.Flags.CASE)) NodeSeq.Empty
|
|
||||||
else NodeSeq fromSeq (entity.attributes map toGroup)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
|
||||||
|
import reporters.Reporter
|
||||||
|
|
||||||
|
/** A documentation processor controls the process of generating Scala documentation, which is as follows.
|
||||||
|
*
|
||||||
|
* * A simplified compiler instance (with only the front-end phases enabled) is created, and additional
|
||||||
|
* ''sourceless'' comments are registered.
|
||||||
|
* * Documentable files are compiled, thereby filling the compiler's symbol table.
|
||||||
|
* * A documentation model is extracted from the post-compilation compiler's symbol table.
|
||||||
|
* * A generator is used to transform the model into the correct final format (HTML).
|
||||||
|
*
|
||||||
|
* A processor contains a single compiler instantiated from the processor's settings. Each call to the `run` method
|
||||||
|
* uses the same compiler instance with the same symbol table. In particular, this implies that the scaladoc site
|
||||||
|
* obtained from a call to `run` will contain documentation about files compiled during previous calls to the same
|
||||||
|
* processor's `run` method.
|
||||||
|
*
|
||||||
|
* @param reporter The reporter to which both documentation and compilation errors will be reported.
|
||||||
|
* @param settings The settings to be used by the documenter and compiler for generating documentation.
|
||||||
|
*
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
class Processor(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) {
|
||||||
|
override protected def computeInternalPhases() {
|
||||||
|
phasesSet += syntaxAnalyzer
|
||||||
|
phasesSet += analyzer.namerFactory
|
||||||
|
phasesSet += analyzer.typerFactory
|
||||||
|
phasesSet += superAccessors
|
||||||
|
phasesSet += pickler
|
||||||
|
phasesSet += refchecks
|
||||||
|
}
|
||||||
|
override def onlyPresentation = true
|
||||||
|
lazy val addSourceless = {
|
||||||
|
val sless = new SourcelessComments { val global = compiler }
|
||||||
|
comments ++= 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 document(files: List[String]): Unit = {
|
||||||
|
(new compiler.Run()) compile files
|
||||||
|
compiler.addSourceless
|
||||||
|
if (!reporter.hasErrors)
|
||||||
|
(new html.SiteFactory(reporter, settings)) generate (new model.EntityFactory(compiler, settings)).makeModel
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,19 +11,14 @@ import java.io.File
|
||||||
import java.lang.System
|
import java.lang.System
|
||||||
|
|
||||||
class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
|
class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
|
||||||
|
|
||||||
/** scaladoc specific options */
|
/** scaladoc specific options */
|
||||||
val memberaccess = ChoiceSetting ("-access", "Show only public, protected/public (default) or all classes and members",
|
val docformat = ChoiceSetting ("-doc-format", "Selects to which format documentation is rendered", List("html"), "html")
|
||||||
List("public", "protected", "private"), "protected")
|
val doctitle = StringSetting ("-doc-title", "doc-title", "Include title for the overview page", "Scala 2 API")
|
||||||
val pagebottom = StringSetting ("-bottom", "pagebottom", "Include bottom text for each page", "")
|
|
||||||
val doccharset = StringSetting ("-charset", "doccharset", "Charset for cross-platform viewing of generated documentation.", "")
|
// working around issue described in r18708.
|
||||||
val doctitle = StringSetting ("-doctitle", "doctitle", "Include title for the overview page", "Scala 2<br/>API Specification")
|
suppressVTWarn.value = true
|
||||||
val pagefooter = StringSetting ("-footer", "pagefooter", "Include footer text for each page", "")
|
|
||||||
val pageheader = StringSetting ("-header", "pageheader", "Include header text for each page", "")
|
|
||||||
val linksource = BooleanSetting ("-linksource", "Generate source in HTML")
|
|
||||||
val nocomment = BooleanSetting ("-nocomment", "Suppress description and tags, generate only declarations.")
|
|
||||||
val stylesheetfile = StringSetting ("-stylesheetfile", "stylesheetfile", "File to change style of the generated documentation", "style.css")
|
|
||||||
val pagetop = StringSetting ("-top", "pagetop", "Include top text for each page", "")
|
|
||||||
val windowtitle = StringSetting ("-windowtitle", "windowtitle", "Specify window title of generated HTML documentation", "Scala 2")
|
|
||||||
|
|
||||||
// working around issue described in r18708.
|
// working around issue described in r18708.
|
||||||
suppressVTWarn.value = true
|
suppressVTWarn.value = true
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains comments to all symbols which pre-exist in Scala, such as 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, String]
|
||||||
|
|
||||||
|
comment(NothingClass) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>Nothing</code> is - together with class <a href="Null.html">
|
||||||
|
* <code>Null</code></a> - at the bottom of the
|
||||||
|
* <a href="http://scala-lang.org" target="_top">Scala</a> type
|
||||||
|
* hierarchy.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Type <code>Nothing</code> is a subtype of every other type
|
||||||
|
* (including <a href="Null.html"><code>Null</code></a>); there
|
||||||
|
* exist <em>no instances</em> of this type. Even though type
|
||||||
|
* <code>Nothing</code> is empty, it is nevertheless useful as a
|
||||||
|
* type parameter. For instance, the <a href="http://scala-lang.org"
|
||||||
|
* target="_top">Scala</a> library defines a value
|
||||||
|
* <a href="Nil$object.html"><code>Nil</code></a> of type
|
||||||
|
* <code><a href="List.html">List</a>[Nothing]</code>. Because lists
|
||||||
|
* are covariant in <a href="http://scala-lang.org" target="_top">Scala</a>,
|
||||||
|
* this makes <a href="Nil$object.html"><code>Nil</code></a> an
|
||||||
|
* instance of <code><a href="List.html">List</a>[T]</code>, for
|
||||||
|
* any element type <code>T</code>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(NullClass) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>Null</code> is - together with class <a href="Nothing.html">
|
||||||
|
* <code>Nothing</code> - at the bottom of the
|
||||||
|
* <a href="http://scala-lang.org" target="_top">Scala</a> type
|
||||||
|
* hierarchy.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Type <code>Null</code> is a subtype of all reference types; its
|
||||||
|
* only instance is the <code>null</code> reference.
|
||||||
|
* Since <code>Null</code> is not a subtype of value types,
|
||||||
|
* <code>null</code> is not a member of any such type. For instance,
|
||||||
|
* 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) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>Any</code> is the root of the <a
|
||||||
|
* href="http://scala-lang.org/"
|
||||||
|
* target="_top">Scala</a> class hierarchy. Every class in a
|
||||||
|
* <a href="http://scala-lang.org/" target="_top">Scala</a> execution
|
||||||
|
* environment inherits directly or indirectly from this class.
|
||||||
|
* Class <code>Any</code> has two direct subclasses:
|
||||||
|
* <a href="AnyRef.html"><code>AnyRef</code></a> and
|
||||||
|
* <a href="AnyVal.html"><code>AnyVal</code></a>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Any_equals) = """
|
||||||
|
/** This method is used to compare the receiver object (<code>this</code>)
|
||||||
|
* with the argument object (<code>arg0</code>) for equivalence.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The default implementations of this method is an <a
|
||||||
|
* href="http://en.wikipedia.org/wiki/Equivalence_relation">equivalence
|
||||||
|
* relation</a>:
|
||||||
|
* <ul>
|
||||||
|
* <li>It is reflexive: for any instance <code>x</code> of type <code>Any</code>,
|
||||||
|
* <code>x.equals(x)</code> should return <code>true</code>.</li>
|
||||||
|
* <li>It is symmetric: for any instances <code>x</code> and <code>y</code> of type
|
||||||
|
* <code>Any</code>, <code>x.equals(y)</code> should return <code>true</code> if and only
|
||||||
|
* if <code>y.equals(x)</code> returns <code>true</code>.</li>
|
||||||
|
* <li>It is transitive: for any instances
|
||||||
|
* <code>x</code>, <code>y</code>, and <code>z</code> of type <code>AnyRef</code>
|
||||||
|
* if <code>x.equals(y)</code> returns <code>true</code> and
|
||||||
|
* <code>y.equals(z)</code> returns
|
||||||
|
* <code>true</code>, then <code>x.equals(z)</code> should return <code>true</code>.</li>
|
||||||
|
*</ul>
|
||||||
|
*</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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 <code>hashCode</code> to ensure that objects that are
|
||||||
|
* "equal" (<code>o1.equals(o2)</code> returns <code>true</code>)
|
||||||
|
* hash to the same <a href="Int.html"><code>Int</code></a>
|
||||||
|
* (<code>o1.hashCode.equals(o2.hashCode)</code>).
|
||||||
|
*
|
||||||
|
* @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_==) = """
|
||||||
|
/** `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_!=) = """
|
||||||
|
/** `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) = """
|
||||||
|
/** 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) = """
|
||||||
|
/**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
|
||||||
|
* erasure semantics. Therefore the expression
|
||||||
|
* <code>1.asInstanceOf[String]</code> will throw a
|
||||||
|
* <code>ClassCastException</code> at runtime, while the expression
|
||||||
|
* <code>List(1).asInstanceOf[List[String]]</code> 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 <code>T0</code>.
|
||||||
|
* @return the receiver object.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Any_isInstanceOf) = """
|
||||||
|
/** 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
|
||||||
|
* semantics. Therefore the expression
|
||||||
|
* <code>1.isInstanceOf[String]</code> will return
|
||||||
|
* <code>false</code>, while the expression
|
||||||
|
* <code>List(1).isInstanceOf[List[String]]</code> will return
|
||||||
|
* <code>true</code>. 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 <code>true</code> if the receiver object is an
|
||||||
|
* instance of erasure of type <code>T0</code>; <code>false</code> otherwise. */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Any_hashCode) = """
|
||||||
|
/** Returns a hash code value for the object.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The default hashing algorithm is platform dependent.
|
||||||
|
*
|
||||||
|
* Note that it is allowed for two objects to have identical hash
|
||||||
|
* codes (<code>o1.hashCode.equals(o2.hashCode)</code>) yet not be
|
||||||
|
* equal (<code>o1.equals(o2)</code> returns <code>false</code>). A
|
||||||
|
* degenerate implementation could always return <code>0</code>.
|
||||||
|
* However, it is required that if two objects are equal
|
||||||
|
* (<code>o1.equals(o2)</code> returns <code>true</code>) that they
|
||||||
|
* have identical hash codes
|
||||||
|
* (<code>o1.hashCode.equals(o2.hashCode)</code>). Therefore, when
|
||||||
|
* overriding this method, be sure to verify that the behavior is
|
||||||
|
* consistent with the <code>equals</code> method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* @return the hash code value for the object.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/* Documentation for AnyRef */
|
||||||
|
|
||||||
|
comment(AnyRefClass) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>AnyRef</code> is the root class of all
|
||||||
|
* <em>reference types</em>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_==) = """
|
||||||
|
/** <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) = """
|
||||||
|
/** <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) = """
|
||||||
|
/** 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>
|
||||||
|
* The details of when and if the <code>finalize</code> method are
|
||||||
|
* invoked, as well as the interaction between <code>finalize</code>
|
||||||
|
* and non-local returns and exceptions, are all platform dependent.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_clone) = """
|
||||||
|
/** This method creates and returns a copy of the receiver object.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The default implementation of the <code>clone</code> method is platform dependent.
|
||||||
|
*
|
||||||
|
* @return a copy of the receiver object.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_getClass) = """
|
||||||
|
/** Returns a representation that corresponds to the dynamic class of the receiver object.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The nature of the representation is platform dependent.
|
||||||
|
*
|
||||||
|
* @return a representation that corresponds to the dynamic class of the receiver object.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_notify) = """
|
||||||
|
/** Wakes up a single thread that is waiting on the receiver object's monitor. */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_notifyAll) = """
|
||||||
|
/** Wakes up all threads that are waiting on the receiver object's monitor. */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(Object_eq) = """
|
||||||
|
/** This method is used to test whether the argument (<code>arg0</code>) is a reference to the
|
||||||
|
* receiver object (<code>this</code>).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The <code>eq</code> method implements an
|
||||||
|
* <a href="http://en.wikipedia.org/wiki/Equivalence_relation">equivalence relation</a> on non-null instances of
|
||||||
|
* <code>AnyRef</code>:
|
||||||
|
* <ul>
|
||||||
|
* <li>It is reflexive: for any non-null instance <code>x</code> of type <code>AnyRef</code>,
|
||||||
|
* <code>x.eq(x)</code> returns <code>true</code>.</li>
|
||||||
|
* <li>It is symmetric: for any non-null instances <code>x</code> and <code>y</code> of type
|
||||||
|
* <code>AnyRef</code>, <code>x.eq(y)</code> returns <code>true</code> if and only
|
||||||
|
* if <code>y.eq(x)</code> returns <code>true</code>.</li>
|
||||||
|
* <li>It is transitive: for any non-null instances
|
||||||
|
* <code>x</code>, <code>y</code>, and <code>z</code> of type <code>AnyRef</code>
|
||||||
|
* if <code>x.eq(y)</code> returns <code>true</code> and
|
||||||
|
* <code>y.eq(z)</code> returns
|
||||||
|
* <code>true</code>, then <code>x.eq(z)</code> returns <code>true</code>.</li>
|
||||||
|
* </ul>
|
||||||
|
* Additionally, the <code>eq</code> method has three other properties.
|
||||||
|
* <ul>
|
||||||
|
* <li>It is consistent: for any non-null instances <code>x</code> and <code>y</code> of type <code>AnyRef</code>,
|
||||||
|
* multiple invocations of <code>x.eq(y)</code> consistently returns <code>true</code>
|
||||||
|
* or consistently returns <code>false</code>.</li>
|
||||||
|
* <li>For any non-null instance <code>x</code> of type <code>AnyRef</code>,
|
||||||
|
* <code>x.eq(null)</code> and <code>null.eq(x)</code> returns <code>false</code>.</li>
|
||||||
|
* <li><code>null.eq(null)</code> returns <code>true</code>.</li>
|
||||||
|
*</ul>
|
||||||
|
*</p>
|
||||||
|
*
|
||||||
|
* <p> When overriding the <code>equals</code> or
|
||||||
|
* <code>hashCode</code> methods, it is important to ensure that
|
||||||
|
* their behavior is consistent with reference equality. Therefore,
|
||||||
|
* if two objects are references to each other (<code>o1 eq
|
||||||
|
* o2</code>), they should be equal to each other (<code>o1 ==
|
||||||
|
* o2</code>) and they should hash to the same value
|
||||||
|
* (<code>o1.hashCode == o2.hashCode</code>).</p>
|
||||||
|
*
|
||||||
|
* @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) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>AnyVal</code> is the root class of all
|
||||||
|
* <em>value types</em>.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* <code>AnyVal</code> has a fixed number subclasses, which
|
||||||
|
* describe values which are not implemented as objects in the
|
||||||
|
* underlying host system.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Classes <a href="Double.html"><code>Double</code></a>,
|
||||||
|
* <a href="Float.html"><code>Float</code></a>,
|
||||||
|
* <a href="Long.html"><code>Long</code></a>,
|
||||||
|
* <a href="Int.html"><code>Int</code></a>,
|
||||||
|
* <a href="Char.html"><code>Char</code></a>,
|
||||||
|
* <a href="Short.html"><code>Short</code></a>, and
|
||||||
|
* <a href="Byte.html"><code>Byte</code></a> are together called
|
||||||
|
* <em>numeric value types</em>.
|
||||||
|
* Classes <a href="Byte.html"><code>Byte</code></a>,
|
||||||
|
* <a href="Short.html"><code>Short</code></a>, or
|
||||||
|
* <a href="Char.html"><code>Char</code></a>
|
||||||
|
* are called <em>subrange types</em>. Subrange types, as well as
|
||||||
|
* <a href="Int.html"><code>Int</code></a> and
|
||||||
|
* <a href="Long.html"><code>Long</code></a> are called
|
||||||
|
* <em>integer types</em>, whereas
|
||||||
|
* <a href="Float.html"><code>Float</code></a> and
|
||||||
|
* <a href="Double.html"><code>Double</code></a> are called
|
||||||
|
* <em>floating point types</em>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(BooleanClass) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>Boolean</code> has only two values: <code>true</code>
|
||||||
|
* and <code>false</code>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
|
||||||
|
comment(UnitClass) = """
|
||||||
|
/** <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) = """
|
||||||
|
/** <p>
|
||||||
|
* Class <code>""" + sym.name + """</code> belongs to the value
|
||||||
|
* classes whose instances are not represented as objects by the
|
||||||
|
* underlying host system. There is an implicit conversion from
|
||||||
|
* instances of <code>""" + sym.name + """</code> to instances of
|
||||||
|
* <a href="runtime/Rich""" + sym.name + """.html"><code>runtime.Rich""" + sym.name + """</code></a> which
|
||||||
|
* provides useful non-primitive operations. All value classes inherit
|
||||||
|
* from class <a href="AnyVal.html"><code>AnyVal</code></a>.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Values <code>""" + maxValue + """</code> and <code>""" + minValue + """</code>
|
||||||
|
* are in defined in object <a href="Math$object.html">scala.Math</a>.
|
||||||
|
* </p> */
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
comment
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
= TODO in Scaladoc =
|
||||||
|
|
||||||
|
== Model extractor ==
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== Parser ==
|
||||||
|
|
||||||
|
* Report more than one error per Scaladoc comment. This is caused by the reporter being used, and the fact that all errors are positioned on the documented symbol.
|
||||||
|
* Maintain position information, and use it in error messages (currently all positions are on symbol being documented)
|
||||||
|
* Parse wiki list syntax
|
||||||
|
* Parse wiki table syntax
|
||||||
|
* Parse URL links
|
||||||
|
* Parse symbol (class or method) links
|
||||||
|
|
||||||
|
== HTML generator ==
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author David Bernard, Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package html
|
||||||
|
|
||||||
|
import model._
|
||||||
|
import comment._
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import scala.xml.dtd.{DocType, PublicID}
|
||||||
|
import xml.{Unparsed, XML, NodeSeq}
|
||||||
|
|
||||||
|
/** An html page that is part of a Scaladoc site.
|
||||||
|
* @author David Bernard
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
abstract class HtmlPage { thisPage =>
|
||||||
|
|
||||||
|
/** The path of this page, relative to the API site. `path.tail` is a list of folder names leading to this page (from
|
||||||
|
* closest package to one-above-root package), `path.head` is the file name of this page. Note that `path` has a
|
||||||
|
* length of at least one. */
|
||||||
|
def path: List[String]
|
||||||
|
|
||||||
|
/** The title of this page. */
|
||||||
|
protected def title: String
|
||||||
|
|
||||||
|
/** Additional header elements (links, scripts, meta tags, etc.) required for this page. */
|
||||||
|
protected def headers: NodeSeq
|
||||||
|
|
||||||
|
/** The body of this page. */
|
||||||
|
protected def body: NodeSeq
|
||||||
|
|
||||||
|
/** Writes this page as a file. The file's location is relative to the generator's site root, and the encoding is
|
||||||
|
* also defined by the generator.
|
||||||
|
* @param generator The generator that is writing this page. */
|
||||||
|
def writeFor(site: SiteFactory): Unit = {
|
||||||
|
val pageFile = new File(site.siteRoot, thisPage.path.reverse.mkString("/"))
|
||||||
|
val pageFolder = pageFile.getParentFile
|
||||||
|
if (!pageFolder.exists) pageFolder.mkdirs()
|
||||||
|
val doctype =
|
||||||
|
DocType("html", PublicID("-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"), Nil)
|
||||||
|
val html =
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{ title }</title>
|
||||||
|
<meta http-equiv="content-type" content={ "text/html; charset=" + site.encoding }/>
|
||||||
|
<script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script>
|
||||||
|
{ headers }
|
||||||
|
</head>
|
||||||
|
{ body }
|
||||||
|
</html>
|
||||||
|
XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype)
|
||||||
|
}
|
||||||
|
|
||||||
|
def templateToPath(tpl: TemplateEntity): List[String] = {
|
||||||
|
def downPacks(pack: Package): List[String] =
|
||||||
|
if (pack.isRootPackage) Nil else (pack.name :: downPacks(pack.inTemplate))
|
||||||
|
def downInner(nme: String, tpl: TemplateEntity): (String, Package) = {
|
||||||
|
tpl.inTemplate match {
|
||||||
|
case inPkg: Package => (nme + ".html", inPkg)
|
||||||
|
case inTpl => downInner(doName(inTpl) + "$" + nme, inTpl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def doName(tpl: TemplateEntity): String =
|
||||||
|
tpl.name + (if (tpl.isObject) "$" else "")
|
||||||
|
val (file, pack) =
|
||||||
|
tpl match {
|
||||||
|
case p: Package => ("package.html", p)
|
||||||
|
case _ => downInner(doName(tpl), tpl)
|
||||||
|
}
|
||||||
|
file :: downPacks(pack)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A relative link from this page to some destination class entity.
|
||||||
|
* @param destEntity The class or object entity that the link will point to. */
|
||||||
|
def relativeLinkTo(destClass: TemplateEntity): String =
|
||||||
|
relativeLinkTo(templateToPath(destClass))
|
||||||
|
|
||||||
|
/** A relative link from this page to some destination page in the Scaladoc site.
|
||||||
|
* @param destPage The page that the link will point to. */
|
||||||
|
def relativeLinkTo(destPage: HtmlPage): String = {
|
||||||
|
relativeLinkTo(destPage.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A relative link from this page to some destination path.
|
||||||
|
* @param destPath The path that the link will point to. */
|
||||||
|
def relativeLinkTo(destPath: List[String]): String = {
|
||||||
|
def relativize(from: List[String], to: List[String]): List[String] = (from, to) match {
|
||||||
|
case (f :: fs, t :: ts) if (f == t) => // both paths are identical to that point
|
||||||
|
relativize(fs, ts)
|
||||||
|
case (fss, tss) =>
|
||||||
|
List.fill(fss.length - 1)("..") ::: tss
|
||||||
|
}
|
||||||
|
relativize(thisPage.path.reverse, destPath.reverse).mkString("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transforms an optional comment into an styled HTML tree representing its body if it is defined, or into an empty
|
||||||
|
* node sequence if it is not. */
|
||||||
|
def commentToHtml(comment: Option[Comment]): NodeSeq =
|
||||||
|
(comment map (commentToHtml(_))) getOrElse NodeSeq.Empty
|
||||||
|
|
||||||
|
/** Transforms a comment into an styled HTML tree representing its body. */
|
||||||
|
def commentToHtml(comment: Comment): NodeSeq =
|
||||||
|
bodyToHtml(comment.body)
|
||||||
|
|
||||||
|
def bodyToHtml(body: Body): NodeSeq =
|
||||||
|
body.blocks flatMap (blockToHtml(_))
|
||||||
|
|
||||||
|
def blockToHtml(block: Block): NodeSeq = block match {
|
||||||
|
case Title(in, 1) => <h1>{ inlineToHtml(in) }</h1>
|
||||||
|
case Title(in, 2) => <h2>{ inlineToHtml(in) }</h2>
|
||||||
|
case Title(in, 3) => <h3>{ inlineToHtml(in) }</h3>
|
||||||
|
case Title(in, _) => <h4>{ inlineToHtml(in) }</h4>
|
||||||
|
case Paragraph(in) => <p>{ inlineToHtml(in) }</p>
|
||||||
|
case Code(data) => <p><code>{ Unparsed(data) }</code></p>
|
||||||
|
case UnorderedList(items) =>
|
||||||
|
<ul>{items map { i => <li>{ blockToHtml(i) }</li>}}</ul>
|
||||||
|
case OrderedList(items) =>
|
||||||
|
<ol>{items map { i => <li>{ blockToHtml(i) }</li>}}</ol>
|
||||||
|
case DefinitionList(items) =>
|
||||||
|
<dl>{items map { case (t, d) => <dt>{ inlineToHtml(t) }</dt><dd>{ blockToHtml(d) }</dd> } }</dl>
|
||||||
|
case HorizontalRule() =>
|
||||||
|
<hr/>
|
||||||
|
}
|
||||||
|
|
||||||
|
def inlineToHtml(inl: Inline): NodeSeq = inl match {
|
||||||
|
//case URLLink(url, text) => <a href={url}>{if(text.isEmpty)url else inlineSeqsToXml(text)}</a>
|
||||||
|
case Chain(items) => items flatMap (inlineToHtml(_))
|
||||||
|
case Italic(in) => <i>{ inlineToHtml(in) }</i>
|
||||||
|
case Bold(in) => <b>{ inlineToHtml(in) }</b>
|
||||||
|
case Underline(in) => <u>{ inlineToHtml(in) }</u>
|
||||||
|
case Superscript(in) => <sup>{ inlineToHtml(in) }</sup>
|
||||||
|
case Subscript(in) => <sub>{ inlineToHtml(in) }</sub>
|
||||||
|
case Link(raw) => Unparsed(raw)//error("link not supported") // TODO
|
||||||
|
case Monospace(text) => <code>{ Unparsed(text) }</code>
|
||||||
|
case Text(text) => Unparsed(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
def typeToHtml(tpe: model.TypeEntity): NodeSeq = {
|
||||||
|
|
||||||
|
// TODO: Generate links using tpe's refEntity map
|
||||||
|
|
||||||
|
xml.Text(tpe.name)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author David Bernard, Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package html
|
||||||
|
|
||||||
|
import reporters.Reporter
|
||||||
|
import model._
|
||||||
|
|
||||||
|
import java.io.{FileOutputStream, File}
|
||||||
|
import scala.collection._
|
||||||
|
|
||||||
|
/** A class that can generate Scaladoc sites to some fixed root folder.
|
||||||
|
* @author David Bernard
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
class SiteFactory(val reporter: Reporter, val settings: Settings) {
|
||||||
|
|
||||||
|
/** The character encoding to be used for generated Scaladoc sites. This value is currently always UTF-8. */
|
||||||
|
def encoding: String = "UTF-8"
|
||||||
|
|
||||||
|
/** The character encoding to be used for generated Scaladoc sites. This value is defined by the generator's
|
||||||
|
* settings. */
|
||||||
|
def siteRoot: File = new File(settings.outdir.value)
|
||||||
|
|
||||||
|
/** Generates the Scaladoc site for a model into the site toot. A scaladoc site is a set of HTML and related files
|
||||||
|
* that document a model extracted from a compiler run.
|
||||||
|
* @param model The model to generate in the form of a sequence of packages. */
|
||||||
|
def generate(modelRoot: Package): Unit = {
|
||||||
|
|
||||||
|
def copyResource(subPath: String) {
|
||||||
|
val buf = new Array[Byte](1024)
|
||||||
|
val in = getClass.getResourceAsStream("/scala/tools/nsc/doc/html/resource/" + subPath)
|
||||||
|
assert(in != null)
|
||||||
|
val dest = new File(siteRoot, subPath)
|
||||||
|
dest.getParentFile.mkdirs()
|
||||||
|
val out = new FileOutputStream(dest)
|
||||||
|
try {
|
||||||
|
var len = 0
|
||||||
|
while ({len = in.read(buf); len != -1})
|
||||||
|
out.write(buf, 0, len)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
in.close()
|
||||||
|
out.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copyResource("lib/jquery.js")
|
||||||
|
copyResource("lib/index.css")
|
||||||
|
copyResource("lib/index.js")
|
||||||
|
copyResource("lib/template.css")
|
||||||
|
copyResource("lib/template.js")
|
||||||
|
copyResource("lib/class.png")
|
||||||
|
copyResource("lib/class_big.png")
|
||||||
|
copyResource("lib/object.png")
|
||||||
|
copyResource("lib/object_big.png")
|
||||||
|
copyResource("lib/trait.png")
|
||||||
|
copyResource("lib/trait_big.png")
|
||||||
|
copyResource("lib/package.png")
|
||||||
|
copyResource("lib/package_big.png")
|
||||||
|
|
||||||
|
new page.Index(modelRoot) writeFor this
|
||||||
|
|
||||||
|
val written = mutable.HashSet.empty[DocTemplateEntity]
|
||||||
|
|
||||||
|
def writeTemplate(tpl: DocTemplateEntity): Unit = {
|
||||||
|
new page.Template(tpl) writeFor this
|
||||||
|
written += tpl
|
||||||
|
tpl.templates filter { t => !(written contains t) } map (writeTemplate(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTemplate(modelRoot)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author David Bernard, Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package html
|
||||||
|
package page
|
||||||
|
|
||||||
|
import model._
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
import scala.xml._
|
||||||
|
|
||||||
|
class Index(modelRoot: Package) extends HtmlPage {
|
||||||
|
|
||||||
|
def path = List("index.html")
|
||||||
|
|
||||||
|
def title = "Scaladoc: all classes and objects"
|
||||||
|
|
||||||
|
def headers =
|
||||||
|
<xml:group>
|
||||||
|
<style type="text/css">
|
||||||
|
@import url({ relativeLinkTo(List("index.css", "lib")) }) screen;
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src={ relativeLinkTo{List("index.js", "lib")} }></script>
|
||||||
|
</xml:group>
|
||||||
|
|
||||||
|
def body =
|
||||||
|
<body>
|
||||||
|
<div id="browser">
|
||||||
|
<input id="quickflt" type="text"/>
|
||||||
|
<div id="tpl">{
|
||||||
|
def packageElem(pack: model.Package): NodeSeq = {
|
||||||
|
<xml:group>
|
||||||
|
{ if (!pack.isRootPackage)
|
||||||
|
<h3><a class="tplshow" href={ relativeLinkTo(pack) }>{ pack.qualifiedName }</a></h3>
|
||||||
|
else NodeSeq.Empty
|
||||||
|
}
|
||||||
|
<ol class="templates">{
|
||||||
|
val tpls: Map[String, Seq[DocTemplateEntity]] =
|
||||||
|
(pack.templates filter (!_.isPackage)) groupBy (_.name)
|
||||||
|
for (tn <- tpls.keySet.toSeq sortWith (_.toLowerCase < _.toLowerCase)) yield {
|
||||||
|
val entries = tpls(tn) sortWith { (less, more) => less.isTrait || more.isObject }
|
||||||
|
def doEntry(ety: DocTemplateEntity, firstEty: Boolean): NodeSeq = {
|
||||||
|
val etyTpe =
|
||||||
|
if (ety.isTrait) "trait" else if (ety.isClass) "class" else if (ety.isObject) "object" else "package"
|
||||||
|
<a class="tplshow" href={ relativeLinkTo(ety) }>
|
||||||
|
{ if (firstEty) Text(packageQualifiedName(ety)) else NodeSeq.Empty }
|
||||||
|
<span class={ etyTpe }>({ Text(etyTpe) })</span>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
<li title={ entries.head.qualifiedName }>{
|
||||||
|
doEntry(entries.head, true) ++ (entries.tail map (doEntry(_, false)))
|
||||||
|
}</li>
|
||||||
|
}
|
||||||
|
}</ol>
|
||||||
|
<ol class="packages"> {
|
||||||
|
for (sp <- pack.packages sortWith (_.name.toLowerCase < _.name.toLowerCase)) yield
|
||||||
|
<li>{ packageElem(sp) }</li>
|
||||||
|
}</ol>
|
||||||
|
</xml:group>
|
||||||
|
}
|
||||||
|
packageElem(modelRoot)
|
||||||
|
}</div>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
<iframe src={ relativeLinkTo{List("package.html")} }/>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
def packageQualifiedName(ety: DocTemplateEntity): String =
|
||||||
|
if (ety.inTemplate.isPackage) ety.name else (packageQualifiedName(ety.inTemplate) + "." + ety.name)
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author David Bernard, Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package html
|
||||||
|
package page
|
||||||
|
|
||||||
|
import model._
|
||||||
|
import comment._
|
||||||
|
import xml.{NodeSeq, Unparsed}
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class Source(sourceFile: File) extends HtmlPage {
|
||||||
|
|
||||||
|
val path = List("source.html")
|
||||||
|
|
||||||
|
val title = "Scaladoc: page source"
|
||||||
|
|
||||||
|
val headers =
|
||||||
|
NodeSeq.Empty
|
||||||
|
|
||||||
|
val body =
|
||||||
|
<body>
|
||||||
|
<h1>Page source is not implmented yet</h1>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
def readTextFromSrcDir(subPath: String) :Option[String] = {
|
||||||
|
readTextFromFile(new File(sourceDir, subPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
def readTextFromFile(f : File) :Option[String] = {
|
||||||
|
if (f.exists) {
|
||||||
|
Some(Source.fromFile(f)(Codec.default).getLines().mkString(""))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def writeTextToFile(f : File, txt : String, header: Option[String], footer: Option[String]) {
|
||||||
|
val out = new FileOutputStream(f)
|
||||||
|
try {
|
||||||
|
val enc = "UTF-8"
|
||||||
|
header.foreach(s => out.write(s.getBytes(enc)))
|
||||||
|
out.write(txt.getBytes(enc))
|
||||||
|
footer.foreach(s => out.write(s.getBytes(enc)))
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
out.close()
|
||||||
|
} catch {
|
||||||
|
case _ => //ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait SourceHtmlizer {
|
||||||
|
def scalaToHtml(src :File) : Option[File]
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val sourceHtmlizer : SourceHtmlizer = {
|
||||||
|
if (cfg.htmlizeSource) {
|
||||||
|
new SourceHtmlizer {
|
||||||
|
|
||||||
|
val inDir: File = cfg.sourcedir
|
||||||
|
val outDir: File = cfg.outputdir
|
||||||
|
|
||||||
|
private def relativize(uri: URI, from: URI) = linkHelper.relativize(uri, from).getOrElse("__notFound__" + uri.getPath)
|
||||||
|
|
||||||
|
def header(dest: URI) = Some("""
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href='""" + relativize(new URI("site:/_highlighter/SyntaxHighlighter.css"), dest) + """' rel='stylesheet' type='text/css'/>
|
||||||
|
<script language='javascript' src='""" + relativize(new URI("site:/_highlighter/shAll.js"), dest) + """'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre name="code" class="scala" style="width:100%">
|
||||||
|
""")
|
||||||
|
|
||||||
|
def footer(dest: URI) = Some("""</pre>
|
||||||
|
<script language='javascript'>
|
||||||
|
dp.SyntaxHighlighter.ClipboardSwf = '""" + relativize(new URI("site:/_highlighter/clipboard.swf"), dest) + """';
|
||||||
|
dp.SyntaxHighlighter.HighlightAll('code');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""")
|
||||||
|
|
||||||
|
//TODO: escape the source code
|
||||||
|
def scalaToHtml(src :File) = {
|
||||||
|
val dest = new File(outDir, fileHelper.relativePathUnderDir(src, inDir) + ".html")
|
||||||
|
if (!dest.exists || dest.lastModified < src.lastModified) {
|
||||||
|
|
||||||
|
//we need to verify whether the directory we are trying to write to has already been created or not
|
||||||
|
if(!dest.getParentFile.exists) dest.getParentFile.mkdirs
|
||||||
|
|
||||||
|
val uri = linkHelper.uriFor(dest).get
|
||||||
|
var txt = fileHelper.readTextFromFile(src).getOrElse("")
|
||||||
|
txt = txt.replace("<", "<")
|
||||||
|
fileHelper.writeTextToFile(dest, txt, header(uri), footer(uri))
|
||||||
|
}
|
||||||
|
Some(dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
def copyResources() {
|
||||||
|
val loader = this.getClass().getClassLoader()
|
||||||
|
val buf = new Array[Byte](1024)
|
||||||
|
def copyResource(name: String) = fileHelper.copyResource("/scala/tools/nsc/doc/html/resource/", name, outDir, loader, buf)
|
||||||
|
copyResource("_highlighter/clipboard.swf")
|
||||||
|
copyResource("_highlighter/shAll.js")
|
||||||
|
copyResource("_highlighter/SyntaxHighlighter.css")
|
||||||
|
}
|
||||||
|
|
||||||
|
copyResources()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new SourceHtmlizer {
|
||||||
|
def scalaToHtml(src :File) = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author David Bernard, Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package html
|
||||||
|
package page
|
||||||
|
|
||||||
|
import model._
|
||||||
|
|
||||||
|
import scala.xml.{NodeSeq, Text}
|
||||||
|
import scala.collection.mutable.HashSet
|
||||||
|
|
||||||
|
class Template(tpl: DocTemplateEntity) extends HtmlPage {
|
||||||
|
|
||||||
|
val path =
|
||||||
|
templateToPath(tpl)
|
||||||
|
|
||||||
|
val title = "Scaladoc for " + tpl.qualifiedName
|
||||||
|
|
||||||
|
val headers =
|
||||||
|
<xml:group>
|
||||||
|
<style type="text/css">
|
||||||
|
@import url({ relativeLinkTo(List("template.css", "lib")) }) screen;
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src={ relativeLinkTo{List("template.js", "lib")} }></script>
|
||||||
|
</xml:group>
|
||||||
|
|
||||||
|
val valueMembers =
|
||||||
|
(tpl.methods ::: tpl.values ::: (tpl.templates filter { tpl => tpl.isObject || tpl.isPackage })) sortWith (_.name < _.name)
|
||||||
|
|
||||||
|
val typeMembers =
|
||||||
|
(tpl.abstractTypes ::: tpl.aliasTypes ::: (tpl.templates filter { tpl => tpl.isTrait || tpl.isClass })) sortWith (_.name < _.name)
|
||||||
|
|
||||||
|
val constructors = (tpl match {
|
||||||
|
case cls: Class => cls.constructors
|
||||||
|
case _ => Nil
|
||||||
|
}) sortWith (_.name < _.name)
|
||||||
|
|
||||||
|
val body =
|
||||||
|
<body class={ if (tpl.isTrait || tpl.isClass) "type" else "value" }>
|
||||||
|
|
||||||
|
{ if (tpl.isRootPackage || tpl.inTemplate.isRootPackage) NodeSeq.Empty
|
||||||
|
else <p id="owner">{ tpl.inTemplate.qualifiedName }</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div id="definition">
|
||||||
|
<img src={ relativeLinkTo(List(kindToString(tpl) + "_big.png", "lib")) }/>
|
||||||
|
<h1>{ if (tpl.isRootPackage) "root package" else tpl.name }</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ signature(tpl, true) }
|
||||||
|
|
||||||
|
{ if (tpl.comment.isEmpty) NodeSeq.Empty else
|
||||||
|
<div id="comment">{ commentToHtml(tpl.comment) }</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div id="template">
|
||||||
|
|
||||||
|
{ if (tpl.linearization.isEmpty) NodeSeq.Empty else
|
||||||
|
<div id="mbrsel">
|
||||||
|
<div id="ancestors">
|
||||||
|
<h3>Inherits</h3>
|
||||||
|
<ol>{ tpl.linearization map { wte => <li class="in" name={ wte.qualifiedName }>{ wte.name }</li> } }</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ if (typeMembers.isEmpty) NodeSeq.Empty else
|
||||||
|
<div id="types" class="members">
|
||||||
|
<h3>Type Members</h3>
|
||||||
|
<ol>{ typeMembers map (memberToHtml(_)) }</ol>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ if (valueMembers.isEmpty) NodeSeq.Empty else
|
||||||
|
<div id="values" class="members">
|
||||||
|
<h3>Value Members</h3>
|
||||||
|
<ol>{ valueMembers map (memberToHtml(_)) }</ol>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{ if (constructors.isEmpty) NodeSeq.Empty else
|
||||||
|
<div id="constructors" class="members">
|
||||||
|
<h3>Instance constructors</h3>
|
||||||
|
<ol>{ constructors map (memberToHtml(_)) }</ol>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
def memberToHtml(mbr: MemberEntity): NodeSeq = {
|
||||||
|
val attributes: List[comment.Body] = Nil
|
||||||
|
<li name={ mbr.definitionName }>
|
||||||
|
{ signature(mbr, false) }
|
||||||
|
{ val prs: List[ParameterEntity] = mbr match {
|
||||||
|
case cls: Class if cls.isCaseClass => cls.typeParams ::: (cls.primaryConstructor map (_.valueParams.flatten)).toList.flatten
|
||||||
|
case trt: Trait => trt.typeParams
|
||||||
|
case dfe: Def => dfe.typeParams ::: dfe.valueParams.flatten
|
||||||
|
case ctr: Constructor => ctr.valueParams.flatten
|
||||||
|
case _ => Nil
|
||||||
|
}
|
||||||
|
def paramCommentToHtml(pr: ParameterEntity) =
|
||||||
|
if (pr.comment.isEmpty) NodeSeq.Empty else
|
||||||
|
<li class={ if (pr.isTypeParam) "tparam" else "param" } name={ pr.name }>{
|
||||||
|
commentToHtml(pr.comment.get)
|
||||||
|
}</li>
|
||||||
|
if (prs.isEmpty) NodeSeq.Empty else
|
||||||
|
<ol class="paramcmts">{ prs map (paramCommentToHtml(_)) }</ol>
|
||||||
|
}
|
||||||
|
{ val fvs: List[comment.Paragraph] = mbr.visibility.toList ::: mbr.flags
|
||||||
|
if (fvs.isEmpty) NodeSeq.Empty else
|
||||||
|
<ol class="attributes">{ fvs map { fv => <li>{ inlineToHtml(fv.text) }</li> } }</ol>
|
||||||
|
|
||||||
|
}
|
||||||
|
{ if (mbr.comment.isEmpty) NodeSeq.Empty else
|
||||||
|
<div class="comment">{ commentToHtml(mbr.comment) }</div>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
|
||||||
|
def kindToString(mbr: MemberEntity): String = mbr match {
|
||||||
|
case tpl: DocTemplateEntity =>
|
||||||
|
if (tpl.isPackage) "package" else if (tpl.isClass) "class" else if (tpl.isTrait) "trait" else "object"
|
||||||
|
case ctor: Constructor => "new"
|
||||||
|
case tme: MemberEntity =>
|
||||||
|
if (tme.isDef) "def" else if (tme.isVal) "val" else if (tme.isVar) "var" else "type"
|
||||||
|
}
|
||||||
|
|
||||||
|
def boundsToString(hi: Option[TypeEntity], lo: Option[TypeEntity]): String = {
|
||||||
|
def bound0(bnd: Option[TypeEntity], pre: String): String = bnd match {
|
||||||
|
case None => ""
|
||||||
|
case Some(tpe) => pre + typeToHtml(tpe)
|
||||||
|
}
|
||||||
|
bound0(hi, " ⊲ ") + bound0(lo, " ⊳ ")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** name, tparams, params, result */
|
||||||
|
def signature(mbr: MemberEntity, isSelf: Boolean): NodeSeq = {
|
||||||
|
val inside: NodeSeq =
|
||||||
|
<xml:group>
|
||||||
|
<div class="kind">{ kindToString(mbr) }</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">{ if (mbr.isConstructor) tpl.name else mbr.name }</span>
|
||||||
|
{ def tparamsToHtml(tpss: List[TypeParam]): NodeSeq =
|
||||||
|
if (tpss.isEmpty) NodeSeq.Empty else {
|
||||||
|
def tparam0(tp: TypeParam): NodeSeq =
|
||||||
|
<span name={ tp.name }>{
|
||||||
|
tp.variance + tp.name + boundsToString(tp.hi, tp.lo)
|
||||||
|
}</span>
|
||||||
|
def tparams0(tpss: List[TypeParam]): NodeSeq = tpss match {
|
||||||
|
case tp :: Nil => tparam0(tp)
|
||||||
|
case tp :: tps => tparam0(tp) ++ Text(",") ++ tparams0(tps)
|
||||||
|
}
|
||||||
|
<span class="tparams">[{ tparams0(tpss) }]</span>
|
||||||
|
}
|
||||||
|
mbr match {
|
||||||
|
case trt: Trait => tparamsToHtml(trt.typeParams)
|
||||||
|
case dfe: Def => tparamsToHtml(dfe.typeParams)
|
||||||
|
case _ => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
|
||||||
|
def param0(vl: ValueParam): NodeSeq =
|
||||||
|
<span name={ vl.name }>{
|
||||||
|
vl.name + ": " + typeToHtml(vl.resultType)
|
||||||
|
}</span>
|
||||||
|
def params0(vlss: List[ValueParam]): NodeSeq = vlss match {
|
||||||
|
case Nil => NodeSeq.Empty
|
||||||
|
case vl :: Nil => param0(vl)
|
||||||
|
case vl :: vls => param0(vl) ++ Text(",") ++ params0(vls)
|
||||||
|
}
|
||||||
|
vlsss map { vlss => <span class="params">({ params0(vlss) })</span> }
|
||||||
|
}
|
||||||
|
mbr match {
|
||||||
|
case cls: Class if cls.isCaseClass => paramsToHtml(cls.primaryConstructor.get.valueParams)
|
||||||
|
case ctr: Constructor => paramsToHtml(ctr.valueParams)
|
||||||
|
case dfe: Def => paramsToHtml(dfe.valueParams)
|
||||||
|
case _ => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ mbr match {
|
||||||
|
case tpl: DocTemplateEntity if (!tpl.isPackage) =>
|
||||||
|
tpl.parentType match {
|
||||||
|
case Some(st) => <span class="result">extends<span>{ typeToHtml(st) }</span></span>
|
||||||
|
case None =>NodeSeq.Empty
|
||||||
|
}
|
||||||
|
case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isVar) =>
|
||||||
|
<span class="result">:<span>{ typeToHtml(tme.resultType) }</span></span>
|
||||||
|
case abt: AbstractType =>
|
||||||
|
val b2s = boundsToString(abt.hi, abt.lo)
|
||||||
|
if (b2s != "")
|
||||||
|
<span class="result"><span>{ b2s }</span></span>
|
||||||
|
else NodeSeq.Empty
|
||||||
|
case alt: AliasType =>
|
||||||
|
<span class="result">=<span>{ typeToHtml(alt.alias) }</span></span>
|
||||||
|
case _ => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</xml:group>
|
||||||
|
mbr match {
|
||||||
|
case dte: DocTemplateEntity if !isSelf =>
|
||||||
|
<a class="signature" href={ relativeLinkTo(dte) }>{ inside }</a>
|
||||||
|
case _ =>
|
||||||
|
<div class="signature">{ inside }</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Scaladoc</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<script type="text/javascript" src="lib/jquery.js"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
@import url("lib/index.css") screen;
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src="lib/index.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="browser">
|
||||||
|
<input id="quickflt" type="text"/>
|
||||||
|
<div id="tpl">
|
||||||
|
<ol class="packages">
|
||||||
|
<li>
|
||||||
|
<h3><a class="tplshow" href="scala/collection/package.html">scala.collection</a></h3>
|
||||||
|
<ol class="templates">
|
||||||
|
<li title="scala.collection.BitSet">
|
||||||
|
<a class="tplshow" href="scala/collection/BitSet.html">BitSet <span class="class">(class)</span></a>
|
||||||
|
<a class="tplshow" href="scala/collection/BitSet$.html"><span class="object">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.BufferedIterator">
|
||||||
|
<a class="tplshow" href="scala/collection/BufferedIterator.html">BufferedIterator <span class="trait">(trait)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.DefaultMap">
|
||||||
|
<a class="tplshow" href="scala/collection/DefaultMap$.html">DefaultMap <span class="class">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.Iterable">
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable.html">Iterable <span class="class">(class)</span></a>
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable$.html"><span class="object">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<ol class="packages">
|
||||||
|
<li>
|
||||||
|
<h3>scala.collection.mutable</h3>
|
||||||
|
<ol class="templates">
|
||||||
|
<li title="scala.collection.mutable.DefaultMap">
|
||||||
|
<a class="tplshow" href="scala/collection/DefaultMap$.html">DefaultMap <span class="class">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.mutable.Iterable">
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable.html">Iterable <span class="class">(class)</span></a>
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable$.html"><span class="object">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.mutable.Iterable">
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable.html">Iterable <span class="class">(class)</span></a>
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable$.html"><span class="object">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li title="scala.collection.mutable.Truc">
|
||||||
|
<a class="tplshow" href="scala/collection/Truc.html">Truc <span class="class">(class)</span></a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3>scala.collection.immutable</h3>
|
||||||
|
<ol class="templates">
|
||||||
|
<li class="template" title="scala.collection.DefaultMap">
|
||||||
|
<a class="tplshow" href="scala/collection/DefaultMap$.html">DefaultMap <span class="class">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="template" title="scala.collection.Iterable">
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable.html">Iterable <span class="class">(class)</span></a>
|
||||||
|
<a class="tplshow" href="scala/collection/Iterable$.html"><span class="object">(object)</span></a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
<iframe src="template.html"></iframe>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
After Width: | Height: | Size: 519 B |
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,91 @@
|
||||||
|
* {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: inherit;
|
||||||
|
font-family: sans-serif;
|
||||||
|
border-width: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#browser {
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 300px;
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#quickflt {
|
||||||
|
height: 22px;
|
||||||
|
right: 0px;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #993300;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tpl {
|
||||||
|
right: 0px;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
top: 30px;
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tpl h3 {
|
||||||
|
background-color: #142556;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2px;
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
border-bottom-color: white;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tpl h3 a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tpl ol > li {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #cccccc;
|
||||||
|
border-bottom-color: white;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tpl ol > li .icon {
|
||||||
|
bottom: -2px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-left-color: black;
|
||||||
|
border-left-style: solid;
|
||||||
|
right: 0px;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
top: 0px;
|
||||||
|
position: fixed;
|
||||||
|
margin-left: 300px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content > iframe {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
$(document).ready(function(){
|
||||||
|
cleanPackage($("#tpl"));
|
||||||
|
$("#tpl ol > li span.class").replaceWith("<img class='icon' src='lib/class.png'/>");
|
||||||
|
$("#tpl ol > li span.object").replaceWith("<img class='icon' src='lib/object.png'/>");
|
||||||
|
$("#tpl ol > li span.trait").replaceWith("<img class='icon' src='lib/trait.png'/>");
|
||||||
|
$("#tpl ol > li span.package").replaceWith("<img class='icon' src='lib/package.png'/>");
|
||||||
|
$("#tpl a.tplshow").click(function(event){
|
||||||
|
$("#content>iframe").attr("src", event.currentTarget.href);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$("#quickflt").focus(function(event) {
|
||||||
|
$("#quickflt").select();
|
||||||
|
});
|
||||||
|
$("#quickflt").keyup(function(event) {
|
||||||
|
var b = $("#quickflt").attr("value");
|
||||||
|
$("#tpl ol.templates > li").each(function(){
|
||||||
|
var a = $(this).attr("title");
|
||||||
|
if (a == "" || a.indexOf(b) >= 0) {
|
||||||
|
$(this).show();
|
||||||
|
$(this).removeClass("hide");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(this).addClass("hide");
|
||||||
|
$(this).hide();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
cleanPackage($("#tpl"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function cleanPackage(pack) {
|
||||||
|
$("> ol.packages > li", pack).each(function(){ cleanPackage($(this)); });
|
||||||
|
if ($("> ol > li:not(.hide)", pack).length > 0) {
|
||||||
|
pack.show();
|
||||||
|
pack.removeClass("hide");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pack.addClass("hide");
|
||||||
|
pack.hide();
|
||||||
|
};
|
||||||
|
if ($("> ol.templates > li:not(.hide)", pack).length > 0) { $("> h3", pack).show(); }
|
||||||
|
else { $("> h3", pack).hide(); };
|
||||||
|
return false;
|
||||||
|
}
|
After Width: | Height: | Size: 518 B |
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,206 @@
|
||||||
|
@import "reset.css";
|
||||||
|
|
||||||
|
/* Javadoc style sheet */
|
||||||
|
|
||||||
|
/* Define colors, fonts and other style attributes here to override the defaults */
|
||||||
|
|
||||||
|
/* Page background color */
|
||||||
|
body { background-color: #FFFFFF }
|
||||||
|
|
||||||
|
a:link.selfref, a:visited.selfref {
|
||||||
|
color: #555 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link, a:visited {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color:#000099;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active, a:hover {
|
||||||
|
color:#990000;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.noref {
|
||||||
|
text-decoration: none;
|
||||||
|
cursor:default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
font.FrameItemFont {
|
||||||
|
font-size:10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link.selfref, a:visited.selfref {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #555 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.a td {
|
||||||
|
background: #ddd;
|
||||||
|
color: #000;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 200%;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: sans-serif;
|
||||||
|
border:solid 1px #999999;
|
||||||
|
padding:10px;
|
||||||
|
background-color:#EEEEEE;
|
||||||
|
color:#990000;
|
||||||
|
font-family:sans-serif;
|
||||||
|
font-weight:bold;
|
||||||
|
/*line-height:2em;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-family: sans-serif;
|
||||||
|
border: 1px solid #555555;
|
||||||
|
background: #cccccc;
|
||||||
|
color:#990000;
|
||||||
|
padding:0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: none;
|
||||||
|
border-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tr.TableHeadingColor td {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 9pt;
|
||||||
|
border: 1px solid #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.TableRowColor td {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 9pt;
|
||||||
|
border: 1px solid #999999;
|
||||||
|
cell-padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 10pt;
|
||||||
|
color:#990000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
font-size:10pt;
|
||||||
|
margin-top:4px;
|
||||||
|
margin-bottom:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd code {
|
||||||
|
color:#333333;
|
||||||
|
font-size:9pt;
|
||||||
|
font-size:normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table colors */
|
||||||
|
.TableHeadingColor { background: #cccccc; color:#990000}
|
||||||
|
.TableSubHeadingColor { background: #bbbbbb; color:black;}
|
||||||
|
.TableRowColor { background: #EEEEEE }
|
||||||
|
|
||||||
|
/* Font used in left-hand frame lists */
|
||||||
|
.FrameTitleFont { font-weight: 900; font-size: normal; font-family: sans-serif; color:#FFFFFF }
|
||||||
|
.FrameHeadingFont {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: normal;
|
||||||
|
font-family: sans-serif;
|
||||||
|
color:#990000;
|
||||||
|
line-height: 2em;
|
||||||
|
border: 1px solid #aaaaaa;
|
||||||
|
padding-left:4px;
|
||||||
|
padding-right:4px;
|
||||||
|
padding-top:2px;
|
||||||
|
padding-bottom:2px;
|
||||||
|
}
|
||||||
|
.FrameItemFont { font-size: normal; font-family: sans-serif; color:#FFFFFF }
|
||||||
|
|
||||||
|
/* Example of smaller, sans-serif font in frames */
|
||||||
|
/* .FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */
|
||||||
|
|
||||||
|
/* Navigation bar fonts and colors */
|
||||||
|
|
||||||
|
.NavBar {
|
||||||
|
background-color:#ddd;
|
||||||
|
border:none;
|
||||||
|
padding: 2px;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 8pt;
|
||||||
|
color:#000000;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.NavBar td {
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
td.NavBarCell1 {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
td.NavBarCell2 {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
td.NavBarCell3 {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
li, dd {
|
||||||
|
padding-left:2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.off {
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.isInherited {
|
||||||
|
background-color: #ede1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.isDeprecated td.name {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
.apiComments {
|
||||||
|
margin-top : .3em;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
margin-left: 2em;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#intro .apiComments {
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detailsBtn {
|
||||||
|
font-size: 80%;
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.signature {
|
||||||
|
}
|
||||||
|
|
||||||
|
code.signature * {
|
||||||
|
font-family:inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.codeAsDoc {
|
||||||
|
border: dashed 1px #909090;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.name, td.type, td.remarks {
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
var showInherited = true;
|
||||||
|
|
||||||
|
var toggleInherited= function() {
|
||||||
|
showInherited = !showInherited;
|
||||||
|
$.cookie('showInherited', showInherited);
|
||||||
|
updateInherited();
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateInherited = function() {
|
||||||
|
$("input.filter_inherited_cb").each(function(){this.checked = showInherited});
|
||||||
|
if (showInherited) {
|
||||||
|
$("tr.isInherited").show();
|
||||||
|
} else {
|
||||||
|
$("tr.isInherited").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
parent.document.title=document.title;
|
||||||
|
showInherited = $.cookie('showInherited');
|
||||||
|
updateInherited();
|
||||||
|
$("div.apiCommentsDetails").hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
var selectPackage = function(name) {
|
||||||
|
if(parent.navFrame) {
|
||||||
|
parent.navFrame.selectPackage(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie plugin
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
|
||||||
|
* Dual licensed under the MIT and GPL licenses:
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* http://www.gnu.org/licenses/gpl.html
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a cookie with the given name and value and other optional parameters.
|
||||||
|
*
|
||||||
|
* @example $.cookie('the_cookie', 'the_value');
|
||||||
|
* @desc Set the value of a cookie.
|
||||||
|
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
|
||||||
|
* @desc Create a cookie with all available options.
|
||||||
|
* @example $.cookie('the_cookie', 'the_value');
|
||||||
|
* @desc Create a session cookie.
|
||||||
|
* @example $.cookie('the_cookie', null);
|
||||||
|
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
|
||||||
|
* used when the cookie was set.
|
||||||
|
*
|
||||||
|
* @param String name The name of the cookie.
|
||||||
|
* @param String value The value of the cookie.
|
||||||
|
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
|
||||||
|
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
|
||||||
|
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
|
||||||
|
* If set to null or omitted, the cookie will be a session cookie and will not be retained
|
||||||
|
* when the the browser exits.
|
||||||
|
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
|
||||||
|
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
|
||||||
|
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
|
||||||
|
* require a secure protocol (like HTTPS).
|
||||||
|
* @type undefined
|
||||||
|
*
|
||||||
|
* @name $.cookie
|
||||||
|
* @cat Plugins/Cookie
|
||||||
|
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a cookie with the given name.
|
||||||
|
*
|
||||||
|
* @example $.cookie('the_cookie');
|
||||||
|
* @desc Get the value of a cookie.
|
||||||
|
*
|
||||||
|
* @param String name The name of the cookie.
|
||||||
|
* @return The value of the cookie.
|
||||||
|
* @type String
|
||||||
|
*
|
||||||
|
* @name $.cookie
|
||||||
|
* @cat Plugins/Cookie
|
||||||
|
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||||
|
*/
|
||||||
|
jQuery.cookie = function(name, value, options) {
|
||||||
|
if (typeof value != 'undefined') { // name and value given, set cookie
|
||||||
|
options = options || {};
|
||||||
|
if (value === null) {
|
||||||
|
value = '';
|
||||||
|
options.expires = -1;
|
||||||
|
}
|
||||||
|
var expires = '';
|
||||||
|
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
|
||||||
|
var date;
|
||||||
|
if (typeof options.expires == 'number') {
|
||||||
|
date = new Date();
|
||||||
|
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
|
||||||
|
} else {
|
||||||
|
date = options.expires;
|
||||||
|
}
|
||||||
|
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
|
||||||
|
}
|
||||||
|
// CAUTION: Needed to parenthesize options.path and options.domain
|
||||||
|
// in the following expressions, otherwise they evaluate to undefined
|
||||||
|
// in the packed version for some reason...
|
||||||
|
var path = options.path ? '; path=' + (options.path) : '';
|
||||||
|
var domain = options.domain ? '; domain=' + (options.domain) : '';
|
||||||
|
var secure = options.secure ? '; secure' : '';
|
||||||
|
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
|
||||||
|
} else { // only name given, get cookie
|
||||||
|
var cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie != '') {
|
||||||
|
var cookies = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
|
var cookie = jQuery.trim(cookies[i]);
|
||||||
|
// Does this cookie string begin with the name we want?
|
||||||
|
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
};
|
After Width: | Height: | Size: 488 B |
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,228 @@
|
||||||
|
* {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 11pt;
|
||||||
|
font-family: sans-serif;
|
||||||
|
border-width: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#owner {
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 12pt;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value #owner {
|
||||||
|
background-color: #ced8f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type #owner {
|
||||||
|
background-color: #f4cece;
|
||||||
|
}
|
||||||
|
|
||||||
|
#definition {
|
||||||
|
display: block;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#definition > img {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#definition > h1 {
|
||||||
|
padding: 12px 0 12px 6px;
|
||||||
|
color: white;
|
||||||
|
font-size: 24pt;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value #definition {
|
||||||
|
background-color: #142556;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type #definition {
|
||||||
|
background-color: #561414;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
background-color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value #definition + .signature {
|
||||||
|
background-color: #ced8f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type #definition + .signature {
|
||||||
|
background-color: #f4cece;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .kind {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12pt;
|
||||||
|
padding: 4px;
|
||||||
|
text-align: right;
|
||||||
|
float: left;
|
||||||
|
width: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .symbol {
|
||||||
|
display: block;
|
||||||
|
font-size: 12pt;
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .name {
|
||||||
|
display: inline-block;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding-top: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .tparams {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .tparams > span {
|
||||||
|
margin-right: 2px;
|
||||||
|
margin-left: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .params {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .params > span {
|
||||||
|
margin-right: 2px;
|
||||||
|
margin-left: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .result {
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature .result span {
|
||||||
|
margin-right: 2px;
|
||||||
|
margin-left: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment > p {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel {
|
||||||
|
padding: 4px;
|
||||||
|
background-color: #cccccc;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel > div > h3 {
|
||||||
|
padding: 4px;
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel > div > ol {
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel > div > ol > li {
|
||||||
|
display: block;
|
||||||
|
padding: 4px 8px 4px 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel > div > ol > li.in {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mbrsel > div > ol > li.out {
|
||||||
|
color: #888888;
|
||||||
|
background-color: #bbbbbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#template > div.members > ol {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#values > h3 {
|
||||||
|
color: white;
|
||||||
|
padding: 4px;
|
||||||
|
background-color: #142556;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#types > h3 {
|
||||||
|
padding: 4px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12pt;
|
||||||
|
background-color: #561414;
|
||||||
|
}
|
||||||
|
|
||||||
|
#constructors > h3 {
|
||||||
|
padding: 4px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12pt;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members > ol > li {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .paramcmts {
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .paramcmts > li.tparam {
|
||||||
|
background-color: #ffcc66;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .paramcmts > li.param {
|
||||||
|
background-color: #cc99ff;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .attributes {
|
||||||
|
border-bottom-color: black;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .attributes > li {
|
||||||
|
padding: 2px;
|
||||||
|
font-size: 10pt;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .comment {
|
||||||
|
display: block;
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members .comment > p {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
margin-top: 4px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
$(document).ready(function(){
|
||||||
|
var prefilters = $("#ancestors > ol > li").filter(function(){
|
||||||
|
var name = $(this).attr("name");
|
||||||
|
return name == "scala.Any" || name == "scala.AnyRef";
|
||||||
|
});
|
||||||
|
prefilters.removeClass("in");
|
||||||
|
prefilters.addClass("out");
|
||||||
|
filterInherit();
|
||||||
|
$("#ancestors > ol > li").click(function(event){
|
||||||
|
if ($(this).hasClass("in")) {
|
||||||
|
$(this).removeClass("in");
|
||||||
|
$(this).addClass("out");
|
||||||
|
}
|
||||||
|
else if ($(this).hasClass("out")) {
|
||||||
|
$(this).removeClass("out");
|
||||||
|
$(this).addClass("in");
|
||||||
|
};
|
||||||
|
filterInherit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function filterInherit() {
|
||||||
|
$("#mbrsel > div > ol > li.in").each(function(){
|
||||||
|
findMembersByOwner($(this).attr("name")).show();
|
||||||
|
});
|
||||||
|
$("#mbrsel > div > ol > li.out").each(function(){
|
||||||
|
findMembersByOwner($(this).attr("name")).hide();
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
function findMembersByOwner(owner0) {
|
||||||
|
return $(".members > ol > li").filter(function(){
|
||||||
|
var qualName1 = $(this).attr("name");
|
||||||
|
if (qualName1 == undefined) return false;
|
||||||
|
return owner0 == qualName1.slice(0, qualName1.indexOf("#"));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function findMemberByName(name0) {
|
||||||
|
return $(".members > ol > li").filter(function(){
|
||||||
|
var qualName1 = $(this).attr("name");
|
||||||
|
if (qualName1 == undefined) return false;
|
||||||
|
return name0 == qualName1.slice(qualName1.indexOf("#") + 1);
|
||||||
|
}).eq(0);
|
||||||
|
};
|
After Width: | Height: | Size: 504 B |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1 @@
|
||||||
|
jquery=1.3.2
|
|
@ -0,0 +1,228 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Scaladoc</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<script type="text/javascript" src="lib/jquery.js"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
@import url("lib/template.css") screen;
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src="lib/template.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="type">
|
||||||
|
<p id="owner">scala.collection.mutable</p>
|
||||||
|
<div id="definition">
|
||||||
|
<img src="lib/class_big.png"/>
|
||||||
|
<h1>ImmutableMapAdaptor</h1>
|
||||||
|
</div>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">class</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">ImmutableMapAdaptor</span>
|
||||||
|
<span class="tparams">[<span name="T">T ⊲ Int</span>,<span name="Y">Y</span>]</span>
|
||||||
|
<span class="result">extends<span>A[X]</span> with <span>C[Y]</span> with <span>B</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="comment">
|
||||||
|
<p>This class can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined if the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.</p>
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
|
||||||
|
</div>
|
||||||
|
<div id="template">
|
||||||
|
<div id="mbrsel">
|
||||||
|
<div id="ancestors">
|
||||||
|
<h3>Inherits</h3>
|
||||||
|
<ol>
|
||||||
|
<li class="in" name="scala.ImmutableMapAdaptor">ImmutableMapAdaptor</li>
|
||||||
|
<li class="in" name="toto.FlawedImpl">FlawedImpl</li>
|
||||||
|
<li class="in" name="Map">Map</li>
|
||||||
|
<li class="in" name="ImmutableThingy">ImmutableThingy</li>
|
||||||
|
<li class="in" name="scala.AnyRef">AnyRef</li>
|
||||||
|
<li class="in" name="scala.Any">Any</li></ol>
|
||||||
|
</div>
|
||||||
|
<div id="implicits">
|
||||||
|
<h3>Implicitly</h3>
|
||||||
|
<ol><li class="out" name="RichAdaptor">RichAdaptor</li><li class="in" name="RaptureFallback">RaptureFallback</li></ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="values" class="members">
|
||||||
|
<h3>Value Members</h3>
|
||||||
|
<ol>
|
||||||
|
<li name="toto.FlawedImpl#transform">
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">def</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">transform</span>
|
||||||
|
<span class="tparams">[<span name="T">T</span>,<span name="U">U ⊲ Int</span>]</span>
|
||||||
|
<span class="params">(<span name="f">f: (A, B) => B</span>,<span name="b">b: Double</span>)</span>
|
||||||
|
<span class="result">:<span>ImmutableMapAdaptor[A, B]</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ol class="paramcmts">
|
||||||
|
<li class="tparam" name="T">
|
||||||
|
<p>T an empty map.</p>
|
||||||
|
</li>
|
||||||
|
<li class="tparam" name="U">
|
||||||
|
<p>U can be used as an adaptor to create mutable maps.</p>
|
||||||
|
</li>
|
||||||
|
<li class="param" name="f">
|
||||||
|
<p>f can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined.</p>
|
||||||
|
</li>
|
||||||
|
<li class="param" name="b">
|
||||||
|
<p>b the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<ol class="attributes"><li>override</li><li>protected</li><li>@inline</li></ol>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li name="Map#curry">
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">def</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">curry</span>
|
||||||
|
<span class="params">(<span name="f">f: (A, B) => B</span>,<span name="b">b: Double</span>)</span><span class="params">(<span name="g">g: Int => B</span>,<span name="c">c: Double</span>)</span>
|
||||||
|
<span class="result">:<span>ImmutableMapAdaptor[A, B]</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li name="randomize">
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">val</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">randomize</span>
|
||||||
|
<span class="result">:<span>ImmutableMapAdaptor[A, B]</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">object</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">babar</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">package</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">fantomette</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div id="types" class="members">
|
||||||
|
<h3>Type Members</h3>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">type</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">T</span>
|
||||||
|
<span class="tparams">[<span name="T">T</span>,<span name="U">U ⊲ Int</span>]</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="signature" href="RandomAccessWaste">
|
||||||
|
<div class="kind">class</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">RandomAccessWaste</span>
|
||||||
|
<span class="tparams">[<span name="T">T</span>,<span name="U">U ⊲ Int</span>]</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="comment">
|
||||||
|
<p>Some inner class</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">[]</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">Y</span>
|
||||||
|
<span class="result">⊲<span>Int</span>⊳<span>Nothing</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">[]</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">X</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>Some type parameter</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">[]</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">Y</span>
|
||||||
|
<span class="result">⊲<span>Int</span>⊳<span>Nothing</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">type</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">U</span>
|
||||||
|
<span class="result">=<span>ImmutableMapAdaptor[A, B]</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">type</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">V</span>
|
||||||
|
<span class="result">⊲<span>Int</span>⊳<span>Boolean</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div id="constructors" class="members">
|
||||||
|
<h3>Constructors</h3>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<div class="signature">
|
||||||
|
<div class="kind">new</div>
|
||||||
|
<div class="symbol">
|
||||||
|
<span class="name">ImmutableMapAdaptor</span>
|
||||||
|
<span class="tparams">[<span name="T">T</span>,<span name="U">U ⊲ Int</span>]</span>
|
||||||
|
<span class="params">(<span name="f">f: (A, B) => B</span>,<span name="b">b: Double</span>)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,141 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
import comment._
|
||||||
|
|
||||||
|
/** Some entity of the Scaladoc model. */
|
||||||
|
trait Entity {
|
||||||
|
def name : String
|
||||||
|
def inTemplate: TemplateEntity
|
||||||
|
def toRoot: List[Entity]
|
||||||
|
def qualifiedName: String
|
||||||
|
def comment: Option[Comment]
|
||||||
|
override def toString = qualifiedName
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** A class, trait, object or package. A package is represented as an instance of the `Package` subclass. A class,
|
||||||
|
* trait, object or package may be directly an instance of `WeakTemplateEntity` if it is not ''documentable'' (that
|
||||||
|
* is, if there is no documentation page for it in the current site), otherwise, it will be represented as an instance
|
||||||
|
* of the `TemplateEntity` subclass. */
|
||||||
|
trait TemplateEntity extends Entity {
|
||||||
|
def isPackage: Boolean
|
||||||
|
def isRootPackage: Boolean
|
||||||
|
def isTrait: Boolean
|
||||||
|
def isClass: Boolean
|
||||||
|
def isObject: Boolean
|
||||||
|
}
|
||||||
|
trait NoDocTemplate extends TemplateEntity
|
||||||
|
|
||||||
|
/** A member of a class, trait, object or package. */
|
||||||
|
trait MemberEntity extends Entity {
|
||||||
|
def inTemplate: DocTemplateEntity
|
||||||
|
def toRoot: List[DocTemplateEntity]
|
||||||
|
def inDefinitionTemplate: TemplateEntity
|
||||||
|
def definitionName: String
|
||||||
|
def visibility: Option[Paragraph]
|
||||||
|
def flags: List[Paragraph]
|
||||||
|
def inheritedFrom: List[TemplateEntity]
|
||||||
|
def isDeprecated: Boolean
|
||||||
|
def resultType: TypeEntity
|
||||||
|
def isDef: Boolean
|
||||||
|
def isVal: Boolean
|
||||||
|
def isVar: Boolean
|
||||||
|
def isConstructor: Boolean
|
||||||
|
def isAliasType: Boolean
|
||||||
|
def isAbstractType: Boolean
|
||||||
|
def isTemplate: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A ''documentable'' class, trait or object (that is, a documentation page will be generated for it in the current
|
||||||
|
* site). */
|
||||||
|
trait DocTemplateEntity extends TemplateEntity with MemberEntity {
|
||||||
|
def inSource: Option[(io.AbstractFile, Int)]
|
||||||
|
def typeParams: List[TypeParam]
|
||||||
|
def parentType: Option[TypeEntity]
|
||||||
|
def linearization: List[TemplateEntity]
|
||||||
|
def subClasses: List[DocTemplateEntity]
|
||||||
|
def members: List[MemberEntity]
|
||||||
|
def templates: List[DocTemplateEntity]
|
||||||
|
def methods: List[Def]
|
||||||
|
def values: List[Val]
|
||||||
|
def abstractTypes: List[AbstractType]
|
||||||
|
def aliasTypes: List[AliasType]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A ''documentable'' trait. */
|
||||||
|
trait Trait extends DocTemplateEntity {
|
||||||
|
def valueParams : List[List[ValueParam]]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A ''documentable'' class. */
|
||||||
|
trait Class extends Trait {
|
||||||
|
def primaryConstructor: Option[Constructor]
|
||||||
|
def constructors: List[Constructor]
|
||||||
|
def isCaseClass: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A ''documentable'' object. */
|
||||||
|
trait Object extends DocTemplateEntity
|
||||||
|
|
||||||
|
/** A package that contains at least one ''documentable'' class, trait, object or package. */
|
||||||
|
trait Package extends Object {
|
||||||
|
def inTemplate: Package
|
||||||
|
def toRoot: List[Package]
|
||||||
|
def packages: List[Package]
|
||||||
|
}
|
||||||
|
|
||||||
|
trait NonTemplateMemberEntity extends MemberEntity
|
||||||
|
|
||||||
|
/** A method (`def`) of a ''documentable'' class, trait or object. */
|
||||||
|
trait Def extends NonTemplateMemberEntity {
|
||||||
|
def typeParams: List[TypeParam]
|
||||||
|
def valueParams : List[List[ValueParam]]
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Constructor extends NonTemplateMemberEntity {
|
||||||
|
def isPrimary: Boolean
|
||||||
|
def valueParams : List[List[ValueParam]]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A value (`val`) or variable (`var`) of a ''documentable'' class, trait or object. */
|
||||||
|
trait Val extends NonTemplateMemberEntity
|
||||||
|
|
||||||
|
/** An abstract type of a ''documentable'' class, trait or object. */
|
||||||
|
trait AbstractType extends NonTemplateMemberEntity {
|
||||||
|
// TODO: typeParams
|
||||||
|
def lo: Option[TypeEntity]
|
||||||
|
def hi: Option[TypeEntity]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An abstract type of a ''documentable'' class, trait or object. */
|
||||||
|
trait AliasType extends NonTemplateMemberEntity {
|
||||||
|
// TODO: typeParams
|
||||||
|
def alias: TypeEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ParameterEntity extends Entity {
|
||||||
|
def inTemplate: DocTemplateEntity
|
||||||
|
def toRoot: List[DocTemplateEntity]
|
||||||
|
def isTypeParam: Boolean
|
||||||
|
def isValueParam: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A type parameter to a class or trait or to a method. */
|
||||||
|
trait TypeParam extends ParameterEntity {
|
||||||
|
def variance: String
|
||||||
|
def lo: Option[TypeEntity]
|
||||||
|
def hi: Option[TypeEntity]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A value parameter to a constructor or to a method. */
|
||||||
|
trait ValueParam extends ParameterEntity {
|
||||||
|
def resultType : TypeEntity
|
||||||
|
}
|
|
@ -0,0 +1,434 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
|
||||||
|
import comment._
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
import symtab.Flags
|
||||||
|
|
||||||
|
/** This trait extracts all required information for documentation from compilation units */
|
||||||
|
class EntityFactory(val global: Global, val settings: doc.Settings) { extractor =>
|
||||||
|
|
||||||
|
import global._
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeModel: Package =
|
||||||
|
makePackage(definitions.RootPackage, null) match {
|
||||||
|
case Some(pack) => pack
|
||||||
|
case None => throw new Error("no documentable class found in compilation units")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
protected val commentFactory = new CommentFactory(reporter)
|
||||||
|
|
||||||
|
/** */
|
||||||
|
protected val commentCache = mutable.Map.empty[Symbol, comment.Comment]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
protected val templatesCache =
|
||||||
|
new mutable.LinkedHashMap[(Symbol, TemplateImpl), DocTemplateImpl]
|
||||||
|
|
||||||
|
/* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */
|
||||||
|
|
||||||
|
/** Provides a default implementation for instances of the `Entity` type. */
|
||||||
|
abstract class EntityImpl(val sym: Symbol, inTpl: => TemplateImpl) extends Entity {
|
||||||
|
val name = sym.nameString
|
||||||
|
def inTemplate = inTpl
|
||||||
|
def toRoot: List[EntityImpl] = inTpl :: inTpl.toRoot
|
||||||
|
def qualifiedName = name
|
||||||
|
val comment = {
|
||||||
|
val whichSym =
|
||||||
|
if (comments isDefinedAt sym) Some(sym) else sym.allOverriddenSymbols find (comments isDefinedAt _)
|
||||||
|
whichSym map { s =>
|
||||||
|
(commentCache get s) getOrElse {
|
||||||
|
val c = commentFactory.parse(comments(s), s.pos)
|
||||||
|
commentCache += s -> c
|
||||||
|
c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a
|
||||||
|
* `SymbolicEntity` to access the compiler symbol that underlies the entity. */
|
||||||
|
trait TemplateImpl extends EntityImpl with TemplateEntity {
|
||||||
|
override def qualifiedName = if (inTemplate.isRootPackage) name else (inTemplate.qualifiedName + "." + name)
|
||||||
|
val isPackage = sym.isPackage
|
||||||
|
val isTrait = sym.isTrait
|
||||||
|
val isClass = sym.isClass && !sym.isTrait
|
||||||
|
val isObject = sym.isModule && !sym.isPackage
|
||||||
|
val isRootPackage = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a
|
||||||
|
* `SymbolicEntity` to access the compiler symbol that underlies the entity. */
|
||||||
|
class NoDocTemplateImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with TemplateImpl with NoDocTemplate
|
||||||
|
|
||||||
|
/** Provides a default implementation for instances of the `MemberEntity` type. It must be instantiated as a
|
||||||
|
* `SymbolicEntity` to access the compiler symbol that underlies the entity. */
|
||||||
|
abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
|
||||||
|
override def inTemplate = inTpl
|
||||||
|
override def toRoot: List[DocTemplateImpl] = inTpl :: inTpl.toRoot
|
||||||
|
lazy val inDefinitionTemplate = if (sym.owner == inTpl.sym) inTpl else makeTemplate(sym.owner)
|
||||||
|
val visibility = {
|
||||||
|
def qual = {
|
||||||
|
val qq =
|
||||||
|
if (sym hasFlag Flags.LOCAL)
|
||||||
|
Some("this")
|
||||||
|
else if (sym.privateWithin != null && sym.privateWithin != NoSymbol)
|
||||||
|
Some(sym.privateWithin.nameString) // TODO: create an inline link to the qualifier entity
|
||||||
|
else None
|
||||||
|
qq match { case Some(q) => "[" + q + "]" case None => "" }
|
||||||
|
}
|
||||||
|
if (sym hasFlag Flags.PRIVATE) Some(Paragraph(Text("private" + qual)))
|
||||||
|
else if (sym hasFlag Flags.PROTECTED) Some(Paragraph(Text("protected" + qual)))
|
||||||
|
else None
|
||||||
|
}
|
||||||
|
val flags = {
|
||||||
|
val fgs = mutable.ListBuffer.empty[Paragraph]
|
||||||
|
if (sym hasFlag Flags.IMPLICIT) fgs += Paragraph(Text("implicit"))
|
||||||
|
if (sym hasFlag Flags.SEALED) fgs += Paragraph(Text("sealed"))
|
||||||
|
if (sym hasFlag Flags.OVERRIDE) fgs += Paragraph(Text("override"))
|
||||||
|
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
|
||||||
|
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
|
||||||
|
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
|
||||||
|
fgs.toList
|
||||||
|
}
|
||||||
|
lazy val inheritedFrom =
|
||||||
|
if (inTemplate.sym == this.sym.owner || inTemplate.sym.isPackage) Nil else
|
||||||
|
makeTemplate(this.sym.owner) :: (sym.allOverriddenSymbols map { os => makeTemplate(os.owner) })
|
||||||
|
val isDeprecated = sym.isDeprecated
|
||||||
|
lazy val resultType = makeType(sym.tpe.finalResultType, inTemplate, sym)
|
||||||
|
val isDef = false
|
||||||
|
val isVal = false
|
||||||
|
val isVar = false
|
||||||
|
val isConstructor = false
|
||||||
|
val isAliasType = false
|
||||||
|
val isAbstractType = false
|
||||||
|
val isTemplate = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides a default implementation for instances of the `TemplateEntity` type. It must be instantiated as a
|
||||||
|
* `TemplateSymbolicEntity` to access the compiler symbol that underlies the entity and to be registered with the
|
||||||
|
* `templatesCache` at the very start of its instantiation.
|
||||||
|
*
|
||||||
|
* The instantiation of `TemplateImpl` triggers the creation of the following entities.
|
||||||
|
* * The owner of the template (as a full template);
|
||||||
|
* * All ancestors of the template (as weak templates);
|
||||||
|
* * All non-package members (including other templates, as full templates). */
|
||||||
|
abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with DocTemplateEntity {
|
||||||
|
templatesCache += ((sym, inTpl) -> this)
|
||||||
|
override def definitionName = inDefinitionTemplate.qualifiedName + "." + name
|
||||||
|
val inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None
|
||||||
|
val typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil
|
||||||
|
val parentType =
|
||||||
|
if (sym.isPackage) None else
|
||||||
|
Some(makeType(RefinedType(sym.tpe.parents filter (_ != definitions.ScalaObjectClass.tpe), EmptyScope)))
|
||||||
|
val linearization = {
|
||||||
|
sym.ancestors filter (_ != definitions.ScalaObjectClass) map (makeTemplate(_))
|
||||||
|
// TODO: Register subclasses
|
||||||
|
}
|
||||||
|
private val subClassesCache = mutable.Buffer.empty[DocTemplateEntity]
|
||||||
|
def registerSubClass(sc: DocTemplateEntity) = subClassesCache += sc
|
||||||
|
def subClasses = subClassesCache.toList
|
||||||
|
def memberSyms = sym.info.nonPrivateMembers
|
||||||
|
val members: List[MemberEntity] = memberSyms flatMap (makeMember(_, this))
|
||||||
|
val templates = members flatMap {case c: DocTemplateEntity => Some(c) case _ => None}
|
||||||
|
val methods = members flatMap {case d: Def => Some(d) case _ => None}
|
||||||
|
val values = members flatMap {case v: Val => Some(v) case _ => None}
|
||||||
|
val abstractTypes = members flatMap {case t: AbstractType => Some(t) case _ => None}
|
||||||
|
val aliasTypes = members flatMap {case t: AliasType => Some(t) case _ => None}
|
||||||
|
override val isTemplate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
|
||||||
|
override def inTemplate = inTpl
|
||||||
|
override def toRoot: List[PackageImpl] = inTpl :: inTpl.toRoot
|
||||||
|
val packages = members flatMap {case p: Package => Some(p) case _ => None}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity {
|
||||||
|
override def qualifiedName = inTemplate.qualifiedName + "#" + name
|
||||||
|
override def definitionName = inDefinitionTemplate.qualifiedName + "#" + name
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
|
||||||
|
override def inTemplate = inTpl
|
||||||
|
override def toRoot: List[DocTemplateImpl] = inTpl :: inTpl.toRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============== MAKER METHODS ============== */
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def normalizeTemplate(aSym: Symbol): Symbol = {
|
||||||
|
if (aSym == null || aSym == definitions.EmptyPackage || aSym == NoSymbol)
|
||||||
|
normalizeTemplate(definitions.RootPackage)
|
||||||
|
else if (aSym == definitions.ScalaObjectClass || aSym == definitions.ObjectClass)
|
||||||
|
normalizeTemplate(definitions.AnyRefClass)
|
||||||
|
else if (aSym.isModuleClass || aSym.isPackageObject)
|
||||||
|
normalizeTemplate(aSym.sourceModule)
|
||||||
|
else
|
||||||
|
aSym
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a package entity for the given symbol or returns `None` if the symbol does not denote a package that
|
||||||
|
* contains at least one ''documentable'' class, trait or object. Creating a package entity */
|
||||||
|
def makePackage(aSym: Symbol, inTpl: => PackageImpl): Option[PackageImpl] = {
|
||||||
|
val bSym = normalizeTemplate(aSym)
|
||||||
|
if (templatesCache isDefinedAt (bSym, inTpl))
|
||||||
|
Some(templatesCache(bSym, inTpl) match {case p: PackageImpl => p})
|
||||||
|
else {
|
||||||
|
val pack =
|
||||||
|
if (bSym == definitions.RootPackage)
|
||||||
|
new PackageImpl(bSym, null) {
|
||||||
|
override val name = "root"
|
||||||
|
override def inTemplate = this
|
||||||
|
override def toRoot = Nil
|
||||||
|
override def qualifiedName = "_root_"
|
||||||
|
override lazy val inheritedFrom = Nil
|
||||||
|
override val isRootPackage = true
|
||||||
|
override def memberSyms =
|
||||||
|
(bSym.info.members ++ definitions.EmptyPackage.info.members) filter { s =>
|
||||||
|
s != definitions.EmptyPackage && s != definitions.RootPackage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new PackageImpl(bSym, inTpl) {}
|
||||||
|
if (pack.templates.isEmpty) None else Some(pack)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeTemplate(aSym: Symbol): TemplateImpl = {
|
||||||
|
val bSym = normalizeTemplate(aSym)
|
||||||
|
if (bSym == definitions.RootPackage)
|
||||||
|
makePackage(bSym, null).get
|
||||||
|
else
|
||||||
|
makeTemplate(bSym, makeTemplate(bSym.owner))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeTemplate(aSym: Symbol, inTpl: => TemplateImpl): TemplateImpl = {
|
||||||
|
val bSym = normalizeTemplate(aSym)
|
||||||
|
if (bSym.isPackage) inTpl match {
|
||||||
|
case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg))
|
||||||
|
case _ => throw new Error("'" + bSym + "' must be in a package")
|
||||||
|
}
|
||||||
|
else if ((bSym.sourceFile != null) && bSym.isPublic && !bSym.isLocal) inTpl match {
|
||||||
|
case inDTpl: DocTemplateImpl => makeDocTemplate(bSym, inDTpl)
|
||||||
|
case _ => throw new Error("documentable '" + bSym + "' must be in a documentable template")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new NoDocTemplateImpl(bSym, inTpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeDocTemplate(aSym: Symbol, inTpl: => DocTemplateImpl): DocTemplateImpl = {
|
||||||
|
val bSym = normalizeTemplate(aSym)
|
||||||
|
val firstInTpl = { // to prevent a complexity explosion in some cases.
|
||||||
|
def sInTpl0(inTpl: DocTemplateImpl): DocTemplateImpl =
|
||||||
|
if ((aSym.owner != inTpl.inTemplate.sym) && (inTpl.inTemplate.sym.info.members contains aSym))
|
||||||
|
sInTpl0(inTpl.inTemplate)
|
||||||
|
else inTpl
|
||||||
|
sInTpl0(inTpl)
|
||||||
|
}
|
||||||
|
if (templatesCache isDefinedAt (bSym, firstInTpl))
|
||||||
|
templatesCache((bSym, firstInTpl))
|
||||||
|
else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
|
||||||
|
new DocTemplateImpl(bSym, firstInTpl) with Object
|
||||||
|
else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
|
||||||
|
new DocTemplateImpl(bSym, firstInTpl) with Trait {
|
||||||
|
val valueParams =
|
||||||
|
List(sym.constrParamAccessors map (makeValueParam(_, this)))
|
||||||
|
}
|
||||||
|
else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
|
||||||
|
new DocTemplateImpl(bSym, firstInTpl) with Class {
|
||||||
|
val valueParams =
|
||||||
|
List(sym.constrParamAccessors map (makeValueParam(_, this)))
|
||||||
|
val constructors =
|
||||||
|
members flatMap {case d: Constructor => Some(d) case _ => None}
|
||||||
|
val primaryConstructor = (constructors find (_.isPrimary))
|
||||||
|
val isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): Option[MemberImpl] = {
|
||||||
|
if (!aSym.isPublic || (aSym hasFlag Flags.SYNTHETIC) || (aSym hasFlag Flags.BRIDGE) || aSym.isLocal || aSym.isModuleClass || aSym.isPackageObject || aSym.isMixinConstructor)
|
||||||
|
None
|
||||||
|
else if (aSym.isGetter && (aSym.accessed hasFlag Flags.MUTABLE))
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with Val {
|
||||||
|
override val isVar = true
|
||||||
|
})
|
||||||
|
else if (aSym.isMethod && !(aSym hasFlag Flags.ACCESSOR) && !aSym.isConstructor && !(aSym hasFlag Flags.FINAL))
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with Def {
|
||||||
|
override val isDef = true
|
||||||
|
val typeParams =
|
||||||
|
sym.tpe.typeParams map (makeTypeParam(_, inTpl))
|
||||||
|
val valueParams =
|
||||||
|
sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
|
||||||
|
if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl)
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
else if (aSym.isConstructor)
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with Constructor {
|
||||||
|
override val isConstructor = true
|
||||||
|
val isPrimary = sym.isPrimaryConstructor
|
||||||
|
val valueParams =
|
||||||
|
sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
|
||||||
|
if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl)
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
else if (aSym.isGetter) // Scala field accessor or Java field
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with Val {
|
||||||
|
override val isVal = true
|
||||||
|
})
|
||||||
|
else if (aSym.isAbstractType)
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with AbstractType {
|
||||||
|
override val isAbstractType = true
|
||||||
|
val lo = sym.info.normalize match {
|
||||||
|
case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => Some(makeType(lo, inTpl, sym))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
val hi = sym.info.normalize match {
|
||||||
|
case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => Some(makeType(hi, inTpl, sym))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else if (aSym.isAliasType)
|
||||||
|
Some(new NonTemplateMemberImpl(aSym, inTpl) with AliasType {
|
||||||
|
override val isAliasType = true
|
||||||
|
val alias = makeType(sym.tpe, inTpl, sym)
|
||||||
|
})
|
||||||
|
else if (aSym.isPackage)
|
||||||
|
inTpl match { case inPkg: PackageImpl => makePackage(aSym, inPkg) }
|
||||||
|
else if ((aSym.isClass || aSym.isModule) && (aSym.sourceFile != null) && aSym.isPublic && !aSym.isLocal)
|
||||||
|
(inTpl.toRoot find (_.sym == aSym )) orElse Some(makeDocTemplate(aSym, inTpl))
|
||||||
|
else
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeTypeParam(aSym: Symbol, inTpl: => DocTemplateImpl): TypeParam = {
|
||||||
|
new ParameterImpl(aSym, inTpl) with TypeParam {
|
||||||
|
val isTypeParam = true
|
||||||
|
val isValueParam = false
|
||||||
|
val variance: String = {
|
||||||
|
if (sym hasFlag Flags.COVARIANT) "+"
|
||||||
|
else if (sym hasFlag Flags.CONTRAVARIANT) "-"
|
||||||
|
else ""
|
||||||
|
}
|
||||||
|
val lo = sym.info.normalize match {
|
||||||
|
case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass =>
|
||||||
|
Some(makeType(lo, inTpl, sym))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
val hi = sym.info.normalize match {
|
||||||
|
case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass =>
|
||||||
|
Some(makeType(hi, inTpl, sym))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl): ValueParam = {
|
||||||
|
makeValueParam(aSym, inTpl, aSym.nameString)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl, newName: String): ValueParam = {
|
||||||
|
new ParameterImpl(aSym, inTpl) with ValueParam {
|
||||||
|
val isTypeParam = false
|
||||||
|
val isValueParam = true
|
||||||
|
val resultType = {
|
||||||
|
makeType(sym.tpe, inTpl, sym)
|
||||||
|
}
|
||||||
|
override val name = newName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeType(aType: Type, seeInTpl: => TemplateImpl, dclSym: Symbol): TypeEntity = {
|
||||||
|
def ownerTpl(sym: Symbol): Symbol =
|
||||||
|
if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner)
|
||||||
|
makeType(aType.asSeenFrom(seeInTpl.sym.thisType, ownerTpl(dclSym)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def makeType(aType: Type): TypeEntity =
|
||||||
|
new TypeEntity {
|
||||||
|
private val nameBuffer = new StringBuilder
|
||||||
|
private var refBuffer = new immutable.TreeMap[Int, (Entity, Int)]
|
||||||
|
private def appendTypes0(types: List[Type], sep: String): Unit = types match {
|
||||||
|
case Nil =>
|
||||||
|
case tp :: Nil =>
|
||||||
|
appendType0(tp)
|
||||||
|
case tp :: tps =>
|
||||||
|
appendType0(tp)
|
||||||
|
nameBuffer append sep
|
||||||
|
appendTypes0(tps, sep)
|
||||||
|
}
|
||||||
|
private def appendType0(tpe: Type): Unit = tpe.normalize match {
|
||||||
|
/* Type refs */
|
||||||
|
case tp: TypeRef if (definitions.isFunctionType(tp)) =>
|
||||||
|
nameBuffer append '('
|
||||||
|
appendTypes0(tp.args.init, ", ")
|
||||||
|
nameBuffer append ") ⇒ "
|
||||||
|
appendType0(tp.args.last)
|
||||||
|
case tp: TypeRef if (tp.typeSymbol == definitions.RepeatedParamClass) =>
|
||||||
|
appendType0(tp.args.head)
|
||||||
|
nameBuffer append '*'
|
||||||
|
case tp: TypeRef if (tp.typeSymbol == definitions.ByNameParamClass) =>
|
||||||
|
nameBuffer append "⇒ "
|
||||||
|
appendType0(tp.args.head)
|
||||||
|
case tp: TypeRef if (definitions.isTupleType(tp)) =>
|
||||||
|
nameBuffer append '('
|
||||||
|
appendTypes0(tp.args, ", ")
|
||||||
|
nameBuffer append ')'
|
||||||
|
case TypeRef(pre, aSym, targs) =>
|
||||||
|
val bSym = normalizeTemplate(aSym)
|
||||||
|
if (bSym.isType)
|
||||||
|
nameBuffer append bSym.name
|
||||||
|
else {
|
||||||
|
val refClass = makeTemplate(bSym)
|
||||||
|
val pos0 = nameBuffer.length
|
||||||
|
nameBuffer append refClass.name
|
||||||
|
refBuffer += pos0 -> (refClass, nameBuffer.length)
|
||||||
|
}
|
||||||
|
if (!targs.isEmpty) {
|
||||||
|
nameBuffer append '['
|
||||||
|
appendTypes0(targs, ", ")
|
||||||
|
nameBuffer append ']'
|
||||||
|
}
|
||||||
|
/* Refined types */
|
||||||
|
case RefinedType(parents, defs) =>
|
||||||
|
appendTypes0((if (parents.length > 1) parents.toList - definitions.ObjectClass.tpe else parents.toList), " with ")
|
||||||
|
if (!defs.isEmpty) {
|
||||||
|
nameBuffer append " {...}" // TODO: actually print the refinement
|
||||||
|
}
|
||||||
|
/* Polymorphic types */
|
||||||
|
case PolyType(tparams, result) if (!tparams.isEmpty) =>
|
||||||
|
appendType0(result)
|
||||||
|
nameBuffer append '['
|
||||||
|
appendTypes0(tparams map (_.tpe), ", ") // TODO: actually print the polytype's symbols (not just types)
|
||||||
|
nameBuffer append ']'
|
||||||
|
/* Eval-by-name types */
|
||||||
|
case PolyType(tparams, result) if (tparams.isEmpty) =>
|
||||||
|
nameBuffer append '⇒'
|
||||||
|
appendType0(result)
|
||||||
|
case tpen =>
|
||||||
|
nameBuffer append tpen.toString
|
||||||
|
}
|
||||||
|
appendType0(aType)
|
||||||
|
val refEntity = refBuffer
|
||||||
|
val name = nameBuffer.toString
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* NSC -- new Scala compiler
|
||||||
|
* Copyright 2007-2009 LAMP/EPFL
|
||||||
|
* @author Manohar Jonnalagedda
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
|
||||||
|
abstract class TypeEntity {
|
||||||
|
|
||||||
|
/** A string reprsentation of this type. */
|
||||||
|
def name: String
|
||||||
|
|
||||||
|
/** Maps which parts of this type's name reference other entities. The map is indexed by the position of the first
|
||||||
|
* character that reference some entity, and contains the entity and the position of the last referenced
|
||||||
|
* character. The referenced character ranges do not to overlap or nest. The map is sorted by position. */
|
||||||
|
def refEntity: SortedMap[Int, (Entity, Int)]
|
||||||
|
|
||||||
|
override def toString =
|
||||||
|
name
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
package comment
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
/** */
|
||||||
|
final case class Body(blocks: Seq[Block])
|
||||||
|
|
||||||
|
/** */
|
||||||
|
sealed abstract class Block
|
||||||
|
|
||||||
|
final case class Title(text: Inline, level: Int) extends Block
|
||||||
|
final case class Paragraph(text: Inline) extends Block
|
||||||
|
final case class Code(data: String) extends Block
|
||||||
|
final case class UnorderedList(items: Seq[Block]) extends Block
|
||||||
|
final case class OrderedList(items: Seq[Block]) extends Block
|
||||||
|
final case class DefinitionList(items: SortedMap[Inline, Block]) extends Block
|
||||||
|
final case class HorizontalRule() extends Block
|
||||||
|
|
||||||
|
/** */
|
||||||
|
sealed abstract class Inline
|
||||||
|
|
||||||
|
final case class Chain(items: Seq[Inline]) extends Inline
|
||||||
|
final case class Italic(text: Inline) extends Inline
|
||||||
|
final case class Bold(text: Inline) extends Inline
|
||||||
|
final case class Underline(text: Inline) extends Inline
|
||||||
|
final case class Superscript(text: Inline) extends Inline
|
||||||
|
final case class Subscript(text: Inline) extends Inline
|
||||||
|
final case class Link(raw: String) extends Inline // TODO
|
||||||
|
final case class Monospace(text: String) extends Inline
|
||||||
|
final case class Text(text: String) extends Inline
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
package comment
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
|
||||||
|
/** A Scaladoc comment and all its tags.
|
||||||
|
*
|
||||||
|
* '''Note:''' the only instantiation site of this class is in `Parser`.
|
||||||
|
*
|
||||||
|
* @author Gilles Dubochet
|
||||||
|
* @author Manohar Jonnalagedda */
|
||||||
|
abstract class Comment {
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def body: Body
|
||||||
|
/* author|deprecated|param|return|see|since|throws|version|todo|tparam */
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def authors: List[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def see: List[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def result: Option[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def throws: Map[String, Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def valueParams: Map[String, Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def typeParams: Map[String, Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def version: Option[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def since: Option[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def todo: List[Body]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
def deprecated: Option[Body]
|
||||||
|
|
||||||
|
override def toString =
|
||||||
|
body.toString + "\n" +
|
||||||
|
(authors map ("@author " + _.toString)).mkString("\n") +
|
||||||
|
(result map ("@return " + _.toString)).mkString
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,525 @@
|
||||||
|
/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
package doc
|
||||||
|
package model
|
||||||
|
package comment
|
||||||
|
|
||||||
|
import reporters.Reporter
|
||||||
|
import util.Position
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
|
import scala.util.matching.Regex
|
||||||
|
import scala.annotation.switch
|
||||||
|
|
||||||
|
/** The comment parser transforms raw comment strings into `Comment` objects. Call `parse` to run the parser. Note that
|
||||||
|
* the parser is stateless and should only be built once for a given Scaladoc run.
|
||||||
|
*
|
||||||
|
* @param reporter The reporter on which user messages (error, warnings) should be printed.
|
||||||
|
*
|
||||||
|
* @author Manohar Jonnalagedda
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
final class CommentFactory(val reporter: Reporter) { parser =>
|
||||||
|
|
||||||
|
final val endOfText = '\u0003'
|
||||||
|
final val endOfLine = '\u000A'
|
||||||
|
|
||||||
|
/** Something that should not have happened, happened, and Scaladoc should exit. */
|
||||||
|
protected def oops(msg: String): Nothing =
|
||||||
|
throw FatalError("program logic: " + msg)
|
||||||
|
|
||||||
|
/** The body of a comment, dropping start and end markers. */
|
||||||
|
protected val CleanComment =
|
||||||
|
new Regex("""(?s)\s*/\*\*((?:[^\*]\*)*)\*/\s*""")
|
||||||
|
|
||||||
|
/** The body of a line, dropping the start star-marker, one leading whitespace and all trailing whitespace. */
|
||||||
|
protected val CleanCommentLine =
|
||||||
|
new Regex("""\*\s?(.*)""")
|
||||||
|
|
||||||
|
/** A Scaladoc tag not linked to a symbol. Returns the name of the tag, and the rest of the line. */
|
||||||
|
protected val SimpleTag =
|
||||||
|
new Regex("""\s*@(\S+)\s+(.*)""")
|
||||||
|
|
||||||
|
/** A Scaladoc tag linked to a symbol. Returns the name of the tag, the name of the symbol, and the rest of the
|
||||||
|
* line. */
|
||||||
|
protected val SymbolTag =
|
||||||
|
new Regex("""\s*@(param|tparam|throws)\s+(\S*)\s*(.*)""")
|
||||||
|
|
||||||
|
/** A key used for a tag map. The key is built from the name of the tag and from the linked symbol if the tag has one.
|
||||||
|
* Equality on tag keys is structural. */
|
||||||
|
protected sealed abstract class TagKey {
|
||||||
|
def name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final case class SimpleTagKey(name: String) extends TagKey
|
||||||
|
protected final case class SymbolTagKey(name: String, symbol: String) extends TagKey
|
||||||
|
|
||||||
|
/** Parses a raw comment string into a `Comment` object.
|
||||||
|
* @param comment The raw comment string (including start and end markers) to be parsed.
|
||||||
|
* @param pos The position of the comment in source. */
|
||||||
|
def parse(comment: String, pos: Position): Comment = {
|
||||||
|
|
||||||
|
/** The cleaned raw comment as a list of lines. Cleaning removes comment start and end markers, line start markers
|
||||||
|
* and unnecessary whitespace. */
|
||||||
|
val cleaned: List[String] = {
|
||||||
|
def cleanLine(line: String): Option[String] = {
|
||||||
|
line.trim match {
|
||||||
|
case CleanCommentLine(ctl) => Some(ctl)
|
||||||
|
case "" =>
|
||||||
|
None
|
||||||
|
case tl =>
|
||||||
|
reporter.warning(pos, "Comment has no start-of-line marker ('*')")
|
||||||
|
Some(tl)
|
||||||
|
}}
|
||||||
|
comment.trim.stripPrefix("/*").stripSuffix("*/").lines.toList flatMap (cleanLine(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Parses a comment (in the form of a list of lines) to a Comment instance, recursively on lines. To do so, it
|
||||||
|
* splits the whole comment into main body and tag bodies, then runs the `WikiParser` on each body before creating
|
||||||
|
* the comment instance.
|
||||||
|
*
|
||||||
|
* @param body The body of the comment parsed until now.
|
||||||
|
* @param tags All tags parsed until now.
|
||||||
|
* @param lastTagKey The last parsed tag, or `None` if the tag section hasn't started. Lines that are not tagged
|
||||||
|
* are part of the previous tag or, if none exists, of the body.
|
||||||
|
* @param remaining The lines that must still recursively be parsed. */
|
||||||
|
def parse0(docBody: String, tags: Map[TagKey, List[String]], lastTagKey: Option[TagKey], remaining: List[String]): Comment =
|
||||||
|
remaining match {
|
||||||
|
|
||||||
|
case SymbolTag(name, sym, body) :: ls =>
|
||||||
|
val key = SymbolTagKey(name, sym)
|
||||||
|
val value = body :: ((tags get key) getOrElse Nil)
|
||||||
|
parse0(docBody, tags + (key -> value), Some(key), ls)
|
||||||
|
|
||||||
|
case SimpleTag(name, body) :: ls =>
|
||||||
|
val key = SimpleTagKey(name)
|
||||||
|
val value = body :: ((tags get key) getOrElse Nil)
|
||||||
|
parse0(docBody, tags + (key -> value), Some(key), ls)
|
||||||
|
|
||||||
|
case line :: ls if (lastTagKey.isDefined) =>
|
||||||
|
val key = lastTagKey.get
|
||||||
|
val value =
|
||||||
|
((tags get key): @unchecked) match {
|
||||||
|
case Some(b :: bs) => (b + endOfLine + line) :: bs
|
||||||
|
case None => oops("lastTagKey set when no tag exists for key")
|
||||||
|
}
|
||||||
|
parse0(docBody, tags + (key -> value), lastTagKey, ls)
|
||||||
|
|
||||||
|
case line :: ls =>
|
||||||
|
val newBody =
|
||||||
|
if (docBody == "") line else docBody + endOfLine + line
|
||||||
|
parse0(newBody, tags, lastTagKey, ls)
|
||||||
|
|
||||||
|
case Nil =>
|
||||||
|
|
||||||
|
val bodyTags: mutable.Map[TagKey, List[Body]] =
|
||||||
|
mutable.Map((tags map { case (key, values) => key -> (values map (parseWiki(_, pos))) }).toSeq:_*)
|
||||||
|
|
||||||
|
def oneTag(key: SimpleTagKey): Option[Body] =
|
||||||
|
((bodyTags remove key): @unchecked) match {
|
||||||
|
case Some(r :: rs) =>
|
||||||
|
if (!rs.isEmpty) reporter.warning(pos, "Only one '@" + key.name + "' tag is allowed")
|
||||||
|
Some(r)
|
||||||
|
case None => None
|
||||||
|
}
|
||||||
|
|
||||||
|
def allTags(key: SimpleTagKey): List[Body] =
|
||||||
|
(bodyTags remove key) getOrElse Nil
|
||||||
|
|
||||||
|
def allSymsOneTag(key: TagKey): Map[String, Body] = {
|
||||||
|
val keys: Sequence[SymbolTagKey] =
|
||||||
|
bodyTags.keys.toSeq flatMap {
|
||||||
|
case stk: SymbolTagKey if (stk.name == key.name) => Some(stk)
|
||||||
|
case stk: SimpleTagKey if (stk.name == key.name) =>
|
||||||
|
reporter.warning(pos, "Tag '@" + stk.name + "' must be followed by a symbol name")
|
||||||
|
None
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
val pairs: Sequence[(String, Body)] =
|
||||||
|
for (key <- keys) yield {
|
||||||
|
val bs = (bodyTags remove key).get
|
||||||
|
if (bs.length > 1)
|
||||||
|
reporter.warning(pos, "Only one '@" + key.name + "' tag for symbol " + key.symbol + " is allowed")
|
||||||
|
(key.symbol, bs.head)
|
||||||
|
}
|
||||||
|
Map.empty[String, Body] ++ pairs
|
||||||
|
}
|
||||||
|
|
||||||
|
val com = new Comment {
|
||||||
|
val body = parseWiki(docBody, pos)
|
||||||
|
val authors = allTags(SimpleTagKey("author"))
|
||||||
|
val see = allTags(SimpleTagKey("see"))
|
||||||
|
val result = oneTag(SimpleTagKey("return"))
|
||||||
|
val throws = allSymsOneTag(SimpleTagKey("throws"))
|
||||||
|
val valueParams = allSymsOneTag(SimpleTagKey("param"))
|
||||||
|
val typeParams = allSymsOneTag(SimpleTagKey("tparam"))
|
||||||
|
val version = oneTag(SimpleTagKey("version"))
|
||||||
|
val since = oneTag(SimpleTagKey("since"))
|
||||||
|
val todo = allTags(SimpleTagKey("todo"))
|
||||||
|
val deprecated = oneTag(SimpleTagKey("deprecated"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (key <- bodyTags.keys)
|
||||||
|
reporter.warning(pos, "Tag '@" + key.name + "' is not recognised")
|
||||||
|
|
||||||
|
com
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
parse0("", Map.empty, None, cleaned)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Parses a string containing wiki syntax into a `Comment` object. Note that the string is assumed to be clean:
|
||||||
|
* * Removed Scaladoc start and end markers.
|
||||||
|
* * Removed start-of-line star and one whitespace afterwards (if present).
|
||||||
|
* * Removed all end-of-line whitespace.
|
||||||
|
* * Only `endOfLine` is used to mark line endings. */
|
||||||
|
protected def parseWiki(string: String, pos: Position): Body =
|
||||||
|
new WikiParser(string.toArray, pos).document()
|
||||||
|
|
||||||
|
/** TODO
|
||||||
|
*
|
||||||
|
* @author Ingo Maier
|
||||||
|
* @author Manohar Jonnalagedda
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
protected final class WikiParser(val buffer: Array[Char], pos: Position) extends CharReader(buffer) { wiki =>
|
||||||
|
|
||||||
|
def document(): Body = {
|
||||||
|
nextChar()
|
||||||
|
val blocks = new mutable.ListBuffer[Block]
|
||||||
|
while(char != endOfText)
|
||||||
|
blocks += block()
|
||||||
|
Body(blocks.toList)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BLOCKS */
|
||||||
|
|
||||||
|
/** {{{ block ::= code | title | hrule | para }}} */
|
||||||
|
def block(): Block = {
|
||||||
|
if (check("{{{"))
|
||||||
|
code()
|
||||||
|
else if (check("="))
|
||||||
|
title()
|
||||||
|
else if (check("----"))
|
||||||
|
hrule()
|
||||||
|
// TODO: Lists
|
||||||
|
else {
|
||||||
|
para()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {{{ code ::= "{{{" { char } '}' "}}" '\n' }}} */
|
||||||
|
def code(): Block = {
|
||||||
|
jump("{{{")
|
||||||
|
readUntil("}}}")
|
||||||
|
if (char == endOfText)
|
||||||
|
reporter.warning(pos, "unclosed code block")
|
||||||
|
else
|
||||||
|
jump("}}}")
|
||||||
|
blockEnded("code block")
|
||||||
|
Code(getRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */
|
||||||
|
def title(): Block = {
|
||||||
|
val inLevel = repeatJump("=")
|
||||||
|
val text = inline(check(Array.fill(inLevel)('=')))
|
||||||
|
val outLevel = repeatJump("=", inLevel)
|
||||||
|
if (inLevel != outLevel)
|
||||||
|
reporter.warning(pos, "unbalanced or unclosed heading")
|
||||||
|
blockEnded("heading")
|
||||||
|
Title(text, inLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {{{ hrule ::= "----" { '-' } '\n' }}} */
|
||||||
|
def hrule(): Block = {
|
||||||
|
repeatJump("-")
|
||||||
|
blockEnded("horizontal rule")
|
||||||
|
HorizontalRule()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {{{ para ::= inline '\n' }}} */
|
||||||
|
def para(): Block = {
|
||||||
|
def checkParaEnd(): Boolean = {
|
||||||
|
check(Array(endOfLine, endOfLine)) ||
|
||||||
|
check(Array(endOfLine, '='))
|
||||||
|
check(Array(endOfLine, '{', '{', '{'))
|
||||||
|
}
|
||||||
|
val p = Paragraph(inline(checkParaEnd()))
|
||||||
|
while (char == endOfLine && char != endOfText)
|
||||||
|
nextChar()
|
||||||
|
p
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INLINES */
|
||||||
|
|
||||||
|
def inline(isBlockEnd: => Boolean): Inline =
|
||||||
|
inline(isBlockEnd, isBlockEnd)
|
||||||
|
|
||||||
|
def inline(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
def inline0(): Inline = {
|
||||||
|
if (check("'''"))
|
||||||
|
bold(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check("''"))
|
||||||
|
italic(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check("`"))
|
||||||
|
monospace(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check("__"))
|
||||||
|
underline(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check("^"))
|
||||||
|
superscript(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check(",,"))
|
||||||
|
subscript(isInlineEnd, isBlockEnd)
|
||||||
|
else if (check("[["))
|
||||||
|
link(isInlineEnd, isBlockEnd)
|
||||||
|
else {
|
||||||
|
readUntil { check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || isBlockEnd || char == endOfLine }
|
||||||
|
Text(getRead())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val inlines: List[Inline] = {
|
||||||
|
val iss = mutable.ListBuffer.empty[Inline]
|
||||||
|
iss += inline0()
|
||||||
|
while(!isInlineEnd && !isBlockEnd && !checkParaEnded) {
|
||||||
|
if (char == endOfLine) nextChar()
|
||||||
|
val current = inline0()
|
||||||
|
(iss.last, current) match {
|
||||||
|
case (Text(t1), Text(t2)) =>
|
||||||
|
iss.update(iss.length - 1, Text(t1 + endOfLine + t2))
|
||||||
|
case _ => iss += current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iss.toList
|
||||||
|
}
|
||||||
|
inlines match {
|
||||||
|
case Nil => Text("")
|
||||||
|
case i :: Nil => i
|
||||||
|
case i :: is => Chain(i :: is)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def bold(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("'''")
|
||||||
|
val i = inline(check("'''"), isBlockEnd)
|
||||||
|
jump("'''")
|
||||||
|
Bold(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
def italic(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("''")
|
||||||
|
val i = inline(check("''"), isBlockEnd)
|
||||||
|
jump("''")
|
||||||
|
Italic(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
def monospace(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("`")
|
||||||
|
readUntil { char == '`' }
|
||||||
|
jump("`")
|
||||||
|
Monospace(getRead())
|
||||||
|
}
|
||||||
|
|
||||||
|
def underline(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("__")
|
||||||
|
val i = inline(check("__"), isBlockEnd)
|
||||||
|
jump("__")
|
||||||
|
Underline(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
def superscript(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("^")
|
||||||
|
val i = inline(check("^"), isBlockEnd)
|
||||||
|
jump("^")
|
||||||
|
Superscript(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
def subscript(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump(",,")
|
||||||
|
val i = inline(check(",,"), isBlockEnd)
|
||||||
|
jump(",,")
|
||||||
|
Subscript(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
def link(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
|
||||||
|
jump("[[")
|
||||||
|
readUntil { check("]]") }
|
||||||
|
jump("]]")
|
||||||
|
Link(getRead())
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UTILITY */
|
||||||
|
|
||||||
|
/** {{{ eol ::= { whitespace } '\n' }}} */
|
||||||
|
def blockEnded(blockType: String): Unit = {
|
||||||
|
if (char != endOfLine && char != endOfText) {
|
||||||
|
reporter.warning(pos, "no additional content on same line after " + blockType)
|
||||||
|
jumpUntil(endOfLine)
|
||||||
|
}
|
||||||
|
while (char == endOfLine)
|
||||||
|
nextChar()
|
||||||
|
}
|
||||||
|
|
||||||
|
def checkParaEnded(): Boolean = {
|
||||||
|
char == endOfText || check(Array(endOfLine, endOfLine)) || check(Array(endOfLine, '{', '{', '{')) || check(Array(endOfLine, '\u003D'))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected sealed class CharReader(buffer: Array[Char]) { reader =>
|
||||||
|
|
||||||
|
var char: Char = _
|
||||||
|
var offset: Int = 0
|
||||||
|
|
||||||
|
final def nextChar(): Unit = {
|
||||||
|
if (offset >= buffer.length)
|
||||||
|
char = endOfText
|
||||||
|
else {
|
||||||
|
char = buffer(offset)
|
||||||
|
offset += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit def strintToChars(s: String): Array[Char] = s.toArray
|
||||||
|
|
||||||
|
def store(body: => Unit): String = {
|
||||||
|
val pre = offset
|
||||||
|
body
|
||||||
|
val post = offset
|
||||||
|
buffer.toArray.slice(pre, post).toString
|
||||||
|
}
|
||||||
|
|
||||||
|
final def check(chars: Array[Char]): Boolean = {
|
||||||
|
val poff = offset
|
||||||
|
val pc = char
|
||||||
|
val ok = jump(chars)
|
||||||
|
offset = poff
|
||||||
|
char = pc
|
||||||
|
ok
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JUMPERS */
|
||||||
|
|
||||||
|
final def jump(chars: Array[Char]): Boolean = {
|
||||||
|
var index = 0
|
||||||
|
while (index < chars.length && char == chars(index) && char != endOfText) {
|
||||||
|
nextChar()
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
index == chars.length
|
||||||
|
}
|
||||||
|
|
||||||
|
final def checkedJump(chars: Array[Char]): Boolean = {
|
||||||
|
val poff = offset
|
||||||
|
val pc = char
|
||||||
|
val ok = jump(chars)
|
||||||
|
if (!ok) {
|
||||||
|
offset = poff
|
||||||
|
char = pc
|
||||||
|
}
|
||||||
|
ok
|
||||||
|
}
|
||||||
|
|
||||||
|
final def repeatJump(chars: Array[Char], max: Int): Int = {
|
||||||
|
var count = 0
|
||||||
|
var more = true
|
||||||
|
while (more && count < max) {
|
||||||
|
if (!checkedJump(chars))
|
||||||
|
more = false
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def repeatJump(chars: Array[Char]): Int = {
|
||||||
|
var count = 0
|
||||||
|
var more = true
|
||||||
|
while (more) {
|
||||||
|
if (!checkedJump(chars))
|
||||||
|
more = false
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def jumpUntil(ch: Char): Int = {
|
||||||
|
var count = 0
|
||||||
|
while(char != ch && char != endOfText)
|
||||||
|
nextChar()
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def jumpUntil(chars: Array[Char]): Int = {
|
||||||
|
assert(chars.length > 0)
|
||||||
|
var count = 0
|
||||||
|
val c = chars(0)
|
||||||
|
while(!check(chars) && char != endOfText) {
|
||||||
|
nextChar()
|
||||||
|
while (char != c && char != endOfText)
|
||||||
|
nextChar()
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def jumpUntil(pred: => Boolean): Int = {
|
||||||
|
var count = 0
|
||||||
|
while (!pred && char != endOfText)
|
||||||
|
nextChar()
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
def jumpWhitespace() = jumpUntil(!isWhitespace(char))
|
||||||
|
|
||||||
|
/* READERS */
|
||||||
|
|
||||||
|
private val readBuilder = new mutable.StringBuilder
|
||||||
|
|
||||||
|
final def getRead(): String = {
|
||||||
|
val bld = readBuilder.toString
|
||||||
|
readBuilder.clear()
|
||||||
|
bld
|
||||||
|
}
|
||||||
|
|
||||||
|
final def readUntil(ch: Char): Int = {
|
||||||
|
var count = 0
|
||||||
|
while(char != ch && char != endOfText) {
|
||||||
|
readBuilder += char
|
||||||
|
nextChar()
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def readUntil(chars: Array[Char]): Int = {
|
||||||
|
assert(chars.length > 0)
|
||||||
|
var count = 0
|
||||||
|
val c = chars(0)
|
||||||
|
while(!check(chars) && char != endOfText) {
|
||||||
|
readBuilder += char
|
||||||
|
nextChar()
|
||||||
|
while (char != c && char != endOfText) {
|
||||||
|
readBuilder += char
|
||||||
|
nextChar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
final def readUntil(pred: => Boolean): Int = {
|
||||||
|
var count = 0
|
||||||
|
while (!pred && char != endOfText) {
|
||||||
|
readBuilder += char
|
||||||
|
nextChar()
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CHARS CLASSES */
|
||||||
|
|
||||||
|
def isWhitespace(c: Char) = (c: @switch) match {
|
||||||
|
case ' ' | '\t' => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,112 +0,0 @@
|
||||||
<!--
|
|
||||||
// NSC -- new Scala compiler
|
|
||||||
// Copyright 2005-2009 LAMP/EPFL
|
|
||||||
// @author Stephane Micheloud
|
|
||||||
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
function setWindowTitle(title) {
|
|
||||||
parent.document.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
var java_api_root = 'http://java.sun.com/javase/6/docs/api/';
|
|
||||||
//var java_api_root = 'http://java.sun.com/j2se/1.5.0/docs/api/';
|
|
||||||
//var java_api_root = 'http://lamp.epfl.ch/~linuxsoft/java/jdk1.5/docs/api/';
|
|
||||||
|
|
||||||
var javax_servlet_api_root = 'http://java.sun.com/products/servlet/2.3/javadoc/';
|
|
||||||
|
|
||||||
var scala_doc_url = parent.document.URL;
|
|
||||||
var scala_api_root = scala_doc_url.substring(0, scala_doc_url.lastIndexOf("/")+1);
|
|
||||||
|
|
||||||
var ant_api_root = 'http://lamp.epfl.ch/~linuxsoft/ant/manual/api/';
|
|
||||||
//var ant_api_root = 'http://www.net-freaks.org/doc/ant-1.6.5/manual/api/';
|
|
||||||
|
|
||||||
var eclipse_api_root = 'http://help.eclipse.org/help32/topic/org.eclipse.platform.doc.isv/reference/api/';
|
|
||||||
|
|
||||||
var fjbg_api_root = 'http://lamp.epfl.ch/~linuxsoft/fjbg/api/';
|
|
||||||
|
|
||||||
var liftweb_api_root = 'http://lamp.epfl.ch/~linuxsoft/liftweb/apidocs/';
|
|
||||||
|
|
||||||
function get_api_root(key) {
|
|
||||||
root = null;
|
|
||||||
if (key.indexOf("ch/epfl/lamp/fjbg/") == 0) { root = fjbg_api_root; }
|
|
||||||
else if (key.indexOf("java/" ) == 0) { root = java_api_root; }
|
|
||||||
else if (key.indexOf("javax/" ) == 0) { root = java_api_root; }
|
|
||||||
else if (key.indexOf("javax/servlet/" ) == 0) { root = javax_servlet_api_root; }
|
|
||||||
else if (key.indexOf("scala/" ) == 0) { root = scala_api_root; }
|
|
||||||
else if (key.indexOf("org/apache/tools/" ) == 0) { root = ant_api_root; }
|
|
||||||
else if (key.indexOf("org/eclipse/" ) == 0) { root = eclipse_api_root; }
|
|
||||||
else if (key.indexOf("net/liftweb/" ) == 0) { root = liftweb_api_root; }
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scala_src_root = 'http://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/';
|
|
||||||
var lib_src_root = scala_src_root + 'src/library/';
|
|
||||||
var comp_src_root = scala_src_root + 'src/compiler/';
|
|
||||||
var actors_src_root = scala_src_root + 'src/actors/';
|
|
||||||
var dbc_src_root = scala_src_root + 'src/dbc/';
|
|
||||||
var swing_src_root = scala_src_root + 'src/swing/';
|
|
||||||
|
|
||||||
//var liftweb_src_root = 'http://liftweb.googlecode.com/svn/trunk/liftweb/lift/src/main/scala/';
|
|
||||||
|
|
||||||
function get_src_root(key) {
|
|
||||||
root = null;
|
|
||||||
if (key.indexOf("scala/actors/") == 0) { root = actors_src_root; }
|
|
||||||
else if (key.indexOf("scala/dbc/" ) == 0) { root = dbc_src_root; }
|
|
||||||
else if (key.indexOf("scala/swing/" ) == 0) { root = swing_src_root; }
|
|
||||||
else if (key.indexOf("scala/tools/" ) == 0) { root = comp_src_root; }
|
|
||||||
else if (key.indexOf("scala/" ) == 0) { root = lib_src_root; }
|
|
||||||
//else if (key.indexOf("net/liftweb/" ) == 0) { root = liftweb_src_root; }
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
elems = document.getElementsByTagName('a');
|
|
||||||
for (i = 0; i < elems.length; i++) {
|
|
||||||
try {
|
|
||||||
key = elems[i].getAttribute('class');
|
|
||||||
href = elems[i].getAttribute('href');
|
|
||||||
api_root = get_api_root(key);
|
|
||||||
if (api_root != null) {
|
|
||||||
href1 = href.substring(href.lastIndexOf("#"))
|
|
||||||
value = api_root + key + ".html" + href1;
|
|
||||||
elems[i].setAttribute('href', value);
|
|
||||||
}
|
|
||||||
src_root = get_src_root(key);
|
|
||||||
if (src_root != null) {
|
|
||||||
value = src_root + key + '.scala?view=markup';
|
|
||||||
elems[i].setAttribute('href', value);
|
|
||||||
elems[i].setAttribute('target' , '_top');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLocation() {
|
|
||||||
kinds = parent.navigationFrame.document.getElementById("kinds");
|
|
||||||
oldLocation = parent.classesFrame.window.location.href;
|
|
||||||
//alert("oldLocation="+oldLocation);
|
|
||||||
pos = oldLocation.lastIndexOf("#");
|
|
||||||
classesURL = (pos > 0) ? oldLocation.substring(0, pos) : oldLocation;
|
|
||||||
newLocation = classesURL + kinds.options[kinds.selectedIndex].value;
|
|
||||||
//alert("newLocation="+newLocation);
|
|
||||||
return newLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotoKind() {
|
|
||||||
parent.classesFrame.window.location = getLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetKind() {
|
|
||||||
kinds = parent.navigationFrame.document.getElementById("kinds");
|
|
||||||
kinds.selectedIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotoName(letter) {
|
|
||||||
parent.classesFrame.window.location = getLocation() + "_" + letter;
|
|
||||||
}
|
|
||||||
-->
|
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
/* Scaladoc style sheet */
|
|
||||||
|
|
||||||
a:link {
|
|
||||||
color: #0000ee;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #551a8b;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:active {
|
|
||||||
color: #0000ee;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.entity {
|
|
||||||
margin: 18px 0px 18px 0px;
|
|
||||||
font-size: x-large;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.doctitle {
|
|
||||||
font-weight: bold;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.doctitle-larger {
|
|
||||||
margin: 0px 0px 10px 0px;
|
|
||||||
font-size: larger;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.kinds {
|
|
||||||
margin: 0.6em 0 0 0; /* top right bottom left */
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.page-title {
|
|
||||||
margin: 15px 0px 15px 0px;
|
|
||||||
font-size: x-large;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.source {
|
|
||||||
font-size: smaller;
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.entity {
|
|
||||||
color: #ff6666;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.member {
|
|
||||||
margin: 0 0 1.2em 0; /* top rigth bottom left */
|
|
||||||
border-collapse: collapse;
|
|
||||||
border: 2px inset #888888;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.member td.title {
|
|
||||||
border: 2px inset #888888;
|
|
||||||
background-color: #ccccff;
|
|
||||||
font-size: x-large;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.inherited {
|
|
||||||
margin: 0 0 1.2em 0; /* top rigth bottom left */
|
|
||||||
border-collapse: collapse;
|
|
||||||
border: 2px inset #888888;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.inherited td.title {
|
|
||||||
background-color: #eeeeff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.member-detail {
|
|
||||||
margin: 10px 0px 0px 0px;
|
|
||||||
border-collapse: collapse;
|
|
||||||
border: 2px inset #888888;
|
|
||||||
background-color: #ffffff;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.member-detail td.title {
|
|
||||||
border: 2px inset #888888;
|
|
||||||
background-color: #ccccff;
|
|
||||||
font-size: x-large;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.navigation {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
font-family: Arial,Helvetica,Sans-Serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.inherited-members {
|
|
||||||
border-top: 2px inset #888888;
|
|
||||||
border-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.inherited-owner {
|
|
||||||
background-color: #eeeeff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.modifiers {
|
|
||||||
border-top: 2px inset #888888;
|
|
||||||
border-right: 2px inset #888888;
|
|
||||||
width: 50px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.navigation-enabled {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #eeeeff;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.navigation-links {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #eeeeff;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.navigation-selected {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #00008b;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.signature {
|
|
||||||
border-top: 2px inset #888888;
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.list {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|