fmt: fix interface fields/methods alignment (#22055)

This commit is contained in:
yuyi 2024-08-16 16:35:53 +08:00 committed by GitHub
parent 384b5c466f
commit 38e23a76f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 51 additions and 41 deletions

View file

@ -1400,27 +1400,36 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
} }
mut type_align := new_field_align() mut type_align := new_field_align()
mut comment_align := new_field_align() mut comment_align := new_field_align(use_threshold: true)
mut default_expr_align := new_field_align() mut default_expr_align := new_field_align(use_threshold: true)
mut attr_align := new_field_align() mut attr_align := new_field_align(use_threshold: true)
mut field_types := []string{cap: node.fields.len} mut field_types := []string{cap: node.fields.len}
// Calculate the alignments first // Calculate the alignments first
f.calculate_alignment(node.fields, mut type_align, mut comment_align, mut default_expr_align, mut f.calculate_alignment(node.fields, mut type_align, mut comment_align, mut default_expr_align, mut
attr_align, mut field_types) attr_align, mut field_types)
mut method_comment_align := new_field_align(use_threshold: true)
for method in node.methods {
end_comments := method.comments.filter(it.pos.pos > method.pos.pos)
if end_comments.len > 0 {
method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')
method_comment_align.add_info(method_str.len, method.pos.line_nr)
}
}
// TODO: alignment, comments, etc. // TODO: alignment, comments, etc.
for field in immut_fields { for field in immut_fields {
if field.has_prev_newline { if field.has_prev_newline {
f.writeln('') f.writeln('')
} }
f.interface_field(field, type_align.max_len(field.pos.line_nr)) f.interface_field(field, mut type_align, mut comment_align)
} }
for method in immut_methods { for method in immut_methods {
if method.has_prev_newline { if method.has_prev_newline {
f.writeln('') f.writeln('')
} }
f.interface_method(method) f.interface_method(method, mut method_comment_align)
} }
if mut_fields.len + mut_methods.len > 0 { if mut_fields.len + mut_methods.len > 0 {
f.writeln('mut:') f.writeln('mut:')
@ -1428,13 +1437,13 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
if field.has_prev_newline { if field.has_prev_newline {
f.writeln('') f.writeln('')
} }
f.interface_field(field, type_align.max_len(field.pos.line_nr)) f.interface_field(field, mut type_align, mut comment_align)
} }
for method in mut_methods { for method in mut_methods {
if method.has_prev_newline { if method.has_prev_newline {
f.writeln('') f.writeln('')
} }
f.interface_method(method) f.interface_method(method, mut method_comment_align)
} }
} }
f.writeln('}\n') f.writeln('}\n')
@ -1497,7 +1506,7 @@ pub fn (mut f Fmt) calculate_alignment(fields []ast.StructField, mut type_align
} }
} }
pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) { pub fn (mut f Fmt) interface_field(field ast.StructField, mut type_align FieldAlign, mut comment_align FieldAlign) {
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias)) ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias))
mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{} mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{}
for cmt in field.comments { for cmt in field.comments {
@ -1507,11 +1516,9 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
else { end_cmts << cmt } else { end_cmts << cmt }
} }
} }
before_len := f.line_len
if pre_cmts.len > 0 { if pre_cmts.len > 0 {
f.comments(pre_cmts, level: .indent) f.comments(pre_cmts, level: .indent)
} }
comments_len := f.line_len - before_len
sym := f.table.sym(field.typ) sym := f.table.sym(field.typ)
if sym.info is ast.Struct { if sym.info is ast.Struct {
@ -1525,10 +1532,12 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
f.write('\t${field.name} ') f.write('\t${field.name} ')
} }
if !(sym.info is ast.Struct && sym.info.is_anon) { if !(sym.info is ast.Struct && sym.info.is_anon) {
f.write(strings.repeat(` `, max_len - field.name.len - comments_len)) f.write(strings.repeat(` `, type_align.max_len(field.pos.line_nr) - field.name.len))
f.write(ft) f.write(ft)
} }
if end_cmts.len > 0 { if end_cmts.len > 0 {
f.write(strings.repeat(` `, comment_align.max_len(field.pos.line_nr) - ft.len))
f.write(' ')
f.comments(end_cmts, level: .indent) f.comments(end_cmts, level: .indent)
} else { } else {
f.writeln('') f.writeln('')
@ -1539,16 +1548,22 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
f.mark_types_import_as_used(field.typ) f.mark_types_import_as_used(field.typ)
} }
pub fn (mut f Fmt) interface_method(method ast.FnDecl) { pub fn (mut f Fmt) interface_method(method ast.FnDecl, mut comment_align FieldAlign) {
before_comments := method.comments.filter(it.pos.pos < method.pos.pos) before_comments := method.comments.filter(it.pos.pos < method.pos.pos)
end_comments := method.comments.filter(it.pos.pos > method.pos.pos) end_comments := method.comments.filter(it.pos.pos > method.pos.pos)
if before_comments.len > 0 { if before_comments.len > 0 {
f.comments(before_comments, level: .indent) f.comments(before_comments, level: .indent)
} }
f.write('\t') f.write('\t')
f.write(f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')) method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')
f.comments(end_comments, same_line: true, has_nl: false, level: .indent) f.write(method_str)
if end_comments.len > 0 {
f.write(strings.repeat(` `, comment_align.max_len(method.pos.line_nr) - method_str.len))
f.write(' ')
f.comments(end_comments, level: .indent)
} else {
f.writeln('') f.writeln('')
}
f.comments(method.next_comments, level: .indent) f.comments(method.next_comments, level: .indent)
for param in method.params { for param in method.params {
f.mark_types_import_as_used(param.typ) f.mark_types_import_as_used(param.typ)

View file

@ -19,23 +19,22 @@ mut:
fn_fails u64 // increase this in .fn_fails() fn_fails u64 // increase this in .fn_fails()
total_assert_passes u64 // increase this in .assert_pass() total_assert_passes u64 // increase this in .assert_pass()
total_assert_fails u64 // increase this in .assert_fail() total_assert_fails u64 // increase this in .assert_fail()
start(ntests int) // called before all tests, you can initialise private data here. ntests is the number of test functions in the _test.v file. start(ntests int) // called before all tests, you can initialise private data here. ntests is the number of test functions in the _test.v file.
finish() // called after all tests are finished, you can print some stats if you want here. finish() // called after all tests are finished, you can print some stats if you want here.
exit_code() int // called right after finish(), it should return the exit code, that the test program will exit with. exit_code() int // called right after finish(), it should return the exit code, that the test program will exit with.
//
fn_start() bool // called before the start of each test_ function. Return false, if the function should be skipped. fn_start() bool // called before the start of each test_ function. Return false, if the function should be skipped.
fn_pass() // called after the end of each test_ function, with NO failed assertion. fn_pass() // called after the end of each test_ function, with NO failed assertion.
fn_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error. fn_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error.
fn_error(line_nr int, file string, mod string, fn_name string, errmsg string) // called only for `fn test_xyz() ? { return error('message') }`, before .fn_fail() is called. fn_error(line_nr int, file string, mod string, fn_name string, errmsg string) // called only for `fn test_xyz() ? { return error('message') }`, before .fn_fail() is called.
//
assert_pass(i &VAssertMetaInfo) // called after each `assert true`. assert_pass(i &VAssertMetaInfo) // called after each `assert true`.
assert_fail(i &VAssertMetaInfo) // called after each `assert false`. assert_fail(i &VAssertMetaInfo) // called after each `assert false`.
//
free() // you should free all the private data of your runner here. free() // you should free all the private data of your runner here.
} }
//
struct VTestFileMetaInfo { struct VTestFileMetaInfo {
file string file string
tests int tests int
@ -57,8 +56,6 @@ fn (i &VTestFileMetaInfo) free() {
} }
} }
//
struct VTestFnMetaInfo { struct VTestFnMetaInfo {
name string name string
mod string mod string
@ -85,8 +82,6 @@ fn (i &VTestFnMetaInfo) free() {
} }
} }
//
@[typedef] @[typedef]
pub struct C.main__TestRunner { pub struct C.main__TestRunner {
mut: mut: