From 90cc4a594960cd6ad0e71422cfbf226a20d6b3f4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 22 Oct 2009 09:41:38 -0700 Subject: [PATCH] go/printer: - handle HTML tagging via (client-installable) Stylers go/doc: - basic styler support - some factoring - ready to contain the search code (but for now excluded) doc/style.css: - updated doc/go_spec.css: - cleanup: replace deprecated uses of tag with tag R=rsc DELTA=302 (160 added, 62 deleted, 80 changed) OCL=35973 CL=35996 --- doc/go_spec.html | 30 +++--- doc/style.css | 35 ++++++- src/cmd/cgo/out.go | 8 +- src/cmd/godoc/godoc.go | 149 +++++++++++++++++++---------- src/cmd/gofmt/gofmt.go | 2 +- src/pkg/go/printer/printer.go | 138 +++++++++++++++----------- src/pkg/go/printer/printer_test.go | 2 +- 7 files changed, 231 insertions(+), 133 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 40c65dfdbd..c743f6d04d 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1868,7 +1868,7 @@ math.Sin

-TODO: Unify this section with Selectors - it's the same syntax. +TODO: Unify this section with Selectors - it's the same syntax.

Composite literals

@@ -2219,9 +2219,9 @@ p.M0 // ((*p).T0).M0 - + TODO: Specify what happens to receivers. - +

Indexes

@@ -2779,7 +2779,7 @@ that is, either a variable, pointer indirection, array or slice indexing operation, or a field selector of an addressable struct operand. A function result variable is not addressable. -(TODO: remove this restriction.) +(TODO: remove this restriction.) Given an operand of pointer type, the pointer indirection operator * retrieves the value pointed to by the operand. @@ -2881,8 +2881,8 @@ zero value for its type (§The zero value).

-TODO: Probably in a separate section, communication semantics -need to be presented regarding send, receive, select, and goroutines. +TODO: Probably in a separate section, communication semantics +need to be presented regarding send, receive, select, and goroutines.

Method expressions

@@ -3161,11 +3161,11 @@ int8(^1) // same as int8(-2)

- + TODO: perhaps ^ should be disallowed on non-uints instead of assuming twos complement. Also it may be possible to make typed constants more like variables, at the cost of fewer overflow etc. errors being caught. - +

