mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
150 lines
3.1 KiB
V
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')
|
|
}
|
|
}
|