summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKato Kazuyoshi <kato.kazuyoshi@gmail.com>2011-06-20 14:20:45 +0000
committerKato Kazuyoshi <kato.kazuyoshi@gmail.com>2011-06-20 14:20:45 +0000
commit2627ab313f0d9f33e1b97e8aeda4447cf34bd27d (patch)
treeb119264c47c6c990395ba3610209905aaf270b51
parentd2fd3d61d1cceb79c731a4be46977384c7cb7c9b (diff)
downloadscala-2627ab313f0d9f33e1b97e8aeda4447cf34bd27d.tar.gz
scala-2627ab313f0d9f33e1b97e8aeda4447cf34bd27d.tar.bz2
scala-2627ab313f0d9f33e1b97e8aeda4447cf34bd27d.zip
Separete index.js to parallelize downloads.
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala1
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala71
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/Page.scala93
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Index.scala70
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala68
-rw-r--r--test/scaladoc/scala/IndexScriptTest.scala52
-rw-r--r--test/scaladoc/scala/IndexTest.scala20
7 files changed, 217 insertions, 158 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
index 8fc044c195..88cd589797 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -97,6 +97,7 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
copyResource("lib/unselected.png")
new page.Index(universe, index) writeFor this
+ new page.IndexScript(universe, index) writeFor this
writeTemplates(page => page.writeFor(this))
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index d99403e5ba..cfa846b097 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -15,18 +15,11 @@ import xml.dtd.{DocType, PublicID}
import scala.collection._
import scala.reflect.NameTransformer
import java.nio.channels.Channels
-import java.io.{FileOutputStream, File}
/** 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]
-
+abstract class HtmlPage extends Page { thisPage =>
/** The title of this page. */
protected def title: String
@@ -36,9 +29,6 @@ abstract class HtmlPage { thisPage =>
/** The body of this page. */
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: HtmlFactory): Unit = {
val doctype =
DocType("html", PublicID("-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"), Nil)
@@ -51,10 +41,7 @@ abstract class HtmlPage { thisPage =>
</head>
{ body }
</html>
- val pageFile = new File(site.siteRoot, absoluteLinkTo(thisPage.path))
- val pageFolder = pageFile.getParentFile
- if (!pageFolder.exists) pageFolder.mkdirs()
- val fos = new FileOutputStream(pageFile.getPath)
+ val fos = createFileOutputStream(site)
val w = Channels.newWriter(fos.getChannel, site.encoding)
try {
w.write("<?xml version='1.0' encoding='" + site.encoding + "'?>\n")
@@ -68,52 +55,6 @@ abstract class HtmlPage { thisPage =>
//XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype)
}
- def templateToPath(tpl: TemplateEntity): List[String] = {
- def doName(tpl: TemplateEntity): String =
- NameTransformer.encode(tpl.name) + (if (tpl.isObject) "$" else "")
- def downPacks(pack: Package): List[String] =
- if (pack.isRootPackage) Nil else (doName(pack) :: 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)
- }
- }
- 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("/")
- }
-
- def absoluteLinkTo(destPath: List[String]): String = {
- 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 =
@@ -229,14 +170,6 @@ abstract class HtmlPage { thisPage =>
case tpl :: tpls => templateToHtml(tpl) ++ sep ++ templatesToHtml(tpls, sep)
}
- def docEntityKindToString(ety: DocTemplateEntity) =
- if (ety.isTrait) "trait"
- else if (ety.isCaseClass) "case class"
- else if (ety.isClass) "class"
- else if (ety.isObject) "object"
- else if (ety.isPackage) "package"
- else "class" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
-
/** Returns the _big image name corresponding to the DocTemplate Entity (upper left icon) */
def docEntityKindToBigImage(ety: DocTemplateEntity) =
if (ety.isTrait && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "trait_to_object_big.png"
diff --git a/src/compiler/scala/tools/nsc/doc/html/Page.scala b/src/compiler/scala/tools/nsc/doc/html/Page.scala
new file mode 100644
index 0000000000..f72b0a49eb
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/Page.scala
@@ -0,0 +1,93 @@
+package scala.tools.nsc.doc.html
+import scala.tools.nsc.doc.model._
+import java.io.{FileOutputStream, File}
+import scala.reflect.NameTransformer
+
+abstract class Page {
+ 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]
+
+ def absoluteLinkTo(path: List[String]) = path.reverse.mkString("/")
+
+ def createFileOutputStream(site: HtmlFactory) = {
+ val file = new File(site.siteRoot, absoluteLinkTo(thisPage.path))
+ val folder = file.getParentFile
+ if (! folder.exists) {
+ folder.mkdirs
+ }
+ new FileOutputStream(file.getPath)
+ }
+
+ /** 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: HtmlFactory): Unit
+
+ def docEntityKindToString(ety: DocTemplateEntity) =
+ if (ety.isTrait) "trait"
+ else if (ety.isCaseClass) "case class"
+ else if (ety.isClass) "class"
+ else if (ety.isObject) "object"
+ else if (ety.isPackage) "package"
+ else "class" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
+
+ def templateToPath(tpl: TemplateEntity): List[String] = {
+ def doName(tpl: TemplateEntity): String =
+ NameTransformer.encode(tpl.name) + (if (tpl.isObject) "$" else "")
+ def downPacks(pack: Package): List[String] =
+ if (pack.isRootPackage) Nil else (doName(pack) :: 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)
+ }
+ }
+ 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("/")
+ }
+
+ def isExcluded(dtpl: DocTemplateEntity) = {
+ val qname = dtpl.qualifiedName
+ ( ( qname.startsWith("scala.Tuple") || qname.startsWith("scala.Product") ||
+ qname.startsWith("scala.Function") || qname.startsWith("scala.runtime.AbstractFunction")
+ ) && !(
+ qname == "scala.Tuple1" || qname == "scala.Tuple2" ||
+ qname == "scala.Product" || qname == "scala.Product1" || qname == "scala.Product2" ||
+ qname == "scala.Function" || qname == "scala.Function1" || qname == "scala.Function2" ||
+ qname == "scala.runtime.AbstractFunction0" || qname == "scala.runtime.AbstractFunction1" ||
+ qname == "scala.runtime.AbstractFunction2"
+ )
+ )
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
index 4fc10b2ec2..7203230084 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
@@ -48,23 +48,7 @@ class Index(universe: doc.Universe, index: doc.Index) extends HtmlPage {
</div>
</body>
-
- def isExcluded(dtpl: DocTemplateEntity) = {
- val qname = dtpl.qualifiedName
- ( ( qname.startsWith("scala.Tuple") || qname.startsWith("scala.Product") ||
- qname.startsWith("scala.Function") || qname.startsWith("scala.runtime.AbstractFunction")
- ) && !(
- qname == "scala.Tuple1" || qname == "scala.Tuple2" ||
- qname == "scala.Product" || qname == "scala.Product1" || qname == "scala.Product2" ||
- qname == "scala.Function" || qname == "scala.Function1" || qname == "scala.Function2" ||
- qname == "scala.runtime.AbstractFunction0" || qname == "scala.runtime.AbstractFunction1" ||
- qname == "scala.runtime.AbstractFunction2"
- )
- )
- }
-
def browser =
- <xml:group>
<div id="browser" class="ui-layout-west">
<div class="ui-west-center">
<div id="filter"></div>
@@ -121,60 +105,8 @@ class Index(universe: doc.Universe, index: doc.Index) extends HtmlPage {
</xml:group>
}
packageElem(universe.rootPackage)
- }</div></div>{ scriptElement }
+ }</div></div><script src="index.js"></script>
</div>
- </xml:group>
-
- def mergeByQualifiedName(source: List[DocTemplateEntity]): Map[String, List[DocTemplateEntity]]= {
- var result = Map[String, List[DocTemplateEntity]]()
-
- for (t <- source) {
- val k = t.qualifiedName
- result += k -> (result.getOrElse(k, List()) :+ t)
- }
-
- result
- }
-
- def scriptElement = {
- val packages = allPackagesWithTemplates.toIterable.map(_ match {
- case (pack, templates) => {
- val merged = mergeByQualifiedName(templates)
-
- val ary = merged.keys.toList.sortBy(_.toLowerCase).map(key => {
- val pairs = merged(key).map(
- t => docEntityKindToString(t) -> relativeLinkTo(t)
- ) :+ ("name" -> key)
-
- JSONObject(scala.collection.immutable.Map(pairs : _*))
- })
-
- pack.qualifiedName -> JSONArray(ary)
- }
- }).toSeq
-
- val obj =
- JSONObject(scala.collection.immutable.Map(packages : _*)).toString()
-
- <script type="text/javascript">
- Index.PACKAGES = {scala.xml.Unparsed(obj)};
- </script>
- }
-
- def allPackagesWithTemplates: Map[Package, List[DocTemplateEntity]] = {
- Map(allPackages.map((key) => {
- key -> key.templates.filter(t => !t.isPackage && !isExcluded(t))
- }) : _*)
- }
-
- def allPackages: List[Package] = {
- def f(parent: Package): List[Package] = {
- parent.packages.flatMap(
- p => f(p) :+ p
- )
- }
- f(universe.rootPackage).sortBy(_.toString)
- }
def packageQualifiedName(ety: DocTemplateEntity): String =
if (ety.inTemplate.isPackage) ety.name else (packageQualifiedName(ety.inTemplate) + "." + ety.name)
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala
new file mode 100644
index 0000000000..2cafe6caa3
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala
@@ -0,0 +1,68 @@
+package scala.tools.nsc.doc.html.page
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.model.{Package, DocTemplateEntity}
+import scala.tools.nsc.doc.html.{Page, HtmlFactory}
+import java.nio.channels.Channels
+import scala.util.parsing.json.{JSONObject, JSONArray}
+
+class IndexScript(universe: doc.Universe, index: doc.Index) extends Page {
+ def path = List("index.js")
+
+ override def writeFor(site: HtmlFactory): Unit = {
+ val stream = createFileOutputStream(site)
+ val writer = Channels.newWriter(stream.getChannel, site.encoding)
+ try {
+ writer.write("Index.PACKAGES = " + packages.toString() + ";")
+ }
+ finally {
+ writer.close
+ stream.close
+ }
+ }
+
+ val packages = {
+ val pairs = allPackagesWithTemplates.toIterable.map(_ match {
+ case (pack, templates) => {
+ val merged = mergeByQualifiedName(templates)
+
+ val ary = merged.keys.toList.sortBy(_.toLowerCase).map(key => {
+ val pairs = merged(key).map(
+ t => docEntityKindToString(t) -> relativeLinkTo(t)
+ ) :+ ("name" -> key)
+
+ JSONObject(scala.collection.immutable.Map(pairs : _*))
+ })
+
+ pack.qualifiedName -> JSONArray(ary)
+ }
+ }).toSeq
+
+ JSONObject(scala.collection.immutable.Map(pairs : _*))
+ }
+
+ def mergeByQualifiedName(source: List[DocTemplateEntity]) = {
+ var result = Map[String, List[DocTemplateEntity]]()
+
+ for (t <- source) {
+ val k = t.qualifiedName
+ result += k -> (result.getOrElse(k, List()) :+ t)
+ }
+
+ result
+ }
+
+ def allPackages = {
+ def f(parent: Package): List[Package] = {
+ parent.packages.flatMap(
+ p => f(p) :+ p
+ )
+ }
+ f(universe.rootPackage).sortBy(_.toString)
+ }
+
+ def allPackagesWithTemplates = {
+ Map(allPackages.map((key) => {
+ key -> key.templates.filter(t => !t.isPackage && !isExcluded(t))
+ }) : _*)
+ }
+}
diff --git a/test/scaladoc/scala/IndexScriptTest.scala b/test/scaladoc/scala/IndexScriptTest.scala
new file mode 100644
index 0000000000..991491c376
--- /dev/null
+++ b/test/scaladoc/scala/IndexScriptTest.scala
@@ -0,0 +1,52 @@
+import org.scalacheck._
+import org.scalacheck.Prop._
+
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.html.page.IndexScript
+import java.net.URLClassLoader
+
+object Test extends Properties("IndexScript") {
+
+ def getClasspath = {
+ val loader = Thread.currentThread.getContextClassLoader
+ val paths = loader.asInstanceOf[URLClassLoader].getURLs
+ val morepaths = loader.getParent.asInstanceOf[URLClassLoader].getURLs
+ (paths ++ morepaths).map(_.getPath).mkString(java.io.File.pathSeparator)
+ }
+
+ val docFactory = {
+ val settings = new doc.Settings({Console.err.println(_)})
+ settings.classpath.value = getClasspath
+ val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
+ new doc.DocFactory(reporter, settings)
+ }
+
+ val indexModelFactory = doc.model.IndexModelFactory
+
+ def createIndexScript(path: String) =
+ docFactory.makeUniverse(List(path)) match {
+ case Some(universe) => {
+ val index = new IndexScript(universe,
+ indexModelFactory.makeIndex(universe))
+ Some(index)
+ }
+ case _ =>
+ None
+ }
+
+ property("allPackages") = {
+ createIndexScript("src/compiler/scala/tools/nsc/doc/html/page/Index.scala") match {
+ case Some(index) =>
+ index.allPackages.map(_.toString) == List(
+ "scala",
+ "scala.tools",
+ "scala.tools.nsc",
+ "scala.tools.nsc.doc",
+ "scala.tools.nsc.doc.html",
+ "scala.tools.nsc.doc.html.page"
+ )
+ case None =>
+ false
+ }
+ }
+}
diff --git a/test/scaladoc/scala/IndexTest.scala b/test/scaladoc/scala/IndexTest.scala
index 5e3d02e045..7679bab0c6 100644
--- a/test/scaladoc/scala/IndexTest.scala
+++ b/test/scaladoc/scala/IndexTest.scala
@@ -79,24 +79,4 @@ object Test extends Properties("Index") {
case None => false
}
}
-
- property("allPackages") = {
- createIndex("src/compiler/scala/tools/nsc/doc/html/page/Index.scala") match {
-
- case Some(index) =>
- index.allPackages.map(_.toString) == List(
- "scala",
- "scala.tools",
- "scala.tools.nsc",
- "scala.tools.nsc.doc",
- "scala.tools.nsc.doc.html",
- "scala.tools.nsc.doc.html.page"
- )
-
- case None =>
- false
-
- }
- }
-
}