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