fmt: align struct field comments (#7632)

pull/7844/head^2
zakuro 2021-01-04 05:10:25 +09:00 committed by GitHub
parent 095857d59b
commit dd516858d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 267 additions and 162 deletions

View File

@ -580,6 +580,60 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
f.writeln('\n')
}
const (
threshold_to_align_struct = 8
)
struct CommentAndExprAlignInfo {
mut:
max_attrs_len int
max_type_len int
first_line int
last_line int
}
fn (mut list []CommentAndExprAlignInfo) add_new_info(attrs_len int, type_len int, line int) {
list << CommentAndExprAlignInfo{
max_attrs_len: attrs_len
max_type_len: type_len
first_line: line
last_line: line
}
}
[inline]
fn abs(v int) int {
return if v >= 0 {
v
} else {
-v
}
}
fn (mut list []CommentAndExprAlignInfo) add_info(attrs_len int, type_len int, line int) {
if list.len == 0 {
list.add_new_info(attrs_len, type_len, line)
return
}
i := list.len - 1
if line - list[i].last_line > 1 {
list.add_new_info(attrs_len, type_len, line)
return
}
d_len := abs(list[i].max_attrs_len - attrs_len) + abs(list[i].max_type_len - type_len)
if !(d_len < threshold_to_align_struct) {
list.add_new_info(attrs_len, type_len, line)
return
}
list[i].last_line = line
if attrs_len > list[i].max_attrs_len {
list[i].max_attrs_len = attrs_len
}
if type_len > list[i].max_type_len {
list[i].max_type_len = type_len
}
}
pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
f.attrs(node.attrs)
if node.is_pub {
@ -605,14 +659,28 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
}
f.writeln(' {')
mut max := 0
mut max_type := 0
mut max_type_len := 0
mut comment_aligns := []CommentAndExprAlignInfo{}
mut default_expr_aligns := []CommentAndExprAlignInfo{}
mut field_types := []string{cap: node.fields.len}
for field in node.fields {
for i, field in node.fields {
mut ft := f.no_cur_mod(f.table.type_to_str(field.typ))
if !ft.contains('C.') && !ft.contains('JS.') && !ft.contains('fn (') {
ft = f.short_module(ft)
}
field_types << ft
if ft.len > max_type_len {
max_type_len = ft.len
}
attrs_len := inline_attrs_len(field.attrs)
end_pos := field.pos.pos + field.pos.len
mut comments_len := 0 // Length of comments between field name and type
for comment in field.comments {
if comment.pos.pos >= end_pos {
break
if comment.pos.line_nr == field.pos.line_nr {
comment_aligns.add_info(attrs_len, field_types[i].len, comment.pos.line_nr)
}
continue
}
if comment.pos.pos > field.pos.pos {
comments_len += '/* $comment.text */ '.len
@ -621,19 +689,16 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
if comments_len + field.name.len > max {
max = comments_len + field.name.len
}
mut ft := f.no_cur_mod(f.table.type_to_str(field.typ))
if !ft.contains('C.') && !ft.contains('JS.') && !ft.contains('fn (') {
ft = f.short_module(ft)
}
field_types << ft
if ft.len > max_type {
max_type = ft.len
if field.has_default_expr {
default_expr_aligns.add_info(attrs_len, field_types[i].len, field.pos.line_nr)
}
}
for embed in node.embeds {
styp := f.table.type_to_str(embed.typ)
f.writeln('\t$styp')
}
mut comment_align_i := 0
mut default_expr_align_i := 0
for i, field in node.fields {
if i == node.mut_pos {
f.writeln('mut:')
@ -665,11 +730,21 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
}
f.write(strings.repeat(` `, max - field.name.len - comments_len))
f.write(field_types[i])
if field.attrs.len > 0 {
f.write(strings.repeat(` `, max_type - field_types[i].len))
after_type_pad_len := max_type_len - field_types[i].len
attrs_len := inline_attrs_len(field.attrs)
has_attrs := field.attrs.len > 0
if has_attrs {
f.write(strings.repeat(` `, after_type_pad_len))
f.inline_attrs(field.attrs)
}
if field.has_default_expr {
mut align := default_expr_aligns[default_expr_align_i]
if align.last_line < field.pos.line_nr {
default_expr_align_i++
align = default_expr_aligns[default_expr_align_i]
}
pad_len := align.max_attrs_len - attrs_len + align.max_type_len - field_types[i].len
f.write(strings.repeat(` `, pad_len))
f.write(' = ')
f.prefix_expr_cast_expr(field.default_expr)
}
@ -678,6 +753,15 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
if comments[comm_idx].pos.line_nr > field.pos.line_nr {
f.writeln('')
} else {
if !field.has_default_expr {
mut align := comment_aligns[comment_align_i]
if align.last_line < field.pos.line_nr {
comment_align_i++
align = comment_aligns[comment_align_i]
}
pad_len := align.max_attrs_len - attrs_len + align.max_type_len - field_types[i].len
f.write(strings.repeat(` `, pad_len))
}
f.write(' ')
}
f.comments(comments[comm_idx..], level: .indent)
@ -1230,6 +1314,21 @@ fn (mut f Fmt) inline_attrs(attrs []table.Attr) {
f.write(']')
}
fn inline_attrs_len(attrs []table.Attr) int {
if attrs.len == 0 {
return 0
}
mut n := 2 // ' ['.len
for i, attr in attrs {
if i > 0 {
n += 2 // '; '.len
}
n += '$attr'.len
}
n++ // ']'.len
return n
}
enum CommentsLevel {
keep
indent

View File

@ -1,15 +1,18 @@
struct User {
name string
name string // name
name2 ustring // name2
very_long_field bool
age int
age int // age
very_long_type_field1 very_looooog_type // long
very_long_type_field2 very_loooooooong_type // long
}
struct Foo {
field1 int
field2 string
field1 int // f1
field2 string // f2
pub:
public_field1 int
public_field2 f64
public_field1 int // f1
public_field2 f64 // f2
mut:
mut_field string
pub mut:

View File

@ -1,15 +1,18 @@
struct User {
name string
name string // name
name2 ustring // name2
very_long_field bool
age int
age int // age
very_long_type_field1 very_looooog_type // long
very_long_type_field2 very_loooooooong_type // long
}
struct Foo {
field1 int
field2 string
field1 int // f1
field2 string // f2
pub:
public_field1 int
public_field2 f64
public_field1 int // f1
public_field2 f64 // f2
mut:
mut_field string
pub mut: