diff options
author | michelou <michelou@epfl.ch> | 2006-11-10 18:37:06 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2006-11-10 18:37:06 +0000 |
commit | 46ff81bfd585e675c1409132b3d4637736ae0c9f (patch) | |
tree | 1713c0e204f9d24b7999e8f95b4ba4623cb64512 | |
parent | 12014a82a3097a3cdb48f089a16aa5f44df8d6d6 (diff) | |
download | scala-46ff81bfd585e675c1409132b3d4637736ae0c9f.tar.gz scala-46ff81bfd585e675c1409132b3d4637736ae0c9f.tar.bz2 scala-46ff81bfd585e675c1409132b3d4637736ae0c9f.zip |
added list of inherited members in DocGenerator
improved quality of generated HTML code
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DocGenerator.scala | 248 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DocUtil.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/script.js | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/style.css | 56 |
4 files changed, 195 insertions, 119 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala index 3899c8dc6d..b18a8e5c1b 100644 --- a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala +++ b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala @@ -11,8 +11,8 @@ import java.util.StringTokenizer import java.util.regex.Pattern import compat.Platform.{EOL => LINE_SEPARATOR} -import scala.collection.immutable._ -import scala.collection.mutable.ListBuffer +import scala.collection.immutable.{ListMap, TreeMap, TreeSet} +import scala.collection.mutable.{HashMap, ListBuffer, Map} import scala.tools.nsc.models.Models import scala.tools.nsc.symtab.Flags import scala.xml._ @@ -190,7 +190,7 @@ abstract class DocGenerator extends Models { val path = "root-content" val title = "All Packages" def modules: TreeMap[String, ModuleClassSymbol] - def body: NodeSeq = { + def body: NodeSeq = <div class="page-title"> Scala 2 <br/>API Specification @@ -210,7 +210,6 @@ abstract class DocGenerator extends Models { </td></tr>; } } </table>; - } } abstract class ListClassFrame extends Frame { @@ -234,7 +233,9 @@ abstract class DocGenerator extends Models { </table>; val body = <div>{ { for (val kind <- KINDS; classes contains kind) yield { - <p><b>{Text(pluralFor(kind))}</b></p> + <p> + <b>{Text(pluralFor(kind))}</b> + </p> <table class="list" summary=""> <tr><td style="white-space;nowrap;"> { { @@ -253,14 +254,18 @@ abstract class DocGenerator extends Models { private def extendsFor(mmbr: HasTree): NodeSeq = mmbr match { case mmbr: ImplMod => - if (!mmbr.treey.impl.parents.isEmpty) - <span><dd><code>{Text(" extends ")}</code> - {forType(mmbr.treey.impl.parents.head.tpe)}</dd> - { { for (val parent <- mmbr.treey.impl.parents.tail) - yield <dd><code>{Text(" with ")}</code> - {forType(parent.tpe)}</dd>; - } } </span>; - else NodeSeq.Empty + val parents = mmbr.treey.impl.parents + if (parents.isEmpty) NodeSeq.Empty + else + <dd> + <code>{Text(" extends ")}</code>{forType(parents.head.tpe)} + </dd>.concat( + { { + for (val parent <- parents.tail) yield + <dd> + <code>{Text(" with ")}</code>{forType(parent.tpe)} + </dd> + } }) case _ => NodeSeq.Empty } @@ -300,23 +305,27 @@ abstract class DocGenerator extends Models { * @param mmbr ... * @return ... */ - def fullHeader(mmbr: HasTree): NodeSeq = <span>{ { - if (!mmbr.isInstanceOf[ImplMod]) - <a name = {Utility.escape(mmbr.tree.symbol.nameString)}></a>; - else NodeSeq.Empty - } }<dl><dt> - { attrsFor(mmbr.tree) } - <code> - { { for (val str <- stringsFor(mmbr.mods)) yield Text(str + " ") } } - { Text(codeFor(mmbr.kind)) } - </code> - <em>{ Text(nameFor(mmbr.tree)) }</em> - { typesFor(mmbr) }{ argsFor(mmbr)}{resultFor(mmbr) } - </dt> { extendsFor(mmbr) } - </dl> - { fullComment(mmbr) } - { listSubclasses(mmbr) } <hr/> - { lists(mmbr) } </span>; + def fullHeader(mmbr: HasTree): NodeSeq = Group( + { { + if (mmbr.isInstanceOf[ImplMod]) NodeSeq.Empty + else <a name = {Utility.escape(mmbr.tree.symbol.nameString)}></a> + } }.concat( + <dl> + <dt> + { attrsFor(mmbr.tree) } + <code> + { { for (val str <- stringsFor(mmbr.mods)) yield Text(str + " ") } } + { Text(codeFor(mmbr.kind)) } + </code> + <em>{ Text(nameFor(mmbr.tree)) }</em> + { typesFor(mmbr) }{ argsFor(mmbr)}{resultFor(mmbr) } + </dt> + <dd>{ extendsFor(mmbr) }</dd> + </dl>) + .concat(fullComment(mmbr)) + .concat(hr(listSubclasses(mmbr))) + .concat(lists(mmbr))) +// { lists(mmbr) } /** Return a NodeSeq with the known subclasses for <code>mmbr</code>, if any. * @@ -334,17 +343,22 @@ abstract class DocGenerator extends Models { </dt> <dd>{ { val links = - for (val subc <- subcs) yield - aref(urlFor(subc), contentFrame, subc.nameString) + for (val subc <- subcs) + yield aref(urlFor(subc), contentFrame, subc.nameString) links.reduceRight { (link: Seq[Node], seq: Seq[Node]) => link.concat(Text(", ")).concat(seq) } } }</dd> </dl>; } - def lists(mmbr: HasTree) = mmbr match { - case cmod: ImplMod => <span>{ listMembersShort(mmbr) } - { listMembersFull (mmbr) }</span> - case _ => NodeSeq.Empty + def lists(mmbr: HasTree): NodeSeq = mmbr match { + case cmod: ImplMod => + <span> + { listMembersShort(mmbr) } + { listInheritedMembers(mmbr) } + { listMembersFull(mmbr) } + </span> + case _ => + NodeSeq.Empty } /** @@ -354,47 +368,96 @@ abstract class DocGenerator extends Models { def listMembersShort(mmbr: HasTree): NodeSeq = if (mmbr.isInstanceOf[Composite]) { val map = organize(mmbr.asInstanceOf[Composite], emptyMap) - <span> { { - for (val kind <- KINDS; map contains kind) yield { - val x = <table cellpadding="3" class="member" summary=""> - <tr><td colspan="2" class="title">{Text(labelFor(kind))} Summary</td></tr> - { { + for (val kind <- KINDS; map contains kind) yield Group(br( + <table cellpadding="3" class="member" summary=""> + <tr> + <td colspan="2" class="title">{Text(labelFor(kind))} Summary</td> + </tr> + { { for (val mmbr <- map(kind).toList) yield shortHeader(mmbr) - } } - </table>; - br(x); - } - } } </span> + } } + </table>)) + } else + NodeSeq.Empty + + /** + * @param mmbr ... + * @return a sequence of HTML tables containing inherited members + */ + def listInheritedMembers(mmbr: HasTree): NodeSeq = + if (mmbr.isInstanceOf[Composite]) { + val sym = mmbr.tree.symbol + val ignored = List(definitions.ObjectClass, definitions.ScalaObjectClass) + val parents = sym.info.parents + for (val p <- parents; !ignored.contains(p.symbol)) yield Group(br( + <table cellpadding="3" class="inherited" summary=""> + <tr> + <td colspan="2" class="title"> + {Text("Methods inherited from ").concat(urlFor(p, contentFrame))} + </td> + </tr> + <tr> + { { + if (p.decls.isEmpty) NodeSeq.Empty // scope empty + else { + def aref1(sym: Symbol): NodeSeq = { + val ns = sym.nameString + val isJava = sym hasFlag Flags.JAVA + if (isJava || sym.sourceFile == null) { + val name = + if (isJava && ns.equals("this")) sym.owner.nameString + else ns + val args = + if (isJava) "()" // todo: arguments + else "" + <a class={sym.owner.fullNameString.replace('.', '_')} + href={"#" + name + args} + target={contentFrame}>{name}</a> + } + else + aref(urlFor(sym), contentFrame, sym.nameString) + } + val members = p.decls.toList.sort( + (x, y) => (x.nameString compareTo y.nameString) < 0) + <td colspan="2" class="signature"> + {aref1(members.head)} + {for (val m <- members.tail) yield Text(", ").concat(aref1(m))} + </td> + } + } } + </tr> + </table>)) } else NodeSeq.Empty + /** + * @param mmbr ... + * @return ... + */ def listMembersFull(mmbr: HasTree): NodeSeq = if (mmbr.isInstanceOf[Composite]) { val map = organize(mmbr.asInstanceOf[Composite], emptyMap) val mmbrx = mmbr val pathx = path - for (val kind0 <- OBJECT :: CLASS :: Nil; map contains kind0) for (val mmbr <- map(kind0)) { - new ContentFrame { - def clazz = mmbr.asInstanceOf[ImplMod]; - def kind = kind0; - def title = - labelFor(kind0) + " " + mmbr.tree.symbol.nameString + " in " + - codeFor(mmbrx.kind) + " " + mmbr.tree.symbol.owner.fullNameString('.') - } - } - <span> { { - for (val kind <- KINDS; map.contains(kind) && kind != OBJECT && kind != CLASS) yield { - val header = - <table cellpadding="3" class="member-detail" summary=""> - <tr><td class="member-title"> - {Text(labelFor(kind))} Detail - </td></tr> - </table> - val body = for (val mmbr <- map(kind).toList) yield <span>{fullHeader(mmbr)}</span>; - header.concat(body) - } - } } </span> + for (val kind0 <- List(OBJECT, CLASS); map contains kind0) + for (val mmbr <- map(kind0)) + new ContentFrame { + def clazz = mmbr.asInstanceOf[ImplMod] + def kind = kind0 + def title = + labelFor(kind0) + " " + mmbr.tree.symbol.nameString + " in " + + codeFor(mmbrx.kind) + " " + mmbr.tree.symbol.owner.fullNameString('.') + } + for (val kind <- List(TRAIT, CONSTRUCTOR, VAL, VAR, DEF); map contains kind) yield Group( + <table cellpadding="3" class="member-detail" summary=""> + <tr> + <td class="title">{Text(labelFor(kind))} Detail</td> + </tr> + </table> + <div> + {for (val mmbr <- map(kind).toList) yield fullHeader(mmbr)} + </div>) } else NodeSeq.Empty @@ -402,7 +465,7 @@ abstract class DocGenerator extends Models { * @param mmbr ... * @return ... */ - def shortHeader(mmbr: HasTree): NodeSeq = { + def shortHeader(mmbr: HasTree): NodeSeq = <tr> <td valign="top" class="modifiers"> { { for (val str <- stringsFor(mmbr.mods)) yield <code>{(Text(str + " "))}</code>; } } @@ -416,7 +479,6 @@ abstract class DocGenerator extends Models { <br>{shortComment(mmbr)}</br> </td> </tr> - } def fullComment(mmbr: HasTree): NodeSeq = comments.get(mmbr.tree.symbol) match { @@ -454,10 +516,9 @@ abstract class DocGenerator extends Models { case sel: Select => forTree(sel.qualifier).concat(Text(sel.symbol.nameString)) case tree: AbsTypeDef => - (Text(tree.symbol.nameString) - .concat(ifT(tree.hi, Text(" <: "), true)) - .concat(ifT(tree.lo, Text(" >: "), true))) - + Text(tree.symbol.nameString) + .concat(ifT(tree.hi, Text(" <: "), true)) + .concat(ifT(tree.lo, Text(" >: "), true)) case tpt: TypeTree => urlFor(tpt.tpe, contentFrame) case id: Ident => @@ -535,26 +596,24 @@ abstract class DocGenerator extends Models { def path = module.fullNameString('/') + "$content" def title = "All Classes and Objects in " + module.fullNameString('.') - def body: NodeSeq = { - <span><div class="page-title"> - Scala 2 - <br/>API Specification - </div> + def body: NodeSeq = + <div class="page-title"> + Scala 2<br/>API Specification + </div> + <p> This document is the API specification for Scala 2. - <p/> - { { - for (val kind <- KINDS; classes contains kind) yield { - <span><hr/><table cellpadding="3" class="member" summary=""> - <tr><td colspan="2" class="title"> + </p>.concat( + for (val kind <- KINDS; classes contains kind) yield Group(hr( + <table cellpadding="3" class="member" summary=""> + <tr> + <td colspan="2" class="title"> {labelFor(kind)} Summary - </td></tr>{ { + </td> + </tr> + { { for (val mmbr <- classes(kind).toList) yield shortHeader(mmbr) - } } - </table></span> - } - } } - </span>; - } + } } + </table>))) } abstract class ContentFrame extends ContentFrame0 { @@ -595,6 +654,13 @@ abstract class DocGenerator extends Models { "Constructor" -> ((s: Symbol) => s.isConstructor) + "Def" -> ((s: Symbol) => s.isMethod) + /** This abstract class contains two abstract methods <code>sym</code> and + * <code>descr</code> which must be defined for each primitive type in + * order to generated the appropriate HTML documentation page. + * + * @author Stephane Micheloud + * @version 1.0 + */ private abstract class PrimitiveContentFrame extends ContentFrame0 { def sym: Symbol def descr: String @@ -678,8 +744,6 @@ abstract class DocGenerator extends Models { private val loader = getClass().getClassLoader() - import scala.collection.mutable.{Map, HashMap} - /** Map a class to it's known subclasses */ private val subclasses = new HashMap[Symbol, List[Symbol]] { override def default(key: Symbol): List[Symbol] = { diff --git a/src/compiler/scala/tools/nsc/doc/DocUtil.scala b/src/compiler/scala/tools/nsc/doc/DocUtil.scala index b78f2a0f8b..a2ec4c274b 100644 --- a/src/compiler/scala/tools/nsc/doc/DocUtil.scala +++ b/src/compiler/scala/tools/nsc/doc/DocUtil.scala @@ -31,10 +31,8 @@ object DocUtil { // def label = "#PCDATA" //} - def br(nodes: NodeSeq): NodeSeq = { - val x = <br/>; - nodes.concat(x) - } + def br(nodes: NodeSeq): NodeSeq = nodes.concat(<br/>) + def hr(nodes: NodeSeq): NodeSeq = nodes.concat(<hr/>) trait UrlContext { def relative: String diff --git a/src/compiler/scala/tools/nsc/doc/script.js b/src/compiler/scala/tools/nsc/doc/script.js index 59bdde90ec..33278f2338 100644 --- a/src/compiler/scala/tools/nsc/doc/script.js +++ b/src/compiler/scala/tools/nsc/doc/script.js @@ -236,9 +236,11 @@ function init() { for (i = 0; i < elems.length; i++) { try { key = elems[i].getAttribute('class'); + href = elems[i].getAttribute('href'); api_root = table[key]; if (api_root != null) { - value = api_root + key.replace(/_/g, "/") + ".html"; + href1 = href.substring(href.lastIndexOf("#")) + value = api_root + key.replace(/_/g, "/") + ".html" + href1; elems[i].setAttribute('href', value); } } diff --git a/src/compiler/scala/tools/nsc/doc/style.css b/src/compiler/scala/tools/nsc/doc/style.css index 5fecb9014e..890a4369ea 100644 --- a/src/compiler/scala/tools/nsc/doc/style.css +++ b/src/compiler/scala/tools/nsc/doc/style.css @@ -46,23 +46,47 @@ span.entity { table.member { border-collapse: collapse; - border: 2px solid #888888; - background-color: #ffffff; - width: 100%; + 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 { + 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 solid #888888; + border: 2px inset #888888; background-color: #ffffff; - width: 100%; + 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; + font-family: Arial,Helvetica,Sans-Serif; } table.list { @@ -72,7 +96,7 @@ table.list { } td.inherited-members { - border-top: 2px solid #888888; + border-top: 2px inset #888888; border-right: 0px; } @@ -81,16 +105,9 @@ td.inherited-owner { font-weight: bold; } -td.member-title { - border: 2px solid #888888; - background-color: #ccccff; - font-size: x-large; - font-weight: bold; -} - td.modifiers { - border-top: 2px solid #888888; - border-right: 2px solid #888888; + border-top: 2px inset #888888; + border-right: 2px inset #888888; width: 50px; text-align: right; } @@ -113,12 +130,7 @@ td.navigation-selected { } td.signature { - border-top: 2px solid #888888; + border-top: 2px inset #888888; width: 90%; } -td.title { - background-color: #ccccff; - font-size: x-large; - font-weight: bold; -} |