tools: implement `cgen` tag for Markdown examples in `v check-md` (#13332)

pull/13336/head
Delyan Angelov 2022-01-31 22:51:04 +02:00 committed by GitHub
parent b34860e39b
commit db50e79d26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 51 deletions

View File

@ -21,6 +21,7 @@ const (
hide_warnings = '-hide-warnings' in os.args || '-w' in os.args hide_warnings = '-hide-warnings' in os.args || '-w' in os.args
show_progress = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args show_progress = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args
non_option_args = cmdline.only_non_options(os.args[2..]) non_option_args = cmdline.only_non_options(os.args[2..])
is_verbose = os.getenv('VERBOSE') != ''
) )
struct CheckResult { struct CheckResult {
@ -75,7 +76,7 @@ fn main() {
res += mdfile.check() res += mdfile.check()
} }
if res.errors == 0 && show_progress { if res.errors == 0 && show_progress {
term.clear_previous_line() clear_previous_line()
} }
if res.warnings > 0 || res.errors > 0 || res.oks > 0 { if res.warnings > 0 || res.errors > 0 || res.oks > 0 {
println('\nWarnings: $res.warnings | Errors: $res.errors | OKs: $res.oks') println('\nWarnings: $res.warnings | Errors: $res.errors | OKs: $res.oks')
@ -131,9 +132,7 @@ fn eline(file_path string, lnumber int, column int, message string) string {
return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message')) return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
} }
const ( const default_command = 'compile'
default_command = 'compile'
)
struct VCodeExample { struct VCodeExample {
mut: mut:
@ -160,7 +159,7 @@ mut:
fn (mut f MDFile) progress(message string) { fn (mut f MDFile) progress(message string) {
if show_progress { if show_progress {
term.clear_previous_line() clear_previous_line()
println('File: ${f.path:-30s}, Lines: ${f.lines.len:5}, $message') println('File: ${f.path:-30s}, Lines: ${f.lines.len:5}, $message')
} }
} }
@ -394,6 +393,7 @@ fn (mut f MDFile) debug() {
} }
fn cmdexecute(cmd string) int { fn cmdexecute(cmd string) int {
verbose_println(cmd)
res := os.execute(cmd) res := os.execute(cmd)
if res.exit_code < 0 { if res.exit_code < 0 {
return 1 return 1
@ -405,6 +405,7 @@ fn cmdexecute(cmd string) int {
} }
fn silent_cmdexecute(cmd string) int { fn silent_cmdexecute(cmd string) int {
verbose_println(cmd)
res := os.execute(cmd) res := os.execute(cmd)
return res.exit_code return res.exit_code
} }
@ -426,6 +427,7 @@ fn (mut f MDFile) check_examples() CheckResult {
} }
fname := os.base(f.path).replace('.md', '_md') fname := os.base(f.path).replace('.md', '_md')
uid := rand.ulid() uid := rand.ulid()
cfile := os.join_path(os.temp_dir(), '${uid}.c')
vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v') vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')
mut should_cleanup_vfile := true mut should_cleanup_vfile := true
// eprintln('>>> checking example $vfile ...') // eprintln('>>> checking example $vfile ...')
@ -438,8 +440,7 @@ fn (mut f MDFile) check_examples() CheckResult {
fmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) } fmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) }
match command { match command {
'compile' { 'compile' {
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}') res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors ${os.quoted_path(vfile)}')
os.rm('x.c') or {}
if res != 0 || fmt_res != 0 { if res != 0 || fmt_res != 0 {
if res != 0 { if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile')) eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
@ -454,9 +455,26 @@ fn (mut f MDFile) check_examples() CheckResult {
} }
oks++ oks++
} }
'cgen' {
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
os.rm(cfile) or {}
if res != 0 || fmt_res != 0 {
if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to generate C code'))
}
if fmt_res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example is not formatted'))
}
eprintln(vcontent)
should_cleanup_vfile = false
errors++
continue
}
oks++
}
'globals' { 'globals' {
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o x.c ${os.quoted_path(vfile)}') res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
os.rm('x.c') or {} os.rm(cfile) or {}
if res != 0 || fmt_res != 0 { if res != 0 || fmt_res != 0 {
if res != 0 { if res != 0 {
eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals')) eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals'))
@ -472,7 +490,8 @@ fn (mut f MDFile) check_examples() CheckResult {
oks++ oks++
} }
'live' { 'live' {
res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o x.c ${os.quoted_path(vfile)}') res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
os.rm(cfile) or {}
if res != 0 || fmt_res != 0 { if res != 0 || fmt_res != 0 {
if res != 0 { if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live')) eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
@ -488,8 +507,8 @@ fn (mut f MDFile) check_examples() CheckResult {
oks++ oks++
} }
'failcompile' { 'failcompile' {
res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}') res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
os.rm('x.c') or {} os.rm(cfile) or {}
if res == 0 || fmt_res != 0 { if res == 0 || fmt_res != 0 {
if res == 0 { if res == 0 {
eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled')) eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled'))
@ -533,7 +552,7 @@ fn (mut f MDFile) check_examples() CheckResult {
} }
'nofmt' {} 'nofmt' {}
else { else {
eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/failcompile/oksyntax/badsyntax')) eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/cgen/failcompile/oksyntax/badsyntax/nofmt'))
should_cleanup_vfile = false should_cleanup_vfile = false
errors++ errors++
} }
@ -548,3 +567,16 @@ fn (mut f MDFile) check_examples() CheckResult {
oks: oks oks: oks
} }
} }
fn verbose_println(message string) {
if is_verbose {
println(message)
}
}
fn clear_previous_line() {
if is_verbose {
return
}
term.clear_previous_line()
}

View File

@ -13,6 +13,7 @@ Flags:
NB: There are several special keywords, which you can put after the code fences for v. NB: There are several special keywords, which you can put after the code fences for v.
These are: These are:
compile - Default, can be omitted. The example will be compiled and formatting is verified. compile - Default, can be omitted. The example will be compiled and formatting is verified.
cgen - The example produces C code, which may not be compilable (when external libs are not installed). Formatting is verified.
live - Compile hot reload examples with the ´-live´ flag set and verify formatting. live - Compile hot reload examples with the ´-live´ flag set and verify formatting.
ignore - Ignore the example, useful for examples that just use the syntax highlighting ignore - Ignore the example, useful for examples that just use the syntax highlighting
failcompile - Known failing compilation. Useful for examples demonstrating compiler errors. failcompile - Known failing compilation. Useful for examples demonstrating compiler errors.

View File

@ -163,7 +163,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
<!-- <!--
NB: there are several special keywords, which you can put after the code fences for v: NB: there are several special keywords, which you can put after the code fences for v:
compile, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt compile, cgen, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt
For more details, do: `v check-md` For more details, do: `v check-md`
--> -->
@ -1393,7 +1393,7 @@ println(s)
You can check the current type of a sum type using `is` and its negated form `!is`. You can check the current type of a sum type using `is` and its negated form `!is`.
You can do it either in an `if`: You can do it either in an `if`:
```v ```v cgen
struct Abc { struct Abc {
val string val string
} }
@ -5102,6 +5102,7 @@ For all supported options check the latest help:
#### `$if` condition #### `$if` condition
```v ```v
fn main() {
// Support for multiple conditions in one branch // Support for multiple conditions in one branch
$if ios || android { $if ios || android {
println('Running on a mobile device!') println('Running on a mobile device!')
@ -5137,6 +5138,7 @@ $if prod {
$if option ? { $if option ? {
println('custom option') println('custom option')
} }
}
``` ```
If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign. If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign.

View File

@ -7,7 +7,7 @@ user's keyboard/mouse input.
## Example: ## Example:
```v ```v cgen
module main module main
import gg import gg

View File

@ -11,7 +11,7 @@ Each `.h` file in the sokol source code is well-documented as can be seen here:
## Example from `@VROOTDIR/examples/sokol/sounds/simple_sin_tones.v`: ## Example from `@VROOTDIR/examples/sokol/sounds/simple_sin_tones.v`:
```v ```v cgen
import time import time
import math import math
import sokol.audio import sokol.audio