@@ -3900,11 +3900,11 @@ func complex_f3() (re float, im float) {

- + TODO: Define when return is required.
TODO: Language about result parameters needs to go into a section on function/method invocation
-
+

Break statements

@@ -3977,7 +3977,7 @@ L:

is erroneous because the jump to label L skips the creation of v. -(TODO: Eliminate in favor of used and not set errors?) +(TODO: Eliminate in favor of used and not set errors?)

Fallthrough statements

@@ -4578,9 +4578,9 @@ The following minimal alignment properties are guaranteed: unsafe.Alignof(x[0]), but at least 1. -

Implementation differences - TODO

+

Implementation differences - TODO

diff --git a/doc/style.css b/doc/style.css index fcbc0b3bd5..cd344df9cf 100644 --- a/doc/style.css +++ b/doc/style.css @@ -1,3 +1,12 @@ +/* + Copyright 2009 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. +*/ + +/* ------------------------------------------------------------------------- */ +/* Styles meant to help page authors achieve beauty. */ + code, .code { font-size: 100%; font-family: monospace; @@ -19,11 +28,15 @@ pre.grammar { } p.rule { - font-style: italic + font-style: italic; } span.event { - font-style: italic + font-style: italic; +} + +span.alert { + color: #ff0000; } body { @@ -41,7 +54,7 @@ h2 { border-top:1px solid #36C; } -pre{ +pre { font-size: 9pt; background-color: #f8f8ff; margin: 1em 0 0 0; @@ -59,8 +72,9 @@ li pre { margin: 0.5em 0px 1em 0px; } -/* Above this comment, styles meant to help page authors achieve beauty. */ -/* Below this comment, styles used in the boilerplate-ish parts of pages. */ + +/* ------------------------------------------------------------------------- */ +/* Styles used in the boilerplate-ish parts of pages. */ div#content { margin-left: 20%; @@ -133,3 +147,14 @@ div#linkList li.navhead { } } + +/* ------------------------------------------------------------------------- */ +/* Styles used by go/printer Styler implementations. */ + +span.comment { + color: #0000a0; +} + +span.highlight { + background-color: #00ff00; +} diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 524786d548..5f55a6ba75 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -37,7 +37,7 @@ func (p *Prog) writeOutput(srcfile string) { // Write Go output: Go input with rewrites of C.xxx to _C_xxx. fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n"); fmt.Fprintf(fgo1, "//line %s:1\n", srcfile); - printer.Fprint(fgo1, p.AST, 0, 8); + printer.Fprint(fgo1, p.AST, 0, 8, nil); // Write second Go output: definitions of _C_xxx. // In a separate file so that the import of "unsafe" does not @@ -48,7 +48,7 @@ func (p *Prog) writeOutput(srcfile string) { for name, def := range p.Typedef { fmt.Fprintf(fgo2, "type %s ", name); - printer.Fprint(fgo2, def, 0, 8); + printer.Fprint(fgo2, def, 0, 8, nil); fmt.Fprintf(fgo2, "\n"); } fmt.Fprintf(fgo2, "type _C_void [0]byte\n"); @@ -63,7 +63,7 @@ func (p *Prog) writeOutput(srcfile string) { for name, def := range p.Vardef { fmt.Fprintf(fc, "#pragma dynld %s·_C_%s %s \"%s/%s_%s.so\"\n", p.Package, name, name, pkgroot, p.PackagePath, base); fmt.Fprintf(fgo2, "var _C_%s ", name); - printer.Fprint(fgo2, &ast.StarExpr{X: def.Go}, 0, 8); + printer.Fprint(fgo2, &ast.StarExpr{X: def.Go}, 0, 8, nil); fmt.Fprintf(fgo2, "\n"); } fmt.Fprintf(fc, "\n"); @@ -74,7 +74,7 @@ func (p *Prog) writeOutput(srcfile string) { Name: &ast.Ident{Value: "_C_"+name}, Type: def.Go, }; - printer.Fprint(fgo2, d, 0, 8); + printer.Fprint(fgo2, d, 0, 8, nil); fmt.Fprintf(fgo2, "\n"); if name == "CString" || name == "GoString" { diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 0916d2ec87..652d8f1265 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -53,53 +53,49 @@ import ( const Pkg = "/pkg/" // name for auto-generated package documentation tree -type delayTime struct { - mutex sync.RWMutex; - minutes int; -} - +// ---------------------------------------------------------------------------- +// Support types -func (dt *delayTime) set(minutes int) { - dt.mutex.Lock(); - dt.minutes = minutes; - dt.mutex.Unlock(); +// An RWValue wraps a value and permits mutually exclusive +// access to it and records the time the value was last set. +type RWValue struct { + mutex sync.RWMutex; + value interface{}; + timestamp int64; // time of last set(), in seconds since epoch } -func (dt *delayTime) backoff(max int) { - dt.mutex.Lock(); - dt.minutes *= 2; - if dt.minutes > max { - dt.minutes = max; - } - dt.mutex.Unlock(); +func (v *RWValue) set(value interface{}) { + v.mutex.Lock(); + v.value = value; + v.timestamp = time.Seconds(); + v.mutex.Unlock(); } -func (dt *delayTime) get() int { - dt.mutex.RLock(); - defer dt.mutex.RUnlock(); - return dt.minutes; +func (v *RWValue) get() (interface{}, int64) { + v.mutex.RLock(); + defer v.mutex.RUnlock(); + return v.value, v.timestamp; } -type timeStamp struct { - mutex sync.RWMutex; - seconds int64; -} - +// ---------------------------------------------------------------------------- +// Globals -func (ts *timeStamp) set() { - ts.mutex.Lock(); - ts.seconds = time.Seconds(); - ts.mutex.Unlock(); +type delayTime struct { + RWValue; } -func (ts *timeStamp) get() int64 { - ts.mutex.RLock(); - defer ts.mutex.RUnlock(); - return ts.seconds; +func (dt *delayTime) backoff(max int) { + dt.mutex.Lock(); + v := dt.value.(int) * 2; + if v > max { + v = max; + } + dt.value = v; + dt.mutex.Unlock(); } @@ -115,7 +111,7 @@ var ( syncCmd = flag.String("sync", "", "sync command; disabled if empty"); syncMin = flag.Int("sync_minutes", 0, "sync interval in minutes; disabled if <= 0"); syncDelay delayTime; // actual sync delay in minutes; usually syncDelay == syncMin, but delay may back off exponentially - syncTime timeStamp; // time of last p4 sync + syncTime RWValue; // time of last p4 sync // layout control tabwidth = flag.Int("tabwidth", 4, "tab width"); @@ -132,7 +128,7 @@ func init() { goroot = "/home/r/go-release/go"; } flag.StringVar(&goroot, "goroot", goroot, "Go root directory"); - syncTime.set(); // have a reasonable initial value + syncTime.set(nil); // have a reasonable initial value (time is shown on web page) } @@ -220,16 +216,62 @@ func parse(path string, mode uint) (*ast.File, *parseErrors) { } +// ---------------------------------------------------------------------------- +// HTML formatting support + +// Styler implements a printer.Styler. +type Styler struct { + highlight string; +} + + +func (s *Styler) LineTag(line int) (text []byte, tag printer.HtmlTag) { + tag = printer.HtmlTag{fmt.Sprintf(``, line), ""}; + return; +} + + +func (s *Styler) Comment(c *ast.Comment, line []byte) (text []byte, tag printer.HtmlTag) { + text = line; + // minimal syntax-coloring of comments for now - people will want more + // (don't do anything more until there's a button to turn it on/off) + tag = printer.HtmlTag{``, ""}; + return; +} + + +func (s *Styler) BasicLit(x *ast.BasicLit) (text []byte, tag printer.HtmlTag) { + text = x.Value; + return; +} + + +func (s *Styler) Ident(id *ast.Ident) (text []byte, tag printer.HtmlTag) { + text = strings.Bytes(id.Value); + if s.highlight == id.Value { + tag = printer.HtmlTag{"", ""}; + } + return; +} + + +func (s *Styler) Token(tok token.Token) (text []byte, tag printer.HtmlTag) { + text = strings.Bytes(tok.String()); + return; +} + + + // ---------------------------------------------------------------------------- // Templates // Write an AST-node to w; optionally html-escaped. -func writeNode(w io.Writer, node interface{}, html bool) { +func writeNode(w io.Writer, node interface{}, html bool, style printer.Styler) { mode := printer.UseSpaces; if html { mode |= printer.GenHTML; } - printer.Fprint(w, node, mode, *tabwidth); + printer.Fprint(w, node, mode, *tabwidth, style); } @@ -251,9 +293,9 @@ func writeAny(w io.Writer, x interface{}, html bool) { case string: writeText(w, strings.Bytes(v), html); case ast.Decl: - writeNode(w, v, html); + writeNode(w, v, html, nil); case ast.Expr: - writeNode(w, v, html); + writeNode(w, v, html, nil); default: if html { var buf bytes.Buffer; @@ -324,11 +366,13 @@ func readTemplate(name string) *template.Template { } -var godocHtml *template.Template -var packageHtml *template.Template -var packageText *template.Template -var parseerrorHtml *template.Template -var parseerrorText *template.Template +var ( + godocHtml, + packageHtml, + packageText, + parseerrorHtml, + parseerrorText *template.Template; +) func readTemplates() { // have to delay until after flags processing, @@ -351,9 +395,10 @@ func servePage(c *http.Conn, title, content interface{}) { content interface{}; } + _, ts := syncTime.get(); d := Data{ title: title, - timestamp: time.SecondsToLocalTime(syncTime.get()).String(), + timestamp: time.SecondsToLocalTime(ts).String(), content: content, }; @@ -420,7 +465,7 @@ func serveParseErrors(c *http.Conn, errors *parseErrors) { } -func serveGoSource(c *http.Conn, filename string) { +func serveGoSource(c *http.Conn, filename string, style printer.Styler) { path := pathutil.Join(goroot, filename); prog, errors := parse(path, parser.ParseComments); if errors != nil { @@ -430,7 +475,7 @@ func serveGoSource(c *http.Conn, filename string) { var buf bytes.Buffer; fmt.Fprintln(&buf, "
");
-	writeNode(&buf, prog, true);
+	writeNode(&buf, prog, true, style);
 	fmt.Fprintln(&buf, "
"); servePage(c, "Source file " + filename, buf.Bytes()); @@ -455,7 +500,7 @@ func serveFile(c *http.Conn, r *http.Request) { serveHtmlDoc(c, r, path); case ext == ".go": - serveGoSource(c, path); + serveGoSource(c, path, &Styler{highlight: r.FormValue("h")}); default: // TODO: @@ -654,7 +699,7 @@ func dosync(c *http.Conn, r *http.Request) { args := []string{"/bin/sh", "-c", *syncCmd}; if exec(c, args) { // sync succeeded - syncTime.set(); + syncTime.set(nil); syncDelay.set(*syncMin); // revert to regular sync schedule } else { // sync failed - back off exponentially, but try at least once a day @@ -722,14 +767,16 @@ func main() { go func() { for { dosync(nil, nil); + _, delay := syncDelay.get(); if *verbose { - log.Stderrf("next sync in %dmin", syncDelay.get()); + log.Stderrf("next sync in %dmin", delay); } - time.Sleep(int64(syncDelay.get())*(60*1e9)); + time.Sleep(int64(delay)*60e9); } }(); } + // Start http server. if err := http.ListenAndServe(*httpaddr, handler); err != nil { log.Exitf("ListenAndServe %s: %v", *httpaddr, err); } diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 3c9131de7b..e4b0762d17 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -91,7 +91,7 @@ func processFile(filename string) os.Error { } var res bytes.Buffer; - _, err = printer.Fprint(&res, file, printerMode(), *tabwidth); + _, err = printer.Fprint(&res, file, printerMode(), *tabwidth, nil); if err != nil { return err; } diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index 0e799eceb9..07cfee364a 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -64,16 +64,20 @@ var ( var noPos token.Position -// A lineTag is a token.Position that is used to print -// line tag id's of the form "L%d" where %d stands for -// the line indicated by position. -// -type lineTag token.Position +// An HtmlTag specifies a start and end tag. +type HtmlTag struct { + Start, End string; // empty if tags are absent +} -// A htmlTag specifies a start and end tag. -type htmlTag struct { - start, end string; // empty if tags are absent +// A Styler specifies the formatting line tags and elementary Go words. +// A format consists of text and a (possibly empty) surrounding HTML tag. +type Styler interface { + LineTag(line int) ([]byte, HtmlTag); + Comment(c *ast.Comment, line []byte) ([]byte, HtmlTag); + BasicLit(x *ast.BasicLit) ([]byte, HtmlTag); + Ident(id *ast.Ident) ([]byte, HtmlTag); + Token(tok token.Token) ([]byte, HtmlTag); } @@ -82,6 +86,7 @@ type printer struct { output io.Writer; mode uint; tabwidth int; + style Styler; errors chan os.Error; // Current state @@ -103,7 +108,6 @@ type printer struct { last token.Position; // HTML support - tag htmlTag; // tag to be used around next item lastTaggedLine int; // last line for which a line tag was written // The list of comments; or nil. @@ -111,10 +115,11 @@ type printer struct { } -func (p *printer) init(output io.Writer, mode uint, tabwidth int) { +func (p *printer) init(output io.Writer, mode uint, tabwidth int, style Styler) { p.output = output; p.mode = mode; p.tabwidth = tabwidth; + p.style = style; p.errors = make(chan os.Error); p.buffer = make([]whiteSpace, 0, 16); // whitespace sequences are short } @@ -216,41 +221,42 @@ func (p *printer) writeNewlines(n int) { } +func (p *printer) writeTaggedItem(data []byte, tag HtmlTag) { + // write start tag, if any + // (no html-escaping and no p.pos update for tags - use write0) + if tag.Start != "" { + p.write0(strings.Bytes(tag.Start)); + } + p.write(data); + // write end tag, if any + if tag.End != "" { + p.write0(strings.Bytes(tag.End)); + } +} + + // writeItem writes data at position pos. data is the text corresponding to // a single lexical token, but may also be comment text. pos is the actual // (or at least very accurately estimated) position of the data in the original -// source text. The data may be tagged, depending on p.mode and the setLineTag -// parameter. writeItem updates p.last to the position immediately following -// the data. +// source text. If tags are present and GenHTML is set, the tags are written +// before and after the data. writeItem updates p.last to the position +// immediately following the data. // -func (p *printer) writeItem(pos token.Position, data []byte, setLineTag bool) { +func (p *printer) writeItem(pos token.Position, data []byte, tag HtmlTag) { p.pos = pos; if debug { // do not update p.pos - use write0 p.write0(strings.Bytes(fmt.Sprintf("[%d:%d]", pos.Line, pos.Column))); } if p.mode & GenHTML != 0 { - // no html-escaping and no p.pos update for tags - use write0 - if setLineTag && pos.Line > p.lastTaggedLine { - // id's must be unique within a document: set - // line tag only if line number has increased - // (note: for now write complete start and end - // tag - shorter versions seem to have issues - // with Safari) - p.tag.start = fmt.Sprintf(``, pos.Line); + // write line tag if on a new line + // TODO(gri): should write line tags on each line at the start + // will be more useful (e.g. to show line numbers) + if p.style != nil && pos.Line > p.lastTaggedLine { + p.writeTaggedItem(p.style.LineTag(pos.Line)); p.lastTaggedLine = pos.Line; } - // write start tag, if any - if p.tag.start != "" { - p.write0(strings.Bytes(p.tag.start)); - p.tag.start = ""; // tag consumed - } - p.write(data); - // write end tag, if any - if p.tag.end != "" { - p.write0(strings.Bytes(p.tag.end)); - p.tag.end = ""; // tag consumed - } + p.writeTaggedItem(data, tag); } else { p.write(data); } @@ -357,7 +363,11 @@ func (p *printer) writeComment(comment *ast.Comment) { } // write comment - p.writeItem(comment.Pos(), text, false); + var tag HtmlTag; + if p.style != nil { + text, tag = p.style.Comment(comment, text); + } + p.writeItem(comment.Pos(), text, tag); } @@ -475,13 +485,13 @@ func (p *printer) writeWhitespace(n int) { // printed, followed by the actual token. // func (p *printer) print(args ...) { - setLineTag := false; v := reflect.NewValue(args).(*reflect.StructValue); for i := 0; i < v.NumField(); i++ { f := v.Field(i); next := p.pos; // estimated position of next item var data []byte; + var tag HtmlTag; switch x := f.Interface().(type) { case whiteSpace: if x == ignore { @@ -501,23 +511,40 @@ func (p *printer) print(args ...) { p.buffer = p.buffer[0 : i+1]; p.buffer[i] = x; case []byte: + // TODO(gri): remove this case once commentList + // handles comments correctly data = x; case string: + // TODO(gri): remove this case once fieldList + // handles comments correctly data = strings.Bytes(x); + case *ast.Ident: + if p.style != nil { + data, tag = p.style.Ident(x); + } else { + data = strings.Bytes(x.Value); + } + case *ast.BasicLit: + if p.style != nil { + data, tag = p.style.BasicLit(x); + } else { + data = x.Value; + } + // escape all literals so they pass through unchanged + // (note that valid Go programs cannot contain esc ('\xff') + // bytes since they do not appear in legal UTF-8 sequences) + // TODO(gri): this this more efficiently. + data = strings.Bytes("\xff" + string(data) + "\xff"); case token.Token: - data = strings.Bytes(x.String()); + if p.style != nil { + data, tag = p.style.Token(x); + } else { + data = strings.Bytes(x.String()); + } case token.Position: if x.IsValid() { next = x; // accurate position of next item } - case lineTag: - pos := token.Position(x); - if pos.IsValid() { - next = pos; // accurate position of next item - setLineTag = true; - } - case htmlTag: - p.tag = x; // tag surrounding next item default: panicln("print: unsupported argument type", f.Type().String()); } @@ -531,8 +558,7 @@ func (p *printer) print(args ...) { // at the end of a file) p.writeNewlines(next.Line - p.pos.Line); - p.writeItem(next, data, setLineTag); - setLineTag = false; + p.writeItem(next, data, tag); } } } @@ -600,6 +626,7 @@ func (p *printer) linebreak(line, min, max int, ws whiteSpace, newSection bool) func (p *printer) commentList(list []*ast.Comment) { for i, c := range list { t := c.Text; + // TODO(gri): this needs to be styled like normal comments p.print(c.Pos(), t); if t[1] == '/' && i+1 < len(list) { //-style comment which is not at the end; print a newline @@ -823,6 +850,7 @@ func (p *printer) fieldList(lbrace token.Position, list []*ast.Field, rbrace tok } } if isIncomplete { + // TODO(gri): this needs to be styled like normal comments p.print("// contains unexported fields"); } @@ -845,6 +873,7 @@ func (p *printer) fieldList(lbrace token.Position, list []*ast.Field, rbrace tok } } if isIncomplete { + // TODO(gri): this needs to be styled like normal comments p.print("// contains unexported methods"); } @@ -960,7 +989,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int) (optSemi bool) { p.print("BadExpr"); case *ast.Ident: - p.print(x.Value); + p.print(x); case *ast.BinaryExpr: p.binaryExpr(x, prec1); @@ -991,10 +1020,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int) (optSemi bool) { } case *ast.BasicLit: - // escape all literals so they pass through unchanged - // (note that valid Go programs cannot contain esc ('\xff') - // bytes since they do not appear in legal UTF-8 sequences) - p.print(esc, x.Value, esc); + p.print(x); case *ast.StringList: p.stringList(x.Strings); @@ -1451,7 +1477,7 @@ func (p *printer) spec(spec ast.Spec, n int, context declContext) { func (p *printer) genDecl(d *ast.GenDecl, context declContext) { p.leadComment(d.Doc); - p.print(lineTag(d.Pos()), d.Tok, blank); + p.print(d.Pos(), d.Tok, blank); if d.Lparen.IsValid() { // group of parenthesized declarations @@ -1483,7 +1509,7 @@ func (p *printer) isOneLiner(b *ast.BlockStmt) bool { // test-print the statement and see if it would fit var buf bytes.Buffer; - _, err := Fprint(&buf, b.List[0], p.mode, p.tabwidth); + _, err := Fprint(&buf, b.List[0], p.mode, p.tabwidth, p.style); if err != nil { return false; // don't try } @@ -1526,7 +1552,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, isLit bool) { func (p *printer) funcDecl(d *ast.FuncDecl) { p.leadComment(d.Doc); - p.print(lineTag(d.Pos()), token.FUNC, blank); + p.print(d.Pos(), token.FUNC, blank); if recv := d.Recv; recv != nil { // method: print receiver p.print(token.LPAREN); @@ -1697,7 +1723,7 @@ var inf = token.Position{Offset: 1<<30, Line: 1<<30} // or assignment-compatible to ast.Expr, ast.Decl, or ast.Stmt. Printing // is controlled by the mode and tabwidth parameters. // -func Fprint(output io.Writer, node interface{}, mode uint, tabwidth int) (int, os.Error) { +func Fprint(output io.Writer, node interface{}, mode uint, tabwidth int, style Styler) (int, os.Error) { // redirect output through a trimmer to eliminate trailing whitespace // (Input to a tabwriter must be untrimmed since trailing tabs provide // formatting information. The tabwriter could provide trimming @@ -1721,7 +1747,7 @@ func Fprint(output io.Writer, node interface{}, mode uint, tabwidth int) (int, o // setup printer and print node var p printer; - p.init(output, mode, tabwidth); + p.init(output, mode, tabwidth, style); go func() { switch n := node.(type) { case ast.Expr: diff --git a/src/pkg/go/printer/printer_test.go b/src/pkg/go/printer/printer_test.go index 9fbc1ad233..1b39b4f442 100644 --- a/src/pkg/go/printer/printer_test.go +++ b/src/pkg/go/printer/printer_test.go @@ -62,7 +62,7 @@ func check(t *testing.T, source, golden string, mode checkMode) { // format source var buf bytes.Buffer; - if _, err := Fprint(&buf, prog, pmode, tabwidth); err != nil { + if _, err := Fprint(&buf, prog, pmode, tabwidth, nil); err != nil { t.Error(err); } res := buf.Bytes(); -- 2.48.1