diff options
author | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-03-09 17:33:37 +0000 |
---|---|---|
committer | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-03-09 17:33:37 +0000 |
commit | c0c963afaf40b85914eff3497e116763268e6aa7 (patch) | |
tree | 6d8508d7f327441bb9d5d27781aebddd80f4bc8d | |
parent | ff46b04fc9c2f68c807cea563b2008e36ff2f260 (diff) | |
download | scala-c0c963afaf40b85914eff3497e116763268e6aa7.tar.gz scala-c0c963afaf40b85914eff3497e116763268e6aa7.tar.bz2 scala-c0c963afaf40b85914eff3497e116763268e6aa7.zip |
Fixed bugs in Scala doc.
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DocGenerator.scala | 294 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/script.js | 5 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/style.css | 124 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/models/SemanticTokens.scala | 17 |
4 files changed, 306 insertions, 134 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala index 1d32a4ec43..9194b8c82d 100644 --- a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala +++ b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala @@ -1,27 +1,23 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2006 LAMP/EPFL - * @author Sean McDirmid - */ -// $Id: $ +package scala.tools.nsc.doc; -package scala.tools.nsc.doc - -import java.io.{File, FileWriter} -import scala.collection.immutable._ -import scala.tools.nsc._ -import scala.tools.nsc.models._ -import scala.xml._ +import scala.tools.nsc._; +import java.io._; +import scala.tools.nsc.models._; +import scala.collection.immutable._; +import scala.xml._; abstract class DocGenerator extends Models { - import global._ - import DocUtil._ - def outdir: String - def contentFrame = "contentFrame" - def classesFrame = "classesFrame" - def modulesFrame = "modulesFrame" - def emptyMap = ListMap.Empty[Kind, TreeSet[HasTree]] + import global._; + import DocUtil._; + def outdir : String; + def contentFrame = "contentFrame"; + def classesFrame = "classesFrame"; + def modulesFrame = "modulesFrame"; + def emptyMap = ListMap.Empty[Kind,TreeSet[HasTree]]; + + + override def acceptPrivate = false; - override def acceptPrivate = false abstract class Frame extends UrlContext { def path : String; // relative to outdir @@ -35,25 +31,27 @@ abstract class DocGenerator extends Models { ct = ct + (if (idx != -1) "../" else ""); idx = idx + (if (idx == -1) 0 else 1); } - ct + ct; } - def body: NodeSeq - def title: String - def save(nodes: NodeSeq) = { - val path0 = outdir + "/" + path + ".html" - //System.err.println("Writing to " + path0) - val file = new File(path0) - val parent = file.getParentFile() - if (!parent.exists()) parent.mkdirs() - val writer = new FileWriter(file) - val str = dtype + "\n" + nodes.toString() - writer.write(str, 0, str.length()) - writer.close() + def body : NodeSeq; + def title : String; + def save(nodes : NodeSeq) = { + val path0 = outdir + "/" + path + ".html"; + //System.err.println("Writing to " + path0); + val file = new File(path0); + val parent = file.getParentFile(); + if (!parent.exists()) parent.mkdirs(); + val writer = new FileWriter(file); + val str = dtype + "\n" + nodes.toString(); + writer.write(str, 0, str.length()); + writer.close(); + } + def urlFor(sym : Symbol, target : String) : NodeSeq = { + if (sym.sourceFile == null) Text(sym.fullNameString('.')); + else aref(urlFor(sym), target, sym.nameString); } - def urlFor(sym: Symbol, target: String): NodeSeq = - aref(urlFor(sym), target, sym.nameString) def urlFor0(sym : Symbol, orig : Symbol) : String = { (if (sym == NoSymbol) { @@ -61,7 +59,9 @@ abstract class DocGenerator extends Models { } else if (sym.owner.isPackageClass) sym.fullNameString('/'); else urlFor0(sym.owner, orig) + "." + Utility.escape(sym.nameString)) + (sym match { case msym : ModuleSymbol => "$object"; - case csym : ClassSymbol => ""; + case csym : ClassSymbol => + if (csym.isModuleClass) "$object"; + else ""; case _ => //System.err.println("XXX: class or object " + orig + " not found in " + sym); "XXXXX"; @@ -88,20 +88,20 @@ abstract class DocGenerator extends Models { val x = div0("Scala 2") concat aref("all-classes.html", classesFrame, "All objects and classes"); val y = <P/><B>Packages</B> - <table class="list"><tr><TD style="white-space:nowrap;"> + <TABLE class="list"><TR><TD style="white-space:nowrap;"> { { for (val top <- modules.elements.toList) yield {br(aref(urlFor(top._2), classesFrame, top._2.fullNameString('.')))}; } } - </TD></tr></table>; + </TD></TR></TABLE>; x.concat(y); } } abstract class ListModuleContentFrame extends Frame { - val path = "root-content" - val title = "All Packages" - def modules : TreeMap[String, ModuleClassSymbol] + val path = "root-content"; + val title = "All Packages"; + def modules : TreeMap[String,ModuleClassSymbol]; def body : NodeSeq = { <SPAN><DIV class="page-title"> Scala 2 @@ -125,30 +125,31 @@ abstract class DocGenerator extends Models { } } - abstract class ListClassFrame extends Frame { - def classes : ListMap[Kind,TreeSet[HasTree]]; + abstract class ListClassFrame extends Frame { + def classes : ListMap[Kind,TreeSet[HasTree]]; + + def navLabel : String; - def navLabel: String + def body : NodeSeq = { + val nav = <TABLE class="navigation"><TR><TD valign="top" class="navigation-links"> + {aref(path + "$content.html", contentFrame, navLabel)} + </TD></TR></TABLE><P/>; - def body : NodeSeq = { - val nav = <table class="navigation"><TR><TD valign="top" class="navigation-links"> - {aref(path + ".html", contentFrame, navLabel)} - </TD></TR></table><P/>; - val body = <span> { { for (val kind <- KINDS; classes.contains(kind)) yield { - val x = <b>{Text(pluralFor(kind))}</b>; + val body = <SPAN> { { for (val kind <- KINDS; classes.contains(kind)) yield { + val x = <B>{Text(pluralFor(kind))}</B>; - val y = <table class="list"><TR><TD style="white-space;nowrap;"> + val y = <TABLE class="list"><TR><TD style="white-space;nowrap;"> { { for (val mmbr <- classes(kind).toList) yield br(urlFor(mmbr.tree.symbol, contentFrame)); } } - </TD></TR></table>; + </TD></TR></TABLE>; val ret :NodeSeq = x.concat(y); ret; - } } } </span>; + } } } </SPAN>; - nav.concat(body) + nav.concat(body); } } @@ -156,16 +157,16 @@ abstract class DocGenerator extends Models { def extendsFor(mmbr : HasTree) : NodeSeq = mmbr match { case mmbr : ImplMod => if (!mmbr.treey.impl.parents.isEmpty) - <span><dd><code>{Text(" extends ")}</code> + <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>; + } } </SPAN>; else NodeSeq.Empty; case _ => NodeSeq.Empty; } - def fullHeader(mmbr: HasTree): NodeSeq = <span>{ { + def fullHeader(mmbr : HasTree) : NodeSeq = <SPAN>{ { if (!mmbr.isInstanceOf[ImplMod]) { <a name = {Utility.escape(mmbr.tree.symbol.nameString)}></a>; } else NodeSeq.Empty; @@ -176,27 +177,28 @@ abstract class DocGenerator extends Models { { typesFor(mmbr) }{ argsFor(mmbr)}{resultFor(mmbr) } </DT> { extendsFor(mmbr) } </DL> { fullComment(mmbr) } <HR/> - { lists(mmbr) } </span>; + { lists(mmbr) } </SPAN>; def lists(mmbr : HasTree) = mmbr match { - case cmod : ImplMod => <span>{ listMembersShort(mmbr) } - { listMembersFull (mmbr) }</span> - case _ => NodeSeq.Empty + case cmod : ImplMod => <SPAN>{ listMembersShort(mmbr) } + { listMembersFull (mmbr) }</SPAN> + case _ => NodeSeq.Empty; } + def listMembersShort(mmbr : HasTree) : NodeSeq = if (mmbr.isInstanceOf[Composite]) { val map = organize(mmbr.asInstanceOf[Composite], emptyMap); - <span> { { + <SPAN> { { for (val kind <- KINDS; map.contains(kind)) yield { - val x = <table cellpadding="3" class="member"> - <tr><td colspan="2" class="title">{Text(labelFor(kind))} Summary</td></tr> + val x = <TABLE cellpadding="3" class="member"> + <TR><TD colspan="2" class="title">{Text(labelFor(kind))} Summary</TD></TR> { { for (val mmbr <- map(kind).toList) yield shortHeader(mmbr); } } - </table>; + </TABLE>; br(x); } - } } </span> + } } </SPAN> } else NodeSeq.Empty; def listMembersFull(mmbr : HasTree) : NodeSeq = if (mmbr.isInstanceOf[Composite]) { @@ -210,43 +212,42 @@ abstract class DocGenerator extends Models { def title = labelFor(kind0) + " " + mmbr.tree.symbol.nameString + " in " + codeFor(mmbrx.kind) + " " + mmbr.tree.symbol.owner.fullNameString('.'); } } - <span> { { + <SPAN> { { for (val kind <- KINDS; map.contains(kind) && kind != OBJECT && kind != CLASS) yield { val header = <table cellpadding="3" class="member-detail"> <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>; + val body = for (val mmbr <- map(kind).toList) yield <SPAN>{fullHeader(mmbr)}</SPAN>; header.concat(body); } - } } </span>; + } } </SPAN>; } else NodeSeq.Empty; - def shortHeader(mmbr: HasTree): NodeSeq = { - <tr> - <td valign="top" class="modifiers"> - { { for (val str <- stringsFor(mmbr.mods)) yield <code>{(Text(str + " "))}</code>; } } - </td> - <td class="signature"> - <code>{Text(codeFor(mmbr.kind))}</code> - <em>{urlFor(mmbr.tree.symbol, contentFrame)}</em> + def shortHeader(mmbr : HasTree) : NodeSeq = { + <TR> + <TD valign="top" class="modifiers"> + { { for (val str <- stringsFor(mmbr.mods)) yield <CODE>{(Text(str + " "))}</CODE>; } } + </TD> + <TD class="signature"> + <CODE>{Text(codeFor(mmbr.kind))}</CODE> + <EM>{urlFor(mmbr.tree.symbol, contentFrame)}</EM> { typesFor(mmbr) } { argsFor(mmbr) } {resultFor(mmbr) } - <br>{shortComment(mmbr)}</br> - </td> - </tr>; + <BR>{shortComment(mmbr)}</BR> + </TD> + </TR>; } - def fullComment(mmbr: HasTree): NodeSeq = { - if (comments.contains(mmbr.tree.symbol)) - comment(comments(mmbr.tree.symbol), false) else NodeSeq.Empty - } - def shortComment(mmbr: HasTree): NodeSeq = { + def fullComment(mmbr : HasTree) : NodeSeq = { if (comments.contains(mmbr.tree.symbol)) - comment(comments(mmbr.tree.symbol), true) else NodeSeq.Empty - } - + comment(comments(mmbr.tree.symbol), false) else NodeSeq.Empty; + }; + def shortComment(mmbr : HasTree) : NodeSeq = { + if (comments.contains(mmbr.tree.symbol)) + comment(comments(mmbr.tree.symbol), true) else NodeSeq.Empty; + }; def ifT (cond : Boolean, nodes : NodeSeq) = if (cond) nodes else NodeSeq.Empty; def ifT (tree : Tree, nodes : NodeSeq, before : Boolean) = { if (tree != EmptyTree && @@ -257,11 +258,12 @@ abstract class DocGenerator extends Models { } else NodeSeq.Empty; } - def forType(tpe: Type): NodeSeq = + def forType(tpe : Type) : NodeSeq = { urlFor(tpe.symbol, contentFrame); + } - def forTree(tree: Tree): NodeSeq = tree match { - case vdef: ValDef => + def forTree(tree : Tree) : NodeSeq = tree match { + case vdef : ValDef => Text(vdef.symbol.name.toString()).concat(Text(" : ")).concat(forTree(vdef.tpt)); case sel : Select => forTree(sel.qualifier).concat(Text(sel.symbol.nameString)); case tree : AbsTypeDef => @@ -343,20 +345,20 @@ abstract class DocGenerator extends Models { } abstract class ContentFrame extends ContentFrame0 { - def clazz: ImplMod - def kind: Kind - def body: NodeSeq = <span>{navigation}{header0}{fullHeader(clazz)}</span>; + def clazz : ImplMod; + def kind : Kind; + def body : NodeSeq = <SPAN>{navigation}{header0}{fullHeader(clazz)}</SPAN>; - final def path = urlFor0(clazz.tree.symbol,clazz.tree.symbol) + final def path = urlFor0(clazz.tree.symbol,clazz.tree.symbol); - def navigation: NodeSeq = - <table class="navigation"> + // <TD class="navigation-enabled">{aref("help.html" , "_self", "Help" )}</TD> + def navigation : NodeSeq = + <TABLE class="navigation"> <TR> <TD valign="top" class="navigation-links"> <TABLE><TR> <TD class="navigation-enabled">{aref("root-page.html", "_self", "Overview")}</TD> <TD class="navigation-enabled">{aref("index.html" , "_self", "Index" )}</TD> - <TD class="navigation-enabled">{aref("help.html" , "_self", "Help" )}</TD> </TR></TABLE> </TD> <TD align="right" valign="top" style="white-space:nowrap;" rowspan="2"> @@ -364,18 +366,22 @@ abstract class DocGenerator extends Models { </TD> </TR> <TR><TD></TD></TR> - </table>; + </TABLE>; - def header0 : NodeSeq = <span> - <hr/> in {aref(urlFor(clazz.tree.symbol.owner), "_self", clazz.tree.symbol.owner.fullNameString('.'))} - <div class="entity"> + def header0 : NodeSeq = <SPAN> + <HR/> in {aref(urlFor(clazz.tree.symbol.owner), "_self", clazz.tree.symbol.owner.fullNameString('.'))} + <DIV class="entity"> {Text(codeFor(kind))} - <span class="entity">{Text(clazz.tree.symbol.nameString)}</span> - </div><hr/> - </span> + <SPAN class="entity">{Text(clazz.tree.symbol.nameString)}</SPAN> + </DIV><HR/> + </SPAN>; + + + + } - def process(units: Iterator[CompilationUnit]) : Unit = { + def process(units : Iterator[CompilationUnit]) : Unit = { var members = emptyMap; var topLevel = ListMap.Empty[ModuleClassSymbol,ListMap[Kind,TreeSet[HasTree]]]; @@ -396,14 +402,14 @@ abstract class DocGenerator extends Models { for (val top <- topLevel.elements) modules0 = modules0.insert(top._1.fullNameString, top._1); modules0; - } + }; new ListModuleFrame { def modules = modules0; - } + }; new ListModuleContentFrame { def modules = modules0; - } + }; new ListClassFrame { def classes = { @@ -442,41 +448,69 @@ abstract class DocGenerator extends Models { def kind = kind0; } } + } new Frame { - def title = "Scala Library Documentation" - def body = index - def path = "index" - override def hasBody = false + def title = "Scala Library Documentation"; + def body = index; + def path = "index"; + override def hasBody = false; + }; + for (val base <- "style.css" :: "script.js" :: Nil) { + val input = getClass().getClassLoader().getResourceAsStream("scala/tools/nsc/doc/" + base); + if (input != null) { + val file = new File(outdir + "/" + base); + val output = new FileOutputStream(file); + var break = false; + val bytes = new Array[byte](1024); + while (!break) { + val read = input.read(bytes); + if (read == -1) { + break = true; + } else { + output.write(bytes, 0, read); + } + } + input.close(); + output.close(); + } } } + + + + + + + def organize(c : Composite, map0 : ListMap[Kind,TreeSet[HasTree]]) = { var map = map0; //System.err.println("MEMBERS: " + c.members.toList); for (val mmbr <- c.members.toList) map = organize0(mmbr, map); map; } - def organize0(mmbr : HasTree, map0 : ListMap[Kind,TreeSet[HasTree]]) = { var map = map0; if (!map.contains(mmbr.kind)) map = map.update(mmbr.kind, new TreeSet[HasTree]); val sz = map(mmbr.kind).size; map = map.update(mmbr.kind, map(mmbr.kind) + mmbr); - /*if (map(mmbr.kind).size == sz) - System.err.println(""+mmbr + " not added");*/ - map + if (map(mmbr.kind).size == sz) + System.err.println(""+mmbr + " not added"); + map; } + def parse(str : String) : NodeSeq = { new SpecialNode { - def label = "#PCDATA" + def label = "#PCDATA"; def toString(sb:StringBuffer): StringBuffer = { sb.append(str.trim()); - sb + sb; } + } /* import java.io.StringReader; @@ -486,7 +520,7 @@ abstract class DocGenerator extends Models { if (parsedxml1 == null) Text("BAD_COMMENT???"); else parsedxml1; */ - } + }; def comment(comment : String, isShort : Boolean) : NodeSeq = { var ret : List[Node] = Nil; @@ -514,14 +548,15 @@ abstract class DocGenerator extends Models { else new Tuple2(attr.substring(0, div), attr.substring(div + 1, attr.length())); attributes = attributes ::: (tuple :: Nil); } - if (isShort) <span>{parse(body)}</span>; - else <span><dl><dd>{parse(body)}</dd></dl><dl> + if (isShort) <SPAN>{parse(body)}</SPAN>; + else <SPAN><DL><DD>{parse(body)}</DD></DL><DL> { { for (val attr <- attributes) yield - <dt style="margin-top:10px;"><b>{Text(attr._1 + ":")}</b></dt> - <dd>{(parse(attr._2))}</dd>; - } } </dl></span>; - } + <DT style="margin-top:10px;"><B>{Text(attr._1 + ":")}</B></DT> + <DD>{(parse(attr._2))}</DD>; + } } </DL></SPAN>; + }; + val index = { <frameset cols="25%, 75%"> @@ -535,6 +570,9 @@ abstract class DocGenerator extends Models { val root = <b></b>; - private val JDOC_START = "/**" - private val JDOC_END = "*/" + + + + private val JDOC_START = "/**"; + private val JDOC_END = "*/"; } diff --git a/src/compiler/scala/tools/nsc/doc/script.js b/src/compiler/scala/tools/nsc/doc/script.js new file mode 100644 index 0000000000..94093ecc50 --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/script.js @@ -0,0 +1,5 @@ +<!-- +function setWindowTitle(title) { + parent.document.title = title; +} +--> diff --git a/src/compiler/scala/tools/nsc/doc/style.css b/src/compiler/scala/tools/nsc/doc/style.css new file mode 100644 index 0000000000..5fecb9014e --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/style.css @@ -0,0 +1,124 @@ +/* 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.page-title { + margin: 15px 0px 15px 0px; + font-size: x-large; + font-weight: bold; + text-align: center; +} + +span.entity { + color: #ff6666; +} + +table.member { + border-collapse: collapse; + border: 2px solid #888888; + background-color: #ffffff; + width: 100%; +} + +table.member-detail { + margin: 10px 0px 0px 0px; + border-collapse: collapse; + border: 2px solid #888888; + background-color: #ffffff; + width: 100%; +} + +table.navigation { + border-collapse: collapse; + width: 100%; + font-family: Arial,Helvetica,Sans-serif; +} + +table.list { + border-collapse: collapse; + border-style: none; + width: 100%; +} + +td.inherited-members { + border-top: 2px solid #888888; + border-right: 0px; +} + +td.inherited-owner { + background-color: #eeeeff; + 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; + 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 solid #888888; + width: 90%; +} + +td.title { + background-color: #ccccff; + font-size: x-large; + font-weight: bold; +} diff --git a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala index 730c460822..ef8f60e6c8 100644 --- a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala +++ b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala @@ -507,9 +507,12 @@ class SemanticTokens(val compiler: Global) { def selectPos(tree : Select): Int = if (tree.pos == Position.NOPOS) Position.NOPOS else { val buf = unit.source.content; if (tree.pos >= buf.length) { + if (false) { System.err.println("" + tree + "@" + tree.pos + " not in " + unit.source.file.getName() + "[" + buf.length + "]"); Thread.dumpStack(); throw new Error(); + } + return 0; } val pos = @@ -568,13 +571,15 @@ class SemanticTokens(val compiler: Global) { sem.symbol.getClass() == tok.symbol.getClass() && sem.symbol.pos == tok.symbol.pos) return; - System.err.println("NOT_GAP: " + sem.symbol + " " + sem.symbol.getClass() + " " + unit.source.dbg(sem.symbol.pos) + " " + sem.symbol.flags); - System.err.println("NOT_GAP: " + tok.symbol + " " + tok.symbol.getClass() + " " + unit.source.dbg(tok.symbol.pos) + " " + tok.symbol.flags); - System.err.println("LIST: " + this); - System.err.println("POS: " + unit.source.dbg(offset)); + if (false) { + System.err.println("NOT_GAP: " + sem.symbol + " " + sem.symbol.getClass() + " " + unit.source.dbg(sem.symbol.pos) + " " + sem.symbol.flags); + System.err.println("NOT_GAP: " + tok.symbol + " " + tok.symbol.getClass() + " " + unit.source.dbg(tok.symbol.pos) + " " + tok.symbol.flags); + System.err.println("LIST: " + this); + System.err.println("POS: " + unit.source.dbg(offset)); - Thread.dumpStack(); - throw new Error(); + Thread.dumpStack(); + throw new Error(); + } } else { val gap = cursor.token.asInstanceOf[Gap]; if (!(offset - cursor.offset + tok.length <= gap.length)) { |