diff --git a/cmd/tools/check_os_api_parity.v b/cmd/tools/check_os_api_parity.v index 4980dde63e..d4b925c66f 100644 --- a/cmd/tools/check_os_api_parity.v +++ b/cmd/tools/check_os_api_parity.v @@ -2,6 +2,7 @@ module main import os import v.util +import v.util.diff import v.pref import v.builder import v.ast @@ -13,6 +14,7 @@ const ( os_names = ['linux', 'macos', 'windows'] skip_modules = [ 'builtin.bare', + 'builtin.linux_bare.old', 'builtin.js', 'strconv', 'strconv.ftoa', @@ -41,7 +43,7 @@ fn main() { vroot := os.dir(vexe) util.set_vroot_folder(vroot) os.chdir(vroot) - cmd := util.find_working_diff_command() or { '' } + cmd := diff.find_working_diff_command() or { '' } mut app := App{ diff_cmd: cmd is_verbose: os.getenv('VERBOSE').len > 0 @@ -117,7 +119,7 @@ fn (app App) gen_api_for_module_in_os(mod_name string, os_name string) string { } fn (mut app App) compare_api(api_base string, api_os string, mod_name string, os_base string, os_target string) { - res := util.color_compare_strings(app.diff_cmd, rand.ulid(), api_base, api_os) + res := diff.color_compare_strings(app.diff_cmd, rand.ulid(), api_base, api_os) if res.len > 0 { summary := 'Different APIs found for module: `$mod_name`, between OS base: `$os_base` and OS: `$os_target`' eprintln(term.header(summary, '-')) diff --git a/cmd/tools/vcreate_test.v b/cmd/tools/vcreate_test.v index 2b5b562cf8..b325adae1f 100644 --- a/cmd/tools/vcreate_test.v +++ b/cmd/tools/vcreate_test.v @@ -3,7 +3,7 @@ import os const test_path = 'vcreate_test' fn init_and_check() ? { - vexe := os.getenv('VEXE') + vexe := @VEXE os.execute_or_panic('$vexe init') assert os.read_file('vcreate_test.v') ? == [ @@ -53,12 +53,12 @@ fn test_v_init() ? { fn test_v_init_in_git_dir() ? { dir := os.join_path(os.temp_dir(), test_path) os.rmdir_all(dir) or {} - os.execute_or_panic('git init $dir') + os.mkdir(dir) ? defer { os.rmdir_all(dir) or {} } os.chdir(dir) - + os.execute_or_panic('git init .') init_and_check() ? } @@ -72,7 +72,7 @@ fn test_v_init_no_overwrite_gitignore() ? { } os.chdir(dir) - vexe := os.getenv('VEXE') + vexe := @VEXE os.execute_or_panic('$vexe init') assert os.read_file('.gitignore') ? == 'blah' diff --git a/cmd/tools/vdoc/tests/testdata/project1/main.out b/cmd/tools/vdoc/tests/testdata/project1/main.out new file mode 100644 index 0000000000..a7b5091064 --- /dev/null +++ b/cmd/tools/vdoc/tests/testdata/project1/main.out @@ -0,0 +1,3 @@ +cmd/tools/vdoc/tests/testdata/project1/main.v:0:1: error: unexpected unknown, expecting `const` + 1 | const ( + 2 | source_root = 'temp' diff --git a/cmd/tools/vdoc/tests/testdata/project1/main.v b/cmd/tools/vdoc/tests/testdata/project1/main.v new file mode 100644 index 0000000000..1a1b52796e --- /dev/null +++ b/cmd/tools/vdoc/tests/testdata/project1/main.v @@ -0,0 +1,8 @@ +const ( + source_root = 'temp' +) + +// funky - comment for function below +fn funky() { + println('hi') +} diff --git a/cmd/tools/vdoc/tests/vdoc_file_test.v b/cmd/tools/vdoc/tests/vdoc_file_test.v new file mode 100644 index 0000000000..49a0130389 --- /dev/null +++ b/cmd/tools/vdoc/tests/vdoc_file_test.v @@ -0,0 +1,72 @@ +import os +import rand +import term +import v.util.vtest +import v.util.diff + +const vexe = @VEXE + +const vroot = @VMODROOT + +const diff_cmd = find_diff_cmd() + +fn find_diff_cmd() string { + return diff.find_working_diff_command() or { '' } +} + +fn test_vet() { + os.setenv('VCOLORS', 'never', true) + os.chdir(vroot) + test_dir := 'cmd/tools/vdoc/tests/testdata' + main_files := get_main_files_in_dir(test_dir) + fails := check_path(vexe, test_dir, main_files) + assert fails == 0 +} + +fn get_main_files_in_dir(dir string) []string { + mut mfiles := os.walk_ext(dir, '.v') + mfiles.sort() + return mfiles +} + +fn check_path(vexe string, dir string, tests []string) int { + mut nb_fail := 0 + paths := vtest.filter_vtest_only(tests, basepath: vroot) + for path in paths { + program := path + print(path + ' ') + res := os.execute('$vexe doc $program') + if res.exit_code < 0 { + panic(res.output) + } + mut expected := os.read_file(program.replace('main.v', 'main.out')) or { panic(err) } + expected = clean_line_endings(expected) + found := clean_line_endings(res.output) + if expected != found { + println(term.red('FAIL')) + println('============') + println('expected:') + println(expected) + println('============') + println('found:') + println(found) + println('============\n') + println('diff:') + println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected)) + println('============\n') + nb_fail++ + } else { + println(term.green('OK')) + } + } + return nb_fail +} + +fn clean_line_endings(s string) string { + mut res := s.trim_space() + res = res.replace(' \n', '\n') + res = res.replace(' \r\n', '\n') + res = res.replace('\r\n', '\n') + res = res.trim('\n') + return res +} diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index c14854832b..2ba8956879 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -11,6 +11,7 @@ import v.ast import v.pref import v.fmt import v.util +import v.util.diff import v.parser import vhelp @@ -203,25 +204,25 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path return } if foptions.is_diff { - diff_cmd := util.find_working_diff_command() or { + diff_cmd := diff.find_working_diff_command() or { eprintln(err) return } if foptions.is_verbose { eprintln('Using diff command: $diff_cmd') } - diff := util.color_compare_files(diff_cmd, file, formatted_file_path) + diff := diff.color_compare_files(diff_cmd, file, formatted_file_path) if diff.len > 0 { println(diff) } return } if foptions.is_verify { - diff_cmd := util.find_working_diff_command() or { + diff_cmd := diff.find_working_diff_command() or { eprintln(err) return } - x := util.color_compare_files(diff_cmd, file, formatted_file_path) + x := diff.color_compare_files(diff_cmd, file, formatted_file_path) if x.len != 0 { println("$file is not vfmt'ed") return error('') diff --git a/cmd/tools/vvet/vet_test.v b/cmd/tools/vvet/vet_test.v index 9bb6443950..3291f20c7d 100644 --- a/cmd/tools/vvet/vet_test.v +++ b/cmd/tools/vvet/vet_test.v @@ -2,12 +2,12 @@ import os import rand import term import v.util.vtest -import v.util +import v.util.diff const diff_cmd = find_diff_cmd() fn find_diff_cmd() string { - res := util.find_working_diff_command() or { '' } + res := diff.find_working_diff_command() or { '' } return res } @@ -52,7 +52,7 @@ fn check_path(vexe string, dir string, tests []string) int { println(found) println('============\n') println('diff:') - println(util.color_compare_strings(diff_cmd, rand.ulid(), found, expected)) + println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected)) println('============\n') nb_fail++ } else { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 69f4262e16..2f7a320269 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -7367,7 +7367,12 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { } } // needed for proper error reporting during vweb route checking - sym.methods[node.method_idx].source_fn = voidptr(node) + if node.method_idx < sym.methods.len { + sym.methods[node.method_idx].source_fn = voidptr(node) + } else { + c.error('method index: $node.method_idx >= sym.methods.len: $sym.methods.len', + node.pos) + } } if node.language == .v { // Make sure all types are valid diff --git a/vlib/v/compiler_errors_test.v b/vlib/v/compiler_errors_test.v index 5c6f7c4faa..e3e1b4156e 100644 --- a/vlib/v/compiler_errors_test.v +++ b/vlib/v/compiler_errors_test.v @@ -1,7 +1,7 @@ import os import rand import term -import v.util +import v.util.diff import v.util.vtest import time import sync @@ -314,9 +314,9 @@ fn clean_line_endings(s string) string { } fn diff_content(s1 string, s2 string) { - diff_cmd := util.find_working_diff_command() or { return } + diff_cmd := diff.find_working_diff_command() or { return } println(term.bold(term.yellow('diff: '))) - println(util.color_compare_strings(diff_cmd, rand.ulid(), s1, s2)) + println(diff.color_compare_strings(diff_cmd, rand.ulid(), s1, s2)) println('============\n') } diff --git a/vlib/v/fmt/fmt_keep_test.v b/vlib/v/fmt/fmt_keep_test.v index 32c64e2977..5f2af07191 100644 --- a/vlib/v/fmt/fmt_keep_test.v +++ b/vlib/v/fmt/fmt_keep_test.v @@ -8,7 +8,7 @@ import v.fmt import v.parser import v.ast import v.pref -import v.util +import v.util.diff import v.util.vtest const ( @@ -32,7 +32,7 @@ fn test_fmt() { os.chdir(vroot) basepath := os.join_path(vroot, '') tmpfolder := os.temp_dir() - diff_cmd := util.find_working_diff_command() or { '' } + diff_cmd := diff.find_working_diff_command() or { '' } mut fmt_bench := benchmark.new_benchmark() keep_input_files := os.walk_ext('vlib/v/fmt/tests', '_keep.vv') expected_input_files := os.walk_ext('vlib/v/fmt/tests', '_expected.vv') @@ -70,7 +70,7 @@ fn test_fmt() { } vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename') os.write_file(vfmt_result_file, result_ocontent) or { panic(err.msg) } - eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file)) + eprintln(diff.color_compare_files(diff_cmd, opath, vfmt_result_file)) continue } fmt_bench.ok() diff --git a/vlib/v/fmt/fmt_test.v b/vlib/v/fmt/fmt_test.v index 06b33163c9..a1130c9b69 100644 --- a/vlib/v/fmt/fmt_test.v +++ b/vlib/v/fmt/fmt_test.v @@ -8,7 +8,7 @@ import v.ast import v.fmt import v.parser import v.pref -import v.util +import v.util.diff const ( error_missing_vexe = 1 @@ -28,7 +28,7 @@ fn test_fmt() { } vroot := os.dir(vexe) tmpfolder := os.temp_dir() - diff_cmd := util.find_working_diff_command() or { '' } + diff_cmd := diff.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') @@ -62,7 +62,7 @@ fn test_fmt() { } vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename') os.write_file(vfmt_result_file, result_ocontent) or { panic(err) } - eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file)) + eprintln(diff.color_compare_files(diff_cmd, opath, vfmt_result_file)) continue } fmt_bench.ok() diff --git a/vlib/v/fmt/fmt_vlib_test.v b/vlib/v/fmt/fmt_vlib_test.v index 9fcf3904b4..9315ff8bbb 100644 --- a/vlib/v/fmt/fmt_vlib_test.v +++ b/vlib/v/fmt/fmt_vlib_test.v @@ -8,7 +8,7 @@ import v.ast import v.fmt import v.parser import v.pref -import v.util +import v.util.diff const ( error_missing_vexe = 1 @@ -31,7 +31,7 @@ fn test_vlib_fmt() { } vroot := os.dir(vexe) tmpfolder := os.temp_dir() - diff_cmd := util.find_working_diff_command() or { '' } + diff_cmd := diff.find_working_diff_command() or { '' } mut fmt_bench := benchmark.new_benchmark() os.chdir(vroot) input_files := os.walk_ext('vlib/v/', '.v').filter(!it.contains('/tests/')) @@ -60,7 +60,7 @@ fn test_vlib_fmt() { } vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename') os.write_file(vfmt_result_file, result_ocontent) or { panic(err) } - eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file)) + eprintln(diff.color_compare_files(diff_cmd, opath, vfmt_result_file)) continue } fmt_bench.ok() diff --git a/vlib/v/tests/inout/compiler_test.v b/vlib/v/tests/inout/compiler_test.v index 1cd0f5f4a1..88178ce876 100644 --- a/vlib/v/tests/inout/compiler_test.v +++ b/vlib/v/tests/inout/compiler_test.v @@ -4,7 +4,7 @@ import os import rand import term -import v.util +import v.util.diff import v.util.vtest const turn_off_vcolors = os.setenv('VCOLORS', 'never', true) @@ -14,7 +14,7 @@ fn test_all() { vexe := os.getenv('VEXE') vroot := os.dir(vexe) os.chdir(vroot) - diff_cmd := util.find_working_diff_command() or { '' } + diff_cmd := diff.find_working_diff_command() or { '' } dir := 'vlib/v/tests/inout' files := os.ls(dir) or { panic(err) } tests := files.filter(it.ends_with('.vv')) @@ -78,7 +78,7 @@ fn test_all() { println(found) if diff_cmd != '' { println(term.header('difference:', '-')) - println(util.color_compare_strings(diff_cmd, rand.ulid(), expected, found)) + println(diff.color_compare_strings(diff_cmd, rand.ulid(), expected, found)) } else { println(term.h_divider('-')) } diff --git a/vlib/v/tests/repl/run.v b/vlib/v/tests/repl/run.v deleted file mode 100644 index 498e432713..0000000000 --- a/vlib/v/tests/repl/run.v +++ /dev/null @@ -1,24 +0,0 @@ -module main - -import v.tests.repl.runner -import log -import benchmark - -fn main() { - mut logger := log.Log{} - logger.set_level(.debug) - options := runner.new_options() - mut bmark := benchmark.new_benchmark() - for file in options.files { - bmark.step() - fres := runner.run_repl_file(options.wd, options.vexec, file) or { - bmark.fail() - logger.error(bmark.step_message_fail(err.msg)) - continue - } - bmark.ok() - logger.info(bmark.step_message_ok(fres)) - } - bmark.stop() - logger.info(bmark.total_message('total time spent running REPL files')) -} diff --git a/vlib/v/tests/repl/runner/runner.v b/vlib/v/tests/repl/runner/runner.v index 9259e28790..482d8d03c6 100644 --- a/vlib/v/tests/repl/runner/runner.v +++ b/vlib/v/tests/repl/runner/runner.v @@ -1,7 +1,7 @@ module runner import os -import v.util +import v.util.diff pub struct RunnerOptions { pub: @@ -35,8 +35,8 @@ pub fn full_path_to_v(dirs_in int) string { } fn diff_files(file_result string, file_expected string) string { - diffcmd := util.find_working_diff_command() or { return err } - return util.color_compare_files(diffcmd, file_result, file_expected) + diffcmd := diff.find_working_diff_command() or { return err } + return diff.color_compare_files(diffcmd, file_result, file_expected) } pub fn run_repl_file(wd string, vexec string, file string) ?string { diff --git a/vlib/v/util/diff.v b/vlib/v/util/diff.v index d28ac3f48d..3e1814e9f0 100644 --- a/vlib/v/util/diff.v +++ b/vlib/v/util/diff.v @@ -1,85 +1,17 @@ module util -import os -import time +import v.util.diff // iterates through a list of known diff cli commands // and returns it with basic options pub fn find_working_diff_command() ?string { - env_difftool := os.getenv('VDIFF_TOOL') - env_diffopts := os.getenv('VDIFF_OPTIONS') - if env_difftool != '' { - return '$env_difftool $env_diffopts' - } - mut known_diff_tools := []string{} - if env_difftool.len > 0 { - known_diff_tools << env_difftool - } - known_diff_tools << ['colordiff', 'gdiff', 'diff', 'colordiff.exe', 'diff.exe', 'opendiff', - 'code', 'code.cmd'] - // NOTE: code.cmd is the Windows variant of the `code` cli tool - for diffcmd in known_diff_tools { - if diffcmd == 'opendiff' { // opendiff has no `--version` option - if opendiff_exists() { - return diffcmd - } - continue - } - p := os.execute('$diffcmd --version') - if p.exit_code < 0 { - continue - } - if p.exit_code == 127 && diffcmd == env_difftool { - // user setup is wonky, fix it - return error('could not find specified VDIFF_TOOL $diffcmd') - } - if p.exit_code == 0 { // success - if diffcmd in ['code', 'code.cmd'] { - // there is no guarantee that the env opts exist - // or include `-d`, so (harmlessly) add it - return '$diffcmd $env_diffopts -d' - } - return '$diffcmd $env_diffopts' - } - } - return error('No working "diff" command found') -} - -// determine if the FileMerge opendiff tool is available -fn opendiff_exists() bool { - o := os.execute('opendiff') - if o.exit_code < 0 { - return false - } - if o.exit_code == 1 { // failed (expected), but found (i.e. not 127) - if o.output.contains('too few arguments') { // got some expected output - return true - } - } - return false + return diff.find_working_diff_command() } pub fn color_compare_files(diff_cmd string, file1 string, file2 string) string { - if diff_cmd != '' { - full_cmd := '$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$file1" "$file2" ' - x := os.execute(full_cmd) - if x.exit_code < 0 { - return 'comparison command: `$full_cmd` not found' - } - return x.output.trim_right('\r\n') - } - return '' + return diff.color_compare_files(diff_cmd, file1, file2) } pub fn color_compare_strings(diff_cmd string, unique_prefix string, expected string, found string) string { - cdir := os.join_path(os.cache_dir(), unique_prefix) - os.mkdir(cdir) or {} - ctime := time.sys_mono_now() - e_file := os.join_path(cdir, '${ctime}.expected.txt') - f_file := os.join_path(cdir, '${ctime}.found.txt') - os.write_file(e_file, expected) or { panic(err) } - os.write_file(f_file, found) or { panic(err) } - res := color_compare_files(diff_cmd, e_file, f_file) - os.rmdir_all(cdir) or {} - return res + return diff.color_compare_strings(diff_cmd, unique_prefix, expected, found) } diff --git a/vlib/v/util/diff/diff.v b/vlib/v/util/diff/diff.v new file mode 100644 index 0000000000..490342a07c --- /dev/null +++ b/vlib/v/util/diff/diff.v @@ -0,0 +1,85 @@ +module diff + +import os +import time + +// iterates through a list of known diff cli commands +// and returns it with basic options +pub fn find_working_diff_command() ?string { + env_difftool := os.getenv('VDIFF_TOOL') + env_diffopts := os.getenv('VDIFF_OPTIONS') + if env_difftool != '' { + return '$env_difftool $env_diffopts' + } + mut known_diff_tools := []string{} + if env_difftool.len > 0 { + known_diff_tools << env_difftool + } + known_diff_tools << ['colordiff', 'gdiff', 'diff', 'colordiff.exe', 'diff.exe', 'opendiff', + 'code', 'code.cmd'] + // NOTE: code.cmd is the Windows variant of the `code` cli tool + for diffcmd in known_diff_tools { + if diffcmd == 'opendiff' { // opendiff has no `--version` option + if opendiff_exists() { + return diffcmd + } + continue + } + p := os.execute('$diffcmd --version') + if p.exit_code < 0 { + continue + } + if p.exit_code == 127 && diffcmd == env_difftool { + // user setup is wonky, fix it + return error('could not find specified VDIFF_TOOL $diffcmd') + } + if p.exit_code == 0 { // success + if diffcmd in ['code', 'code.cmd'] { + // there is no guarantee that the env opts exist + // or include `-d`, so (harmlessly) add it + return '$diffcmd $env_diffopts -d' + } + return '$diffcmd $env_diffopts' + } + } + return error('No working "diff" command found') +} + +// determine if the FileMerge opendiff tool is available +fn opendiff_exists() bool { + o := os.execute('opendiff') + if o.exit_code < 0 { + return false + } + if o.exit_code == 1 { // failed (expected), but found (i.e. not 127) + if o.output.contains('too few arguments') { // got some expected output + return true + } + } + return false +} + +pub fn color_compare_files(diff_cmd string, file1 string, file2 string) string { + if diff_cmd != '' { + full_cmd := '$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$file1" "$file2" ' + x := os.execute(full_cmd) + if x.exit_code < 0 { + return 'comparison command: `$full_cmd` not found' + } + return x.output.trim_right('\r\n') + } + return '' +} + +pub fn color_compare_strings(diff_cmd string, unique_prefix string, expected string, found string) string { + cdir := os.join_path(os.cache_dir(), unique_prefix) + os.mkdir(cdir) or {} + ctime := time.sys_mono_now() + e_file := os.join_path(cdir, '${ctime}.expected.txt') + f_file := os.join_path(cdir, '${ctime}.found.txt') + os.write_file(e_file, expected) or { panic(err) } + os.write_file(f_file, found) or { panic(err) } + res := color_compare_files(diff_cmd, e_file, f_file) + os.rmdir_all(cdir) or {} + return res +}