Skip to content

Commit

Permalink
fmt: fix interface fields/methods alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Aug 16, 2024
1 parent 384b5c4 commit 9d8b4b7
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 40 deletions.
8 changes: 4 additions & 4 deletions cmd/tools/modules/testing/output.v
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ pub:

pub interface Reporter {
mut:
session_start(message string, mut ts TestSession) // called once per test session, in the main thread, suitable for setting up supporting infrastructure.
session_stop(message string, mut ts TestSession) // called once per test session, in the main thread, after everything else, suitable for summaries, creating .xml reports, uploads etc.
session_start(message string, mut ts TestSession) // called once per test session, in the main thread, suitable for setting up supporting infrastructure.
session_stop(message string, mut ts TestSession) // called once per test session, in the main thread, after everything else, suitable for summaries, creating .xml reports, uploads etc.
worker_threads_start(files []string, mut ts TestSession) // called once per test session, in the main thread, right before all the worker threads start
worker_threads_finish(mut ts TestSession) // called once per test session, in the main thread, right after all the worker threads finish
worker_threads_finish(mut ts TestSession) // called once per test session, in the main thread, right after all the worker threads finish
//
report(index int, log_msg LogMessage) // called once per each message, that will be shown (ok/fail/skip etc), only in the reporting thread.
report_stop() // called just once after all messages are processed, only in the reporting thread, but before stop_session.
report_stop() // called just once after all messages are processed, only in the reporting thread, but before stop_session.
//
// TODO: reconsider, whether the next methods, should be kept for all reporters, or just moved inside the normal reporter, to simplify the interface
progress(index int, message string)
Expand Down
44 changes: 30 additions & 14 deletions vlib/v/fmt/fmt.v
Original file line number Diff line number Diff line change
Expand Up @@ -1400,41 +1400,50 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
}

mut type_align := new_field_align()
mut comment_align := new_field_align()
mut default_expr_align := new_field_align()
mut attr_align := new_field_align()
mut comment_align := new_field_align(use_threshold: true)
mut default_expr_align := new_field_align(use_threshold: true)
mut attr_align := new_field_align(use_threshold: true)
mut field_types := []string{cap: node.fields.len}

// Calculate the alignments first
f.calculate_alignment(node.fields, mut type_align, mut comment_align, mut default_expr_align, mut
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.
for field in immut_fields {
if field.has_prev_newline {
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 {
if method.has_prev_newline {
f.writeln('')
}
f.interface_method(method)
f.interface_method(method, mut method_comment_align)
}
if mut_fields.len + mut_methods.len > 0 {
f.writeln('mut:')
for field in mut_fields {
if field.has_prev_newline {
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 {
if method.has_prev_newline {
f.writeln('')
}
f.interface_method(method)
f.interface_method(method, mut method_comment_align)
}
}
f.writeln('}\n')
Expand Down Expand Up @@ -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))
mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{}
for cmt in field.comments {
Expand All @@ -1511,7 +1520,6 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
if pre_cmts.len > 0 {
f.comments(pre_cmts, level: .indent)
}
comments_len := f.line_len - before_len

sym := f.table.sym(field.typ)
if sym.info is ast.Struct {
Expand All @@ -1525,10 +1533,12 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
f.write('\t${field.name} ')
}
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)
}
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)
} else {
f.writeln('')
Expand All @@ -1539,16 +1549,22 @@ pub fn (mut f Fmt) interface_field(field ast.StructField, max_len int) {
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)
end_comments := method.comments.filter(it.pos.pos > method.pos.pos)
if before_comments.len > 0 {
f.comments(before_comments, level: .indent)
}
f.write('\t')
f.write(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.writeln('')
method_str := f.table.stringify_fn_decl(&method, f.cur_mod, f.mod2alias, false).all_after_first('fn ')
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.comments(method.next_comments, level: .indent)
for param in method.params {
f.mark_types_import_as_used(param.typ)
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/fmt/tests/interface_declaration_comments_keep.vv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub interface ReaderWriter {
read(mut buf []u8) ?int // from Reader
write(buf []u8) ?int // from Writer
write(buf []u8) ?int // from Writer
}

interface Speaker {
Expand Down Expand Up @@ -38,10 +38,10 @@ mut:
assert_fails u64
test_fn_info &TestFnMetaInfo // filled in by generated code, before .fn_start() is called.
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 should free all the private data here.
finish() // called after all tests are finished, you should free all the private data here.
//
fn_start() // called at the start of each test_ function
fn_pass() // called at the end of each test_ function, with no failed assertion
fn_pass() // called at the end of each test_ function, with no failed assertion
fn_error(line_nr int, file string, mod string, fn_name string, errmsg string) // called only for `fn test_xyz() ? { return error('message') }`
fn_fail() // called at the end of each test_ function, with a failed assertion, *or* returning an error
//
Expand Down
33 changes: 14 additions & 19 deletions vlib/v/preludes/test_runner.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,28 @@ __global test_runner TestRunner
interface TestRunner {
mut:
file_test_info VTestFileMetaInfo // filled in by generated code, before .start() is called.
fn_test_info VTestFnMetaInfo // filled in by generated code, before .fn_start() is called.
fn_assert_passes u64 // reset this to 0 in .fn_start(), increase it in .assert_pass()
fn_passes u64 // increase this in .fn_pass()
fn_fails u64 // increase this in .fn_fails()
total_assert_passes u64 // increase this in .assert_pass()
total_assert_fails u64 // increase this in .assert_fail()
fn_test_info VTestFnMetaInfo // filled in by generated code, before .fn_start() is called.
fn_assert_passes u64 // reset this to 0 in .fn_start(), increase it in .assert_pass()
fn_passes u64 // increase this in .fn_pass()
fn_fails u64 // increase this in .fn_fails()
total_assert_passes u64 // increase this in .assert_pass()
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.
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.
//
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.

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_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error.
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_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_fail(i &VAssertMetaInfo) // called after each `assert false`.
//

free() // you should free all the private data of your runner here.
}

//

struct VTestFileMetaInfo {
file string
tests int
Expand All @@ -57,8 +56,6 @@ fn (i &VTestFileMetaInfo) free() {
}
}

//

struct VTestFnMetaInfo {
name string
mod string
Expand All @@ -85,8 +82,6 @@ fn (i &VTestFnMetaInfo) free() {
}
}

//

@[typedef]
pub struct C.main__TestRunner {
mut:
Expand Down

0 comments on commit 9d8b4b7

Please sign in to comment.