1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Module file printer.
15 // Format returns a go.mod file as a byte slice, formatted in standard style.
16 func Format(f *FileSyntax) []byte {
22 // A printer collects the state during printing of a file or expression.
24 bytes.Buffer // output buffer
25 comment []Comment // pending end-of-line comments
26 margin int // left margin (indent), a number of tabs
29 // printf prints to the buffer.
30 func (p *printer) printf(format string, args ...interface{}) {
31 fmt.Fprintf(p, format, args...)
34 // indent returns the position on the current line, in bytes, 0-indexed.
35 func (p *printer) indent() int {
38 for n < len(b) && b[len(b)-1-n] != '\n' {
44 // newline ends the current line, flushing end-of-line comments.
45 func (p *printer) newline() {
46 if len(p.comment) > 0 {
48 for i, com := range p.comment {
52 for i := 0; i < p.margin; i++ {
56 p.printf("%s", strings.TrimSpace(com.Token))
58 p.comment = p.comment[:0]
63 for i := 0; i < p.margin; i++ {
68 // trim removes trailing spaces and tabs from the current line.
69 func (p *printer) trim() {
70 // Remove trailing spaces and tabs from line we're about to end.
73 for n > 0 && (b[n-1] == '\t' || b[n-1] == ' ') {
79 // file formats the given file into the print buffer.
80 func (p *printer) file(f *FileSyntax) {
81 for _, com := range f.Before {
82 p.printf("%s", strings.TrimSpace(com.Token))
86 for i, stmt := range f.Stmt {
87 switch x := stmt.(type) {
89 // comments already handled
97 for _, com := range stmt.Comment().After {
98 p.printf("%s", strings.TrimSpace(com.Token))
102 if i+1 < len(f.Stmt) {
108 func (p *printer) expr(x Expr) {
109 // Emit line-comments preceding this expression.
110 if before := x.Comment().Before; len(before) > 0 {
111 // Want to print a line comment.
112 // Line comments must be at the current margin.
115 // There's other text on the line. Start a new line.
118 // Re-indent to margin.
119 for i := 0; i < p.margin; i++ {
122 for _, com := range before {
123 p.printf("%s", strings.TrimSpace(com.Token))
128 switch x := x.(type) {
130 panic(fmt.Errorf("printer: unexpected type %T", x))
148 for _, l := range x.Line {
157 // Queue end-of-line comments for printing when we
158 // reach the end of the line.
159 p.comment = append(p.comment, x.Comment().Suffix...)
162 func (p *printer) tokens(tokens []string) {
164 for _, t := range tokens {
165 if t == "," || t == ")" || t == "]" || t == "}" {
168 p.printf("%s%s", sep, t)
170 if t == "(" || t == "[" || t == "{" {