diff --git a/vlib/v/util/module.v b/vlib/v/util/module.v index e4832fcd01..0454878a4b 100644 --- a/vlib/v/util/module.v +++ b/vlib/v/util/module.v @@ -1,14 +1,23 @@ module util +// 2022-01-30 TODO: this whole file should not exist :-|. It should just use the existing `v.vmod` instead, +// 2022-01-30 that already does handle v.mod lookup properly, stopping at .git folders, supporting `.v.mod.stop` etc. import os import v.pref -[if trace_mod_path_to_full_name ?] -fn trace_mod_path_to_full_name(line string, mod string, file_path string, res string) { - eprintln('> $line ${@FN} mod: ${mod:-20} | file_path: ${file_path:-30} | result: $res') +[if trace_util_qualify ?] +fn trace_qualify(callfn string, mod string, file_path string, kind_res string, result string, detail string) { + eprintln('> ${callfn:15}: ${mod:-18} | file_path: ${file_path:-71} | => ${kind_res:14}: ${result:-18} ; $detail') } +// 2022-01-30 qualify_import - used by V's parser, to find the full module name of import statements +// 2022-01-30 i.e. when parsing `import automaton` inside a .v file in examples/game_of_life/life_gg.v +// 2022-01-30 it returns just 'automaton' +// 2022-01-30 TODO: this seems to always just return `mod` itself, for modules inside the V main folder. +// 2022-01-30 It does also return `mod` itself, for stuff installed in ~/.vmodules like `vls` but for +// 2022-01-30 other reasons (see res 2 below). pub fn qualify_import(pref &pref.Preferences, mod string, file_path string) string { + // comments are from workdir: /v/vls mut mod_paths := pref.lookup_path.clone() mod_paths << os.vmodules_paths() mod_path := mod.replace('.', os.path_separator) @@ -16,32 +25,62 @@ pub fn qualify_import(pref &pref.Preferences, mod string, file_path string) stri try_path := os.join_path_single(search_path, mod_path) if os.is_dir(try_path) { if m1 := mod_path_to_full_name(pref, mod, try_path) { - trace_mod_path_to_full_name(@LINE, mod, try_path, m1) + trace_qualify(@FN, mod, file_path, 'import_res 1', m1, try_path) + // > qualify_import: term | file_path: /v/vls/server/diagnostics.v | => import_res 1: term ; /v/cleanv/vlib/term return m1 } } } if m1 := mod_path_to_full_name(pref, mod, file_path) { - trace_mod_path_to_full_name(@LINE, mod, file_path, m1) + trace_qualify(@FN, mod, file_path, 'import_res 2', m1, file_path) + // > qualify_module: analyzer | file_path: /v/vls/analyzer/store.v | => module_res 2: analyzer ; clean_file_path - getwd == mod + // > qualify_import: analyzer.depgraph | file_path: /v/vls/analyzer/store.v | => import_res 2: analyzer.depgraph ; /v/vls/analyzer/store.v + // > qualify_import: tree_sitter | file_path: /v/vls/analyzer/store.v | => import_res 2: tree_sitter ; /v/vls/analyzer/store.v + // > qualify_import: tree_sitter_v | file_path: /v/vls/analyzer/store.v | => import_res 1: tree_sitter_v ; ~/.vmodules/tree_sitter_v + // > qualify_import: jsonrpc | file_path: /v/vls/server/features.v | => import_res 2: jsonrpc ; /v/vls/server/features.v return m1 } + trace_qualify(@FN, mod, file_path, 'import_res 3', mod, '---, mod_path: $mod_path') + // > qualify_import: server | file_path: cmd/vls/host.v | => import_res 3: server ; --- + // > qualify_import: cli | file_path: cmd/vls/main.v | => import_res 1: cli ; /v/cleanv/vlib/cli + // > qualify_import: server | file_path: cmd/vls/main.v | => import_res 3: server ; --- + // > qualify_import: os | file_path: cmd/vls/main.v | => import_res 1: os ; /v/cleanv/vlib/os return mod } +// 2022-01-30 qualify_module - used by V's parser to find the full module name +// 2022-01-30 i.e. when parsing `module textscanner`, inside vlib/strings/textscanner/textscanner.v +// 2022-01-30 it will return `strings.textscanner` pub fn qualify_module(pref &pref.Preferences, mod string, file_path string) string { if mod == 'main' { + trace_qualify(@FN, mod, file_path, 'module_res 1', mod, 'main') return mod } clean_file_path := file_path.all_before_last(os.path_separator) // relative module (relative to working directory) // TODO: find most stable solution & test with -usecache + // + // TODO 2022-01-30: Using os.getwd() here does not seem right *at all* imho. + // TODO 2022-01-30: That makes lookup dependent on fragile enviroment factors. + // TODO 2022-01-30: The lookup should be relative to the folder, in which the current file is, + // TODO 2022-01-30: *NOT* to the working folder of the compiler, which can change easily. if clean_file_path.replace(os.getwd() + os.path_separator, '') == mod { + trace_qualify(@FN, mod, file_path, 'module_res 2', mod, 'clean_file_path - getwd == mod, clean_file_path: $clean_file_path') return mod } if m1 := mod_path_to_full_name(pref, mod, clean_file_path) { - trace_mod_path_to_full_name(@LINE, mod, clean_file_path, m1) + trace_qualify(@FN, mod, file_path, 'module_res 3', m1, 'm1 == f($clean_file_path)') + // > qualify_module: net | file_path: /v/cleanv/vlib/net/util.v | => module_res 3: net ; m1 == f(/v/cleanv/vlib/net) + // > qualify_module: term | file_path: /v/cleanv/vlib/term/control.v | => module_res 3: term ; m1 == f(/v/cleanv/vlib/term) + // > qualify_module: log | file_path: /v/vls/lsp/log/log.v | => module_res 3: lsp.log ; m1 == f(/v/vls/lsp/log) + + // zzz BUG: when ../v.mod exists above V root folder: + // zzz > qualify_module: help | file_path: /v/cleanv/cmd/v/help/help.v | => module_res 3: v.cmd.v.help ; m1 == f(/v/cleanv/cmd/v/help) return m1 } + // zzzzzzz WORKING, when there is NO ../v.mod: + // zzzzzzz > qualify_module: help | file_path: /v/cleanv/cmd/v/help/help.v | => module_res 4: help ; ---, clean_file_path: /v/cleanv/cmd/v/help + trace_qualify(@FN, mod, file_path, 'module_res 4', mod, '---, clean_file_path: $clean_file_path') return mod } @@ -50,11 +89,19 @@ pub fn qualify_module(pref &pref.Preferences, mod string, file_path string) stri // * if possible split this function in two, one which gets the // parent module path and another which turns it into the full name // * create shared logic between these fns and builder.find_module_path -pub fn mod_path_to_full_name(pref &pref.Preferences, mod string, path string) ?string { +// 2022-01-30 TODO: the reliance on os.path_separator here, is also a potential problem. +// 2022-01-30 On windows that leads to: +// 2022-01-30 `v path/subfolder/` behaving very differently than `v path\subfolder\` +// 2022-01-30 (see daa5be4, that skips checking `vlib/v/checker/tests/modules/deprecated_module` +// 2022-01-30 just on windows, because while `vlib\v\checker\tests\modules\deprecated_module` works, +// 2022-01-30 it leads to path differences, and the / version on windows triggers a module lookip bug, +// 2022-01-30 leading to completely different errors) +fn mod_path_to_full_name(pref &pref.Preferences, mod string, path string) ?string { // TODO: explore using `pref.lookup_path` & `os.vmodules_paths()` // absolute paths instead of 'vlib' & '.vmodules' mut vmod_folders := ['vlib', '.vmodules', 'modules'] - for base in pref.lookup_path.map(os.base(it)) { + bases := pref.lookup_path.map(os.base(it)) + for base in bases { if base !in vmod_folders { vmod_folders << base }