diff --git a/TESTS.md b/TESTS.md index 0ba073a5ba..b0a4120cab 100644 --- a/TESTS.md +++ b/TESTS.md @@ -23,6 +23,11 @@ General runnable tests for different features of the V compiler. Test output of running a V program matches an expected .out file. Check the source for how to test panics. +* `vlib/v/tests/run_project_folders_test.v` +Tests whether whole project folders can be compiled, and run. +NB: Each project in these folders, should finish with exit code 0, +and it should output `OK` as its last stdout line. + ## Test building of actual V programs (examples, tools, V itself) * `v build-tools` diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 5757640792..6c028a3ee3 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -653,7 +653,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn { is_variadic: is_variadic return_type: return_type } - name := 'anon_fn_${p.table.fn_type_signature(func)}_$p.tok.pos' + name := 'anon_fn_${p.unique_prefix}_${p.table.fn_type_signature(func)}_$p.tok.pos' keep_fn_name := p.cur_fn_name p.cur_fn_name = name if p.tok.kind == .lcbr { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index b923cd8e22..0b8353a9a6 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -11,6 +11,7 @@ import v.util import v.vet import v.errors import os +import hash const ( builtin_functions = ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit'] @@ -22,6 +23,7 @@ mut: file_base string // "hello.v" file_name string // "/home/user/hello.v" file_name_dir string // "/home/user" + unique_prefix string // a hash of p.file_name, used for making anon fn generation unique file_backend_mode ast.Language // .c for .c.v|.c.vv|.c.vsh files; .js for .js.v files, .amd64/.rv32/other arches for .amd64.v/.rv32.v/etc. files, .v otherwise. scanner &scanner.Scanner comments_mode scanner.CommentsMode = .skip_comments @@ -141,6 +143,7 @@ pub fn (mut p Parser) set_path(path string) { p.file_name = path p.file_base = os.base(path) p.file_name_dir = os.dir(path) + p.unique_prefix = hash.sum64_string(p.file_name, 13).hex_full() if p.file_base.ends_with('_test.v') || p.file_base.ends_with('_test.vv') { p.inside_test_file = true } diff --git a/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/a.v b/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/a.v new file mode 100644 index 0000000000..9bd4150f3e --- /dev/null +++ b/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/a.v @@ -0,0 +1,8 @@ +module main + +fn a() int { + f := fn (i int) int { + return i + } + return f(1) +} diff --git a/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/b.v b/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/b.v new file mode 100644 index 0000000000..fd97e4220b --- /dev/null +++ b/vlib/v/tests/run_project_folders/issue_10023_multiple_anon_fns_with_same_position/b.v @@ -0,0 +1,14 @@ +module main + +fn b() int { + f := fn (i int) int { + return i + } + return f(1) +} + +fn main() { + println(a()) + println(b()) + println('OK') +} diff --git a/vlib/v/tests/run_project_folders_test.v b/vlib/v/tests/run_project_folders_test.v new file mode 100644 index 0000000000..089d18354e --- /dev/null +++ b/vlib/v/tests/run_project_folders_test.v @@ -0,0 +1,36 @@ +import os +import term + +const vexe = os.getenv('VEXE') + +const vroot = os.dir(vexe) + +fn test_vexe_exists() { + assert vexe.len > 0 + assert os.is_file(vexe) +} + +fn test_v_profile_works() ? { + os.chdir(vroot) + folders_root := os.join_path(vroot, 'vlib/v/tests/run_project_folders') + folder_names := os.ls(folders_root) ? + mut folder_paths := []string{} + for fname in folder_names { + folder_path := os.join_path(folders_root, fname) + if os.is_dir(folder_path) { + folder_paths << folder_path + } + } + for folder_path in folder_paths { + local_path := folder_path.replace(vroot + os.path_separator, '').replace('\\', + '/') + println('..... $local_path/') + res := os.execute('"$vexe" run $folder_path') + // eprintln('res: $res') + assert res.exit_code == 0 + assert res.output.len > 0 + assert res.output.contains('OK') + term.clear_previous_line() + println('${term.bold('OK')} $local_path/') + } +}