1
2
3
4
5
6
7
8
9 package printer
10
11 import (
12 "go/ast"
13 "go/token"
14 "math"
15 "strconv"
16 "strings"
17 "unicode"
18 "unicode/utf8"
19 )
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (nbreaks int) {
47 n := max(nlimit(line-p.pos.Line), min)
48 if n > 0 {
49 p.print(ws)
50 if newSection {
51 p.print(formfeed)
52 n--
53 nbreaks = 2
54 }
55 nbreaks += n
56 for ; n > 0; n-- {
57 p.print(newline)
58 }
59 }
60 return
61 }
62
63
64
65
66
67 func (p *printer) setComment(g *ast.CommentGroup) {
68 if g == nil || !p.useNodeComments {
69 return
70 }
71 if p.comments == nil {
72
73 p.comments = make([]*ast.CommentGroup, 1)
74 } else if p.cindex < len(p.comments) {
75
76
77
78 p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
79 p.comments = p.comments[0:1]
80
81 p.internalError("setComment found pending comments")
82 }
83 p.comments[0] = g
84 p.cindex = 0
85
86
87
88
89 if p.commentOffset == infinity {
90 p.nextComment()
91 }
92 }
93
94 type exprListMode uint
95
96 const (
97 commaTerm exprListMode = 1 << iota
98 noIndent
99 )
100
101
102
103 func (p *printer) identList(list []*ast.Ident, indent bool) {
104
105 xlist := make([]ast.Expr, len(list))
106 for i, x := range list {
107 xlist[i] = x
108 }
109 var mode exprListMode
110 if !indent {
111 mode = noIndent
112 }
113 p.exprList(token.NoPos, xlist, 1, mode, token.NoPos, false)
114 }
115
116 const filteredMsg = "contains filtered or unexported fields"
117
118
119
120
121
122
123
124
125
126 func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos, isIncomplete bool) {
127 if len(list) == 0 {
128 if isIncomplete {
129 prev := p.posFor(prev0)
130 next := p.posFor(next0)
131 if prev.IsValid() && prev.Line == next.Line {
132 p.print("/* " + filteredMsg + " */")
133 } else {
134 p.print(newline)
135 p.print(indent, "// "+filteredMsg, unindent, newline)
136 }
137 }
138 return
139 }
140
141 prev := p.posFor(prev0)
142 next := p.posFor(next0)
143 line := p.lineFor(list[0].Pos())
144 endLine := p.lineFor(list[len(list)-1].End())
145
146 if prev.IsValid() && prev.Line == line && line == endLine {
147
148 for i, x := range list {
149 if i > 0 {
150
151
152 p.setPos(x.Pos())
153 p.print(token.COMMA, blank)
154 }
155 p.expr0(x, depth)
156 }
157 if isIncomplete {
158 p.print(token.COMMA, blank, "/* "+filteredMsg+" */")
159 }
160 return
161 }
162
163
164
165
166
167
168 ws := ignore
169 if mode&noIndent == 0 {
170 ws = indent
171 }
172
173
174
175 prevBreak := -1
176 if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) > 0 {
177 ws = ignore
178 prevBreak = 0
179 }
180
181
182 size := 0
183
184
185
186
187
188 lnsum := 0.0
189 count := 0
190
191
192 prevLine := prev.Line
193 for i, x := range list {
194 line = p.lineFor(x.Pos())
195
196
197
198
199
200
201 useFF := true
202
203
204
205
206
207 prevSize := size
208 const infinity = 1e6
209 size = p.nodeSize(x, infinity)
210 pair, isPair := x.(*ast.KeyValueExpr)
211 if size <= infinity && prev.IsValid() && next.IsValid() {
212
213 if isPair {
214 size = p.nodeSize(pair.Key, infinity)
215 }
216 } else {
217
218 size = 0
219 }
220
221
222
223
224
225
226 if prevSize > 0 && size > 0 {
227 const smallSize = 40
228 if count == 0 || prevSize <= smallSize && size <= smallSize {
229 useFF = false
230 } else {
231 const r = 2.5
232 geomean := math.Exp(lnsum / float64(count))
233 ratio := float64(size) / geomean
234 useFF = r*ratio <= 1 || r <= ratio
235 }
236 }
237
238 needsLinebreak := 0 < prevLine && prevLine < line
239 if i > 0 {
240
241
242
243 if !needsLinebreak {
244 p.setPos(x.Pos())
245 }
246 p.print(token.COMMA)
247 needsBlank := true
248 if needsLinebreak {
249
250
251
252 nbreaks := p.linebreak(line, 0, ws, useFF || prevBreak+1 < i)
253 if nbreaks > 0 {
254 ws = ignore
255 prevBreak = i
256 needsBlank = false
257 }
258
259
260
261
262 if nbreaks > 1 {
263 lnsum = 0
264 count = 0
265 }
266 }
267 if needsBlank {
268 p.print(blank)
269 }
270 }
271
272 if len(list) > 1 && isPair && size > 0 && needsLinebreak {
273
274
275
276
277
278 p.expr(pair.Key)
279 p.setPos(pair.Colon)
280 p.print(token.COLON, vtab)
281 p.expr(pair.Value)
282 } else {
283 p.expr0(x, depth)
284 }
285
286 if size > 0 {
287 lnsum += math.Log(float64(size))
288 count++
289 }
290
291 prevLine = line
292 }
293
294 if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
295
296 p.print(token.COMMA)
297 if isIncomplete {
298 p.print(newline)
299 p.print("// " + filteredMsg)
300 }
301 if ws == ignore && mode&noIndent == 0 {
302
303 p.print(unindent)
304 }
305 p.print(formfeed)
306 return
307 }
308
309 if isIncomplete {
310 p.print(token.COMMA, newline)
311 p.print("// "+filteredMsg, newline)
312 }
313
314 if ws == ignore && mode&noIndent == 0 {
315
316 p.print(unindent)
317 }
318 }
319
320 type paramMode int
321
322 const (
323 funcParam paramMode = iota
324 funcTParam
325 typeTParam
326 )
327
328 func (p *printer) parameters(fields *ast.FieldList, mode paramMode) {
329 openTok, closeTok := token.LPAREN, token.RPAREN
330 if mode != funcParam {
331 openTok, closeTok = token.LBRACK, token.RBRACK
332 }
333 p.setPos(fields.Opening)
334 p.print(openTok)
335 if len(fields.List) > 0 {
336 prevLine := p.lineFor(fields.Opening)
337 ws := indent
338 for i, par := range fields.List {
339
340
341
342 parLineBeg := p.lineFor(par.Pos())
343 parLineEnd := p.lineFor(par.End())
344
345 needsLinebreak := 0 < prevLine && prevLine < parLineBeg
346 if i > 0 {
347
348
349
350 if !needsLinebreak {
351 p.setPos(par.Pos())
352 }
353 p.print(token.COMMA)
354 }
355
356 if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) > 0 {
357
358 ws = ignore
359 } else if i > 0 {
360 p.print(blank)
361 }
362
363 if len(par.Names) > 0 {
364
365
366
367
368
369
370 p.identList(par.Names, ws == indent)
371 p.print(blank)
372 }
373
374 p.expr(stripParensAlways(par.Type))
375 prevLine = parLineEnd
376 }
377
378
379
380 if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
381 p.print(token.COMMA)
382 p.linebreak(closing, 0, ignore, true)
383 } else if mode == typeTParam && fields.NumFields() == 1 && combinesWithName(fields.List[0].Type) {
384
385
386
387
388 p.print(token.COMMA)
389 }
390
391
392 if ws == ignore {
393 p.print(unindent)
394 }
395 }
396
397 p.setPos(fields.Closing)
398 p.print(closeTok)
399 }
400
401
402
403
404
405
406 func combinesWithName(x ast.Expr) bool {
407 switch x := x.(type) {
408 case *ast.StarExpr:
409
410 return !isTypeElem(x.X)
411 case *ast.BinaryExpr:
412 return combinesWithName(x.X) && !isTypeElem(x.Y)
413 case *ast.ParenExpr:
414
415
416 panic("unexpected parenthesized expression")
417 }
418 return false
419 }
420
421
422
423 func isTypeElem(x ast.Expr) bool {
424 switch x := x.(type) {
425 case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
426 return true
427 case *ast.UnaryExpr:
428 return x.Op == token.TILDE
429 case *ast.BinaryExpr:
430 return isTypeElem(x.X) || isTypeElem(x.Y)
431 case *ast.ParenExpr:
432 return isTypeElem(x.X)
433 }
434 return false
435 }
436
437 func (p *printer) signature(sig *ast.FuncType) {
438 if sig.TypeParams != nil {
439 p.parameters(sig.TypeParams, funcTParam)
440 }
441 if sig.Params != nil {
442 p.parameters(sig.Params, funcParam)
443 } else {
444 p.print(token.LPAREN, token.RPAREN)
445 }
446 res := sig.Results
447 n := res.NumFields()
448 if n > 0 {
449
450 p.print(blank)
451 if n == 1 && res.List[0].Names == nil {
452
453 p.expr(stripParensAlways(res.List[0].Type))
454 return
455 }
456 p.parameters(res, funcParam)
457 }
458 }
459
460 func identListSize(list []*ast.Ident, maxSize int) (size int) {
461 for i, x := range list {
462 if i > 0 {
463 size += len(", ")
464 }
465 size += utf8.RuneCountInString(x.Name)
466 if size >= maxSize {
467 break
468 }
469 }
470 return
471 }
472
473 func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
474 if len(list) != 1 {
475 return false
476 }
477 f := list[0]
478 if f.Tag != nil || f.Comment != nil {
479 return false
480 }
481
482 const maxSize = 30
483 namesSize := identListSize(f.Names, maxSize)
484 if namesSize > 0 {
485 namesSize = 1
486 }
487 typeSize := p.nodeSize(f.Type, maxSize)
488 return namesSize+typeSize <= maxSize
489 }
490
491 func (p *printer) setLineComment(text string) {
492 p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}})
493 }
494
495 func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
496 lbrace := fields.Opening
497 list := fields.List
498 rbrace := fields.Closing
499 hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
500 srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
501
502 if !hasComments && srcIsOneLine {
503
504 if len(list) == 0 {
505
506 p.setPos(lbrace)
507 p.print(token.LBRACE)
508 p.setPos(rbrace)
509 p.print(token.RBRACE)
510 return
511 } else if p.isOneLineFieldList(list) {
512
513
514 p.setPos(lbrace)
515 p.print(token.LBRACE, blank)
516 f := list[0]
517 if isStruct {
518 for i, x := range f.Names {
519 if i > 0 {
520
521 p.print(token.COMMA, blank)
522 }
523 p.expr(x)
524 }
525 if len(f.Names) > 0 {
526 p.print(blank)
527 }
528 p.expr(f.Type)
529 } else {
530 if len(f.Names) > 0 {
531 name := f.Names[0]
532 p.expr(name)
533 p.signature(f.Type.(*ast.FuncType))
534 } else {
535
536 p.expr(f.Type)
537 }
538 }
539 p.print(blank)
540 p.setPos(rbrace)
541 p.print(token.RBRACE)
542 return
543 }
544 }
545
546
547 p.print(blank)
548 p.setPos(lbrace)
549 p.print(token.LBRACE, indent)
550 if hasComments || len(list) > 0 {
551 p.print(formfeed)
552 }
553
554 if isStruct {
555
556 sep := vtab
557 if len(list) == 1 {
558 sep = blank
559 }
560 var line int
561 for i, f := range list {
562 if i > 0 {
563 p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0)
564 }
565 extraTabs := 0
566 p.setComment(f.Doc)
567 p.recordLine(&line)
568 if len(f.Names) > 0 {
569
570 p.identList(f.Names, false)
571 p.print(sep)
572 p.expr(f.Type)
573 extraTabs = 1
574 } else {
575
576 p.expr(f.Type)
577 extraTabs = 2
578 }
579 if f.Tag != nil {
580 if len(f.Names) > 0 && sep == vtab {
581 p.print(sep)
582 }
583 p.print(sep)
584 p.expr(f.Tag)
585 extraTabs = 0
586 }
587 if f.Comment != nil {
588 for ; extraTabs > 0; extraTabs-- {
589 p.print(sep)
590 }
591 p.setComment(f.Comment)
592 }
593 }
594 if isIncomplete {
595 if len(list) > 0 {
596 p.print(formfeed)
597 }
598 p.flush(p.posFor(rbrace), token.RBRACE)
599 p.setLineComment("// " + filteredMsg)
600 }
601
602 } else {
603
604 var line int
605 var prev *ast.Ident
606 for i, f := range list {
607 var name *ast.Ident
608 if len(f.Names) > 0 {
609 name = f.Names[0]
610 }
611 if i > 0 {
612
613
614
615 min := 1
616 if prev != nil && name == prev {
617 min = 0
618 }
619 p.linebreak(p.lineFor(f.Pos()), min, ignore, p.linesFrom(line) > 0)
620 }
621 p.setComment(f.Doc)
622 p.recordLine(&line)
623 if name != nil {
624
625 p.expr(name)
626 p.signature(f.Type.(*ast.FuncType))
627 prev = nil
628 } else {
629
630 p.expr(f.Type)
631 prev = nil
632 }
633 p.setComment(f.Comment)
634 }
635 if isIncomplete {
636 if len(list) > 0 {
637 p.print(formfeed)
638 }
639 p.flush(p.posFor(rbrace), token.RBRACE)
640 p.setLineComment("// contains filtered or unexported methods")
641 }
642
643 }
644 p.print(unindent, formfeed)
645 p.setPos(rbrace)
646 p.print(token.RBRACE)
647 }
648
649
650
651
652 func walkBinary(e *ast.BinaryExpr) (has4, has5 bool, maxProblem int) {
653 switch e.Op.Precedence() {
654 case 4:
655 has4 = true
656 case 5:
657 has5 = true
658 }
659
660 switch l := e.X.(type) {
661 case *ast.BinaryExpr:
662 if l.Op.Precedence() < e.Op.Precedence() {
663
664
665 break
666 }
667 h4, h5, mp := walkBinary(l)
668 has4 = has4 || h4
669 has5 = has5 || h5
670 maxProblem = max(maxProblem, mp)
671 }
672
673 switch r := e.Y.(type) {
674 case *ast.BinaryExpr:
675 if r.Op.Precedence() <= e.Op.Precedence() {
676
677
678 break
679 }
680 h4, h5, mp := walkBinary(r)
681 has4 = has4 || h4
682 has5 = has5 || h5
683 maxProblem = max(maxProblem, mp)
684
685 case *ast.StarExpr:
686 if e.Op == token.QUO {
687 maxProblem = 5
688 }
689
690 case *ast.UnaryExpr:
691 switch e.Op.String() + r.Op.String() {
692 case "/*", "&&", "&^":
693 maxProblem = 5
694 case "++", "--":
695 maxProblem = max(maxProblem, 4)
696 }
697 }
698 return
699 }
700
701 func cutoff(e *ast.BinaryExpr, depth int) int {
702 has4, has5, maxProblem := walkBinary(e)
703 if maxProblem > 0 {
704 return maxProblem + 1
705 }
706 if has4 && has5 {
707 if depth == 1 {
708 return 5
709 }
710 return 4
711 }
712 if depth == 1 {
713 return 6
714 }
715 return 4
716 }
717
718 func diffPrec(expr ast.Expr, prec int) int {
719 x, ok := expr.(*ast.BinaryExpr)
720 if !ok || prec != x.Op.Precedence() {
721 return 1
722 }
723 return 0
724 }
725
726 func reduceDepth(depth int) int {
727 depth--
728 if depth < 1 {
729 depth = 1
730 }
731 return depth
732 }
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770 func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
771 prec := x.Op.Precedence()
772 if prec < prec1 {
773
774
775
776 p.print(token.LPAREN)
777 p.expr0(x, reduceDepth(depth))
778 p.print(token.RPAREN)
779 return
780 }
781
782 printBlank := prec < cutoff
783
784 ws := indent
785 p.expr1(x.X, prec, depth+diffPrec(x.X, prec))
786 if printBlank {
787 p.print(blank)
788 }
789 xline := p.pos.Line
790 yline := p.lineFor(x.Y.Pos())
791 p.setPos(x.OpPos)
792 p.print(x.Op)
793 if xline != yline && xline > 0 && yline > 0 {
794
795
796 if p.linebreak(yline, 1, ws, true) > 0 {
797 ws = ignore
798 printBlank = false
799 }
800 }
801 if printBlank {
802 p.print(blank)
803 }
804 p.expr1(x.Y, prec+1, depth+1)
805 if ws == ignore {
806 p.print(unindent)
807 }
808 }
809
810 func isBinary(expr ast.Expr) bool {
811 _, ok := expr.(*ast.BinaryExpr)
812 return ok
813 }
814
815 func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
816 p.setPos(expr.Pos())
817
818 switch x := expr.(type) {
819 case *ast.BadExpr:
820 p.print("BadExpr")
821
822 case *ast.Ident:
823 p.print(x)
824
825 case *ast.BinaryExpr:
826 if depth < 1 {
827 p.internalError("depth < 1:", depth)
828 depth = 1
829 }
830 p.binaryExpr(x, prec1, cutoff(x, depth), depth)
831
832 case *ast.KeyValueExpr:
833 p.expr(x.Key)
834 p.setPos(x.Colon)
835 p.print(token.COLON, blank)
836 p.expr(x.Value)
837
838 case *ast.StarExpr:
839 const prec = token.UnaryPrec
840 if prec < prec1 {
841
842 p.print(token.LPAREN)
843 p.print(token.MUL)
844 p.expr(x.X)
845 p.print(token.RPAREN)
846 } else {
847
848 p.print(token.MUL)
849 p.expr(x.X)
850 }
851
852 case *ast.UnaryExpr:
853 const prec = token.UnaryPrec
854 if prec < prec1 {
855
856 p.print(token.LPAREN)
857 p.expr(x)
858 p.print(token.RPAREN)
859 } else {
860
861 p.print(x.Op)
862 if x.Op == token.RANGE {
863
864 p.print(blank)
865 }
866 p.expr1(x.X, prec, depth)
867 }
868
869 case *ast.BasicLit:
870 if p.Config.Mode&normalizeNumbers != 0 {
871 x = normalizedNumber(x)
872 }
873 p.print(x)
874
875 case *ast.FuncLit:
876 p.setPos(x.Type.Pos())
877 p.print(token.FUNC)
878
879 startCol := p.out.Column - len("func")
880 p.signature(x.Type)
881 p.funcBody(p.distanceFrom(x.Type.Pos(), startCol), blank, x.Body)
882
883 case *ast.ParenExpr:
884 if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
885
886
887 p.expr0(x.X, depth)
888 } else {
889 p.print(token.LPAREN)
890 p.expr0(x.X, reduceDepth(depth))
891 p.setPos(x.Rparen)
892 p.print(token.RPAREN)
893 }
894
895 case *ast.SelectorExpr:
896 p.selectorExpr(x, depth, false)
897
898 case *ast.TypeAssertExpr:
899 p.expr1(x.X, token.HighestPrec, depth)
900 p.print(token.PERIOD)
901 p.setPos(x.Lparen)
902 p.print(token.LPAREN)
903 if x.Type != nil {
904 p.expr(x.Type)
905 } else {
906 p.print(token.TYPE)
907 }
908 p.setPos(x.Rparen)
909 p.print(token.RPAREN)
910
911 case *ast.IndexExpr:
912
913 p.expr1(x.X, token.HighestPrec, 1)
914 p.setPos(x.Lbrack)
915 p.print(token.LBRACK)
916 p.expr0(x.Index, depth+1)
917 p.setPos(x.Rbrack)
918 p.print(token.RBRACK)
919
920 case *ast.IndexListExpr:
921
922
923 p.expr1(x.X, token.HighestPrec, 1)
924 p.setPos(x.Lbrack)
925 p.print(token.LBRACK)
926 p.exprList(x.Lbrack, x.Indices, depth+1, commaTerm, x.Rbrack, false)
927 p.setPos(x.Rbrack)
928 p.print(token.RBRACK)
929
930 case *ast.SliceExpr:
931
932 p.expr1(x.X, token.HighestPrec, 1)
933 p.setPos(x.Lbrack)
934 p.print(token.LBRACK)
935 indices := []ast.Expr{x.Low, x.High}
936 if x.Max != nil {
937 indices = append(indices, x.Max)
938 }
939
940 var needsBlanks bool
941 if depth <= 1 {
942 var indexCount int
943 var hasBinaries bool
944 for _, x := range indices {
945 if x != nil {
946 indexCount++
947 if isBinary(x) {
948 hasBinaries = true
949 }
950 }
951 }
952 if indexCount > 1 && hasBinaries {
953 needsBlanks = true
954 }
955 }
956 for i, x := range indices {
957 if i > 0 {
958 if indices[i-1] != nil && needsBlanks {
959 p.print(blank)
960 }
961 p.print(token.COLON)
962 if x != nil && needsBlanks {
963 p.print(blank)
964 }
965 }
966 if x != nil {
967 p.expr0(x, depth+1)
968 }
969 }
970 p.setPos(x.Rbrack)
971 p.print(token.RBRACK)
972
973 case *ast.CallExpr:
974 if len(x.Args) > 1 {
975 depth++
976 }
977
978
979
980 paren := false
981 switch t := x.Fun.(type) {
982 case *ast.FuncType:
983 paren = true
984 case *ast.ChanType:
985 paren = t.Dir == ast.RECV
986 }
987 if paren {
988 p.print(token.LPAREN)
989 }
990 wasIndented := p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
991 if paren {
992 p.print(token.RPAREN)
993 }
994
995 p.setPos(x.Lparen)
996 p.print(token.LPAREN)
997 if x.Ellipsis.IsValid() {
998 p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
999 p.setPos(x.Ellipsis)
1000 p.print(token.ELLIPSIS)
1001 if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
1002 p.print(token.COMMA, formfeed)
1003 }
1004 } else {
1005 p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
1006 }
1007 p.setPos(x.Rparen)
1008 p.print(token.RPAREN)
1009 if wasIndented {
1010 p.print(unindent)
1011 }
1012
1013 case *ast.CompositeLit:
1014
1015 if x.Type != nil {
1016 p.expr1(x.Type, token.HighestPrec, depth)
1017 }
1018 p.level++
1019 p.setPos(x.Lbrace)
1020 p.print(token.LBRACE)
1021 p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace, x.Incomplete)
1022
1023
1024
1025 mode := noExtraLinebreak
1026
1027
1028 if len(x.Elts) > 0 {
1029 mode |= noExtraBlank
1030 }
1031
1032
1033 p.print(indent, unindent, mode)
1034 p.setPos(x.Rbrace)
1035 p.print(token.RBRACE, mode)
1036 p.level--
1037
1038 case *ast.Ellipsis:
1039 p.print(token.ELLIPSIS)
1040 if x.Elt != nil {
1041 p.expr(x.Elt)
1042 }
1043
1044 case *ast.ArrayType:
1045 p.print(token.LBRACK)
1046 if x.Len != nil {
1047 p.expr(x.Len)
1048 }
1049 p.print(token.RBRACK)
1050 p.expr(x.Elt)
1051
1052 case *ast.StructType:
1053 p.print(token.STRUCT)
1054 p.fieldList(x.Fields, true, x.Incomplete)
1055
1056 case *ast.FuncType:
1057 p.print(token.FUNC)
1058 p.signature(x)
1059
1060 case *ast.InterfaceType:
1061 p.print(token.INTERFACE)
1062 p.fieldList(x.Methods, false, x.Incomplete)
1063
1064 case *ast.MapType:
1065 p.print(token.MAP, token.LBRACK)
1066 p.expr(x.Key)
1067 p.print(token.RBRACK)
1068 p.expr(x.Value)
1069
1070 case *ast.ChanType:
1071 switch x.Dir {
1072 case ast.SEND | ast.RECV:
1073 p.print(token.CHAN)
1074 case ast.RECV:
1075 p.print(token.ARROW, token.CHAN)
1076 case ast.SEND:
1077 p.print(token.CHAN)
1078 p.setPos(x.Arrow)
1079 p.print(token.ARROW)
1080 }
1081 p.print(blank)
1082 p.expr(x.Value)
1083
1084 default:
1085 panic("unreachable")
1086 }
1087 }
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 func normalizedNumber(lit *ast.BasicLit) *ast.BasicLit {
1098 if lit.Kind != token.INT && lit.Kind != token.FLOAT && lit.Kind != token.IMAG {
1099 return lit
1100 }
1101 if len(lit.Value) < 2 {
1102 return lit
1103 }
1104
1105
1106
1107
1108 x := lit.Value
1109 switch x[:2] {
1110 default:
1111
1112 if i := strings.LastIndexByte(x, 'E'); i >= 0 {
1113 x = x[:i] + "e" + x[i+1:]
1114 break
1115 }
1116
1117 if x[len(x)-1] == 'i' && !strings.ContainsAny(x, ".e") {
1118 x = strings.TrimLeft(x, "0_")
1119 if x == "i" {
1120 x = "0i"
1121 }
1122 }
1123 case "0X":
1124 x = "0x" + x[2:]
1125
1126 if i := strings.LastIndexByte(x, 'P'); i >= 0 {
1127 x = x[:i] + "p" + x[i+1:]
1128 }
1129 case "0x":
1130
1131 i := strings.LastIndexByte(x, 'P')
1132 if i == -1 {
1133 return lit
1134 }
1135 x = x[:i] + "p" + x[i+1:]
1136 case "0O":
1137 x = "0o" + x[2:]
1138 case "0o":
1139 return lit
1140 case "0B":
1141 x = "0b" + x[2:]
1142 case "0b":
1143 return lit
1144 }
1145
1146 return &ast.BasicLit{ValuePos: lit.ValuePos, Kind: lit.Kind, Value: x}
1147 }
1148
1149 func (p *printer) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool {
1150 if x, ok := expr.(*ast.SelectorExpr); ok {
1151 return p.selectorExpr(x, depth, true)
1152 }
1153 p.expr1(expr, prec1, depth)
1154 return false
1155 }
1156
1157
1158
1159 func (p *printer) selectorExpr(x *ast.SelectorExpr, depth int, isMethod bool) bool {
1160 p.expr1(x.X, token.HighestPrec, depth)
1161 p.print(token.PERIOD)
1162 if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
1163 p.print(indent, newline)
1164 p.setPos(x.Sel.Pos())
1165 p.print(x.Sel)
1166 if !isMethod {
1167 p.print(unindent)
1168 }
1169 return true
1170 }
1171 p.setPos(x.Sel.Pos())
1172 p.print(x.Sel)
1173 return false
1174 }
1175
1176 func (p *printer) expr0(x ast.Expr, depth int) {
1177 p.expr1(x, token.LowestPrec, depth)
1178 }
1179
1180 func (p *printer) expr(x ast.Expr) {
1181 const depth = 1
1182 p.expr1(x, token.LowestPrec, depth)
1183 }
1184
1185
1186
1187
1188
1189
1190
1191 func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
1192 if nindent > 0 {
1193 p.print(indent)
1194 }
1195 var line int
1196 i := 0
1197 for _, s := range list {
1198
1199 if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty {
1200
1201
1202 if len(p.output) > 0 {
1203
1204
1205 p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || p.linesFrom(line) > 0)
1206 }
1207 p.recordLine(&line)
1208 p.stmt(s, nextIsRBrace && i == len(list)-1)
1209
1210
1211
1212 for t := s; ; {
1213 lt, _ := t.(*ast.LabeledStmt)
1214 if lt == nil {
1215 break
1216 }
1217 line++
1218 t = lt.Stmt
1219 }
1220 i++
1221 }
1222 }
1223 if nindent > 0 {
1224 p.print(unindent)
1225 }
1226 }
1227
1228
1229 func (p *printer) block(b *ast.BlockStmt, nindent int) {
1230 p.setPos(b.Lbrace)
1231 p.print(token.LBRACE)
1232 p.stmtList(b.List, nindent, true)
1233 p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
1234 p.setPos(b.Rbrace)
1235 p.print(token.RBRACE)
1236 }
1237
1238 func isTypeName(x ast.Expr) bool {
1239 switch t := x.(type) {
1240 case *ast.Ident:
1241 return true
1242 case *ast.SelectorExpr:
1243 return isTypeName(t.X)
1244 }
1245 return false
1246 }
1247
1248 func stripParens(x ast.Expr) ast.Expr {
1249 if px, strip := x.(*ast.ParenExpr); strip {
1250
1251
1252
1253 ast.Inspect(px.X, func(node ast.Node) bool {
1254 switch x := node.(type) {
1255 case *ast.ParenExpr:
1256
1257 return false
1258 case *ast.CompositeLit:
1259 if isTypeName(x.Type) {
1260 strip = false
1261 }
1262 return false
1263 }
1264
1265 return true
1266 })
1267 if strip {
1268 return stripParens(px.X)
1269 }
1270 }
1271 return x
1272 }
1273
1274 func stripParensAlways(x ast.Expr) ast.Expr {
1275 if x, ok := x.(*ast.ParenExpr); ok {
1276 return stripParensAlways(x.X)
1277 }
1278 return x
1279 }
1280
1281 func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) {
1282 p.print(blank)
1283 needsBlank := false
1284 if init == nil && post == nil {
1285
1286 if expr != nil {
1287 p.expr(stripParens(expr))
1288 needsBlank = true
1289 }
1290 } else {
1291
1292
1293 if init != nil {
1294 p.stmt(init, false)
1295 }
1296 p.print(token.SEMICOLON, blank)
1297 if expr != nil {
1298 p.expr(stripParens(expr))
1299 needsBlank = true
1300 }
1301 if isForStmt {
1302 p.print(token.SEMICOLON, blank)
1303 needsBlank = false
1304 if post != nil {
1305 p.stmt(post, false)
1306 needsBlank = true
1307 }
1308 }
1309 }
1310 if needsBlank {
1311 p.print(blank)
1312 }
1313 }
1314
1315
1316
1317
1318 func (p *printer) indentList(list []ast.Expr) bool {
1319
1320
1321
1322 if len(list) >= 2 {
1323 var b = p.lineFor(list[0].Pos())
1324 var e = p.lineFor(list[len(list)-1].End())
1325 if 0 < b && b < e {
1326
1327 n := 0
1328 line := b
1329 for _, x := range list {
1330 xb := p.lineFor(x.Pos())
1331 xe := p.lineFor(x.End())
1332 if line < xb {
1333
1334
1335 return true
1336 }
1337 if xb < xe {
1338
1339 n++
1340 }
1341 line = xe
1342 }
1343 return n > 1
1344 }
1345 }
1346 return false
1347 }
1348
1349 func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
1350 p.setPos(stmt.Pos())
1351
1352 switch s := stmt.(type) {
1353 case *ast.BadStmt:
1354 p.print("BadStmt")
1355
1356 case *ast.DeclStmt:
1357 p.decl(s.Decl)
1358
1359 case *ast.EmptyStmt:
1360
1361
1362 case *ast.LabeledStmt:
1363
1364
1365
1366 p.print(unindent)
1367 p.expr(s.Label)
1368 p.setPos(s.Colon)
1369 p.print(token.COLON, indent)
1370 if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
1371 if !nextIsRBrace {
1372 p.print(newline)
1373 p.setPos(e.Pos())
1374 p.print(token.SEMICOLON)
1375 break
1376 }
1377 } else {
1378 p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
1379 }
1380 p.stmt(s.Stmt, nextIsRBrace)
1381
1382 case *ast.ExprStmt:
1383 const depth = 1
1384 p.expr0(s.X, depth)
1385
1386 case *ast.SendStmt:
1387 const depth = 1
1388 p.expr0(s.Chan, depth)
1389 p.print(blank)
1390 p.setPos(s.Arrow)
1391 p.print(token.ARROW, blank)
1392 p.expr0(s.Value, depth)
1393
1394 case *ast.IncDecStmt:
1395 const depth = 1
1396 p.expr0(s.X, depth+1)
1397 p.setPos(s.TokPos)
1398 p.print(s.Tok)
1399
1400 case *ast.AssignStmt:
1401 var depth = 1
1402 if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
1403 depth++
1404 }
1405 p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos, false)
1406 p.print(blank)
1407 p.setPos(s.TokPos)
1408 p.print(s.Tok, blank)
1409 p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos, false)
1410
1411 case *ast.GoStmt:
1412 p.print(token.GO, blank)
1413 p.expr(s.Call)
1414
1415 case *ast.DeferStmt:
1416 p.print(token.DEFER, blank)
1417 p.expr(s.Call)
1418
1419 case *ast.ReturnStmt:
1420 p.print(token.RETURN)
1421 if s.Results != nil {
1422 p.print(blank)
1423
1424
1425
1426
1427
1428 if p.indentList(s.Results) {
1429 p.print(indent)
1430
1431
1432 p.exprList(token.NoPos, s.Results, 1, noIndent, token.NoPos, false)
1433 p.print(unindent)
1434 } else {
1435 p.exprList(token.NoPos, s.Results, 1, 0, token.NoPos, false)
1436 }
1437 }
1438
1439 case *ast.BranchStmt:
1440 p.print(s.Tok)
1441 if s.Label != nil {
1442 p.print(blank)
1443 p.expr(s.Label)
1444 }
1445
1446 case *ast.BlockStmt:
1447 p.block(s, 1)
1448
1449 case *ast.IfStmt:
1450 p.print(token.IF)
1451 p.controlClause(false, s.Init, s.Cond, nil)
1452 p.block(s.Body, 1)
1453 if s.Else != nil {
1454 p.print(blank, token.ELSE, blank)
1455 switch s.Else.(type) {
1456 case *ast.BlockStmt, *ast.IfStmt:
1457 p.stmt(s.Else, nextIsRBrace)
1458 default:
1459
1460
1461
1462 p.print(token.LBRACE, indent, formfeed)
1463 p.stmt(s.Else, true)
1464 p.print(unindent, formfeed, token.RBRACE)
1465 }
1466 }
1467
1468 case *ast.CaseClause:
1469 if s.List != nil {
1470 p.print(token.CASE, blank)
1471 p.exprList(s.Pos(), s.List, 1, 0, s.Colon, false)
1472 } else {
1473 p.print(token.DEFAULT)
1474 }
1475 p.setPos(s.Colon)
1476 p.print(token.COLON)
1477 p.stmtList(s.Body, 1, nextIsRBrace)
1478
1479 case *ast.SwitchStmt:
1480 p.print(token.SWITCH)
1481 p.controlClause(false, s.Init, s.Tag, nil)
1482 p.block(s.Body, 0)
1483
1484 case *ast.TypeSwitchStmt:
1485 p.print(token.SWITCH)
1486 if s.Init != nil {
1487 p.print(blank)
1488 p.stmt(s.Init, false)
1489 p.print(token.SEMICOLON)
1490 }
1491 p.print(blank)
1492 p.stmt(s.Assign, false)
1493 p.print(blank)
1494 p.block(s.Body, 0)
1495
1496 case *ast.CommClause:
1497 if s.Comm != nil {
1498 p.print(token.CASE, blank)
1499 p.stmt(s.Comm, false)
1500 } else {
1501 p.print(token.DEFAULT)
1502 }
1503 p.setPos(s.Colon)
1504 p.print(token.COLON)
1505 p.stmtList(s.Body, 1, nextIsRBrace)
1506
1507 case *ast.SelectStmt:
1508 p.print(token.SELECT, blank)
1509 body := s.Body
1510 if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
1511
1512 p.setPos(body.Lbrace)
1513 p.print(token.LBRACE)
1514 p.setPos(body.Rbrace)
1515 p.print(token.RBRACE)
1516 } else {
1517 p.block(body, 0)
1518 }
1519
1520 case *ast.ForStmt:
1521 p.print(token.FOR)
1522 p.controlClause(true, s.Init, s.Cond, s.Post)
1523 p.block(s.Body, 1)
1524
1525 case *ast.RangeStmt:
1526 p.print(token.FOR, blank)
1527 if s.Key != nil {
1528 p.expr(s.Key)
1529 if s.Value != nil {
1530
1531
1532 p.setPos(s.Value.Pos())
1533 p.print(token.COMMA, blank)
1534 p.expr(s.Value)
1535 }
1536 p.print(blank)
1537 p.setPos(s.TokPos)
1538 p.print(s.Tok, blank)
1539 }
1540 p.print(token.RANGE, blank)
1541 p.expr(stripParens(s.X))
1542 p.print(blank)
1543 p.block(s.Body, 1)
1544
1545 default:
1546 panic("unreachable")
1547 }
1548 }
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577 func keepTypeColumn(specs []ast.Spec) []bool {
1578 m := make([]bool, len(specs))
1579
1580 populate := func(i, j int, keepType bool) {
1581 if keepType {
1582 for ; i < j; i++ {
1583 m[i] = true
1584 }
1585 }
1586 }
1587
1588 i0 := -1
1589 var keepType bool
1590 for i, s := range specs {
1591 t := s.(*ast.ValueSpec)
1592 if t.Values != nil {
1593 if i0 < 0 {
1594
1595 i0 = i
1596 keepType = false
1597 }
1598 } else {
1599 if i0 >= 0 {
1600
1601 populate(i0, i, keepType)
1602 i0 = -1
1603 }
1604 }
1605 if t.Type != nil {
1606 keepType = true
1607 }
1608 }
1609 if i0 >= 0 {
1610
1611 populate(i0, len(specs), keepType)
1612 }
1613
1614 return m
1615 }
1616
1617 func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
1618 p.setComment(s.Doc)
1619 p.identList(s.Names, false)
1620 extraTabs := 3
1621 if s.Type != nil || keepType {
1622 p.print(vtab)
1623 extraTabs--
1624 }
1625 if s.Type != nil {
1626 p.expr(s.Type)
1627 }
1628 if s.Values != nil {
1629 p.print(vtab, token.ASSIGN, blank)
1630 p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
1631 extraTabs--
1632 }
1633 if s.Comment != nil {
1634 for ; extraTabs > 0; extraTabs-- {
1635 p.print(vtab)
1636 }
1637 p.setComment(s.Comment)
1638 }
1639 }
1640
1641 func sanitizeImportPath(lit *ast.BasicLit) *ast.BasicLit {
1642
1643
1644
1645
1646
1647
1648
1649
1650 if lit.Kind != token.STRING {
1651 return lit
1652 }
1653 s, err := strconv.Unquote(lit.Value)
1654 if err != nil {
1655 return lit
1656 }
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666 if s == "" {
1667 return lit
1668 }
1669 const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
1670 for _, r := range s {
1671 if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
1672 return lit
1673 }
1674 }
1675
1676
1677 s = strconv.Quote(s)
1678 if s == lit.Value {
1679 return lit
1680 }
1681 return &ast.BasicLit{ValuePos: lit.ValuePos, Kind: token.STRING, Value: s}
1682 }
1683
1684
1685
1686
1687 func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
1688 switch s := spec.(type) {
1689 case *ast.ImportSpec:
1690 p.setComment(s.Doc)
1691 if s.Name != nil {
1692 p.expr(s.Name)
1693 p.print(blank)
1694 }
1695 p.expr(sanitizeImportPath(s.Path))
1696 p.setComment(s.Comment)
1697 p.setPos(s.EndPos)
1698
1699 case *ast.ValueSpec:
1700 if n != 1 {
1701 p.internalError("expected n = 1; got", n)
1702 }
1703 p.setComment(s.Doc)
1704 p.identList(s.Names, doIndent)
1705 if s.Type != nil {
1706 p.print(blank)
1707 p.expr(s.Type)
1708 }
1709 if s.Values != nil {
1710 p.print(blank, token.ASSIGN, blank)
1711 p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
1712 }
1713 p.setComment(s.Comment)
1714
1715 case *ast.TypeSpec:
1716 p.setComment(s.Doc)
1717 p.expr(s.Name)
1718 if s.TypeParams != nil {
1719 p.parameters(s.TypeParams, typeTParam)
1720 }
1721 if n == 1 {
1722 p.print(blank)
1723 } else {
1724 p.print(vtab)
1725 }
1726 if s.Assign.IsValid() {
1727 p.print(token.ASSIGN, blank)
1728 }
1729 p.expr(s.Type)
1730 p.setComment(s.Comment)
1731
1732 default:
1733 panic("unreachable")
1734 }
1735 }
1736
1737 func (p *printer) genDecl(d *ast.GenDecl) {
1738 p.setComment(d.Doc)
1739 p.setPos(d.Pos())
1740 p.print(d.Tok, blank)
1741
1742 if d.Lparen.IsValid() || len(d.Specs) != 1 {
1743
1744 p.setPos(d.Lparen)
1745 p.print(token.LPAREN)
1746 if n := len(d.Specs); n > 0 {
1747 p.print(indent, formfeed)
1748 if n > 1 && (d.Tok == token.CONST || d.Tok == token.VAR) {
1749
1750
1751 keepType := keepTypeColumn(d.Specs)
1752 var line int
1753 for i, s := range d.Specs {
1754 if i > 0 {
1755 p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
1756 }
1757 p.recordLine(&line)
1758 p.valueSpec(s.(*ast.ValueSpec), keepType[i])
1759 }
1760 } else {
1761 var line int
1762 for i, s := range d.Specs {
1763 if i > 0 {
1764 p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
1765 }
1766 p.recordLine(&line)
1767 p.spec(s, n, false)
1768 }
1769 }
1770 p.print(unindent, formfeed)
1771 }
1772 p.setPos(d.Rparen)
1773 p.print(token.RPAREN)
1774
1775 } else if len(d.Specs) > 0 {
1776
1777 p.spec(d.Specs[0], 1, true)
1778 }
1779 }
1780
1781
1782
1783 type sizeCounter struct {
1784 hasNewline bool
1785 size int
1786 }
1787
1788 func (c *sizeCounter) Write(p []byte) (int, error) {
1789 if !c.hasNewline {
1790 for _, b := range p {
1791 if b == '\n' || b == '\f' {
1792 c.hasNewline = true
1793 break
1794 }
1795 }
1796 }
1797 c.size += len(p)
1798 return len(p), nil
1799 }
1800
1801
1802
1803
1804
1805 func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
1806
1807
1808
1809
1810 if size, found := p.nodeSizes[n]; found {
1811 return size
1812 }
1813
1814 size = maxSize + 1
1815 p.nodeSizes[n] = size
1816
1817
1818
1819
1820 cfg := Config{Mode: RawFormat}
1821 var counter sizeCounter
1822 if err := cfg.fprint(&counter, p.fset, n, p.nodeSizes); err != nil {
1823 return
1824 }
1825 if counter.size <= maxSize && !counter.hasNewline {
1826
1827 size = counter.size
1828 p.nodeSizes[n] = size
1829 }
1830 return
1831 }
1832
1833
1834 func (p *printer) numLines(n ast.Node) int {
1835 if from := n.Pos(); from.IsValid() {
1836 if to := n.End(); to.IsValid() {
1837 return p.lineFor(to) - p.lineFor(from) + 1
1838 }
1839 }
1840 return infinity
1841 }
1842
1843
1844 func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
1845 pos1 := b.Pos()
1846 pos2 := b.Rbrace
1847 if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
1848
1849 return maxSize + 1
1850 }
1851 if len(b.List) > 5 {
1852
1853 return maxSize + 1
1854 }
1855
1856 bodySize := p.commentSizeBefore(p.posFor(pos2))
1857 for i, s := range b.List {
1858 if bodySize > maxSize {
1859 break
1860 }
1861 if i > 0 {
1862 bodySize += 2
1863 }
1864 bodySize += p.nodeSize(s, maxSize)
1865 }
1866 return bodySize
1867 }
1868
1869
1870
1871
1872
1873
1874 func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
1875 if b == nil {
1876 return
1877 }
1878
1879
1880 defer func(level int) {
1881 p.level = level
1882 }(p.level)
1883 p.level = 0
1884
1885 const maxSize = 100
1886 if headerSize+p.bodySize(b, maxSize) <= maxSize {
1887 p.print(sep)
1888 p.setPos(b.Lbrace)
1889 p.print(token.LBRACE)
1890 if len(b.List) > 0 {
1891 p.print(blank)
1892 for i, s := range b.List {
1893 if i > 0 {
1894 p.print(token.SEMICOLON, blank)
1895 }
1896 p.stmt(s, i == len(b.List)-1)
1897 }
1898 p.print(blank)
1899 }
1900 p.print(noExtraLinebreak)
1901 p.setPos(b.Rbrace)
1902 p.print(token.RBRACE, noExtraLinebreak)
1903 return
1904 }
1905
1906 if sep != ignore {
1907 p.print(blank)
1908 }
1909 p.block(b, 1)
1910 }
1911
1912
1913
1914
1915 func (p *printer) distanceFrom(startPos token.Pos, startOutCol int) int {
1916 if startPos.IsValid() && p.pos.IsValid() && p.posFor(startPos).Line == p.pos.Line {
1917 return p.out.Column - startOutCol
1918 }
1919 return infinity
1920 }
1921
1922 func (p *printer) funcDecl(d *ast.FuncDecl) {
1923 p.setComment(d.Doc)
1924 p.setPos(d.Pos())
1925 p.print(token.FUNC, blank)
1926
1927
1928
1929 startCol := p.out.Column - len("func ")
1930 if d.Recv != nil {
1931 p.parameters(d.Recv, funcParam)
1932 p.print(blank)
1933 }
1934 p.expr(d.Name)
1935 p.signature(d.Type)
1936 p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)
1937 }
1938
1939 func (p *printer) decl(decl ast.Decl) {
1940 switch d := decl.(type) {
1941 case *ast.BadDecl:
1942 p.setPos(d.Pos())
1943 p.print("BadDecl")
1944 case *ast.GenDecl:
1945 p.genDecl(d)
1946 case *ast.FuncDecl:
1947 p.funcDecl(d)
1948 default:
1949 panic("unreachable")
1950 }
1951 }
1952
1953
1954
1955
1956 func declToken(decl ast.Decl) (tok token.Token) {
1957 tok = token.ILLEGAL
1958 switch d := decl.(type) {
1959 case *ast.GenDecl:
1960 tok = d.Tok
1961 case *ast.FuncDecl:
1962 tok = token.FUNC
1963 }
1964 return
1965 }
1966
1967 func (p *printer) declList(list []ast.Decl) {
1968 tok := token.ILLEGAL
1969 for _, d := range list {
1970 prev := tok
1971 tok = declToken(d)
1972
1973
1974
1975
1976
1977
1978
1979 if len(p.output) > 0 {
1980
1981
1982 min := 1
1983 if prev != tok || getDoc(d) != nil {
1984 min = 2
1985 }
1986
1987
1988 p.linebreak(p.lineFor(d.Pos()), min, ignore, tok == token.FUNC && p.numLines(d) > 1)
1989 }
1990 p.decl(d)
1991 }
1992 }
1993
1994 func (p *printer) file(src *ast.File) {
1995 p.setComment(src.Doc)
1996 p.setPos(src.Pos())
1997 p.print(token.PACKAGE, blank)
1998 p.expr(src.Name)
1999 p.declList(src.Decls)
2000 p.print(newline)
2001 }
2002
View as plain text