mirror of
https://github.com/golang/go
synced 2024-11-24 09:20:02 -07:00
some godoc cleanup:
- simplified dealing with parse errors: no need to intersperse them in the source - improve visibility of highlighted identifiers by showing them in bold R=rsc https://golang.org/cl/163051
This commit is contained in:
parent
330139e3f2
commit
9e450880e9
@ -194,6 +194,7 @@ span.comment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
span.highlight {
|
span.highlight {
|
||||||
|
font-weight: bold;
|
||||||
background-color: #ffffa0;
|
background-color: #ffffa0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
parse errors:
|
|
||||||
{.repeated section list}
|
|
||||||
{.section msg}
|
|
||||||
{filename}:{line}: {msg}
|
|
||||||
{.end}
|
|
||||||
{.end}
|
|
@ -4,7 +4,10 @@
|
|||||||
license that can be found in the LICENSE file.
|
license that can be found in the LICENSE file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<pre>
|
{.section Error}
|
||||||
{.repeated section list}
|
<p>
|
||||||
{src|html}{.section msg}<b><span class="alert">«{msg|html}»</span></b>{.end}{.end}
|
<span class="alert" style="font-size:120%">{@|html}</span>
|
||||||
</pre>
|
</p>
|
||||||
|
{.or}
|
||||||
|
<pre>{Source|html}</pre>
|
||||||
|
{.end}
|
@ -12,7 +12,6 @@ import (
|
|||||||
"go/doc";
|
"go/doc";
|
||||||
"go/parser";
|
"go/parser";
|
||||||
"go/printer";
|
"go/printer";
|
||||||
"go/scanner";
|
|
||||||
"go/token";
|
"go/token";
|
||||||
"http";
|
"http";
|
||||||
"io";
|
"io";
|
||||||
@ -122,7 +121,7 @@ func isPkgDir(dir *os.Dir) bool {
|
|||||||
|
|
||||||
|
|
||||||
func pkgName(filename string) string {
|
func pkgName(filename string) string {
|
||||||
file, err := parse(filename, parser.PackageClauseOnly);
|
file, err := parser.ParseFile(filename, nil, parser.PackageClauseOnly);
|
||||||
if err != nil || file == nil {
|
if err != nil || file == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -397,74 +396,6 @@ func listing(dirs []*os.Dir) *DirList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Parsing
|
|
||||||
|
|
||||||
// A single error in the parsed file.
|
|
||||||
type parseError struct {
|
|
||||||
src []byte; // source before error
|
|
||||||
line int; // line number of error
|
|
||||||
msg string; // error message
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// All the errors in the parsed file, plus surrounding source code.
|
|
||||||
// Each error has a slice giving the source text preceding it
|
|
||||||
// (starting where the last error occurred). The final element in list[]
|
|
||||||
// has msg = "", to give the remainder of the source code.
|
|
||||||
// This data structure is handed to the templates parseerror.txt and parseerror.html.
|
|
||||||
//
|
|
||||||
type parseErrors struct {
|
|
||||||
filename string; // path to file
|
|
||||||
list []parseError; // the errors
|
|
||||||
src []byte; // the file's entire source code
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parses a file (path) and returns the corresponding AST and
|
|
||||||
// a sorted list (by file position) of errors, if any.
|
|
||||||
//
|
|
||||||
func parse(path string, mode uint) (*ast.File, *parseErrors) {
|
|
||||||
src, err := io.ReadFile(path);
|
|
||||||
if err != nil {
|
|
||||||
log.Stderrf("%v", err);
|
|
||||||
errs := []parseError{parseError{nil, 0, err.String()}};
|
|
||||||
return nil, &parseErrors{path, errs, nil};
|
|
||||||
}
|
|
||||||
|
|
||||||
prog, err := parser.ParseFile(path, src, mode);
|
|
||||||
if err != nil {
|
|
||||||
var errs []parseError;
|
|
||||||
if errors, ok := err.(scanner.ErrorList); ok {
|
|
||||||
// convert error list (already sorted)
|
|
||||||
// TODO(gri) If the file contains //line comments, the errors
|
|
||||||
// may not be sorted in increasing file offset value
|
|
||||||
// which will lead to incorrect output.
|
|
||||||
errs = make([]parseError, len(errors)+1); // +1 for final fragment of source
|
|
||||||
offs := 0;
|
|
||||||
for i, r := range errors {
|
|
||||||
// Should always be true, but check for robustness.
|
|
||||||
if 0 <= r.Pos.Offset && r.Pos.Offset <= len(src) {
|
|
||||||
errs[i].src = src[offs:r.Pos.Offset];
|
|
||||||
offs = r.Pos.Offset;
|
|
||||||
}
|
|
||||||
errs[i].line = r.Pos.Line;
|
|
||||||
errs[i].msg = r.Msg;
|
|
||||||
}
|
|
||||||
errs[len(errors)].src = src[offs:];
|
|
||||||
} else {
|
|
||||||
// single error of unspecified type
|
|
||||||
errs = make([]parseError, 2);
|
|
||||||
errs[0] = parseError{[]byte{}, 0, err.String()};
|
|
||||||
errs[1].src = src;
|
|
||||||
}
|
|
||||||
return nil, &parseErrors{path, errs, src};
|
|
||||||
}
|
|
||||||
|
|
||||||
return prog, nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// HTML formatting support
|
// HTML formatting support
|
||||||
|
|
||||||
@ -544,6 +475,12 @@ func writeText(w io.Writer, text []byte, html bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type StyledNode struct {
|
||||||
|
node interface{};
|
||||||
|
styler printer.Styler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Write anything to w; optionally html-escaped.
|
// Write anything to w; optionally html-escaped.
|
||||||
func writeAny(w io.Writer, x interface{}, html bool) {
|
func writeAny(w io.Writer, x interface{}, html bool) {
|
||||||
switch v := x.(type) {
|
switch v := x.(type) {
|
||||||
@ -551,10 +488,10 @@ func writeAny(w io.Writer, x interface{}, html bool) {
|
|||||||
writeText(w, v, html)
|
writeText(w, v, html)
|
||||||
case string:
|
case string:
|
||||||
writeText(w, strings.Bytes(v), html)
|
writeText(w, strings.Bytes(v), html)
|
||||||
case ast.Decl:
|
case ast.Decl, ast.Expr, ast.Stmt, *ast.File:
|
||||||
writeNode(w, v, html, &defaultStyler)
|
writeNode(w, x, html, &defaultStyler)
|
||||||
case ast.Expr:
|
case StyledNode:
|
||||||
writeNode(w, v, html, &defaultStyler)
|
writeNode(w, v.node, html, v.styler)
|
||||||
default:
|
default:
|
||||||
if html {
|
if html {
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
@ -713,9 +650,8 @@ var (
|
|||||||
godocHTML,
|
godocHTML,
|
||||||
packageHTML,
|
packageHTML,
|
||||||
packageText,
|
packageText,
|
||||||
parseerrorHTML,
|
searchHTML,
|
||||||
parseerrorText,
|
sourceHTML *template.Template;
|
||||||
searchHTML *template.Template;
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func readTemplates() {
|
func readTemplates() {
|
||||||
@ -725,9 +661,8 @@ func readTemplates() {
|
|||||||
godocHTML = readTemplate("godoc.html");
|
godocHTML = readTemplate("godoc.html");
|
||||||
packageHTML = readTemplate("package.html");
|
packageHTML = readTemplate("package.html");
|
||||||
packageText = readTemplate("package.txt");
|
packageText = readTemplate("package.txt");
|
||||||
parseerrorHTML = readTemplate("parseerror.html");
|
|
||||||
parseerrorText = readTemplate("parseerror.txt");
|
|
||||||
searchHTML = readTemplate("search.html");
|
searchHTML = readTemplate("search.html");
|
||||||
|
sourceHTML = readTemplate("source.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -802,29 +737,24 @@ func serveHTMLDoc(c *http.Conn, r *http.Request, path string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func serveParseErrors(c *http.Conn, errors *parseErrors) {
|
func serveGoSource(c *http.Conn, r *http.Request, path string) {
|
||||||
// format errors
|
var info struct {
|
||||||
var buf bytes.Buffer;
|
Source StyledNode;
|
||||||
if err := parseerrorHTML.Execute(errors, &buf); err != nil {
|
Error string;
|
||||||
log.Stderrf("parseerrorHTML.Execute: %s", err)
|
|
||||||
}
|
}
|
||||||
servePage(c, "Parse errors in source file "+errors.filename, "", buf.Bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
file, err := parser.ParseFile(path, nil, parser.ParseComments);
|
||||||
func serveGoSource(c *http.Conn, r *http.Request, path string, styler printer.Styler) {
|
info.Source = StyledNode{file, &Styler{linetags: true, highlight: r.FormValue("h")}};
|
||||||
prog, errors := parse(path, parser.ParseComments);
|
if err != nil {
|
||||||
if errors != nil {
|
info.Error = err.String()
|
||||||
serveParseErrors(c, errors);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
fmt.Fprintln(&buf, "<pre>");
|
if err := sourceHTML.Execute(info, &buf); err != nil {
|
||||||
writeNode(&buf, prog, true, styler);
|
log.Stderrf("sourceHTML.Execute: %s", err)
|
||||||
fmt.Fprintln(&buf, "</pre>");
|
}
|
||||||
|
|
||||||
servePage(c, "Source file "+r.URL.Path, "", buf.Bytes());
|
servePage(c, "Source file "+path, "", buf.Bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -940,7 +870,7 @@ func serveFile(c *http.Conn, r *http.Request) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case ext == ".go":
|
case ext == ".go":
|
||||||
serveGoSource(c, r, path, &Styler{linetags: true, highlight: r.FormValue("h")});
|
serveGoSource(c, r, path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +217,7 @@ func main() {
|
|||||||
|
|
||||||
// Command line mode.
|
// Command line mode.
|
||||||
if *html {
|
if *html {
|
||||||
packageText = packageHTML;
|
packageText = packageHTML
|
||||||
parseerrorText = parseerrorHTML;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info := pkgHandler.getPageInfo(flag.Arg(0));
|
info := pkgHandler.getPageInfo(flag.Arg(0));
|
||||||
|
Loading…
Reference in New Issue
Block a user