1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package format
16
17 import (
18 "fmt"
19 "strings"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/literal"
23 "cuelang.org/go/cue/token"
24 "cuelang.org/go/internal"
25 )
26
27 func printNode(node interface{}, f *printer) error {
28 s := newFormatter(f)
29
30 ls := labelSimplifier{scope: map[string]bool{}}
31
32
33 f.allowed = nooverride
34 switch x := node.(type) {
35 case *ast.File:
36 if f.cfg.simplify {
37 ls.markReferences(x)
38 }
39 s.file(x)
40 case ast.Expr:
41 if f.cfg.simplify {
42 ls.markReferences(x)
43 }
44 s.expr(x)
45 case ast.Decl:
46 if f.cfg.simplify {
47 ls.markReferences(x)
48 }
49 s.decl(x)
50
51
52 case []ast.Decl:
53 if f.cfg.simplify {
54 ls.processDecls(x)
55 }
56 s.walkDeclList(x)
57 default:
58 goto unsupported
59 }
60
61 return s.errs
62
63 unsupported:
64 return fmt.Errorf("cue/format: unsupported node type %T", node)
65 }
66
67 func isRegularField(tok token.Token) bool {
68 return tok == token.ILLEGAL || tok == token.COLON
69 }
70
71
72
73 func nestDepth(f *ast.Field) int {
74 d := 1
75 if s, ok := f.Value.(*ast.StructLit); ok {
76 switch {
77 case len(s.Elts) != 1:
78 d = 0
79 default:
80 if f, ok := s.Elts[0].(*ast.Field); ok {
81 d += nestDepth(f)
82 }
83 }
84 }
85 return d
86 }
87
88
89 func hasDocComments(d ast.Decl) bool {
90 if len(d.Comments()) > 0 {
91 return true
92 }
93 switch x := d.(type) {
94 case *ast.Field:
95 return len(x.Label.Comments()) > 0
96 case *ast.Alias:
97 return len(x.Ident.Comments()) > 0
98 case *ast.LetClause:
99 return len(x.Ident.Comments()) > 0
100 }
101 return false
102 }
103
104 func (f *formatter) walkDeclList(list []ast.Decl) {
105 f.before(nil)
106 d := 0
107 hasEllipsis := false
108 for i, x := range list {
109 if i > 0 {
110 f.print(declcomma)
111 nd := 0
112 if f, ok := x.(*ast.Field); ok {
113 nd = nestDepth(f)
114 }
115 if f.current.parentSep == newline && (d == 0 || nd != d) {
116 f.print(f.formfeed())
117 }
118 if hasDocComments(x) {
119 switch x := list[i-1].(type) {
120 case *ast.Field:
121 if internal.IsDefinition(x.Label) {
122 f.print(newsection)
123 }
124
125 default:
126 f.print(newsection)
127 }
128 }
129 }
130 if f.printer.cfg.simplify && internal.IsEllipsis(x) {
131 hasEllipsis = true
132 continue
133 }
134 f.decl(x)
135 d = 0
136 if f, ok := x.(*ast.Field); ok {
137 d = nestDepth(f)
138 }
139 if j := i + 1; j < len(list) {
140 switch x := list[j].(type) {
141 case *ast.Field:
142 switch x := x.Value.(type) {
143 case *ast.StructLit:
144
145
146
147 if x.Lbrace.IsValid() || len(x.Elts) != 1 {
148 f.print(f.formfeed())
149 continue
150 }
151 case *ast.ListLit:
152 f.print(f.formfeed())
153 continue
154 }
155 }
156 }
157 f.print(f.current.parentSep)
158 }
159 if hasEllipsis {
160 f.decl(&ast.Ellipsis{})
161 f.print(f.current.parentSep)
162 }
163 f.after(nil)
164 }
165
166 func (f *formatter) walkSpecList(list []*ast.ImportSpec) {
167 f.before(nil)
168 for _, x := range list {
169 f.before(x)
170 f.importSpec(x)
171 f.after(x)
172 }
173 f.after(nil)
174 }
175
176 func (f *formatter) walkClauseList(list []ast.Clause, ws whiteSpace) {
177 f.before(nil)
178 for _, x := range list {
179 f.before(x)
180 f.print(ws)
181 f.clause(x)
182 f.after(x)
183 }
184 f.after(nil)
185 }
186
187 func (f *formatter) walkListElems(list []ast.Expr) {
188 f.before(nil)
189 for _, x := range list {
190 f.before(x)
191 switch n := x.(type) {
192 case *ast.Comprehension:
193 f.walkClauseList(n.Clauses, blank)
194 f.print(blank, nooverride)
195 f.expr(n.Value)
196
197 case *ast.Ellipsis:
198 f.ellipsis(n)
199
200 case *ast.Alias:
201 f.expr(n.Ident)
202 f.print(n.Equal, token.BIND)
203 f.expr(n.Expr)
204
205
206
207 case ast.Expr:
208 f.exprRaw(n, token.LowestPrec, 1)
209 }
210 f.print(comma, blank)
211 f.after(x)
212 }
213 f.after(nil)
214 }
215
216 func (f *formatter) walkArgsList(list []ast.Expr, depth int) {
217 f.before(nil)
218 for _, x := range list {
219 f.before(x)
220 f.exprRaw(x, token.LowestPrec, depth)
221 f.print(comma, blank)
222 f.after(x)
223 }
224 f.after(nil)
225 }
226
227 func (f *formatter) file(file *ast.File) {
228 f.before(file)
229 f.walkDeclList(file.Decls)
230 f.after(file)
231 f.print(token.EOF)
232 }
233
234 func (f *formatter) inlineField(n *ast.Field) *ast.Field {
235 regular := internal.IsRegularField(n)
236
237
238
239 if !n.Label.Pos().IsValid() && !(f.printer.cfg.simplify && regular) {
240 return nil
241 }
242
243 obj, ok := n.Value.(*ast.StructLit)
244 if !ok || len(obj.Elts) != 1 ||
245 (obj.Lbrace.IsValid() && !f.printer.cfg.simplify) ||
246 (obj.Lbrace.IsValid() && hasDocComments(n)) ||
247 len(n.Attrs) > 0 {
248 return nil
249 }
250
251 mem, ok := obj.Elts[0].(*ast.Field)
252 if !ok || len(mem.Attrs) > 0 {
253 return nil
254 }
255
256 if hasDocComments(mem) {
257
258
259
260
261
262 return nil
263 }
264 return mem
265 }
266
267 func (f *formatter) decl(decl ast.Decl) {
268 if decl == nil {
269 return
270 }
271 defer f.after(decl)
272 if !f.before(decl) {
273 return
274 }
275
276 switch n := decl.(type) {
277 case *ast.Field:
278 constraint, _ := internal.ConstraintToken(n)
279 f.label(n.Label, constraint)
280
281 regular := isRegularField(n.Token)
282 if regular {
283 f.print(noblank, nooverride, n.TokenPos, token.COLON)
284 } else {
285 f.print(blank, nooverride, n.Token)
286 }
287
288 if mem := f.inlineField(n); mem != nil {
289 switch {
290 default:
291 fallthrough
292
293 case regular && f.cfg.simplify:
294 f.print(blank, nooverride)
295 f.decl(mem)
296
297 case mem.Label.Pos().IsNewline():
298 f.print(indent, formfeed)
299 f.decl(mem)
300 f.indent--
301 }
302 return
303 }
304
305 nextFF := f.nextNeedsFormfeed(n.Value)
306 tab := vtab
307 if nextFF {
308 tab = blank
309 }
310
311 f.print(tab)
312
313 if n.Value != nil {
314 switch n.Value.(type) {
315 case *ast.ListLit, *ast.StructLit:
316 f.expr(n.Value)
317 default:
318 f.print(indent)
319 f.expr(n.Value)
320 f.markUnindentLine()
321 }
322 } else {
323 f.current.pos++
324 f.visitComments(f.current.pos)
325 }
326
327 space := tab
328 for _, a := range n.Attrs {
329 if f.before(a) {
330 f.print(space, a.At, a)
331 }
332 f.after(a)
333 space = blank
334 }
335
336 if nextFF {
337 f.print(formfeed)
338 }
339
340 case *ast.BadDecl:
341 f.print(n.From, "*bad decl*", declcomma)
342
343 case *ast.Package:
344 f.print(n.PackagePos, "package")
345 f.print(blank, n.Name, newsection, nooverride)
346
347 case *ast.ImportDecl:
348 f.print(n.Import, "import")
349 if len(n.Specs) == 0 {
350 f.print(blank, n.Lparen, token.LPAREN, n.Rparen, token.RPAREN, newline)
351 break
352 }
353 switch {
354 case len(n.Specs) == 1 && len(n.Specs[0].Comments()) == 0:
355 if !n.Lparen.IsValid() {
356 f.print(blank)
357 f.walkSpecList(n.Specs)
358 break
359 }
360 fallthrough
361 default:
362 f.print(blank, n.Lparen, token.LPAREN, newline, indent)
363 f.walkSpecList(n.Specs)
364 f.print(unindent, newline, n.Rparen, token.RPAREN, newline)
365 }
366 f.print(newsection, nooverride)
367
368 case *ast.LetClause:
369 if !decl.Pos().HasRelPos() || decl.Pos().RelPos() >= token.Newline {
370 f.print(formfeed)
371 }
372 f.print(n.Let, token.LET, blank, nooverride)
373 f.expr(n.Ident)
374 f.print(blank, nooverride, n.Equal, token.BIND, blank)
375 f.expr(n.Expr)
376 f.print(declcomma)
377
378 case *ast.EmbedDecl:
379 if !n.Pos().HasRelPos() || n.Pos().RelPos() >= token.Newline {
380 f.print(formfeed)
381 }
382 f.expr(n.Expr)
383 f.print(newline, noblank)
384
385 case *ast.Attribute:
386 f.print(n.At, n)
387
388 case *ast.CommentGroup:
389 f.printComment(n)
390 f.print(newsection)
391
392 case ast.Expr:
393 f.embedding(n)
394 }
395 }
396
397 func (f *formatter) embedding(decl ast.Expr) {
398 switch n := decl.(type) {
399 case *ast.Comprehension:
400 if !n.Pos().HasRelPos() || n.Pos().RelPos() >= token.Newline {
401 f.print(formfeed)
402 }
403 f.walkClauseList(n.Clauses, blank)
404 f.print(blank, nooverride)
405 f.expr(n.Value)
406
407 case *ast.Ellipsis:
408 f.ellipsis(n)
409
410 case *ast.Alias:
411 if !decl.Pos().HasRelPos() || decl.Pos().RelPos() >= token.Newline {
412 f.print(formfeed)
413 }
414 f.expr(n.Ident)
415 f.print(blank, n.Equal, token.BIND, blank)
416 f.expr(n.Expr)
417 f.print(declcomma)
418
419
420
421 case ast.Expr:
422 f.exprRaw(n, token.LowestPrec, 1)
423 }
424 }
425
426 func (f *formatter) nextNeedsFormfeed(n ast.Expr) bool {
427 switch x := n.(type) {
428 case *ast.StructLit:
429 return true
430 case *ast.BasicLit:
431 return strings.IndexByte(x.Value, '\n') >= 0
432 case *ast.ListLit:
433 return true
434 case *ast.UnaryExpr:
435 return f.nextNeedsFormfeed(x.X)
436 case *ast.BinaryExpr:
437 return f.nextNeedsFormfeed(x.X) || f.nextNeedsFormfeed(x.Y)
438 case *ast.CallExpr:
439 for _, arg := range x.Args {
440 if f.nextNeedsFormfeed(arg) {
441 return true
442 }
443 }
444 }
445 return false
446 }
447
448 func (f *formatter) importSpec(x *ast.ImportSpec) {
449 if x.Name != nil {
450 f.label(x.Name, token.ILLEGAL)
451 f.print(blank)
452 } else {
453 f.current.pos++
454 f.visitComments(f.current.pos)
455 }
456 f.expr(x.Path)
457 f.print(newline)
458 }
459
460 func (f *formatter) label(l ast.Label, constraint token.Token) {
461 f.before(l)
462 defer f.after(l)
463 switch n := l.(type) {
464 case *ast.Alias:
465 f.expr(n)
466
467 case *ast.Ident:
468
469
470 name := n.Name
471 if !ast.IsValidIdent(name) {
472 name = literal.String.Quote(n.Name)
473 }
474 f.print(n.NamePos, name)
475
476 case *ast.BasicLit:
477 str := n.Value
478
479
480 if strings.HasPrefix(str, `"""`) || strings.HasPrefix(str, "#") {
481 if u, err := literal.Unquote(str); err == nil {
482 str = literal.String.Quote(u)
483 }
484 }
485 f.print(n.ValuePos, str)
486
487 case *ast.ListLit:
488 f.expr(n)
489
490 case *ast.ParenExpr:
491 f.expr(n)
492
493 case *ast.Interpolation:
494 f.expr(n)
495
496 default:
497 panic(fmt.Sprintf("unknown label type %T", n))
498 }
499 if constraint != token.ILLEGAL {
500 f.print(constraint)
501 }
502 }
503
504 func (f *formatter) ellipsis(x *ast.Ellipsis) {
505 f.print(x.Ellipsis, token.ELLIPSIS)
506 if x.Type != nil && !isTop(x.Type) {
507 f.expr(x.Type)
508 }
509 }
510
511 func (f *formatter) expr(x ast.Expr) {
512 const depth = 1
513 f.expr1(x, token.LowestPrec, depth)
514 }
515
516 func (f *formatter) expr0(x ast.Expr, depth int) {
517 f.expr1(x, token.LowestPrec, depth)
518 }
519
520 func (f *formatter) expr1(expr ast.Expr, prec1, depth int) {
521 if f.before(expr) {
522 f.exprRaw(expr, prec1, depth)
523 }
524 f.after(expr)
525 }
526
527 func (f *formatter) exprRaw(expr ast.Expr, prec1, depth int) {
528
529 switch x := expr.(type) {
530 case *ast.BadExpr:
531 f.print(x.From, "_|_")
532
533 case *ast.BottomLit:
534 f.print(x.Bottom, token.BOTTOM)
535
536 case *ast.Alias:
537
538 f.label(x.Ident, token.ILLEGAL)
539 f.print(x.Equal, token.BIND)
540 f.expr(x.Expr)
541
542 case *ast.Ident:
543 f.print(x.NamePos, x)
544
545 case *ast.BinaryExpr:
546 if depth < 1 {
547 f.internalError("depth < 1:", depth)
548 depth = 1
549 }
550 f.binaryExpr(x, prec1, cutoff(x, depth), depth)
551
552 case *ast.UnaryExpr:
553 const prec = token.UnaryPrec
554 if prec < prec1 {
555
556 f.print(token.LPAREN, nooverride)
557 f.expr(x)
558 f.print(token.RPAREN)
559 } else {
560
561 f.print(x.OpPos, x.Op, nooverride)
562 f.expr1(x.X, prec, depth)
563 }
564
565 case *ast.BasicLit:
566 f.print(x.ValuePos, x)
567
568 case *ast.Interpolation:
569 f.before(nil)
570 for _, x := range x.Elts {
571 f.expr0(x, depth+1)
572 }
573 f.after(nil)
574
575 case *ast.ParenExpr:
576 if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
577
578
579 f.expr0(x.X, depth)
580 } else {
581 f.print(x.Lparen, token.LPAREN)
582 f.expr0(x.X, reduceDepth(depth))
583 f.print(x.Rparen, token.RPAREN)
584 }
585
586 case *ast.SelectorExpr:
587 f.selectorExpr(x, depth)
588
589 case *ast.IndexExpr:
590 f.expr1(x.X, token.HighestPrec, 1)
591 f.print(x.Lbrack, token.LBRACK)
592 f.expr0(x.Index, depth+1)
593 f.print(x.Rbrack, token.RBRACK)
594
595 case *ast.SliceExpr:
596 f.expr1(x.X, token.HighestPrec, 1)
597 f.print(x.Lbrack, token.LBRACK)
598 indices := []ast.Expr{x.Low, x.High}
599 for i, y := range indices {
600 if i > 0 {
601
602 x := indices[i-1]
603 if depth <= 1 && x != nil && y != nil && (isBinary(x) || isBinary(y)) {
604 f.print(blank, token.COLON, blank)
605 } else {
606 f.print(token.COLON)
607 }
608 }
609 if y != nil {
610 f.expr0(y, depth+1)
611 }
612 }
613 f.print(x.Rbrack, token.RBRACK)
614
615 case *ast.CallExpr:
616 if len(x.Args) > 1 {
617 depth++
618 }
619 wasIndented := f.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
620 f.print(x.Lparen, token.LPAREN)
621 f.walkArgsList(x.Args, depth)
622 f.print(trailcomma, noblank, x.Rparen, token.RPAREN)
623 if wasIndented {
624 f.print(unindent)
625 }
626
627 case *ast.StructLit:
628 var l line
629 ws := noblank
630 ff := f.formfeed()
631
632 switch {
633 case len(x.Elts) == 0:
634 if !x.Rbrace.HasRelPos() {
635
636 ffAlt := blank | nooverride
637 for _, c := range x.Comments() {
638 if c.Position == 1 {
639 ffAlt = ff
640 }
641 }
642 ff = ffAlt
643 }
644 case !x.Rbrace.HasRelPos() || !x.Elts[0].Pos().HasRelPos():
645 ws |= newline | nooverride
646 }
647 f.print(x.Lbrace, token.LBRACE, &l, ws, ff, indent)
648
649 f.walkDeclList(x.Elts)
650 f.matchUnindent()
651
652 ws = noblank
653 if f.lineout != l {
654 ws |= newline
655 if f.lastTok != token.RBRACE && f.lastTok != token.RBRACK {
656 ws |= nooverride
657 }
658 }
659 f.print(ws, x.Rbrace, token.RBRACE)
660
661 case *ast.ListLit:
662 f.print(x.Lbrack, token.LBRACK, noblank, indent)
663 f.walkListElems(x.Elts)
664 f.print(trailcomma, noblank)
665 f.visitComments(f.current.pos)
666 f.matchUnindent()
667 f.print(noblank, x.Rbrack, token.RBRACK)
668
669 case *ast.Ellipsis:
670 f.ellipsis(x)
671
672 default:
673 panic(fmt.Sprintf("unimplemented type %T", x))
674 }
675 }
676
677 func (f *formatter) clause(clause ast.Clause) {
678 switch n := clause.(type) {
679 case *ast.ForClause:
680 f.print(n.For, "for", blank)
681 f.print(indent)
682 if n.Key != nil {
683 f.label(n.Key, token.ILLEGAL)
684 f.print(n.Colon, token.COMMA, blank)
685 } else {
686 f.current.pos++
687 f.visitComments(f.current.pos)
688 }
689 f.label(n.Value, token.ILLEGAL)
690 f.print(blank, n.In, "in", blank)
691 f.expr(n.Source)
692 f.markUnindentLine()
693
694 case *ast.IfClause:
695 f.print(n.If, "if", blank)
696 f.print(indent)
697 f.expr(n.Condition)
698 f.markUnindentLine()
699
700 case *ast.LetClause:
701 f.print(n.Let, token.LET, blank, nooverride)
702 f.print(indent)
703 f.expr(n.Ident)
704 f.print(blank, nooverride, n.Equal, token.BIND, blank)
705 f.expr(n.Expr)
706 f.markUnindentLine()
707
708 default:
709 panic("unknown clause type")
710 }
711 }
712
713 func walkBinary(e *ast.BinaryExpr) (has6, has7, has8 bool, maxProblem int) {
714 switch e.Op.Precedence() {
715 case 6:
716 has6 = true
717 case 7:
718 has7 = true
719 case 8:
720 has8 = true
721 }
722
723 switch l := e.X.(type) {
724 case *ast.BinaryExpr:
725 if l.Op.Precedence() < e.Op.Precedence() {
726
727
728 break
729 }
730 h6, h7, h8, mp := walkBinary(l)
731 has6 = has6 || h6
732 has7 = has7 || h7
733 has8 = has8 || h8
734 if maxProblem < mp {
735 maxProblem = mp
736 }
737 }
738
739 switch r := e.Y.(type) {
740 case *ast.BinaryExpr:
741 if r.Op.Precedence() <= e.Op.Precedence() {
742
743
744 break
745 }
746 h6, h7, h8, mp := walkBinary(r)
747 has6 = has6 || h6
748 has7 = has7 || h7
749 has8 = has8 || h8
750 if maxProblem < mp {
751 maxProblem = mp
752 }
753
754 case *ast.UnaryExpr:
755 switch e.Op.String() + r.Op.String() {
756 case "/*":
757 maxProblem = 8
758 case "++", "--":
759 if maxProblem < 6 {
760 maxProblem = 6
761 }
762 }
763 }
764 return
765 }
766
767 func cutoff(e *ast.BinaryExpr, depth int) int {
768 has6, has7, has8, maxProblem := walkBinary(e)
769 if maxProblem > 0 {
770 return maxProblem + 1
771 }
772 if (has6 || has7) && has8 {
773 if depth == 1 {
774 return 8
775 }
776 if has7 {
777 return 7
778 }
779 return 6
780 }
781 if has6 && has7 {
782 if depth == 1 {
783 return 7
784 }
785 return 6
786 }
787 if depth == 1 {
788 return 8
789 }
790 return 6
791 }
792
793 func diffPrec(expr ast.Expr, prec int) int {
794 x, ok := expr.(*ast.BinaryExpr)
795 if !ok || prec != x.Op.Precedence() {
796 return 1
797 }
798 return 0
799 }
800
801 func reduceDepth(depth int) int {
802 depth--
803 if depth < 1 {
804 depth = 1
805 }
806 return depth
807 }
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845 func (f *formatter) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
846 f.nestExpr++
847 defer func() { f.nestExpr-- }()
848
849 prec := x.Op.Precedence()
850 if prec < prec1 {
851
852
853
854
855 f.print(token.LPAREN, nooverride)
856 f.expr0(x, reduceDepth(depth))
857 f.print(token.RPAREN)
858 return
859 }
860
861 printBlank := prec < cutoff
862
863 f.expr1(x.X, prec, depth+diffPrec(x.X, prec))
864 f.print(nooverride)
865 if printBlank {
866 f.print(blank)
867 }
868 f.print(x.OpPos, x.Op)
869 if x.Y.Pos().IsNewline() {
870
871
872 f.print(formfeed)
873 printBlank = false
874 } else {
875 f.print(nooverride)
876 }
877 if printBlank {
878 f.print(blank)
879 }
880 f.expr1(x.Y, prec+1, depth+1)
881 }
882
883 func isBinary(expr ast.Expr) bool {
884 _, ok := expr.(*ast.BinaryExpr)
885 return ok
886 }
887
888 func (f *formatter) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool {
889 if x, ok := expr.(*ast.SelectorExpr); ok {
890 return f.selectorExpr(x, depth)
891 }
892 f.expr1(expr, prec1, depth)
893 return false
894 }
895
896
897
898 func (f *formatter) selectorExpr(x *ast.SelectorExpr, depth int) bool {
899 f.expr1(x.X, token.HighestPrec, depth)
900 f.print(token.PERIOD)
901 if x.Sel.Pos().IsNewline() {
902 f.print(indent, formfeed)
903 f.expr(x.Sel.(ast.Expr))
904 f.print(unindent)
905 return true
906 }
907 f.print(noblank)
908 f.expr(x.Sel.(ast.Expr))
909 return false
910 }
911
912 func isTop(e ast.Expr) bool {
913 ident, ok := e.(*ast.Ident)
914 return ok && ident.Name == "_"
915 }
916
View as plain text