From b991ca4ebc7e6c1eacc42c4b8b1abfeb471d1960 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 18 Feb 2020 18:54:14 +0200 Subject: [PATCH] vfmt2: more convenient way to test multiple files for correct formatting --- .gitattributes | 3 +- vlib/v/fmt/fmt.v | 15 ++-- vlib/v/fmt/fmt_test.v | 92 ++++++++++++++++------ vlib/v/fmt/tests/1_out.vv | 0 vlib/v/fmt/tests/simple_expected.vv | 47 +++++++++++ vlib/v/fmt/tests/{1.vv => simple_input.vv} | 13 +++ vlib/v/parser/parser.v | 2 +- 7 files changed, 143 insertions(+), 29 deletions(-) delete mode 100644 vlib/v/fmt/tests/1_out.vv create mode 100644 vlib/v/fmt/tests/simple_expected.vv rename vlib/v/fmt/tests/{1.vv => simple_input.vv} (65%) diff --git a/.gitattributes b/.gitattributes index 576b86b103..bea12d4b71 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ -*.v linguist-language=V +*.v linguist-language=V text=auto eol=lf +*.vv linguist-language=V text=auto eol=lf diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index e0e9ed0d07..f37943ab80 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -22,15 +22,14 @@ mut: empty_line bool } -pub fn fmt(file ast.File, table &table.Table) { +pub fn fmt(file ast.File, table &table.Table) string { mut f := Fmt{ out: strings.new_builder(1000) table: table indent: -1 } f.stmts(file.stmts) - println('vfmt output:') - println(f.out.str()) + return f.out.str() } pub fn (f mut Fmt) write(s string) { @@ -98,7 +97,13 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.writeln('') } ast.FnDecl { - f.writeln('fn ${it.name}() {') + return_type_sym := f.table.get_type_symbol(it.typ) + rtype_name := if return_type_sym.name == 'void' { + '' + } else { + '${return_type_sym.name} ' + } + f.writeln('fn ${it.name}() ${rtype_name}{') f.stmts(it.stmts) f.writeln('}\n') } @@ -208,7 +213,7 @@ fn (f mut Fmt) expr(node ast.Expr) { f.stmts(it.stmts) f.write('}') if it.else_stmts.len > 0 { - f.writeln(' else { ') + f.writeln(' else {') f.stmts(it.else_stmts) f.write('}') } diff --git a/vlib/v/fmt/fmt_test.v b/vlib/v/fmt/fmt_test.v index c08ef6979e..5a87bf98b5 100644 --- a/vlib/v/fmt/fmt_test.v +++ b/vlib/v/fmt/fmt_test.v @@ -1,35 +1,83 @@ import ( os - v.fmt - filepath term - v.table + benchmark + filepath + v.fmt v.parser + v.table ) const ( - nr_tests = 1 + error_missing_vexe = 1 + error_missing_diff = 2 + error_failed_tests = 3 ) fn test_fmt() { - println('Running vfmt tests') + fmt_message := 'vfmt tests' + eprintln(term.header(fmt_message,'-')) vexe := os.getenv('VEXE') - vroot := filepath.dir(vexe) - term_ok := term.ok_message('OK') - term_fail := term.fail_message('FAIL') - // for i in 1 .. nr_tests + 1 { - // path := '$vroot/vlib/v/fmt/tests/${i}.vv' - path := '$vroot/vlib/compiler/aparser.v' - println(path) - /* - mut ctext := os.read_file('$vroot/vlib/v/fmt/tests/${i}_out.vv') or { - panic(err) + if vexe.len == 0 || !os.exists(vexe) { + eprintln('VEXE must be set') + exit(error_missing_vexe) + } + vroot := filepath.dir(vexe) + tmpfolder := os.tmpdir() + diff_cmd := find_working_diff_command() or { '' } + mut fmt_bench := benchmark.new_benchmark() + // Lookup the existing test _input.vv files: + input_files := os.walk_ext('$vroot/vlib/v/fmt/tests', '_input.vv') + fmt_bench.set_total_expected_steps( input_files.len ) + for istep, ipath in input_files { + fmt_bench.cstep = istep + fmt_bench.step() + ifilename := filepath.filename(ipath) + opath := ipath.replace('_input.vv', '_expected.vv') + if !os.exists(opath) { + fmt_bench.fail() + eprintln(fmt_bench.step_message_fail('missing file ${opath}')) + continue + } + expected_ocontent := os.read_file(opath) or { + fmt_bench.fail() + eprintln(fmt_bench.step_message_fail('cannot read from ${opath}')) + continue + } + table := table.new_table() + file_ast := parser.parse_file(ipath, table) + result_ocontent := fmt.fmt(file_ast, table) + if expected_ocontent != result_ocontent { + fmt_bench.fail() + eprintln(fmt_bench.step_message_fail('file ${ipath} after formatting, does not look as expected.')) + if diff_cmd == '' { + eprintln('>> sorry, but no working "diff" CLI command can be found') + continue + } + vfmt_result_file := filepath.join(tmpfolder,'vfmt_run_over_${ifilename}') + os.write_file(vfmt_result_file, result_ocontent) + os.system('$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$opath" "$vfmt_result_file"') + continue + } + fmt_bench.ok() + eprintln(fmt_bench.step_message_ok('${ipath}')) + } + fmt_bench.stop() + eprintln(term.h_divider('-')) + eprintln(fmt_bench.total_message(fmt_message)) + if fmt_bench.nfail > 0 { + exit(error_failed_tests) } - ctext = ctext // unused warn - */ - - table := table.new_table() - file := parser.parse_file(path, table) - fmt.fmt(file, table) - // } +} + +fn find_working_diff_command() ?string { + for diffcmd in ['colordiff', 'diff', 'colordiff.exe', 'diff.exe'] { + p := os.exec('$diffcmd --version') or { + continue + } + if p.exit_code == 0 { + return diffcmd + } + } + return error('no working diff command found') } diff --git a/vlib/v/fmt/tests/1_out.vv b/vlib/v/fmt/tests/1_out.vv deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/vlib/v/fmt/tests/simple_expected.vv b/vlib/v/fmt/tests/simple_expected.vv new file mode 100644 index 0000000000..4b3d7ab945 --- /dev/null +++ b/vlib/v/fmt/tests/simple_expected.vv @@ -0,0 +1,47 @@ +fn hello() { + mut a := 3 + 3 + a = 10 + a++ + -23 + b := 42 + println('hello') + abc() + if true { + a = 10 + a++ + } else { + println('false') + } +} + +const ( + pi = 3.14 +) + +struct User { + name string + age int + very_long_field bool +} + +fn abc() int { + mut u := User{ + name: 'Bob' + } + u.age = 20 + nums := [1, 2, 3] + number := nums[0] + return 0 +} + +fn new_user() User { + return User{ + name: 'Serious Sam' + age: 19 + } +} + +fn voidfn() { + println('this is a function that does not return anything') +} + diff --git a/vlib/v/fmt/tests/1.vv b/vlib/v/fmt/tests/simple_input.vv similarity index 65% rename from vlib/v/fmt/tests/1.vv rename to vlib/v/fmt/tests/simple_input.vv index 6bfb2cf084..2f223f7d0c 100644 --- a/vlib/v/fmt/tests/1.vv +++ b/vlib/v/fmt/tests/simple_input.vv @@ -35,3 +35,16 @@ fn abc() int { number := nums[0] return 0 } + +fn new_user() +User +{ + return User{ + name: 'Serious Sam' + age: 19 + } +} + +fn voidfn(){ + println('this is a function that does not return anything') + } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 270fc08d45..35d7642dfb 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -459,7 +459,7 @@ pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident { fn (p mut Parser) struct_init() ast.StructInit { typ := p.parse_type() sym := p.table.get_type_symbol(typ) - p.warn('struct init typ=$sym.name') + //p.warn('struct init typ=$sym.name') p.check(.lcbr) mut field_names := []string mut exprs := []ast.Expr