From 007430ef2bcd66a3e3a9fbed7796523d56696288 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 26 Oct 2022 21:47:36 +0300 Subject: [PATCH] tools: support `VAUTOFIX=1 v check-md vlib/term/README.md` for fixing unformatted examples without manual edits --- cmd/tools/vcheck-md.v | 100 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/cmd/tools/vcheck-md.v b/cmd/tools/vcheck-md.v index 722e09e051..2fce788317 100644 --- a/cmd/tools/vcheck-md.v +++ b/cmd/tools/vcheck-md.v @@ -8,7 +8,6 @@ import os.cmdline import rand import term import vhelp -import v.pref import regex const ( @@ -23,6 +22,8 @@ const ( non_option_args = cmdline.only_non_options(os.args[2..]) is_verbose = os.getenv('VERBOSE') != '' vcheckfolder = os.join_path(os.temp_dir(), 'v', 'vcheck_$os.getuid()') + should_autofix = os.getenv('VAUTOFIX') != '' + vexe = @VEXE ) struct CheckResult { @@ -154,9 +155,9 @@ enum MDFileParserState { } struct MDFile { - path string - lines []string + path string mut: + lines []string examples []VCodeExample current VCodeExample state MDFileParserState = .markdown @@ -422,8 +423,7 @@ fn get_fmt_exit_code(vfile string, vexe string) int { fn (mut f MDFile) check_examples() CheckResult { mut errors := 0 mut oks := 0 - vexe := pref.vexe_path() - for e in f.examples { + recheck_all_examples: for e in f.examples { if e.command == 'ignore' { continue } @@ -451,8 +451,10 @@ fn (mut f MDFile) check_examples() CheckResult { if res != 0 { eprintln(eline(f.path, e.sline, 0, 'example failed to compile')) } - if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, 'example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -467,8 +469,10 @@ fn (mut f MDFile) check_examples() CheckResult { 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')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -483,8 +487,10 @@ fn (mut f MDFile) check_examples() CheckResult { if res != 0 { eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals')) } - if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, '`example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -499,8 +505,10 @@ fn (mut f MDFile) check_examples() CheckResult { if res != 0 { eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live')) } - if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, 'example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -515,8 +523,10 @@ fn (mut f MDFile) check_examples() CheckResult { if res == 0 { eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled')) } - if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, 'example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -531,8 +541,10 @@ fn (mut f MDFile) check_examples() CheckResult { if res != 0 { eprintln(eline(f.path, e.sline, 0, '`oksyntax` example with invalid syntax')) } - if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, '`oksyntax` example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } } eprintln(vcontent) should_cleanup_vfile = false @@ -543,7 +555,11 @@ fn (mut f MDFile) check_examples() CheckResult { } 'okfmt' { if fmt_res != 0 { - eprintln(eline(f.path, e.sline, 0, 'okfmt example is not formatted')) + f.report_not_formatted_example_if_needed(e, fmt_res, vfile) or { + unsafe { + goto recheck_all_examples + } + } eprintln(vcontent) should_cleanup_vfile = false errors++ @@ -594,3 +610,51 @@ fn clear_previous_line() { } term.clear_previous_line() } + +fn (mut f MDFile) report_not_formatted_example_if_needed(e VCodeExample, fmt_res int, vfile string) ! { + if fmt_res == 0 { + return + } + eprintln(eline(f.path, e.sline, 0, 'example is not formatted')) + if !should_autofix { + return + } + f.autofix_example(e, vfile) or { + if err is ExampleWasRewritten { + eprintln('>> f.path: $f.path | example from $e.sline to $e.eline was re-formated by vfmt') + return err + } + eprintln('>> f.path: $f.path | encountered error while autofixing the example: $err') + } +} + +struct ExampleWasRewritten { + Error +} + +fn (mut f MDFile) autofix_example(e VCodeExample, vfile string) ! { + eprintln('>>> AUTOFIXING f.path: $f.path | e.sline: $e.sline | vfile: $vfile') + res := cmdexecute('${os.quoted_path(vexe)} fmt -w ${os.quoted_path(vfile)}') + if res != 0 { + return error('could not autoformat the example') + } + formatted_content_lines := os.read_lines(vfile) or { return } + mut new_lines := []string{} + new_lines << f.lines#[0..e.sline + 1] + new_lines << formatted_content_lines + new_lines << f.lines#[e.eline..] + f.update_examples(new_lines)! + os.rm(vfile) or {} + return ExampleWasRewritten{} +} + +fn (mut f MDFile) update_examples(new_lines []string) ! { + os.write_file(f.path, new_lines.join('\n'))! + f.lines = new_lines + f.examples = [] + f.current = VCodeExample{} + f.state = .markdown + for j, line in f.lines { + f.parse_line(j, line) + } +}