42
noExtraLinebreak pmode = 1 << iota
42
noExtraBlank pmode = 1 << iota // disables extra blank after /*-style comment
43
noExtraLinebreak // disables extra line break after /*-style comment
46
type commentInfo struct {
47
cindex int // current comment index
48
comment *ast.CommentGroup // = printer.comments[cindex]; or nil
49
commentOffset int // = printer.posFor(printer.comments[cindex].List[0].Pos()).Offset; or infinity
50
commentNewline bool // true if the comment group contains newlines
45
53
type printer struct {
46
54
// Configuration (does not change after initialization)
52
60
indent int // current indentation
53
61
mode pmode // current printer mode
54
62
impliedSemi bool // if set, a linebreak implies a semicolon
55
lastTok token.Token // the last token printed (token.ILLEGAL if it's whitespace)
63
lastTok token.Token // last token printed (token.ILLEGAL if it's whitespace)
64
prevOpen token.Token // previous non-brace "open" token (, [, or token.ILLEGAL
56
65
wsbuf []whiteSpace // delayed white space
61
70
// white space). If there's a difference and SourcePos is set in
62
71
// ConfigMode, //line comments are used in the output to restore
63
72
// original source positions for a reader.
64
pos token.Position // current position in AST (source) space
65
out token.Position // current position in output space
66
last token.Position // value of pos after calling writeString
73
pos token.Position // current position in AST (source) space
74
out token.Position // current position in output space
75
last token.Position // value of pos after calling writeString
76
linePtr *int // if set, record out.Line for the next token in *linePtr
68
78
// The list of all source comments, in order of appearance.
69
79
comments []*ast.CommentGroup // may be nil
70
cindex int // current comment index
71
80
useNodeComments bool // if not set, ignore lead and line comments of nodes
73
82
// Information about p.comments[p.cindex]; set up by nextComment.
74
comment *ast.CommentGroup // = p.comments[p.cindex]; or nil
75
commentOffset int // = p.posFor(p.comments[p.cindex].List[0].Pos()).Offset; or infinity
76
commentNewline bool // true if the comment group contains newlines
78
85
// Cache of already computed node sizes.
79
86
nodeSizes map[ast.Node]int
103
func (p *printer) internalError(msg ...interface{}) {
105
fmt.Print(p.pos.String() + ": ")
96
111
// commentsHaveNewline reports whether a list of comments belonging to
97
112
// an *ast.CommentGroup contains newlines. Because the position information
98
113
// may only be partially correct, we also have to read the comment text.
129
144
p.commentOffset = infinity
132
func (p *printer) internalError(msg ...interface{}) {
134
fmt.Print(p.pos.String() + ": ")
147
// commentBefore returns true iff the current comment group occurs
148
// before the next position in the source code and printing it does
149
// not introduce implicit semicolons.
151
func (p *printer) commentBefore(next token.Position) bool {
152
return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline)
155
// commentSizeBefore returns the estimated size of the
156
// comments on the same line before the next position.
158
func (p *printer) commentSizeBefore(next token.Position) int {
159
// save/restore current p.commentInfo (p.nextComment() modifies it)
160
defer func(info commentInfo) {
165
for p.commentBefore(next) {
166
for _, c := range p.comment.List {
174
// recordLine records the output line number for the next non-whitespace
175
// token in *linePtr. It is used to compute an accurate line number for a
176
// formatted construct, independent of pending (not yet emitted) whitespace
179
func (p *printer) recordLine(linePtr *int) {
183
// linesFrom returns the number of output lines between the current
184
// output line and the line argument, ignoring any pending (not yet
185
// emitted) whitespace or comments. It is used to compute an accurate
186
// size (in number of lines) for a formatted construct.
188
func (p *printer) linesFrom(line int) int {
189
return p.out.Line - line
140
192
func (p *printer) posFor(pos token.Pos) token.Position {
677
729
// if the last comment is a /*-style comment and the next item
678
// follows on the same line but is not a comma or a "closing"
679
// token, add an extra blank for separation
680
if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line && tok != token.COMMA &&
681
tok != token.RPAREN && tok != token.RBRACK && tok != token.RBRACE {
730
// follows on the same line but is not a comma, and not a "closing"
731
// token immediately following its corresponding "opening" token,
732
// add an extra blank for separation unless explicitly disabled
733
if p.mode&noExtraBlank == 0 &&
734
last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line &&
735
tok != token.COMMA &&
736
(tok != token.RPAREN || p.prevOpen == token.LPAREN) &&
737
(tok != token.RBRACK || p.prevOpen == token.LBRACK) {
682
738
p.writeByte(' ', 1)
684
740
// ensure that there is a line break after a //-style comment,
737
793
// shift remaining entries down
739
for ; n < len(p.wsbuf); n++ {
740
p.wsbuf[i] = p.wsbuf[n]
743
p.wsbuf = p.wsbuf[0:i]
794
l := copy(p.wsbuf, p.wsbuf[n:])
795
p.wsbuf = p.wsbuf[:l]
746
798
// ----------------------------------------------------------------------------
791
843
var impliedSemi bool // value for p.impliedSemi after this arg
845
// record previous opening token, if any
848
// ignore (white space)
849
case token.LPAREN, token.LBRACK:
850
p.prevOpen = p.lastTok
852
// other tokens followed any opening token
853
p.prevOpen = token.ILLEGAL
793
856
switch x := arg.(type) {
795
858
// toggle printer mode
965
// the next token starts now - record its line number if requested
966
if p.linePtr != nil {
967
*p.linePtr = p.out.Line
902
971
p.writeString(next, data, isLit)
903
972
p.impliedSemi = impliedSemi
907
// commentBefore returns true iff the current comment group occurs
908
// before the next position in the source code and printing it does
909
// not introduce implicit semicolons.
911
func (p *printer) commentBefore(next token.Position) (result bool) {
912
return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline)
915
976
// flush prints any pending comments and whitespace occurring textually
916
977
// before the position of the next token tok. The flush result indicates
917
978
// if a newline was written or if a formfeed was dropped from the whitespace