From c8471528ce0b121a930437c8781e7ceb935402cc Mon Sep 17 00:00:00 2001
From: Enzo <enzo.baldisserri@outlook.fr>
Date: Fri, 10 Sep 2021 19:56:55 +0200
Subject: [PATCH] fmt: format long sum-types with a line for each type (#11461)

---
 vlib/orm/orm.v                            |  16 ++-
 vlib/v/ast/ast.v                          | 118 +++++++++++++++++++---
 vlib/v/ast/comptime_const_values.v        |  15 ++-
 vlib/v/ast/types.v                        |  16 ++-
 vlib/v/fmt/fmt.v                          |  29 ++++--
 vlib/v/fmt/tests/long_sumtype_expected.vv |  13 +++
 vlib/v/fmt/tests/long_sumtype_input.vv    |   6 ++
 vlib/x/json2/decoder.v                    |   3 +-
 8 files changed, 182 insertions(+), 34 deletions(-)
 create mode 100644 vlib/v/fmt/tests/long_sumtype_expected.vv
 create mode 100644 vlib/v/fmt/tests/long_sumtype_input.vv

diff --git a/vlib/orm/orm.v b/vlib/orm/orm.v
index 11cfc9a941..c741fa7adb 100644
--- a/vlib/orm/orm.v
+++ b/vlib/orm/orm.v
@@ -37,8 +37,20 @@ pub const (
 	string_max_len = 2048
 )
 
-pub type Primitive = InfixType | bool | byte | f32 | f64 | i16 | i64 | i8 | int | string |
-	time.Time | u16 | u32 | u64
+pub type Primitive = InfixType
+	| bool
+	| byte
+	| f32
+	| f64
+	| i16
+	| i64
+	| i8
+	| int
+	| string
+	| time.Time
+	| u16
+	| u32
+	| u64
 
 pub enum OperationKind {
 	neq // !=
diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v
index 45f1c1c967..4e76758276 100644
--- a/vlib/v/ast/ast.v
+++ b/vlib/v/ast/ast.v
@@ -9,25 +9,104 @@ import v.pref
 
 pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
 
-pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
-	CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
-	ComptimeSelector | ConcatExpr | DumpExpr | EmptyExpr | EnumVal | FloatLiteral | GoExpr |
-	Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | IsRefType |
-	Likely | LockExpr | MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr |
-	PostfixExpr | PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr |
-	StringInterLiteral | StringLiteral | StructInit | TypeNode | TypeOf | UnsafeExpr
+pub type Expr = AnonFn
+	| ArrayDecompose
+	| ArrayInit
+	| AsCast
+	| Assoc
+	| AtExpr
+	| BoolLiteral
+	| CTempVar
+	| CallExpr
+	| CastExpr
+	| ChanInit
+	| CharLiteral
+	| Comment
+	| ComptimeCall
+	| ComptimeSelector
+	| ConcatExpr
+	| DumpExpr
+	| EmptyExpr
+	| EnumVal
+	| FloatLiteral
+	| GoExpr
+	| Ident
+	| IfExpr
+	| IfGuardExpr
+	| IndexExpr
+	| InfixExpr
+	| IntegerLiteral
+	| IsRefType
+	| Likely
+	| LockExpr
+	| MapInit
+	| MatchExpr
+	| NodeError
+	| None
+	| OffsetOf
+	| OrExpr
+	| ParExpr
+	| PostfixExpr
+	| PrefixExpr
+	| RangeExpr
+	| SelectExpr
+	| SelectorExpr
+	| SizeOf
+	| SqlExpr
+	| StringInterLiteral
+	| StringLiteral
+	| StructInit
+	| TypeNode
+	| TypeOf
+	| UnsafeExpr
 
-pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
-	DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
-	GlobalDecl | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | NodeError |
-	Return | SqlStmt | StructDecl | TypeDecl
+pub type Stmt = AsmStmt
+	| AssertStmt
+	| AssignStmt
+	| Block
+	| BranchStmt
+	| CompFor
+	| ConstDecl
+	| DeferStmt
+	| EmptyStmt
+	| EnumDecl
+	| ExprStmt
+	| FnDecl
+	| ForCStmt
+	| ForInStmt
+	| ForStmt
+	| GlobalDecl
+	| GotoLabel
+	| GotoStmt
+	| HashStmt
+	| Import
+	| InterfaceDecl
+	| Module
+	| NodeError
+	| Return
+	| SqlStmt
+	| StructDecl
+	| TypeDecl
 
 pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var
 
 // TODO: replace Param
-pub type Node = CallArg | ConstField | EmptyNode | EnumField | Expr | File | GlobalField |
-	IfBranch | MatchBranch | NodeError | Param | ScopeObject | SelectBranch | Stmt | StructField |
-	StructInitField
+pub type Node = CallArg
+	| ConstField
+	| EmptyNode
+	| EnumField
+	| Expr
+	| File
+	| GlobalField
+	| IfBranch
+	| MatchBranch
+	| NodeError
+	| Param
+	| ScopeObject
+	| SelectBranch
+	| Stmt
+	| StructField
+	| StructInitField
 
 pub struct TypeNode {
 pub:
@@ -1155,8 +1234,15 @@ pub mut:
 }
 
 // [eax+5] | j | displacement literal (e.g. 123 in [rax + 123] ) | eax | true | `a` | 0.594 | 123 | label_name
-pub type AsmArg = AsmAddressing | AsmAlias | AsmDisp | AsmRegister | BoolLiteral | CharLiteral |
-	FloatLiteral | IntegerLiteral | string
+pub type AsmArg = AsmAddressing
+	| AsmAlias
+	| AsmDisp
+	| AsmRegister
+	| BoolLiteral
+	| CharLiteral
+	| FloatLiteral
+	| IntegerLiteral
+	| string
 
 pub struct AsmRegister {
 pub mut:
diff --git a/vlib/v/ast/comptime_const_values.v b/vlib/v/ast/comptime_const_values.v
index 6f9ef6a1c9..8e1337a38a 100644
--- a/vlib/v/ast/comptime_const_values.v
+++ b/vlib/v/ast/comptime_const_values.v
@@ -1,7 +1,18 @@
 module ast
 
-pub type ComptTimeConstValue = EmptyExpr | byte | f32 | f64 | i16 | i64 | i8 | int | rune |
-	string | u16 | u32 | u64
+pub type ComptTimeConstValue = EmptyExpr
+	| byte
+	| f32
+	| f64
+	| i16
+	| i64
+	| i8
+	| int
+	| rune
+	| string
+	| u16
+	| u32
+	| u64
 
 pub fn empty_comptime_const_expr() ComptTimeConstValue {
 	return EmptyExpr{}
diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v
index 73d40a822d..a053f0f02b 100644
--- a/vlib/v/ast/types.v
+++ b/vlib/v/ast/types.v
@@ -16,8 +16,20 @@ import v.pref
 
 pub type Type = int
 
-pub type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType | GenericInst |
-	Interface | Map | MultiReturn | Struct | SumType | Thread
+pub type TypeInfo = Aggregate
+	| Alias
+	| Array
+	| ArrayFixed
+	| Chan
+	| Enum
+	| FnType
+	| GenericInst
+	| Interface
+	| Map
+	| MultiReturn
+	| Struct
+	| SumType
+	| Thread
 
 pub enum Language {
 	v
diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v
index 3c7f3387df..62297b98a1 100644
--- a/vlib/v/fmt/fmt.v
+++ b/vlib/v/fmt/fmt.v
@@ -1262,6 +1262,7 @@ pub fn (mut f Fmt) fn_type_decl(node ast.FnTypeDecl) {
 }
 
 pub fn (mut f Fmt) sum_type_decl(node ast.SumTypeDecl) {
+	start_pos := f.out.len
 	if node.is_pub {
 		f.write('pub ')
 	}
@@ -1269,19 +1270,27 @@ pub fn (mut f Fmt) sum_type_decl(node ast.SumTypeDecl) {
 	f.write_generic_types(node.generic_types)
 	f.write(' = ')
 
-	mut sum_type_names := []string{}
-	for t in node.variants {
-		sum_type_names << f.table.type_to_str_using_aliases(t.typ, f.mod2alias)
-	}
+	mut sum_type_names := node.variants.map(f.table.type_to_str_using_aliases(it.typ,
+		f.mod2alias))
 	sum_type_names.sort()
+
+	mut separator := ' | '
+	// if line length is too long, put each type on its own line
+	mut line_length := f.out.len - start_pos
+	for sum_type_name in sum_type_names {
+		// 3 = length of ' = ' or ' | '
+		line_length += 3 + sum_type_name.len
+		if line_length > fmt.max_len.last() {
+			separator = '\n\t| '
+			break
+		}
+	}
+
 	for i, name in sum_type_names {
+		if i > 0 {
+			f.write(separator)
+		}
 		f.write(name)
-		if i < sum_type_names.len - 1 {
-			f.write(' | ')
-		}
-		if i < sum_type_names.len - 1 {
-			f.wrap_long_line(3, true)
-		}
 	}
 
 	f.comments(node.comments, has_nl: false)
diff --git a/vlib/v/fmt/tests/long_sumtype_expected.vv b/vlib/v/fmt/tests/long_sumtype_expected.vv
new file mode 100644
index 0000000000..89a34efdd2
--- /dev/null
+++ b/vlib/v/fmt/tests/long_sumtype_expected.vv
@@ -0,0 +1,13 @@
+import v.ast
+
+type ManyExpr = ast.AnonFn
+	| ast.ArrayDecompose
+	| ast.ArrayInit
+	| ast.AsCast
+	| ast.AtExpr
+	| ast.BoolLiteral
+	| ast.CTempVar
+	| ast.CallExpr
+	| ast.CastExpr
+
+type SomeStmt = ast.AsmStmt | ast.AssertStmt
diff --git a/vlib/v/fmt/tests/long_sumtype_input.vv b/vlib/v/fmt/tests/long_sumtype_input.vv
new file mode 100644
index 0000000000..f7db7ee2e5
--- /dev/null
+++ b/vlib/v/fmt/tests/long_sumtype_input.vv
@@ -0,0 +1,6 @@
+import v.ast
+
+type ManyExpr = ast.AnonFn | ast.ArrayDecompose | ast.ArrayInit | ast.AsCast | ast.AtExpr | ast.BoolLiteral | ast.CTempVar | ast.CallExpr | ast.CastExpr
+
+type SomeStmt = ast.AsmStmt
+	| ast.AssertStmt
diff --git a/vlib/x/json2/decoder.v b/vlib/x/json2/decoder.v
index a45a091e7d..991be8abc6 100644
--- a/vlib/x/json2/decoder.v
+++ b/vlib/x/json2/decoder.v
@@ -4,8 +4,7 @@
 module json2
 
 // `Any` is a sum type that lists the possible types to be decoded and used.
-pub type Any = Null | []Any | bool | f32 | f64 | i64 | int | map[string]Any | string |
-	u64
+pub type Any = Null | []Any | bool | f32 | f64 | i64 | int | map[string]Any | string | u64
 
 // `Null` struct is a simple representation of the `null` value in JSON.
 pub struct Null {