Commit 2a9f1ee2 authored by Robert Griesemer's avatar Robert Griesemer

Daily snapshot.

- godoc now supports the following url prefixes:
  /doc/ for package documentation
  /file/ for files (directories, html, and .go files)
  /spec for the spec
  /mem for the memory model
- formatting of comments has been fixed
- tons of minor cleanups (still more to do)

Still missing:
- pretty printing of source is not as pretty as it used to be
(still a relict from the massive AST cleanup which has't quite made it's way everywhere)
- documentation entries should be sorted
- comments in code is not printed or not properly printed

TBR=r
DELTA=416  (182 added, 100 deleted, 134 changed)
OCL=27078
CL=27078
parent 461fb393
...@@ -5,22 +5,20 @@ ...@@ -5,22 +5,20 @@
package astPrinter package astPrinter
import ( import (
"io"; "ast";
"vector";
"tabwriter";
"flag"; "flag";
"fmt"; "fmt";
"io";
"os";
"strings"; "strings";
"utf8"; "tabwriter";
"unicode";
"utils";
"token"; "token";
"ast"; "unicode";
"template"; "utf8";
"symboltable"; "vector";
) )
var ( var (
debug = flag.Bool("ast_debug", false, "print debugging information"); debug = flag.Bool("ast_debug", false, "print debugging information");
...@@ -75,9 +73,48 @@ func hasExportedNames(names []*ast.Ident) bool { ...@@ -75,9 +73,48 @@ func hasExportedNames(names []*ast.Ident) bool {
} }
// ----------------------------------------------------------------------------
// TokenPrinter
// TODO This is not yet used - should fix this.
// An implementation of a TokenPrinter may be provided when
// initializing an AST Printer. It is used to print tokens.
//
type TokenPrinter interface {
PrintLit(w io.Write, tok token.Token, value []byte);
PrintIdent(w io.Write, value string);
PrintToken(w io.Write, token token.Token);
PrintComment(w io.Write, value []byte);
}
type defaultPrinter struct {}
func (p defaultPrinter) PrintLit(w io.Write, tok token.Token, value []byte) {
w.Write(value);
}
func (p defaultPrinter) PrintIdent(w io.Write, value string) {
fmt.Fprint(w, value);
}
func (p defaultPrinter) PrintToken(w io.Write, token token.Token) {
fmt.Fprint(w, token.String());
}
func (p defaultPrinter) PrintComment(w io.Write, value []byte) {
w.Write(value);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ASTPrinter // ASTPrinter
// Separators - printed in a delayed fashion, depending on context. // Separators - printed in a delayed fashion, depending on context.
const ( const (
none = iota; none = iota;
...@@ -101,14 +138,17 @@ type Printer struct { ...@@ -101,14 +138,17 @@ type Printer struct {
// output // output
text io.Write; text io.Write;
// token printing
tprinter TokenPrinter;
// formatting control // formatting control
html bool; html bool;
full bool; // if false, print interface only; print all otherwise full bool; // if false, print interface only; print all otherwise
// comments // comments
comments []*ast.Comment; // the list of unassociated comments comments []*ast.Comment; // the list of unassociated comments
cindex int; // the current comment group index cindex int; // the current comment index
cpos token.Position; // the position of the next comment group cpos token.Position; // the position of the next comment
// current state // current state
lastpos token.Position; // position after last string lastpos token.Position; // position after last string
...@@ -144,10 +184,17 @@ func (P *Printer) nextComments() { ...@@ -144,10 +184,17 @@ func (P *Printer) nextComments() {
} }
func (P *Printer) Init(text io.Write, comments []*ast.Comment, html bool) { func (P *Printer) Init(text io.Write, tprinter TokenPrinter, comments []*ast.Comment, html bool) {
// writers // writers
P.text = text; P.text = text;
// token printing
if tprinter != nil {
P.tprinter = tprinter;
} else {
P.tprinter = defaultPrinter{};
}
// formatting control // formatting control
P.html = html; P.html = html;
...@@ -227,7 +274,7 @@ func (P *Printer) newline(n int) { ...@@ -227,7 +274,7 @@ func (P *Printer) newline(n int) {
func (P *Printer) TaggedString(pos token.Position, tag, s, endtag string) { func (P *Printer) TaggedString(pos token.Position, tag, s, endtag string) {
// use estimate for pos if we don't have one // use estimate for pos if we don't have one
offs := pos.Offset; offs := pos.Offset;
if offs == 0 { if pos.Line == 0 {
offs = P.lastpos.Offset; offs = P.lastpos.Offset;
} }
...@@ -401,6 +448,17 @@ func (P *Printer) Error(pos token.Position, tok token.Token, msg string) { ...@@ -401,6 +448,17 @@ func (P *Printer) Error(pos token.Position, tok token.Token, msg string) {
} }
// An astPrinter implements io.Write.
// TODO this is not yet used.
func (P *Printer) Write(p []byte) (n int, err *os.Error) {
// TODO
// - no string conversion every time
// - return proper results
P.String(noPos, string(p));
return len(p), nil;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// HTML support // HTML support
......
...@@ -136,25 +136,27 @@ func (doc *PackageDoc) addFunc(fun *ast.FuncDecl) { ...@@ -136,25 +136,27 @@ func (doc *PackageDoc) addFunc(fun *ast.FuncDecl) {
typ.methods[name] = fdoc; typ.methods[name] = fdoc;
} }
// if the type wasn't found, it wasn't exported // if the type wasn't found, it wasn't exported
// TODO: a non-exported type may still have exported functions
// determine what to do in that case
return;
}
} else { // perhaps a factory function
// perhaps a factory function // determine result type, if any
// determine result type, if any if len(fun.Type.Results) >= 1 {
if len(fun.Type.Results) >= 1 { res := fun.Type.Results[0];
res := fun.Type.Results[0]; if len(res.Names) <= 1 {
if len(res.Names) <= 1 { // exactly one (named or anonymous) result type
// exactly one (named or anonymous) result type typ = doc.lookupTypeDoc(res.Type);
typ = doc.lookupTypeDoc(res.Type); if typ != nil {
if typ != nil { typ.factories[name] = fdoc;
typ.factories[name] = fdoc; return;
return;
}
} }
} }
// ordinary function
doc.funcs[name] = fdoc;
} }
// ordinary function
doc.funcs[name] = fdoc;
} }
...@@ -279,18 +281,6 @@ func untabify(s []byte) []byte { ...@@ -279,18 +281,6 @@ func untabify(s []byte) []byte {
} }
func stripWhiteSpace(s []byte) []byte {
i, j := 0, len(s);
for i < len(s) && s[i] <= ' ' {
i++;
}
for j > i && s[j-1] <= ' ' {
j--
}
return s[i : j];
}
func stripCommentDelimiters(s []byte) []byte { func stripCommentDelimiters(s []byte) []byte {
switch s[1] { switch s[1] {
case '/': return s[2 : len(s)-1]; case '/': return s[2 : len(s)-1];
...@@ -308,8 +298,25 @@ const /* formatting mode */ ( ...@@ -308,8 +298,25 @@ const /* formatting mode */ (
) )
func printLine(p *astPrinter.Printer, line []byte, mode int) int { func printLine(p *astPrinter.Printer, line []byte, mode int) int {
indented := len(line) > 0 && line[0] == '\t'; // If a line starts with " *" (as a result of a vertical /****/ comment),
line = stripWhiteSpace(line); // strip it away. For an example of such a comment, see src/lib/flag.go.
if len(line) >= 2 && line[0] == ' ' && line[1] == '*' {
line = line[2 : len(line)];
}
// The line is indented if it starts with a tab.
// In either case strip away a leading space or tab.
indented := false;
if len(line) > 0 {
switch line[0] {
case '\t':
indented = true;
fallthrough;
case ' ':
line = line[1 : len(line)];
}
}
if len(line) == 0 { if len(line) == 0 {
// empty line // empty line
switch mode { switch mode {
...@@ -426,7 +433,7 @@ func (t *typeDoc) print(p *astPrinter.Printer) { ...@@ -426,7 +433,7 @@ func (t *typeDoc) print(p *astPrinter.Printer) {
func (doc *PackageDoc) Print(writer io.Write) { func (doc *PackageDoc) Print(writer io.Write) {
var p astPrinter.Printer; var p astPrinter.Printer;
p.Init(writer, nil, true); p.Init(writer, nil, nil, true);
// program header // program header
fmt.Fprintf(writer, "<h1>package %s</h1>\n", doc.name); fmt.Fprintf(writer, "<h1>package %s</h1>\n", doc.name);
......
This diff is collapsed.
...@@ -50,7 +50,7 @@ func print(prog *ast.Program) { ...@@ -50,7 +50,7 @@ func print(prog *ast.Program) {
// initialize printer // initialize printer
var printer astPrinter.Printer; var printer astPrinter.Printer;
printer.Init(writer, prog.Comments, *html); printer.Init(writer, nil, prog.Comments, *html);
printer.DoProgram(prog); printer.DoProgram(prog);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment