// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module pref import os fn (p &Preferences) effective_vroot() string { if p.vroot.len > 0 { return p.vroot } return os.getwd() } pub fn (p &Preferences) get_vlib_module_path(mod string) string { mod_path := mod.replace('.', os.path_separator) return module_path_join(module_path_join(p.effective_vroot(), 'vlib'), mod_path) } fn module_path_join(base string, name string) string { if base.len == 0 { return name } if name.len == 0 { return base } last := base[base.len - 1] if last == `/` || last == `\\` { return base + name } return base + os.path_separator + name } fn module_root_for_file(path string) string { mut dir := os.dir(path) for dir.len > 0 { if os.exists(module_path_join(dir, 'v.mod')) { return dir } parent := os.dir(dir) if parent == dir { break } dir = parent } return '' } fn find_module_path_in_parent_dirs(mod_path string, importing_file_path string) ?string { mut dir := os.dir(importing_file_path) for dir.len > 0 { parent_relative_path := module_path_join(dir, mod_path) if dir_exists(parent_relative_path) { return parent_relative_path } parent := os.dir(dir) if parent == dir { break } dir = parent } return none } // check for relative and then vlib pub fn (p &Preferences) get_module_path(mod string, importing_file_path string) string { mod_path := mod.replace('.', os.path_separator) vroot := p.effective_vroot() // relative to file importing it relative_path := module_path_join(os.dir(importing_file_path), mod_path) if dir_exists(relative_path) { return relative_path } module_root := module_root_for_file(importing_file_path) if module_root != '' { root_relative_path := module_path_join(module_root, mod_path) if dir_exists(root_relative_path) { return root_relative_path } } if parent_relative_path := find_module_path_in_parent_dirs(mod_path, importing_file_path) { return parent_relative_path } cwd_relative_path := module_path_join(os.getwd(), mod_path) if dir_exists(cwd_relative_path) { return cwd_relative_path } // TODO: is this the best order? // vlib vlib_path := module_path_join(module_path_join(vroot, 'vlib'), mod_path) if dir_exists(vlib_path) { return vlib_path } // V1 compiler modules under vlib/v use legacy bare sibling imports // (`import token` from vlib/v/checker, with sources in vlib/v/token). vlib_v_path := module_path_join(module_path_join(vroot, 'vlib'), 'v') normalized_importer := importing_file_path.replace('\\', '/') normalized_vlib_v := vlib_v_path.replace('\\', '/') if normalized_importer.starts_with(normalized_vlib_v + '/') || normalized_importer.starts_with('vlib/v/') { legacy_v_path := module_path_join(vlib_v_path, mod_path) if dir_exists(legacy_v_path) { return legacy_v_path } } // ~/.vmodules vmodules_path := module_path_join(p.vmodules_path, mod_path) if dir_exists(vmodules_path) { // V convention: if a module dir has a src/ subdirectory, use that src_path := module_path_join(vmodules_path, 'src') if dir_exists(src_path) { return src_path } return vmodules_path } panic('Preferences.get_module_path: cannot find module path for `${mod}`') }