1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/v/doc/doc.v
2020-05-15 23:09:38 +02:00

150 lines
3.1 KiB
V

module doc
import strings
import v.pref
import v.table
import v.parser
import v.ast
import os
struct Doc {
out strings.Builder
table &table.Table
mod string
mut:
stmts []ast.Stmt // all module statements from all files
}
type FilterFn = fn (node ast.FnDecl) bool
pub fn doc(mod string, table &table.Table, prefs &pref.Preferences) string {
mut d := Doc{
out: strings.new_builder(1000)
table: table
mod: mod
}
vlib_path := os.dir(pref.vexe_path()) + '/vlib'
mod_path := mod.replace('.', os.path_separator)
path := os.join_path(vlib_path, mod_path)
if mod == '' || !os.exists(path) {
if mod != '' {
println('module "$mod" not found')
}
println('\navailable modules:')
mut files := os.ls(vlib_path) or {
return ''
}
files.sort()
for file in files {
println(file)
}
// println(path)
return ''
}
// vfiles := os.walk_ext(path, '.v')
files := os.ls(path) or {
panic(err)
}
filtered_files := prefs.should_compile_filtered_files(path, files)
for file in filtered_files {
fscope := &ast.Scope{
parent: 0
}
file_ast := parser.parse_file(file, table, .skip_comments, prefs, fscope)
d.stmts << file_ast.stmts
}
if d.stmts.len == 0 {
println('nothing here')
exit(1)
}
d.print_structs()
d.print_enums()
d.print_fns()
d.out.writeln('')
d.print_methods()
/*
for stmt in file_ast.stmts {
d.stmt(stmt)
}
println(path)
*/
return d.out.str().trim_space()
}
fn (d &Doc) get_fn_node(f ast.FnDecl) string {
return f.str(d.table).replace_each([d.mod + '.', '', 'pub ', ''])
}
fn (mut d Doc) print_fns() {
fn_signatures := d.get_fn_signatures(is_pub_function)
d.write_fn_signatures(fn_signatures)
}
fn (mut d Doc) print_methods() {
fn_signatures := d.get_fn_signatures(is_pub_method)
d.write_fn_signatures(fn_signatures)
}
[inline]
fn (mut d Doc) write_fn_signatures(fn_signatures []string) {
for s in fn_signatures {
d.out.writeln(s)
}
}
fn (d Doc) get_fn_signatures(filter_fn FilterFn) []string {
mut fn_signatures := []string{}
for stmt in d.stmts {
match stmt {
ast.FnDecl {
if filter_fn(it) {
fn_signatures << d.get_fn_node(it)
}
}
else {}
}
}
fn_signatures.sort()
return fn_signatures
}
fn is_pub_method(node ast.FnDecl) bool {
return node.is_pub && node.is_method && !node.is_deprecated
}
fn is_pub_function(node ast.FnDecl) bool {
return node.is_pub && !node.is_method && !node.is_deprecated
}
// TODO it's probably better to keep using AST, not `table`
fn (mut d Doc) print_enums() {
for typ in d.table.types {
if typ.kind != .enum_ {
continue
}
d.out.writeln('enum $typ.name {')
info := typ.info as table.Enum
for val in info.vals {
d.out.writeln('\t$val')
}
d.out.writeln('}')
}
}
fn (mut d Doc) print_structs() {
for typ in d.table.types {
if typ.kind != .struct_ || !typ.name.starts_with(d.mod + '.') {
// !typ.name[0].is_capital() || typ.name.starts_with('C.') {
continue
}
name := typ.name.after('.')
d.out.writeln('struct $name {')
info := typ.info as table.Struct
for field in info.fields {
sym := d.table.get_type_symbol(field.typ)
d.out.writeln('\t$field.name $sym.name')
}
d.out.writeln('}\n')
}
}