Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / mod@v0.3.0 / modfile / print.go
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.
4
5 // Module file printer.
6
7 package modfile
8
9 import (
10         "bytes"
11         "fmt"
12         "strings"
13 )
14
15 // Format returns a go.mod file as a byte slice, formatted in standard style.
16 func Format(f *FileSyntax) []byte {
17         pr := &printer{}
18         pr.file(f)
19         return pr.Bytes()
20 }
21
22 // A printer collects the state during printing of a file or expression.
23 type printer struct {
24         bytes.Buffer           // output buffer
25         comment      []Comment // pending end-of-line comments
26         margin       int       // left margin (indent), a number of tabs
27 }
28
29 // printf prints to the buffer.
30 func (p *printer) printf(format string, args ...interface{}) {
31         fmt.Fprintf(p, format, args...)
32 }
33
34 // indent returns the position on the current line, in bytes, 0-indexed.
35 func (p *printer) indent() int {
36         b := p.Bytes()
37         n := 0
38         for n < len(b) && b[len(b)-1-n] != '\n' {
39                 n++
40         }
41         return n
42 }
43
44 // newline ends the current line, flushing end-of-line comments.
45 func (p *printer) newline() {
46         if len(p.comment) > 0 {
47                 p.printf(" ")
48                 for i, com := range p.comment {
49                         if i > 0 {
50                                 p.trim()
51                                 p.printf("\n")
52                                 for i := 0; i < p.margin; i++ {
53                                         p.printf("\t")
54                                 }
55                         }
56                         p.printf("%s", strings.TrimSpace(com.Token))
57                 }
58                 p.comment = p.comment[:0]
59         }
60
61         p.trim()
62         p.printf("\n")
63         for i := 0; i < p.margin; i++ {
64                 p.printf("\t")
65         }
66 }
67
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.
71         b := p.Bytes()
72         n := len(b)
73         for n > 0 && (b[n-1] == '\t' || b[n-1] == ' ') {
74                 n--
75         }
76         p.Truncate(n)
77 }
78
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))
83                 p.newline()
84         }
85
86         for i, stmt := range f.Stmt {
87                 switch x := stmt.(type) {
88                 case *CommentBlock:
89                         // comments already handled
90                         p.expr(x)
91
92                 default:
93                         p.expr(x)
94                         p.newline()
95                 }
96
97                 for _, com := range stmt.Comment().After {
98                         p.printf("%s", strings.TrimSpace(com.Token))
99                         p.newline()
100                 }
101
102                 if i+1 < len(f.Stmt) {
103                         p.newline()
104                 }
105         }
106 }
107
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.
113                 p.trim()
114                 if p.indent() > 0 {
115                         // There's other text on the line. Start a new line.
116                         p.printf("\n")
117                 }
118                 // Re-indent to margin.
119                 for i := 0; i < p.margin; i++ {
120                         p.printf("\t")
121                 }
122                 for _, com := range before {
123                         p.printf("%s", strings.TrimSpace(com.Token))
124                         p.newline()
125                 }
126         }
127
128         switch x := x.(type) {
129         default:
130                 panic(fmt.Errorf("printer: unexpected type %T", x))
131
132         case *CommentBlock:
133                 // done
134
135         case *LParen:
136                 p.printf("(")
137         case *RParen:
138                 p.printf(")")
139
140         case *Line:
141                 p.tokens(x.Token)
142
143         case *LineBlock:
144                 p.tokens(x.Token)
145                 p.printf(" ")
146                 p.expr(&x.LParen)
147                 p.margin++
148                 for _, l := range x.Line {
149                         p.newline()
150                         p.expr(l)
151                 }
152                 p.margin--
153                 p.newline()
154                 p.expr(&x.RParen)
155         }
156
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...)
160 }
161
162 func (p *printer) tokens(tokens []string) {
163         sep := ""
164         for _, t := range tokens {
165                 if t == "," || t == ")" || t == "]" || t == "}" {
166                         sep = ""
167                 }
168                 p.printf("%s%s", sep, t)
169                 sep = " "
170                 if t == "(" || t == "[" || t == "{" {
171                         sep = ""
172                 }
173         }
174 }