Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tools: support
v doc -run-examples math
, to ensure that all `// Exa…
…mple: code` doc comments are working (#19852)
- Loading branch information
Showing
15 changed files
with
351 additions
and
191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
module main | ||
|
||
import os | ||
import os.cmdline | ||
import term | ||
import v.doc | ||
import v.vmod | ||
|
||
const vexe = os.getenv_opt('VEXE') or { @VEXE } | ||
|
||
const vroot = os.dir(vexe) | ||
|
||
const allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm'] | ||
|
||
fn main() { | ||
if os.args.len < 2 || '-h' in os.args || '-help' in os.args || '--help' in os.args | ||
|| os.args[1..] == ['doc', 'help'] { | ||
os.system('${os.quoted_path(vexe)} help doc') | ||
exit(0) | ||
} | ||
args := os.args[2..].clone() | ||
cfg := parse_arguments(args) | ||
if cfg.input_path.len == 0 { | ||
eprintln('vdoc: No input path found.') | ||
exit(1) | ||
} | ||
// Config is immutable from this point on | ||
mut vd := &VDoc{ | ||
cfg: cfg | ||
manifest: vmod.Manifest{ | ||
repo_url: '' | ||
} | ||
} | ||
vd.vprintln('Setting output type to "${cfg.output_type}"') | ||
vd.generate_docs_from_file() | ||
if cfg.run_examples { | ||
println('') | ||
if vd.example_oks == 0 && vd.example_failures == 0 { | ||
println(term.colorize(term.bright_yellow, 'Found NO examples.')) | ||
} else { | ||
println(term.colorize(term.gray, 'Found ${vd.example_oks} ok examples.')) | ||
} | ||
if vd.example_failures > 0 { | ||
println(term.colorize(term.red, 'Found ${vd.example_failures} failing examples.')) | ||
exit(1) | ||
} | ||
} | ||
} | ||
|
||
fn parse_arguments(args []string) Config { | ||
mut cfg := Config{} | ||
cfg.is_color = term.can_show_color_on_stdout() | ||
for i := 0; i < args.len; i++ { | ||
arg := args[i] | ||
current_args := args[i..] | ||
match arg { | ||
'-all' { | ||
cfg.pub_only = false | ||
} | ||
'-f' { | ||
format := cmdline.option(current_args, '-f', '') | ||
if format !in allowed_formats { | ||
allowed_str := allowed_formats.join(', ') | ||
eprintln('vdoc: "${format}" is not a valid format. Only ${allowed_str} are allowed.') | ||
exit(1) | ||
} | ||
cfg.output_type = set_output_type_from_str(format) | ||
i++ | ||
} | ||
'-color' { | ||
cfg.is_color = true | ||
} | ||
'-no-color' { | ||
cfg.is_color = false | ||
} | ||
'-inline-assets' { | ||
cfg.inline_assets = true | ||
} | ||
'-theme-dir' { | ||
cfg.theme_dir = cmdline.option(current_args, '-theme-dir', default_theme) | ||
} | ||
'-l' { | ||
cfg.show_loc = true | ||
} | ||
'-comments' { | ||
cfg.include_comments = true | ||
} | ||
'-m' { | ||
cfg.is_multi = true | ||
} | ||
'-o' { | ||
opath := cmdline.option(current_args, '-o', '') | ||
cfg.output_path = if opath == 'stdout' { opath } else { os.real_path(opath) } | ||
i++ | ||
} | ||
'-os' { | ||
platform_str := cmdline.option(current_args, '-os', '') | ||
if platform_str == 'cross' { | ||
eprintln('`v doc -os cross` is not supported yet.') | ||
exit(1) | ||
} | ||
selected_platform := doc.platform_from_string(platform_str) or { | ||
eprintln(err.msg()) | ||
exit(1) | ||
} | ||
cfg.platform = selected_platform | ||
i++ | ||
} | ||
'-run-examples' { | ||
cfg.run_examples = true | ||
} | ||
'-no-timestamp' { | ||
cfg.no_timestamp = true | ||
} | ||
'-no-examples' { | ||
cfg.include_examples = false | ||
} | ||
'-readme' { | ||
cfg.include_readme = true | ||
} | ||
'-v' { | ||
cfg.is_verbose = true | ||
} | ||
else { | ||
if cfg.input_path.len < 1 { | ||
cfg.input_path = arg | ||
} else if !cfg.is_multi { | ||
// Symbol name filtering should not be enabled | ||
// in multi-module documentation mode. | ||
cfg.symbol_name = arg | ||
} | ||
if i == args.len - 1 { | ||
break | ||
} | ||
} | ||
} | ||
} | ||
// Correct from configuration from user input | ||
if cfg.output_path == 'stdout' && cfg.output_type == .html { | ||
cfg.inline_assets = true | ||
} | ||
$if windows { | ||
cfg.input_path = cfg.input_path.replace('/', os.path_separator) | ||
} $else { | ||
cfg.input_path = cfg.input_path.replace('\\', os.path_separator) | ||
} | ||
is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len > 1 | ||
|| cfg.input_path == '.' | ||
if cfg.input_path.trim_right('/') == 'vlib' { | ||
cfg.is_vlib = true | ||
cfg.is_multi = true | ||
cfg.input_path = os.join_path(vroot, 'vlib') | ||
} else if !is_path { | ||
// TODO vd.vprintln('Input "$cfg.input_path" is not a valid path. Looking for modules named "$cfg.input_path"...') | ||
mod_path := doc.lookup_module(cfg.input_path) or { | ||
eprintln('vdoc: ${err}') | ||
exit(1) | ||
} | ||
cfg.input_path = mod_path | ||
} | ||
return cfg | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
module main | ||
|
||
import v.doc | ||
import v.vmod | ||
import strings | ||
import os | ||
import rand | ||
import term | ||
|
||
const normalised_default_vmodules_path = os.vmodules_dir().replace('\\', '/') | ||
|
||
fn get_mod_name_by_file_path(file_path string) string { | ||
mut mcache := vmod.get_cache() | ||
dn_folder := os.dir(os.real_path(file_path)).replace('\\', '/').trim_string_right('/src') | ||
vmodpath := mcache.get_by_folder(dn_folder) | ||
normal_folder := dn_folder.replace('\\', '/') | ||
vmod_folder := vmodpath.vmod_folder.replace('\\', '/') | ||
mut relative_mod_path := normal_folder | ||
relative_mod_path = relative_mod_path.trim_string_left(vmod_folder).trim_string_left('/') | ||
relative_mod_path = relative_mod_path.trim_string_left(normalised_default_vmodules_path) | ||
relative_mod_path = relative_mod_path.trim_string_left('vlib/') | ||
mod_name := relative_mod_path.replace('/', '.').trim('.') | ||
return mod_name | ||
} | ||
|
||
fn (mut vd VDoc) run_examples(dn doc.DocNode, mut pw strings.Builder) { | ||
if dn.comments.len == 0 || !vd.cfg.run_examples { | ||
return | ||
} | ||
examples := dn.examples() | ||
if examples.len == 0 { | ||
return | ||
} | ||
efolder := os.vtmp_dir() | ||
mut example_program_source_files := []string{} | ||
defer { | ||
for sfile in example_program_source_files { | ||
os.rm(sfile) or {} | ||
} | ||
} | ||
mut failures := 0 | ||
mut oks := 0 | ||
for example in examples { | ||
code := example.all_after('Example:').all_after('example:').trim_space() | ||
mod_name := get_mod_name_by_file_path(dn.file_path) | ||
vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v') | ||
// eprintln('>>> example dn.file_path: ${dn.file_path} | mod_name: ${mod_name} | vsource_path: ${vsource_path} | code: `${code}`') | ||
import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' } | ||
source := '${import_clause}fn main() {\n\t${code}\n}\n' | ||
os.write_file(vsource_path, source) or { continue } | ||
cmd := '${os.quoted_path(vexe)} -g run ${os.quoted_path(vsource_path)}' | ||
res := os.execute(cmd) | ||
if res.exit_code != 0 { | ||
eprintln('${dn_to_location(dn)}:${term.ecolorize(term.red, 'error in documentation example')}') | ||
eprintln('cmd: ${cmd}') | ||
eprintln('result: ${res.output}') | ||
failures++ | ||
continue | ||
} | ||
example_program_source_files << vsource_path | ||
oks++ | ||
} | ||
vd.example_failures += failures | ||
vd.example_oks += oks | ||
} |
Empty file.
5 changes: 5 additions & 0 deletions
5
cmd/tools/vdoc/tests/testdata/run_examples_bad/main.comments.out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module main | ||
|
||
fn abc() | ||
abc just prints 'xyz'. The important thing however is the next line, that does an assertion, that should FAIL to be executed with `v doc -run-examples good.v`: | ||
Example: assert 5 * 5 == 77 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module main | ||
|
||
fn abc() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// abc just prints 'xyz'. The important thing however is the next line, that does an assertion, | ||
// that should FAIL to be executed with `v doc -run-examples good.v`: | ||
// Example: assert 5 * 5 == 77 | ||
pub fn abc() { | ||
println('xyz') | ||
} | ||
|
||
fn main() { | ||
abc() | ||
} |
Empty file.
5 changes: 5 additions & 0 deletions
5
cmd/tools/vdoc/tests/testdata/run_examples_good/main.comments.out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module main | ||
|
||
fn abc() | ||
abc just prints 'xyz'. The important thing however is the next line, that does an assertion, that should be executed with `v doc -run-examples good.v`, and should succeed: | ||
Example: assert 5 * 5 == 25 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module main | ||
|
||
fn abc() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// abc just prints 'xyz'. The important thing however is the next line, that does an assertion, | ||
// that should be executed with `v doc -run-examples good.v`, and should succeed: | ||
// Example: assert 5 * 5 == 25 | ||
pub fn abc() { | ||
println('xyz') | ||
} | ||
|
||
fn main() { | ||
abc() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.