summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcremet <cremet@epfl.ch>2004-01-19 18:18:40 +0000
committercremet <cremet@epfl.ch>2004-01-19 18:18:40 +0000
commit752abae33821117456300793288fb66504fb77b1 (patch)
tree419e84d0a0b6835eed1c8cf102f8723c38356521
parent91082606334e89c0748cf48793e4560a4a798d29 (diff)
downloadscala-752abae33821117456300793288fb66504fb77b1.tar.gz
scala-752abae33821117456300793288fb66504fb77b1.tar.bz2
scala-752abae33821117456300793288fb66504fb77b1.zip
- Fixed bugs in Scaladoc.
- Added XHTML validation of documentation comments.
-rw-r--r--Makefile4
-rw-r--r--sources/scala/tools/scaladoc/Comment.java101
-rw-r--r--sources/scala/tools/scaladoc/HTMLGenerator.java89
-rw-r--r--sources/scala/tools/scaladoc/HTMLGeneratorCommand.java2
-rw-r--r--sources/scala/tools/scaladoc/Page.java21
-rw-r--r--sources/scala/tools/scaladoc/ScalaSearch.java7
-rw-r--r--sources/scalac/typechecker/Analyzer.java3
7 files changed, 188 insertions, 39 deletions
diff --git a/Makefile b/Makefile
index 4e4d271901..51ee24d92c 100644
--- a/Makefile
+++ b/Makefile
@@ -114,7 +114,9 @@ SCALADOC_LIST += $(call READLIST,$(PROJECT_LISTDIR)/scaladoc.lst)
SCALADOC_SOURCES += $(SCALADOC_LIST:%=$(SCALADOC_ROOT)/%)
SCALADOC_JC_FILES += $(filter %.java,$(SCALADOC_SOURCES))
SCALADOC_SC_FILES += $(filter %.scala,$(SCALADOC_SOURCES))
-SCALADOC_RSRC_LIST += resources/style.css resources/script.js
+SCALADOC_RSRC_LIST += resources/style.css resources/script.js \
+ resources/xhtml1-transitional.dtd resources/xhtml-lat1.ent \
+ resources/xhtml-special.ent resources/xhtml-symbol.ent
SCALADOC_RSRC_FILES += $(SCALADOC_RSRC_LIST:%=$(SCALADOC_ROOT)/%)
SCALADOC_RSRC_OUTPUTDIR = $(SCALADOC_ROOT:$(PROJECT_SOURCEDIR)/%=$(PROJECT_OUTPUTDIR)/%)
diff --git a/sources/scala/tools/scaladoc/Comment.java b/sources/scala/tools/scaladoc/Comment.java
index fc76d8438e..db12da4f80 100644
--- a/sources/scala/tools/scaladoc/Comment.java
+++ b/sources/scala/tools/scaladoc/Comment.java
@@ -12,13 +12,21 @@ import java.util.*;
import java.util.regex.*;
import ch.epfl.lamp.util.Pair;
import scalac.symtab.Symbol;
+import scalac.Unit;
+
+import java.io.StringReader;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
/**
* Class <code>Comment</code> contains all information in comment part.
* It allows users to get first sentence of this comment, get comment
* for different tags...
*/
-public class Comment {
+public class Comment extends DefaultHandler {
/**
* Holder of the comment.
@@ -26,6 +34,11 @@ public class Comment {
public final Symbol holder;
/**
+ * Unit of the symbol associated with this comment.
+ */
+ Unit unit;
+
+ /**
* Raw text of the comment.
*/
public final String rawText;
@@ -46,9 +59,12 @@ public class Comment {
* @param holder
* @param rawText
*/
- public Comment(Symbol holder, String rawText) {
+ public Comment(String rawText, Symbol holder, Unit unit, HTMLValidator html) {
this.holder = holder;
this.rawText = cleanComment(rawText);
+ this.unit = unit;
+ if (!isEmpty())
+ html.validate(this.rawText, this);
parseComment();
}
@@ -60,6 +76,17 @@ public class Comment {
}
/**
+ * Tests if the comment contains a specified tag.
+ */
+ public boolean containsTag(String name) {
+ name = name.startsWith("@") ? name : "@" + name;
+ for(int i = 0; i < tags.length; i++)
+ if (tags[i].name.equals(name))
+ return true;
+ return false;
+ }
+
+ /**
* Removes the leading white spaces and asterixes.
*
* @param comment
@@ -158,4 +185,74 @@ public class Comment {
return text;
}
+ // Implementation methods for the SAX error handler.
+
+ public void warning(SAXParseException e) {
+ //showHtmlError(e);
+ }
+
+ public void error(SAXParseException e) {
+ showHtmlError(e);
+ }
+
+ public void fatalError(SAXParseException e) {
+ showHtmlError(e);
+ }
+
+ void showHtmlError(SAXParseException e) {
+ String msg = "";
+ msg += "documentation comments should be written in HTML" + "\n";
+ msg += e.getMessage() + "\n";
+ if (unit != null)
+ unit.warning(holder.pos, msg);
+ }
+
}
+
+public class HTMLValidator {
+
+ /** The URL of the file containing the DTD. */
+ String dtd;
+
+ /** HTML parser. */
+ XMLReader xmlReader;
+
+ public HTMLValidator(String dtd) {
+ this.dtd = dtd;
+ // parser
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(true);
+ factory.setNamespaceAware(true);
+ SAXParser saxParser = factory.newSAXParser();
+ xmlReader = saxParser.getXMLReader();
+ }
+ catch(ParserConfigurationException e) { System.err.println(e.toString()); }
+ catch(SAXException e) { System.err.println(e.toString()); }
+ }
+
+ public String makeDoc(String s) {
+ String doc = "";
+ // specify the DTD
+ doc += "<?xml version=\"1.0\"?>" + "\n";
+ doc += "<!DOCTYPE html SYSTEM \"" + dtd + "\">" + "\n";
+ // enclose the string into a valid HTML skeletton
+ doc += "<html><head><title>notitle</title></head><body>" + "\n";
+ doc += s + "\n";
+ doc += "</body></html>" + "\n";
+ return doc;
+ }
+
+ public void validate(String s, ErrorHandler errorHandler) {
+ // source to parse
+ String doc = makeDoc(s);
+ InputSource source = new InputSource(new StringReader(doc));
+ try {
+ xmlReader.setErrorHandler(errorHandler);
+ xmlReader.parse(source);
+ }
+ catch(SAXException e) { }
+ catch(Exception e) { System.err.println(e.toString()); }
+ }
+}
+
diff --git a/sources/scala/tools/scaladoc/HTMLGenerator.java b/sources/scala/tools/scaladoc/HTMLGenerator.java
index cddf35f9c2..40c22c1ad2 100644
--- a/sources/scala/tools/scaladoc/HTMLGenerator.java
+++ b/sources/scala/tools/scaladoc/HTMLGenerator.java
@@ -8,6 +8,7 @@
package scala.tools.scaladoc;
+import java.io.Writer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
@@ -34,6 +35,7 @@ import ch.epfl.lamp.util.Position;
import ch.epfl.lamp.util.XHTMLPrinter;
import scalac.Global;
+import scalac.Unit;
import scalac.symtab.Kinds;
import scalac.symtab.Modifiers;
import scalac.symtab.NoSymbol;
@@ -74,6 +76,19 @@ public class HTMLGenerator {
protected final String CLASSES_FRAME = "classesFrame";
protected final String SELF_FRAME = "_self";
+ /**
+ * HTML DTD
+ */
+ protected final String[] HTML_DTD = new String[] { "xhtml1-transitional.dtd",
+ "xhtml-lat1.ent",
+ "xhtml-special.ent",
+ "xhtml-symbol.ent" };
+
+ /**
+ * HTML validator.
+ */
+ protected HTMLValidator xhtml;
+
/*
* XML attributes.
*/
@@ -249,7 +264,8 @@ public class HTMLGenerator {
final DocSyms docSyms = new DocSyms(global, packages);
this.isDocumented = new SymbolBooleanFunction() {
public boolean apply(Symbol sym) {
- return docSyms.contains(sym) && ScalaSearch.isRelevant(sym);
+ return docSyms.contains(sym) && ScalaSearch.isRelevant(sym)
+ && !getComment(sym).containsTag("@ignore");
// (ScalaSearch.isRelevant(sym) ||
// ((sym.isModuleClass() && !sym.isPackage()*/)
// && ScalaSearch.isRelevant(sym.module())));
@@ -277,6 +293,16 @@ public class HTMLGenerator {
return new Symbol[] { root };
}
+ /** Get a file writer to a page.
+ */
+ protected static Writer fileWriter(File rootDirectory, URI uri) {
+ try {
+ File f = new File(rootDirectory, uri.toString());
+ f.getParentFile().mkdirs();
+ return new BufferedWriter(new FileWriter(f));
+ } catch(IOException e) { throw Debug.abort(e); }
+ }
+
/**
* Open a new documentation page and make it the current page.
* @param uri URL of the page
@@ -286,7 +312,7 @@ public class HTMLGenerator {
stack.push(page);
stack.push(symtab);
// Create a new page.
- page = new Page(directory, uri, destinationFrame,
+ page = new Page(fileWriter(directory, uri), uri, destinationFrame,
title, representation,
stylesheet/*, script*/);
// Create a printer to print symbols and types.
@@ -331,6 +357,16 @@ public class HTMLGenerator {
protected void apply() {
if (! checkOutpath())
return;
+ /*
+ // xhtml DTD for validating comments (could be removed after).
+ for(int i = 0; i < HTML_DTD.length; i++)
+ createResource(HTML_DTD[i], "resources");
+ // HTML validator creation
+ String dtdFile =
+ directory.getAbsolutePath() + File.separator +
+ "resources" + File.separator + HTML_DTD[0];
+ */
+ this.xhtml = new HTMLValidator(getResourceURL(HTML_DTD[0]));
// page with list of packages
createPackageIndexPage();
@@ -360,10 +396,10 @@ public class HTMLGenerator {
createFramePage();
// style sheet
- createResource(HTMLPrinter.DEFAULT_STYLESHEET);
+ createResource(HTMLPrinter.DEFAULT_STYLESHEET, null);
// script
- createResource(HTMLPrinter.DEFAULT_JAVASCRIPT);
+ createResource(HTMLPrinter.DEFAULT_JAVASCRIPT, null);
}
/**
@@ -381,15 +417,21 @@ public class HTMLGenerator {
protected Comment getComment(Symbol sym) {
Comment comment = (Comment) comments.get(sym);
if (comment == null) {
- String s = (String) global.mapSymbolComment.get(sym);
- // comment inheritance
- if (s == null) {
+ Pair p = (Pair) global.mapSymbolComment.get(sym);
+ if (p != null) {
+ String s = (String) p.fst;
+ Unit unit = (Unit) p.snd;
+ comment = new Comment(s, sym, unit, xhtml);
+ }
+ else { // comment inheritance
Symbol overriden = ScalaSearch.overridenBySymbol(sym);
- if (overriden != Symbol.NONE)
- s = "/** (Inherited comment) " + getComment(overriden).rawText + "*/";
+ if (overriden == Symbol.NONE)
+ comment = new Comment(null, sym, null, xhtml);
+ else
+ comment = getComment(overriden);
+ //s = "/** (Inherited comment) " + getComment(overriden).rawText + "*/";
}
- comment = new Comment(sym, s);
- comments.put(sym, comment);
+ comments.put(sym, comment);
}
return comment;
}
@@ -882,18 +924,37 @@ public class HTMLGenerator {
}
/**
+ * Get the URL (as a string) of a resource located in the
+ * directory "resources" relative to the classfile of this class.
+ */
+ protected String getResourceURL(String name) {
+ String rsc = HTMLGenerator.class
+ .getResource("resources/" + name)
+ .toString();
+ // System.out.println("Some used resource: " + rsc);
+ return rsc;
+ }
+
+ /**
* Generates a resource file.
*
* @param name The name of the resource file
*/
- protected void createResource(String name) {
+ protected void createResource(String name, String dir) {
+ File dest;
+ if (dir == null)
+ dest = new File(directory, name);
+ else {
+ File f = new File(directory, dir);
+ f.mkdirs();
+ dest = new File(f, name);
+ }
String rsrcName = "resources/" + name;
InputStream in = HTMLGenerator.class.getResourceAsStream(rsrcName);
if (in == null)
throw Debug.abort("Resource file \"" + rsrcName + "\" not found");
try {
- FileOutputStream out = new FileOutputStream(
- directory.getPath() + File.separator + name);
+ FileOutputStream out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int len;
diff --git a/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java b/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
index 4b82dd1a78..3d947a929e 100644
--- a/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
+++ b/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
@@ -59,7 +59,7 @@ public class HTMLGeneratorCommand extends CompilerCommand {
public HTMLGeneratorCommand(String product, String version,
Reporter reporter, HTMLGeneratorPhases phases)
{
- this(product, version, "<source files>", reporter, phases);
+ this(product, version, "<source files> [-- <packages>]", reporter, phases);
}
/**
diff --git a/sources/scala/tools/scaladoc/Page.java b/sources/scala/tools/scaladoc/Page.java
index 993d62ae95..41bcd659de 100644
--- a/sources/scala/tools/scaladoc/Page.java
+++ b/sources/scala/tools/scaladoc/Page.java
@@ -28,10 +28,6 @@ import scalac.util.Debug;
*/
class Page extends HTMLPrinter {
- /** Root directory.
- */
- protected File rootDirectory;
-
/** Page URL relative to the root directory.
*/
protected URI uri;
@@ -43,28 +39,15 @@ class Page extends HTMLPrinter {
/** Build a page.
*/
- public Page(File rootDirectory, URI uri, String destinationFrame,
+ public Page(Writer writer, URI uri, String destinationFrame,
String title, HTMLRepresentation representation,
String stylesheet/*, String script*/) {
- super(getWriter(rootDirectory, uri), title, representation,
+ super(writer, title, representation,
asSeenFrom(mkURI(stylesheet), uri).toString()/*, script*/);
- this.rootDirectory = rootDirectory;
this.uri = uri;
this.destinationFrame = destinationFrame;
}
- /** Get a writer to the page.
- */
- protected static Writer getWriter(File rootDirectory, URI uri) {
- try {
- File f = new File(rootDirectory, uri.toString());
- f.getParentFile().mkdirs();
- return new BufferedWriter(new FileWriter(f));
- } catch(IOException e) {
- throw Debug.abort(e);
- }
- }
-
/** Open the page.
*/
public void open() {}
diff --git a/sources/scala/tools/scaladoc/ScalaSearch.java b/sources/scala/tools/scaladoc/ScalaSearch.java
index eb1a425aec..fc84992dd9 100644
--- a/sources/scala/tools/scaladoc/ScalaSearch.java
+++ b/sources/scala/tools/scaladoc/ScalaSearch.java
@@ -76,6 +76,11 @@ public class ScalaSearch {
return sym.isModule() && sym.isJava() && !sym.isPackage() && (members(sym).length == 0);
}
+ /** Test if the given symbol is access method for a val.
+ */
+ public static boolean isValMethod(Symbol sym) {
+ return (sym.isInitializedMethod() && (sym.flags & Modifiers.STABLE) != 0);
+ }
/** Test if the given symbol is relevant for the documentation.
*/
@@ -293,7 +298,7 @@ public class ScalaSearch {
else if (sym.isClass()) classes.add(sym);
else if (sym.isPackage()) packages.add(sym);
else if (sym.isModule()) objects.add(sym);
- else if (sym.isMethod()) methods.add(sym);
+ else if (sym.isMethod() && !isValMethod(sym)) methods.add(sym);
else fields.add(sym);
}
return new Symbol[][] {
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 84c9c6b4a4..174dd6269f 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -16,6 +16,7 @@
package scalac.typechecker;
import ch.epfl.lamp.util.Position;
+import ch.epfl.lamp.util.Pair;
import scalac.*;
import scalac.util.*;
import scalac.ast.*;
@@ -830,7 +831,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// set the comment associated with a symbol
String comment = (String) global.mapTreeComment.get(tree);
if (comment != null)
- global.mapSymbolComment.put(sym, comment);
+ global.mapSymbolComment.put(sym, new Pair(comment, unit));
return sym;
}