92 lines
2.9 KiB
V
92 lines
2.9 KiB
V
module doc
|
|
|
|
import os
|
|
import v.table
|
|
import v.parser
|
|
import v.ast
|
|
import v.pref
|
|
|
|
// get_parent_mod returns the parent mod name, in dot format.
|
|
// It works by climbing up the folder hierarchy, until a folder,
|
|
// that either contains main .v files, or a v.mod file is reached.
|
|
// For example, given something like /languages/v/vlib/x/websocket/tests/autobahn
|
|
// it returns `x.websocket.tests`, because /languages/v/ has v.mod file in it.
|
|
// NB: calling this is expensive, so keep the result, instead of recomputing it.
|
|
fn get_parent_mod(input_dir string) ?string {
|
|
$if windows {
|
|
// windows root path is C: or D:
|
|
if input_dir.len <= 2 {
|
|
return error('root folder reached')
|
|
}
|
|
} $else {
|
|
if input_dir.len == 0 {
|
|
return error('root folder reached')
|
|
}
|
|
}
|
|
base_dir := os.dir(input_dir)
|
|
input_dir_name := os.file_name(base_dir)
|
|
prefs := new_vdoc_preferences()
|
|
fentries := os.ls(base_dir) or { []string{} }
|
|
files := fentries.filter(!os.is_dir(it))
|
|
if 'v.mod' in files {
|
|
// the top level is reached, no point in climbing up further
|
|
return ''
|
|
}
|
|
v_files := prefs.should_compile_filtered_files(base_dir, files)
|
|
if v_files.len == 0 {
|
|
parent_mod := get_parent_mod(base_dir) or { return input_dir_name }
|
|
if parent_mod.len > 0 {
|
|
return parent_mod + '.' + input_dir_name
|
|
}
|
|
return error('No V files found.')
|
|
}
|
|
tbl := table.new_table()
|
|
scope := &ast.Scope{
|
|
parent: 0
|
|
}
|
|
file_ast := parser.parse_file(v_files[0], tbl, .skip_comments, prefs, scope)
|
|
if file_ast.mod.name == 'main' {
|
|
return ''
|
|
}
|
|
parent_mod := get_parent_mod(base_dir) or { return input_dir_name }
|
|
if parent_mod.len > 0 {
|
|
return '${parent_mod}.$file_ast.mod.name'
|
|
}
|
|
return file_ast.mod.name
|
|
}
|
|
|
|
// lookup_module_with_path looks up the path of a given module name.
|
|
// Throws an error if the module was not found.
|
|
pub fn lookup_module_with_path(mod string, base_path string) ?string {
|
|
vexe := pref.vexe_path()
|
|
vroot := os.dir(vexe)
|
|
mod_path := mod.replace('.', os.path_separator)
|
|
compile_dir := os.real_path(base_path)
|
|
modules_dir := os.join_path(compile_dir, 'modules', mod_path)
|
|
vlib_path := os.join_path(vroot, 'vlib', mod_path)
|
|
mut paths := [modules_dir, vlib_path]
|
|
vmodules_paths := os.vmodules_paths()
|
|
for vmpath in vmodules_paths {
|
|
paths << os.join_path(vmpath, mod_path)
|
|
}
|
|
for path in paths {
|
|
if !os.exists(path) || os.is_dir_empty(path) {
|
|
continue
|
|
}
|
|
return path
|
|
}
|
|
return error('module "$mod" not found.')
|
|
}
|
|
|
|
// lookup_module returns the result of the `lookup_module_with_path`
|
|
// but with the current directory as the provided base lookup path.
|
|
pub fn lookup_module(mod string) ?string {
|
|
return lookup_module_with_path(mod, os.dir('.'))
|
|
}
|
|
|
|
// generate_from_mod generates a documentation from a specific module.
|
|
pub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) ?Doc {
|
|
mod_path := lookup_module(module_name) ?
|
|
return generate(mod_path, pub_only, with_comments)
|
|
}
|