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(stripParensAlways(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 return !isTypeElem(x.X)
415 }
416 return false
417 }
418
419
420
421 func isTypeElem(x ast.Expr) bool {
422 switch x := x.(type) {
423 case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
424 return true
425 case *ast.UnaryExpr:
426 return x.Op == token.TILDE
427 case *ast.BinaryExpr:
428 return isTypeElem(x.X) || isTypeElem(x.Y)
429 case *ast.ParenExpr:
430 return isTypeElem(x.X)
431 }
432 return false
433 }
434
435 func (p *printer) signature(sig *ast.FuncType) {
436 if sig.TypeParams != nil {
437 p.parameters(sig.TypeParams, funcTParam)
438 }
439 if sig.Params != nil {
440 p.parameters(sig.Params, funcParam)
441 } else {
442 p.print(token.LPAREN, token.RPAREN)
443 }
444 res := sig.Results
445 n := res.NumFields()
446 if n > 0 {
447
448 p.print(blank)
449 if n == 1 && res.List[0].Names == nil {
450
451 p.expr(stripParensAlways(res.List[0].Type))
452 return
453 }
454 p.parameters(res, funcParam)
455 }
456 }
457
458 func identListSize(list []*ast.Ident, maxSize int) (size int) {
459 for i, x := range list {
460 if i > 0 {
461 size += len(", ")
462 }
463 size += utf8.RuneCountInString(x.Name)
464 if size >= maxSize {
465 break
466 }
467 }
468 return
469 }
470
471 func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
472 if len(list) != 1 {
473 return false
474 }
475 f := list[0]
476 if f.Tag != nil || f.Comment != nil {
477 return false
478 }
479
480 const maxSize = 30
481 namesSize := identListSize(f.Names, maxSize)
482 if namesSize > 0 {
483 namesSize = 1
484 }
485 typeSize := p.nodeSize(f.Type, maxSize)
486 return namesSize+typeSize <= maxSize
487 }
488
489 func (p *printer) setLineComment(text string) {
490 p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}})
491 }
492
493 func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
494 lbrace := fields.Opening
495 list := fields.List
496 rbrace := fields.Closing
497 hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
498 srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
499
500 if !hasComments && srcIsOneLine {
501
502 if len(list) == 0 {
503
504 p.setPos(lbrace)
505 p.print(token.LBRACE)
506 p.setPos(rbrace)
507 p.print(token.RBRACE)
508 return
509 } else if p.isOneLineFieldList(list) {
510
511
512 p.setPos(lbrace)
513 p.print(token.LBRACE, blank)
514 f := list[0]
515 if isStruct {
516 for i, x := range f.Names {
517 if i > 0 {
518
519 p.print(token.COMMA, blank)
520 }
521 p.expr(x)
522 }
523 if len(f.Names) > 0 {
524 p.print(blank)
525 }
526 p.expr(f.Type)
527 } else {
528 if len(f.Names) > 0 {
529 name := f.Names[0]
530 p.expr(name)
531 p.signature(f.Type.(*ast.FuncType))
532 } else {
533
534 p.expr(f.Type)
535 }
536 }
537 p.print(blank)
538 p.setPos(rbrace)
539 p.print(token.RBRACE)
540 return
541 }
542 }
543
544
545 p.print(blank)
546 p.setPos(lbrace)
547 p.print(token.LBRACE, indent)
548 if hasComments || len(list) > 0 {
549 p.print(formfeed)
550 }
551
552 if isStruct {
553
554 sep := vtab
555 if len(list) == 1 {
556 sep = blank
557 }
558 var line int
559 for i, f := range list {
560 if i > 0 {
561 p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0)
562 }
563 extraTabs := 0
564 p.setComment(f.Doc)
565 p.recordLine(&line)
566 if len(f.Names) > 0 {
567
568 p.identList(f.Names, false)
569 p.print(sep)
570 p.expr(f.Type)
571 extraTabs = 1
572 } else {
573
574 p.expr(f.Type)
575 extraTabs = 2
576 }
577 if f.Tag != nil {
578 if len(f.Names) > 0 && sep == vtab {
579 p.print(sep)
580 }
581 p.print(sep)
582 p.expr(f.Tag)
583 extraTabs = 0
584 }
585 if f.Comment != nil {
586 for ; extraTabs > 0; extraTabs-- {
587 p.print(sep)
588 }
589 p.setComment(f.Comment)
590 }
591 }
592 if isIncomplete {
593 if len(list) > 0 {
594 p.print(formfeed)
595 }
596 p.flush(p.posFor(rbrace), token.RBRACE)
597 p.setLineComment("// " + filteredMsg)
598 }
599
600 } else {
601
602 var line int
603 var prev *ast.Ident
604 for i, f := range list {
605 var name *ast.Ident
606 if len(f.Names) > 0 {
607 name = f.Names[0]
608 }
609 if i > 0 {
610
611
612
613 min := 1
614 if prev != nil && name == prev {
615 min = 0
616 }
617 p.linebreak(p.lineFor(f.Pos()), min, ignore, p.linesFrom(line) > 0)
618 }
619 p.setComment(f.Doc)
620 p.recordLine(&line)
621 if name != nil {
622
623 p.expr(name)
624 p.signature(f.Type.(*ast.FuncType))
625 prev = nil
626 } else {
627
628 p.expr(f.Type)
629 prev = nil
630 }
631 p.setComment(f.Comment)
632 }
633 if isIncomplete {
634 if len(list) > 0 {
635 p.print(formfeed)
636 }
637 p.flush(p.posFor(rbrace), token.RBRACE)
638 p.setLineComment("// contains filtered or unexported methods")
639 }
640
641 }
642 p.print(unindent, formfeed)
643 p.setPos(rbrace)
644 p.print(token.RBRACE)
645 }
646
647
648
649
650 func walkBinary(e *ast.BinaryExpr) (has4, has5 bool, maxProblem int) {
651 switch e.Op.Precedence() {
652 case 4:
653 has4 = true
654 case 5:
655 has5 = true
656 }
657
658 switch l := e.X.(type) {
659 case *ast.BinaryExpr:
660 if l.Op.Precedence() < e.Op.Precedence() {
661
662
663 break
664 }
665 h4, h5, mp := walkBinary(l)
666 has4 = has4 || h4
667 has5 = has5 || h5
668 maxProblem = max(maxProblem, mp)
669 }
670
671 switch r := e.Y.(type) {
672 case *ast.BinaryExpr:
673 if r.Op.Precedence() <= e.Op.Precedence() {
674
675
676 break
677 }
678 h4, h5, mp := walkBinary(r)
679 has4 = has4 || h4
680 has5 = has5 || h5
681 maxProblem = max(maxProblem, mp)
682
683 case *ast.StarExpr:
684 if e.Op == token.QUO {
685 maxProblem = 5
686 }
687
688 case *ast.UnaryExpr:
689 switch e.Op.String() + r.Op.String() {
690 case "/*", "&&", "&^":
691 maxProblem = 5
692 case "++", "--":
693 maxProblem = max(maxProblem, 4)
694 }
695 }
696 return
697 }
698
699 func cutoff(e *ast.BinaryExpr, depth int) int {
700 has4, has5, maxProblem := walkBinary(e)
701 if maxProblem > 0 {
702 return maxProblem + 1
703 }
704 if has4 && has5 {
705 if depth == 1 {
706 return 5
707 }
708 return 4
709 }
710 if depth == 1 {
711 return 6
712 }
713 return 4
714 }
715
716 func diffPrec(expr ast.Expr, prec int) int {
717 x, ok := expr.(*ast.BinaryExpr)
718 if !ok || prec != x.Op.Precedence() {
719 return 1
720 }
721 return 0
722 }
723
724 func reduceDepth(depth int) int {
725 depth--
726 if depth < 1 {
727 depth = 1
728 }
729 return depth
730 }
731
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 func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
769 prec := x.Op.Precedence()
770 if prec < prec1 {
771
772
773
774 p.print(token.LPAREN)
775 p.expr0(x, reduceDepth(depth))
776 p.print(token.RPAREN)
777 return
778 }
779
780 printBlank := prec < cutoff
781
782 ws := indent
783 p.expr1(x.X, prec, depth+diffPrec(x.X, prec))
784 if printBlank {
785 p.print(blank)
786 }
787 xline := p.pos.Line
788 yline := p.lineFor(x.Y.Pos())
789 p.setPos(x.OpPos)
790 p.print(x.Op)
791 if xline != yline && xline > 0 && yline > 0 {
792
793
794 if p.linebreak(yline, 1, ws, true) > 0 {
795 ws = ignore
796 printBlank = false
797 }
798 }
799 if printBlank {
800 p.print(blank)
801 }
802 p.expr1(x.Y, prec+1, depth+1)
803 if ws == ignore {
804 p.print(unindent)
805 }
806 }
807
808 func isBinary(expr ast.Expr) bool {
809 _, ok := expr.(*ast.BinaryExpr)
810 return ok
811 }
812
813 func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
814 p.setPos(expr.Pos())
815
816 switch x := expr.(type) {
817 case *ast.BadExpr:
818 p.print("BadExpr")
819
820 case *ast.Ident:
821 p.print(x)
822
823 case *ast.BinaryExpr:
824 if depth < 1 {
825 p.internalError("depth < 1:", depth)
826 depth = 1
827 }
828 p.binaryExpr(x, prec1, cutoff(x, depth), depth)
829
830 case *ast.KeyValueExpr:
831 p.expr(x.Key)
832 p.setPos(x.Colon)
833 p.print(token.COLON, blank)
834 p.expr(x.Value)
835
836 case *ast.StarExpr:
837 const prec = token.UnaryPrec
838 if prec < prec1 {
839
840 p.print(token.LPAREN)
841 p.print(token.MUL)
842 p.expr(x.X)
843 p.print(token.RPAREN)
844 } else {
845
846 p.print(token.MUL)
847 p.expr(x.X)
848 }
849
850 case *ast.UnaryExpr:
851 const prec = token.UnaryPrec
852 if prec < prec1 {
853
854 p.print(token.LPAREN)
855 p.expr(x)
856 p.print(token.RPAREN)
857 } else {
858
859 p.print(x.Op)
860 if x.Op == token.RANGE {
861
862 p.print(blank)
863 }
864 p.expr1(x.X, prec, depth)
865 }
866
867 case *ast.BasicLit:
868 if p.Config.Mode&normalizeNumbers != 0 {
869 x = normalizedNumber(x)
870 }
871 p.print(x)
872
873 case *ast.FuncLit:
874 p.setPos(x.Type.Pos())
875 p.print(token.FUNC)
876
877 startCol := p.out.Column - len("func")
878 p.signature(x.Type)
879 p.funcBody(p.distanceFrom(x.Type.Pos(), startCol), blank, x.Body)
880
881 case *ast.ParenExpr:
882 if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
883
884
885 p.expr0(x.X, depth)
886 } else {
887 p.print(token.LPAREN)
888 p.expr0(x.X, reduceDepth(depth))
889 p.setPos(x.Rparen)
890 p.print(token.RPAREN)
891 }
892
893 case *ast.SelectorExpr:
894 p.selectorExpr(x, depth, false)
895
896 case *ast.TypeAssertExpr:
897 p.expr1(x.X, token.HighestPrec, depth)
898 p.print(token.PERIOD)
899 p.setPos(x.Lparen)
900 p.print(token.LPAREN)
901 if x.Type != nil {
902 p.expr(x.Type)
903 } else {
904 p.print(token.TYPE)
905 }
906 p.setPos(x.Rparen)
907 p.print(token.RPAREN)
908
909 case *ast.IndexExpr:
910
911 p.expr1(x.X, token.HighestPrec, 1)
912 p.setPos(x.Lbrack)
913 p.print(token.LBRACK)
914 p.expr0(x.Index, depth+1)
915 p.setPos(x.Rbrack)
916 p.print(token.RBRACK)
917
918 case *ast.IndexListExpr:
919
920
921 p.expr1(x.X, token.HighestPrec, 1)
922 p.setPos(x.Lbrack)
923 p.print(token.LBRACK)
924 p.exprList(x.Lbrack, x.Indices, depth+1, commaTerm, x.Rbrack, false)
925 p.setPos(x.Rbrack)
926 p.print(token.RBRACK)
927
928 case *ast.SliceExpr:
929
930 p.expr1(x.X, token.HighestPrec, 1)
931 p.setPos(x.Lbrack)
932 p.print(token.LBRACK)
933 indices := []ast.Expr{x.Low, x.High}
934 if x.Max != nil {
935 indices = append(indices, x.Max)
936 }
937
938 var needsBlanks bool
939 if depth <= 1 {
940 var indexCount int
941 var hasBinaries bool
942 for _, x := range indices {
943 if x != nil {
944 indexCount++
945 if isBinary(x) {
946 hasBinaries = true
947 }
948 }
949 }
950 if indexCount > 1 && hasBinaries {
951 needsBlanks = true
952 }
953 }
954 for i, x := range indices {
955 if i > 0 {
956 if indices[i-1] != nil && needsBlanks {
957 p.print(blank)
958 }
959 p.print(token.COLON)
960 if x != nil && needsBlanks {
961 p.print(blank)
962 }
963 }
964 if x != nil {
965 p.expr0(x, depth+1)
966 }
967 }
968 p.setPos(x.Rbrack)
969 p.print(token.RBRACK)
970
971 case *ast.CallExpr:
972 if len(x.Args) > 1 {
973 depth++
974 }
975
976
977
978 paren := false
979 switch t := x.Fun.(type) {
980 case *ast.FuncType:
981 paren = true
982 case *ast.ChanType:
983 paren = t.Dir == ast.RECV
984 }
985 if paren {
986 p.print(token.LPAREN)
987 }
988 wasIndented := p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
989 if paren {
990 p.print(token.RPAREN)
991 }
992
993 p.setPos(x.Lparen)
994 p.print(token.LPAREN)
995 if x.Ellipsis.IsValid() {
996 p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
997 p.setPos(x.Ellipsis)
998 p.print(token.ELLIPSIS)
999 if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
1000 p.print(token.COMMA, formfeed)
1001 }
1002 } else {
1003 p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
1004 }
1005 p.setPos(x.Rparen)
1006 p.print(token.RPAREN)
1007 if wasIndented {
1008 p.print(unindent)
1009 }
1010
1011 case *ast.CompositeLit:
1012
1013 if x.Type != nil {
1014 p.expr1(x.Type, token.HighestPrec, depth)
1015 }
1016 p.level++
1017 p.setPos(x.Lbrace)
1018 p.print(token.LBRACE)
1019 p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace, x.Incomplete)
1020
1021
1022
1023 mode := noExtraLinebreak
1024
1025
1026 if len(x.Elts) > 0 {
1027 mode |= noExtraBlank
1028 }
1029
1030
1031 p.print(indent, unindent, mode)
1032 p.setPos(x.Rbrace)
1033 p.print(token.RBRACE, mode)
1034 p.level--
1035
1036 case *ast.Ellipsis:
1037 p.print(token.ELLIPSIS)
1038 if x.Elt != nil {
1039 p.expr(x.Elt)
1040 }
1041
1042 case *ast.ArrayType:
1043 p.print(token.LBRACK)
1044 if x.Len != nil {
1045 p.expr(x.Len)
1046 }
1047 p.print(token.RBRACK)
1048 p.expr(x.Elt)
1049
1050 case *ast.StructType:
1051 p.print(token.STRUCT)
1052 p.fieldList(x.Fields, true, x.Incomplete)
1053
1054 case *ast.FuncType:
1055 p.print(token.FUNC)
1056 p.signature(x)
1057
1058 case *ast.InterfaceType:
1059 p.print(token.INTERFACE)
1060 p.fieldList(x.Methods, false, x.Incomplete)
1061
1062 case *ast.MapType:
1063 p.print(token.MAP, token.LBRACK)
1064 p.expr(x.Key)
1065 p.print(token.RBRACK)
1066 p.expr(x.Value)
1067
1068 case *ast.ChanType:
1069 switch x.Dir {
1070 case ast.SEND | ast.RECV:
1071 p.print(token.CHAN)
1072 case ast.RECV:
1073 p.print(token.ARROW, token.CHAN)
1074 case ast.SEND:
1075 p.print(token.CHAN)
1076 p.setPos(x.Arrow)
1077 p.print(token.ARROW)
1078 }
1079 p.print(blank)
1080 p.expr(x.Value)
1081
1082 default:
1083 panic("unreachable")
1084 }
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 func normalizedNumber(lit *ast.BasicLit) *ast.BasicLit {
1096 if lit.Kind != token.INT && lit.Kind != token.FLOAT && lit.Kind != token.IMAG {
1097 return lit
1098 }
1099 if len(lit.Value) < 2 {
1100 return lit
1101 }
1102
1103
1104
1105
1106 x := lit.Value
1107 switch x[:2] {
1108 default:
1109
1110 if i := strings.LastIndexByte(x, 'E'); i >= 0 {
1111 x = x[:i] + "e" + x[i+1:]
1112 break
1113 }
1114
1115 if x[len(x)-1] == 'i' && !strings.ContainsAny(x, ".e") {
1116 x = strings.TrimLeft(x, "0_")
1117 if x == "i" {
1118 x = "0i"
1119 }
1120 }
1121 case "0X":
1122 x = "0x" + x[2:]
1123
1124 if i := strings.LastIndexByte(x, 'P'); i >= 0 {
1125 x = x[:i] + "p" + x[i+1:]
1126 }
1127 case "0x":
1128
1129 i := strings.LastIndexByte(x, 'P')
1130 if i == -1 {
1131 return lit
1132 }
1133 x = x[:i] + "p" + x[i+1:]
1134 case "0O":
1135 x = "0o" + x[2:]
1136 case "0o":
1137 return lit
1138 case "0B":
1139 x = "0b" + x[2:]
1140 case "0b":
1141 return lit
1142 }
1143
1144 return &ast.BasicLit{ValuePos: lit.ValuePos, Kind: lit.Kind, Value: x}
1145 }
1146
1147 func (p *printer) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool {
1148 if x, ok := expr.(*ast.SelectorExpr); ok {
1149 return p.selectorExpr(x, depth, true)
1150 }
1151 p.expr1(expr, prec1, depth)
1152 return false
1153 }
1154
1155
1156
1157 func (p *printer) selectorExpr(x *ast.SelectorExpr, depth int, isMethod bool) bool {
1158 p.expr1(x.X, token.HighestPrec, depth)
1159 p.print(token.PERIOD)
1160 if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
1161 p.print(indent, newline)
1162 p.setPos(x.Sel.Pos())
1163 p.print(x.Sel)
1164 if !isMethod {
1165 p.print(unindent)
1166 }
1167 return true
1168 }
1169 p.setPos(x.Sel.Pos())
1170 p.print(x.Sel)
1171 return false
1172 }
1173
1174 func (p *printer) expr0(x ast.Expr, depth int) {
1175 p.expr1(x, token.LowestPrec, depth)
1176 }
1177
1178 func (p *printer) expr(x ast.Expr) {
1179 const depth = 1
1180 p.expr1(x, token.LowestPrec, depth)
1181 }
1182
1183
1184
1185
1186
1187
1188
1189 func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
1190 if nindent > 0 {
1191 p.print(indent)
1192 }
1193 var line int
1194 i := 0
1195 for _, s := range list {
1196
1197 if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty {
1198
1199
1200 if len(p.output) > 0 {
1201
1202
1203 p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || p.linesFrom(line) > 0)
1204 }
1205 p.recordLine(&line)
1206 p.stmt(s, nextIsRBrace && i == len(list)-1)
1207
1208
1209
1210 for t := s; ; {
1211 lt, _ := t.(*ast.LabeledStmt)
1212 if lt == nil {
1213 break
1214 }
1215 line++
1216 t = lt.Stmt
1217 }
1218 i++
1219 }
1220 }
1221 if nindent > 0 {
1222 p.print(unindent)
1223 }
1224 }
1225
1226
1227 func (p *printer) block(b *ast.BlockStmt, nindent int) {
1228 p.setPos(b.Lbrace)
1229 p.print(token.LBRACE)
1230 p.stmtList(b.List, nindent, true)
1231 p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
1232 p.setPos(b.Rbrace)
1233 p.print(token.RBRACE)
1234 }
1235
1236 func isTypeName(x ast.Expr) bool {
1237 switch t := x.(type) {
1238 case *ast.Ident:
1239 return true
1240 case *ast.SelectorExpr:
1241 return isTypeName(t.X)
1242 }
1243 return false
1244 }
1245
1246 func stripParens(x ast.Expr) ast.Expr {
1247 if px, strip := x.(*ast.ParenExpr); strip {
1248
1249
1250
1251 ast.Inspect(px.X, func(node ast.Node) bool {
1252 switch x := node.(type) {
1253 case *ast.ParenExpr:
1254
1255 return false
1256 case *ast.CompositeLit:
1257 if isTypeName(x.Type) {
1258 strip = false
1259 }
1260 return false
1261 }
1262
1263 return true
1264 })
1265 if strip {
1266 return stripParens(px.X)
1267 }
1268 }
1269 return x
1270 }
1271
1272 func stripParensAlways(x ast.Expr) ast.Expr {
1273 if x, ok := x.(*ast.ParenExpr); ok {
1274 return stripParensAlways(x.X)
1275 }
1276 return x
1277 }
1278
1279 func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) {
1280 p.print(blank)
1281 needsBlank := false
1282 if init == nil && post == nil {
1283
1284 if expr != nil {
1285 p.expr(stripParens(expr))
1286 needsBlank = true
1287 }
1288 } else {
1289
1290
1291 if init != nil {
1292 p.stmt(init, false)
1293 }
1294 p.print(token.SEMICOLON, blank)
1295 if expr != nil {
1296 p.expr(stripParens(expr))
1297 needsBlank = true
1298 }
1299 if isForStmt {
1300 p.print(token.SEMICOLON, blank)
1301 needsBlank = false
1302 if post != nil {
1303 p.stmt(post, false)
1304 needsBlank = true
1305 }
1306 }
1307 }
1308 if needsBlank {
1309 p.print(blank)
1310 }
1311 }
1312
1313
1314
1315
1316 func (p *printer) indentList(list []ast.Expr) bool {
1317
1318
1319
1320 if len(list) >= 2 {
1321 var b = p.lineFor(list[0].Pos())
1322 var e = p.lineFor(list[len(list)-1].End())
1323 if 0 < b && b < e {
1324
1325 n := 0
1326 line := b
1327 for _, x := range list {
1328 xb := p.lineFor(x.Pos())
1329 xe := p.lineFor(x.End())
1330 if line < xb {
1331
1332
1333 return true
1334 }
1335 if xb < xe {
1336
1337 n++
1338 }
1339 line = xe
1340 }
1341 return n > 1
1342 }
1343 }
1344 return false
1345 }
1346
1347 func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
1348 p.setPos(stmt.Pos())
1349
1350 switch s := stmt.(type) {
1351 case *ast.BadStmt:
1352 p.print("BadStmt")
1353
1354 case *ast.DeclStmt:
1355 p.decl(s.Decl)
1356
1357 case *ast.EmptyStmt:
1358
1359
1360 case *ast.LabeledStmt:
1361
1362
1363
1364 p.print(unindent)
1365 p.expr(s.Label)
1366 p.setPos(s.Colon)
1367 p.print(token.COLON, indent)
1368 if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
1369 if !nextIsRBrace {
1370 p.print(newline)
1371 p.setPos(e.Pos())
1372 p.print(token.SEMICOLON)
1373 break
1374 }
1375 } else {
1376 p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
1377 }
1378 p.stmt(s.Stmt, nextIsRBrace)
1379
1380 case *ast.ExprStmt:
1381 const depth = 1
1382 p.expr0(s.X, depth)
1383
1384 case *ast.SendStmt:
1385 const depth = 1
1386 p.expr0(s.Chan, depth)
1387 p.print(blank)
1388 p.setPos(s.Arrow)
1389 p.print(token.ARROW, blank)
1390 p.expr0(s.Value, depth)
1391
1392 case *ast.IncDecStmt:
1393 const depth = 1
1394 p.expr0(s.X, depth+1)
1395 p.setPos(s.TokPos)
1396 p.print(s.Tok)
1397
1398 case *ast.AssignStmt:
1399 var depth = 1
1400 if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
1401 depth++
1402 }
1403 p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos, false)
1404 p.print(blank)
1405 p.setPos(s.TokPos)
1406 p.print(s.Tok, blank)
1407 p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos, false)
1408
1409 case *ast.GoStmt:
1410 p.print(token.GO, blank)
1411 p.expr(s.Call)
1412
1413 case *ast.DeferStmt:
1414 p.print(token.DEFER, blank)
1415 p.expr(s.Call)
1416
1417 case *ast.ReturnStmt:
1418 p.print(token.RETURN)
1419 if s.Results != nil {
1420 p.print(blank)
1421
1422
1423
1424
1425
1426 if p.indentList(s.Results) {
1427 p.print(indent)
1428
1429
1430 p.exprList(token.NoPos, s.Results, 1, noIndent, token.NoPos, false)
1431 p.print(unindent)
1432 } else {
1433 p.exprList(token.NoPos, s.Results, 1, 0, token.NoPos, false)
1434 }
1435 }
1436
1437 case *ast.BranchStmt:
1438 p.print(s.Tok)
1439 if s.Label != nil {
1440 p.print(blank)
1441 p.expr(s.Label)
1442 }
1443
1444 case *ast.BlockStmt:
1445 p.block(s, 1)
1446
1447 case *ast.IfStmt:
1448 p.print(token.IF)
1449 p.controlClause(false, s.Init, s.Cond, nil)
1450 p.block(s.Body, 1)
1451 if s.Else != nil {
1452 p.print(blank, token.ELSE, blank)
1453 switch s.Else.(type) {
1454 case *ast.BlockStmt, *ast.IfStmt:
1455 p.stmt(s.Else, nextIsRBrace)
1456 default:
1457
1458
1459
1460 p.print(token.LBRACE, indent, formfeed)
1461 p.stmt(s.Else, true)
1462 p.print(unindent, formfeed, token.RBRACE)
1463 }
1464 }
1465
1466 case *ast.CaseClause:
1467 if s.List != nil {
1468 p.print(token.CASE, blank)
1469 p.exprList(s.Pos(), s.List, 1, 0, s.Colon, false)
1470 } else {
1471 p.print(token.DEFAULT)
1472 }
1473 p.setPos(s.Colon)
1474 p.print(token.COLON)
1475 p.stmtList(s.Body, 1, nextIsRBrace)
1476
1477 case *ast.SwitchStmt:
1478 p.print(token.SWITCH)
1479 p.controlClause(false, s.Init, s.Tag, nil)
1480 p.block(s.Body, 0)
1481
1482 case *ast.TypeSwitchStmt:
1483 p.print(token.SWITCH)
1484 if s.Init != nil {
1485 p.print(blank)
1486 p.stmt(s.Init, false)
1487 p.print(token.SEMICOLON)
1488 }
1489 p.print(blank)
1490 p.stmt(s.Assign, false)
1491 p.print(blank)
1492 p.block(s.Body, 0)
1493
1494 case *ast.CommClause:
1495 if s.Comm != nil {
1496 p.print(token.CASE, blank)
1497 p.stmt(s.Comm, false)
1498 } else {
1499 p.print(token.DEFAULT)
1500 }
1501 p.setPos(s.Colon)
1502 p.print(token.COLON)
1503 p.stmtList(s.Body, 1, nextIsRBrace)
1504
1505 case *ast.SelectStmt:
1506 p.print(token.SELECT, blank)
1507 body := s.Body
1508 if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
1509
1510 p.setPos(body.Lbrace)
1511 p.print(token.LBRACE)
1512 p.setPos(body.Rbrace)
1513 p.print(token.RBRACE)
1514 } else {
1515 p.block(body, 0)
1516 }
1517
1518 case *ast.ForStmt:
1519 p.print(token.FOR)
1520 p.controlClause(true, s.Init, s.Cond, s.Post)
1521 p.block(s.Body, 1)
1522
1523 case *ast.RangeStmt:
1524 p.print(token.FOR, blank)
1525 if s.Key != nil {
1526 p.expr(s.Key)
1527 if s.Value != nil {
1528
1529
1530 p.setPos(s.Value.Pos())
1531 p.print(token.COMMA, blank)
1532 p.expr(s.Value)
1533 }
1534 p.print(blank)
1535 p.setPos(s.TokPos)
1536 p.print(s.Tok, blank)
1537 }
1538 p.print(token.RANGE, blank)
1539 p.expr(stripParens(s.X))
1540 p.print(blank)
1541 p.block(s.Body, 1)
1542
1543 default:
1544 panic("unreachable")
1545 }
1546 }
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 func keepTypeColumn(specs []ast.Spec) []bool {
1576 m := make([]bool, len(specs))
1577
1578 populate := func(i, j int, keepType bool) {
1579 if keepType {
1580 for ; i < j; i++ {
1581 m[i] = true
1582 }
1583 }
1584 }
1585
1586 i0 := -1
1587 var keepType bool
1588 for i, s := range specs {
1589 t := s.(*ast.ValueSpec)
1590 if t.Values != nil {
1591 if i0 < 0 {
1592
1593 i0 = i
1594 keepType = false
1595 }
1596 } else {
1597 if i0 >= 0 {
1598
1599 populate(i0, i, keepType)
1600 i0 = -1
1601 }
1602 }
1603 if t.Type != nil {
1604 keepType = true
1605 }
1606 }
1607 if i0 >= 0 {
1608
1609 populate(i0, len(specs), keepType)
1610 }
1611
1612 return m
1613 }
1614
1615 func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
1616 p.setComment(s.Doc)
1617 p.identList(s.Names, false)
1618 extraTabs := 3
1619 if s.Type != nil || keepType {
1620 p.print(vtab)
1621 extraTabs--
1622 }
1623 if s.Type != nil {
1624 p.expr(s.Type)
1625 }
1626 if s.Values != nil {
1627 p.print(vtab, token.ASSIGN, blank)
1628 p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
1629 extraTabs--
1630 }
1631 if s.Comment != nil {
1632 for ; extraTabs > 0; extraTabs-- {
1633 p.print(vtab)
1634 }
1635 p.setComment(s.Comment)
1636 }
1637 }
1638
1639 func sanitizeImportPath(lit *ast.BasicLit) *ast.BasicLit {
1640
1641
1642
1643
1644
1645
1646
1647
1648 if lit.Kind != token.STRING {
1649 return lit
1650 }
1651 s, err := strconv.Unquote(lit.Value)
1652 if err != nil {
1653 return lit
1654 }
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664 if s == "" {
1665 return lit
1666 }
1667 const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
1668 for _, r := range s {
1669 if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
1670 return lit
1671 }
1672 }
1673
1674
1675 s = strconv.Quote(s)
1676 if s == lit.Value {
1677 return lit
1678 }
1679 return &ast.BasicLit{ValuePos: lit.ValuePos, Kind: token.STRING, Value: s}
1680 }
1681
1682
1683
1684
1685 func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
1686 switch s := spec.(type) {
1687 case *ast.ImportSpec:
1688 p.setComment(s.Doc)
1689 if s.Name != nil {
1690 p.expr(s.Name)
1691 p.print(blank)
1692 }
1693 p.expr(sanitizeImportPath(s.Path))
1694 p.setComment(s.Comment)
1695 p.setPos(s.EndPos)
1696
1697 case *ast.ValueSpec:
1698 if n != 1 {
1699 p.internalError("expected n = 1; got", n)
1700 }
1701 p.setComment(s.Doc)
1702 p.identList(s.Names, doIndent)
1703 if s.Type != nil {
1704 p.print(blank)
1705 p.expr(s.Type)
1706 }
1707 if s.Values != nil {
1708 p.print(blank, token.ASSIGN, blank)
1709 p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
1710 }
1711 p.setComment(s.Comment)
1712
1713 case *ast.TypeSpec:
1714 p.setComment(s.Doc)
1715 p.expr(s.Name)
1716 if s.TypeParams != nil {
1717 p.parameters(s.TypeParams, typeTParam)
1718 }
1719 if n == 1 {
1720 p.print(blank)
1721 } else {
1722 p.print(vtab)
1723 }
1724 if s.Assign.IsValid() {
1725 p.print(token.ASSIGN, blank)
1726 }
1727 p.expr(s.Type)
1728 p.setComment(s.Comment)
1729
1730 default:
1731 panic("unreachable")
1732 }
1733 }
1734
1735 func (p *printer) genDecl(d *ast.GenDecl) {
1736 p.setComment(d.Doc)
1737 p.setPos(d.Pos())
1738 p.print(d.Tok, blank)
1739
1740 if d.Lparen.IsValid() || len(d.Specs) != 1 {
1741
1742 p.setPos(d.Lparen)
1743 p.print(token.LPAREN)
1744 if n := len(d.Specs); n > 0 {
1745 p.print(indent, formfeed)
1746 if n > 1 && (d.Tok == token.CONST || d.Tok == token.VAR) {
1747
1748
1749 keepType := keepTypeColumn(d.Specs)
1750 var line int
1751 for i, s := range d.Specs {
1752 if i > 0 {
1753 p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
1754 }
1755 p.recordLine(&line)
1756 p.valueSpec(s.(*ast.ValueSpec), keepType[i])
1757 }
1758 } else {
1759 var line int
1760 for i, s := range d.Specs {
1761 if i > 0 {
1762 p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0)
1763 }
1764 p.recordLine(&line)
1765 p.spec(s, n, false)
1766 }
1767 }
1768 p.print(unindent, formfeed)
1769 }
1770 p.setPos(d.Rparen)
1771 p.print(token.RPAREN)
1772
1773 } else if len(d.Specs) > 0 {
1774
1775 p.spec(d.Specs[0], 1, true)
1776 }
1777 }
1778
1779
1780
1781 type sizeCounter struct {
1782 hasNewline bool
1783 size int
1784 }
1785
1786 func (c *sizeCounter) Write(p []byte) (int, error) {
1787 if !c.hasNewline {
1788 for _, b := range p {
1789 if b == '\n' || b == '\f' {
1790 c.hasNewline = true
1791 break
1792 }
1793 }
1794 }
1795 c.size += len(p)
1796 return len(p), nil
1797 }
1798
1799
1800
1801
1802
1803 func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
1804
1805
1806
1807
1808 if size, found := p.nodeSizes[n]; found {
1809 return size
1810 }
1811
1812 size = maxSize + 1
1813 p.nodeSizes[n] = size
1814
1815
1816
1817
1818 cfg := Config{Mode: RawFormat}
1819 var counter sizeCounter
1820 if err := cfg.fprint(&counter, p.fset, n, p.nodeSizes); err != nil {
1821 return
1822 }
1823 if counter.size <= maxSize && !counter.hasNewline {
1824
1825 size = counter.size
1826 p.nodeSizes[n] = size
1827 }
1828 return
1829 }
1830
1831
1832 func (p *printer) numLines(n ast.Node) int {
1833 if from := n.Pos(); from.IsValid() {
1834 if to := n.End(); to.IsValid() {
1835 return p.lineFor(to) - p.lineFor(from) + 1
1836 }
1837 }
1838 return infinity
1839 }
1840
1841
1842 func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
1843 pos1 := b.Pos()
1844 pos2 := b.Rbrace
1845 if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
1846
1847 return maxSize + 1
1848 }
1849 if len(b.List) > 5 {
1850
1851 return maxSize + 1
1852 }
1853
1854 bodySize := p.commentSizeBefore(p.posFor(pos2))
1855 for i, s := range b.List {
1856 if bodySize > maxSize {
1857 break
1858 }
1859 if i > 0 {
1860 bodySize += 2
1861 }
1862 bodySize += p.nodeSize(s, maxSize)
1863 }
1864 return bodySize
1865 }
1866
1867
1868
1869
1870
1871
1872 func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
1873 if b == nil {
1874 return
1875 }
1876
1877
1878 defer func(level int) {
1879 p.level = level
1880 }(p.level)
1881 p.level = 0
1882
1883 const maxSize = 100
1884 if headerSize+p.bodySize(b, maxSize) <= maxSize {
1885 p.print(sep)
1886 p.setPos(b.Lbrace)
1887 p.print(token.LBRACE)
1888 if len(b.List) > 0 {
1889 p.print(blank)
1890 for i, s := range b.List {
1891 if i > 0 {
1892 p.print(token.SEMICOLON, blank)
1893 }
1894 p.stmt(s, i == len(b.List)-1)
1895 }
1896 p.print(blank)
1897 }
1898 p.print(noExtraLinebreak)
1899 p.setPos(b.Rbrace)
1900 p.print(token.RBRACE, noExtraLinebreak)
1901 return
1902 }
1903
1904 if sep != ignore {
1905 p.print(blank)
1906 }
1907 p.block(b, 1)
1908 }
1909
1910
1911
1912
1913 func (p *printer) distanceFrom(startPos token.Pos, startOutCol int) int {
1914 if startPos.IsValid() && p.pos.IsValid() && p.posFor(startPos).Line == p.pos.Line {
1915 return p.out.Column - startOutCol
1916 }
1917 return infinity
1918 }
1919
1920 func (p *printer) funcDecl(d *ast.FuncDecl) {
1921 p.setComment(d.Doc)
1922 p.setPos(d.Pos())
1923 p.print(token.FUNC, blank)
1924
1925
1926
1927 startCol := p.out.Column - len("func ")
1928 if d.Recv != nil {
1929 p.parameters(d.Recv, funcParam)
1930 p.print(blank)
1931 }
1932 p.expr(d.Name)
1933 p.signature(d.Type)
1934 p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)
1935 }
1936
1937 func (p *printer) decl(decl ast.Decl) {
1938 switch d := decl.(type) {
1939 case *ast.BadDecl:
1940 p.setPos(d.Pos())
1941 p.print("BadDecl")
1942 case *ast.GenDecl:
1943 p.genDecl(d)
1944 case *ast.FuncDecl:
1945 p.funcDecl(d)
1946 default:
1947 panic("unreachable")
1948 }
1949 }
1950
1951
1952
1953
1954 func declToken(decl ast.Decl) (tok token.Token) {
1955 tok = token.ILLEGAL
1956 switch d := decl.(type) {
1957 case *ast.GenDecl:
1958 tok = d.Tok
1959 case *ast.FuncDecl:
1960 tok = token.FUNC
1961 }
1962 return
1963 }
1964
1965 func (p *printer) declList(list []ast.Decl) {
1966 tok := token.ILLEGAL
1967 for _, d := range list {
1968 prev := tok
1969 tok = declToken(d)
1970
1971
1972
1973
1974
1975
1976
1977 if len(p.output) > 0 {
1978
1979
1980 min := 1
1981 if prev != tok || getDoc(d) != nil {
1982 min = 2
1983 }
1984
1985
1986 p.linebreak(p.lineFor(d.Pos()), min, ignore, tok == token.FUNC && p.numLines(d) > 1)
1987 }
1988 p.decl(d)
1989 }
1990 }
1991
1992 func (p *printer) file(src *ast.File) {
1993 p.setComment(src.Doc)
1994 p.setPos(src.Pos())
1995 p.print(token.PACKAGE, blank)
1996 p.expr(src.Name)
1997 p.declList(src.Decls)
1998 p.print(newline)
1999 }
2000
View as plain text