@@ -619,7 +619,14 @@ impl formatter {
619619 self.formatType(d.Kind)
620620 }
621621
622- fn varDecl(&self, mut d: &ast::Var, head: bool) {
622+ fn varDecl(&self, mut d: &ast::Var, head: bool, mut counts: [5]int) {
623+ // Layout of counts.
624+ mut typeAnnoMax := counts[0] // maximum name length for type alignment column
625+ mut nameMax := counts[1] // maximum name length of the group
626+ nameMaxHaveType := counts[2] == 1 // whether nameMax owner have type annotation
627+ mut typeMax := counts[3] // maximum length of the type annotations
628+ table := counts[4] == 1 // whether the alignment is like table, column-by-column
629+
623630 if head {
624631 if len(d.Directives) != 0 {
625632 self.directives(d.Directives)
@@ -642,14 +649,63 @@ impl formatter {
642649 self.write("&")
643650 }
644651 }
652+ nameLen := utf8::RuneCountStr(d.Ident)
645653 self.write(d.Ident)
646654 self.row = d.Token.Row
655+ mut typ := 0
647656 if d.Kind != nil {
648657 self.write(": ")
658+ // If typeAnnoMax>0, add the missing leading spaces for type annotation.
659+ if typeAnnoMax > 0 {
660+ diff := typeAnnoMax - nameLen
661+ if diff > 0 {
662+ self.write(strings::Repeat(" ", diff))
663+ }
664+ }
665+ n := len(self.ubuf())
649666 self.formatType(d.Kind)
667+ typ = utf8::RuneCount(self.ubuf()[n:]) // subtract the runes of type
650668 self.row = d.Kind.Token.Row
651669 }
652670 if d.Expr != nil {
671+ // If nameMax>0, we have to do alignment.
672+ if nameMax > 0 {
673+ // If typeMax>0 and d.Kind==nil, we have type alignment.
674+ // But this variable have not type annotation.
675+ // Add spaces for the missing ": " part of type annotations.
676+ if (nameMaxHaveType || table) && typeMax > 0 && d.Kind == nil {
677+ nameMax += 2
678+ }
679+ // If the maximum name have not type annotation and this variable have,
680+ // remove the spaces of the ": " part of type annotations.
681+ if !nameMaxHaveType && d.Kind != nil {
682+ nameMax -= 2
683+ }
684+ // If we have type alignment and this variable have type annotation,
685+ // add missing trailing spaces to reach maximum type annotation length.
686+ if typeMax > 0 && d.Kind != nil {
687+ diff := typeMax - typ
688+ if diff > 0 {
689+ self.write(strings::Repeat(" ", diff))
690+ }
691+ // Remove the added spaces from alignment.
692+ nameMax -= diff
693+ }
694+ // Remove the spaces of type annotation length of this variable.
695+ nameMax -= typ
696+ // If type annotation alignemnt exist and this variable have type annotation,
697+ // remove the spaces of annotation alignment, because type annotation is aligned.
698+ // Otherwise, remove spaces for name length,
699+ // there are still missing spaces for type annotations.
700+ if typeAnnoMax > 0 && d.Kind != nil {
701+ nameMax -= typeAnnoMax
702+ } else {
703+ nameMax -= nameLen
704+ }
705+ if nameMax > 0 {
706+ self.write(strings::Repeat(" ", nameMax))
707+ }
708+ }
653709 self.write(" ")
654710 self.write(d.Setter.Kind)
655711 self.write(" ")
@@ -704,7 +760,7 @@ impl formatter {
704760 }
705761 fm += utf8::RuneCountStr(decl.f.Ident)
706762 self.formatType(decl.f.Kind)
707- tm := len (self.ubuf()) - n
763+ tm := utf8::RuneCount (self.ubuf()[n:])
708764 self.setBuf(self.ubuf()[:n])
709765 if row != -1 && decl.token.Row != self.row {
710766 break
@@ -770,16 +826,144 @@ impl formatter {
770826 ret
771827 }
772828
773- fn varGroup(&self, mut root: &ast::Var) {
774- mut lines := make([][]byte, 0, len(root.Group))
775- mut rows := make([]int, 0, len(root.Group))
829+ fn varSubGroup(&self, mut vars: []&ast::Var, mut &i: int) {
830+ // Do not increase the i, because all grouped variables are represented by the root.
831+ mut lines := make([][]byte, 0, len(vars[i:]))
832+ mut rows := make([]int, 0, len(vars[i:]))
833+ mut counts := make([][2]int, 0, len(vars[i:]))
776834
777- self.buf.Write(self.indent)!
778- self.write("const (\n")
779- self.addIndent()
835+ start := i
780836 mut n := self.buf.Len()
781- for (_, mut v) in root.Group {
782- self.varDecl(v, false)
837+
838+ // Returns maximum length of identifiers for type annotation alignment.
839+ // j is the current varaible.
840+ getTypeAnnoMax := fn(mut j: int): (nameMax: int) {
841+ counts = counts[:unsafe { i }-start] // use all capacity of counts
842+ for j > start {
843+ v := vars[j-1]
844+ if v.Kind != nil {
845+ j--
846+ } else {
847+ break
848+ }
849+ }
850+ for j < unsafe { i }; j++ {
851+ mut v := vars[j]
852+ if !isPub(v.Ident) {
853+ continue
854+ }
855+ if v.Kind != nil {
856+ name := counts[j-start][0]
857+ if name > nameMax {
858+ nameMax = name
859+ }
860+ } else {
861+ break
862+ }
863+ }
864+ ret
865+ }
866+
867+ // Returns maximum length of assignment alignment.
868+ // j is the current varaible
869+ getAssignMax := fn(mut j: int, mut &typeAnnoMax: int): (nameMax: int, nameMaxHaveType: int, typeMax: int, table: int) {
870+ counts = counts[:unsafe { i }-start] // use all capacity of counts
871+ for j > start {
872+ v := vars[j-1]
873+ if v.Expr != nil || self.isPopsRowCommentsByF(v.Token.Row, -1) {
874+ j--
875+ } else {
876+ break
877+ }
878+ }
879+ mut fullComment := true // whether the all group members have comment
880+ mut maxPlainName := 0
881+ mut maxNameWithType := typeAnnoMax
882+ for j < unsafe { i }; j++ {
883+ mut v := vars[j]
884+ if !isPub(v.Ident) {
885+ continue
886+ }
887+ comment := self.isPopsRowCommentsByF(v.Token.Row, -1)
888+ if v.Expr == nil && !comment {
889+ break
890+ }
891+ fullComment = fullComment && comment
892+ c := counts[j-start]
893+ t := c[0]
894+ if maxPlainName < t {
895+ maxPlainName = t
896+ }
897+ if v.Kind != nil {
898+ if maxNameWithType < t {
899+ maxNameWithType = t
900+ }
901+ }
902+ if c[1] > typeMax {
903+ typeMax = c[1]
904+ }
905+ }
906+ if fullComment {
907+ table = 1
908+ // typeAnnoMax must strore the maximum length of the group for type alignment.
909+ typeAnnoMax = maxNameWithType
910+ if typeAnnoMax < maxPlainName {
911+ typeAnnoMax = maxPlainName
912+ }
913+ // add typeMax to maxPlainName for type alignment.
914+ // Because all the group must be aligned column-by-column.
915+ maxPlainName += typeMax
916+ }
917+ maxNameWithType += typeMax
918+ maxNameWithType += 2 // add space for ": " part of type annotation
919+ if maxNameWithType > maxPlainName {
920+ maxNameWithType -= 2 // remove space for ": " part of type annotation
921+ nameMax = maxNameWithType
922+ nameMaxHaveType = 1
923+ } else {
924+ nameMax = maxPlainName
925+ nameMaxHaveType = 0
926+ }
927+ ret
928+ }
929+
930+ self.row = -1
931+ for i < len(vars); i++ {
932+ mut v := vars[i]
933+ if !isPub(v.Ident) {
934+ continue
935+ }
936+ row := self.row // save the first row data to after use
937+ // If the row is not first, compare current row with the previous one.
938+ // If the difference greatest than one row, end the iteration.
939+ if row != -1 && v.Token.Row-vars[i-1].Token.Row > 1 {
940+ break
941+ }
942+ self.row = v.Token.Row
943+ mut name := utf8::RuneCountStr(v.Ident)
944+ mut typ := 0
945+ if v.Kind != nil {
946+ self.formatType(v.Kind)
947+ typ = utf8::RuneCount(self.ubuf()[n:])
948+ self.setBuf(self.ubuf()[:n])
949+ if row != -1 && v.Token.Row != self.row {
950+ break
951+ }
952+ }
953+ if v.Expr != nil {
954+ self.formatExpr(v.Expr)
955+ self.setBuf(self.ubuf()[:n])
956+ if row != -1 && v.Token.Row != self.row {
957+ break
958+ }
959+ }
960+ counts = append(counts, [name, typ])
961+ }
962+ mut z := start
963+ for z < i; z++ {
964+ mut typeAnnoMax := getTypeAnnoMax(z)
965+ nameMax, nameMaxHaveType, typeMax, table := getAssignMax(z, typeAnnoMax)
966+ self.varDecl(vars[z], false, [typeAnnoMax, nameMax, nameMaxHaveType, typeMax, table])
783967 mut line := cloneBuf(self.ubuf()[n:])
784968 lines = append(lines, line)
785969 rows = append(rows, self.row)
@@ -789,7 +973,7 @@ impl formatter {
789973 mut max := 0
790974 mut rowBreak := indexRowBrake(rows)
791975 for j, line in lines {
792- isPub := isPub(root.Group[ j].Ident) // Ignore private ones.
976+ isPub := isPub(vars[start+ j].Ident) // Ignore private ones.
793977 row := rows[j]
794978 if j == rowBreak {
795979 self.write("\n")
@@ -819,10 +1003,28 @@ impl formatter {
8191003 self.write("\n")
8201004 }
8211005 }
1006+ self.row = rows[len(rows)-1] + 1 // Add +1 offset for "\n)" suffix.
1007+ }
1008+
1009+ fn varGroup(&self, mut root: &ast::Var) {
1010+ self.buf.Write(self.indent)!
1011+ self.write("const (\n")
1012+ self.addIndent()
1013+ mut j := 0
1014+ for j < len(root.Group) {
1015+ old := j
1016+ self.varSubGroup(root.Group, j)
1017+ if old != j {
1018+ if j < len(root.Group) {
1019+ self.write("\n")
1020+ }
1021+ } else {
1022+ j++
1023+ }
1024+ }
8221025 self.doneIndent()
8231026 self.buf.Write(self.indent)!
8241027 self.write(")")
825- self.row = rows[len(rows)-1] + 1 // Add +1 offset for "\n)" suffix.
8261028 }
8271029
8281030 fn groupDecls[T, Node](&self, mut nodes: []Node, mut &i: int, writer: fn(mut &d: T)) {
@@ -952,7 +1154,7 @@ impl formatter {
9521154 if d.Group != nil {
9531155 self.varGroup(d)
9541156 } else {
955- self.varDecl(d, true)
1157+ self.varDecl(d, true, [] )
9561158 }
9571159 ret
9581160 | &ast::Func:
0 commit comments