mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v fmt: process .v files from a module too
This commit is contained in:
committed by
Alexander Medvednikov
parent
411a83e283
commit
96fa15c125
167
tools/vfmt.v
167
tools/vfmt.v
@@ -5,6 +5,7 @@ module main
|
||||
|
||||
import (
|
||||
os
|
||||
os.cmdline
|
||||
filepath
|
||||
compiler
|
||||
)
|
||||
@@ -14,67 +15,139 @@ struct FormatOptions {
|
||||
is_diff bool
|
||||
is_verbose bool
|
||||
is_all bool
|
||||
is_worker bool
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foptions := FormatOptions{
|
||||
is_w: '-w' in os.args
|
||||
is_diff: '-diff' in os.args
|
||||
is_verbose: '-verbose' in os.args || '--verbose' in os.args
|
||||
is_all: '-all' in os.args || '--all' in os.args
|
||||
}
|
||||
toolexe := os.executable()
|
||||
compiler.set_vroot_folder(filepath.dir(filepath.dir(toolexe)))
|
||||
args := compiler.env_vflags_and_os_args()
|
||||
foptions := FormatOptions{
|
||||
is_w: '-w' in args
|
||||
is_diff: '-diff' in args
|
||||
is_verbose: '-verbose' in args || '--verbose' in args
|
||||
is_all: '-all' in args || '--all' in args
|
||||
is_worker: '-worker' in args
|
||||
}
|
||||
if foptions.is_worker {
|
||||
// -worker should be added by a parent vfmt process.
|
||||
// We launch a sub process for each file because
|
||||
// the v compiler can do an early exit if it detects
|
||||
// a syntax error, but we want to process ALL passed
|
||||
// files if possible.
|
||||
foptions.format_file(cmdline.option(args, '-worker', ''))
|
||||
exit(0)
|
||||
}
|
||||
// we are NOT a worker at this stage, i.e. we are a parent vfmt process
|
||||
possible_files := cmdline.only_non_options(cmdline.after(args, ['fmt']))
|
||||
if foptions.is_verbose {
|
||||
eprintln('vfmt toolexe: $toolexe')
|
||||
eprintln('vfmt args: ' + os.args.str())
|
||||
eprintln('vfmt env_vflags_and_os_args: ' + args.str())
|
||||
eprintln('vfmt possible_files: ' + possible_files.str())
|
||||
eprintln('vfmt foptions: $foptions')
|
||||
}
|
||||
mut files := []string
|
||||
for i := 1; i < args.len; i++ {
|
||||
a := args[i]
|
||||
if a == 'fmt' {
|
||||
continue
|
||||
for file in possible_files {
|
||||
if !os.exists(file) {
|
||||
compiler.verror('"$file" does not exist.')
|
||||
}
|
||||
if !a.starts_with('-') {
|
||||
file := a
|
||||
if !os.exists(file) {
|
||||
compiler.verror('"$file" does not exist.')
|
||||
}
|
||||
if !file.ends_with('.v') {
|
||||
compiler.verror('v fmt can only be used on .v files.\nOffending file: "$file" .')
|
||||
}
|
||||
files << a
|
||||
if !file.ends_with('.v') {
|
||||
compiler.verror('v fmt can only be used on .v files.\nOffending file: "$file" .')
|
||||
}
|
||||
files << file
|
||||
}
|
||||
if files.len == 0 {
|
||||
usage()
|
||||
exit(0)
|
||||
}
|
||||
if foptions.is_all {
|
||||
os.setenv('VFMT_OPTION_ALL', 'yes', true)
|
||||
mut cli_args_no_files := []string
|
||||
for a in os.args {
|
||||
if !a in files {
|
||||
cli_args_no_files << a
|
||||
}
|
||||
}
|
||||
mut errors := 0
|
||||
for file in files {
|
||||
format_file(file, foptions)
|
||||
fpath := os.realpath(file)
|
||||
mut worker_command_array := cli_args_no_files.clone()
|
||||
worker_command_array << ['-worker', fpath]
|
||||
worker_cmd := worker_command_array.join(' ')
|
||||
if foptions.is_verbose {
|
||||
eprintln('vfmt worker_cmd: $worker_cmd')
|
||||
}
|
||||
cmdcode := os.system(worker_cmd)
|
||||
if cmdcode != 0 {
|
||||
eprintln('vfmt error while formatting file: $file .')
|
||||
errors++
|
||||
}
|
||||
}
|
||||
if errors > 0 {
|
||||
eprintln('Encountered a total of: ${errors} errors.')
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fn format_file(file string, foptions FormatOptions) {
|
||||
mut v := compiler.new_v_compiler_with_args([file])
|
||||
if foptions.is_verbose {
|
||||
eprintln('vfmt format_file: $file | v.dir: $v.dir')
|
||||
fn (foptions &FormatOptions) format_file(file string) {
|
||||
tmpfolder := os.tmpdir()
|
||||
mut compiler_params := []string
|
||||
mut cfile := file
|
||||
mut mod_folder_parent := tmpfolder
|
||||
fcontent := os.read_file(file) or {
|
||||
return
|
||||
}
|
||||
is_test_file := file.ends_with('_test.v')
|
||||
is_module_file := fcontent.contains('module ') && !fcontent.contains('module main\n')
|
||||
use_tmp_main_program := is_module_file && !is_test_file
|
||||
mod_folder := filepath.basedir(file)
|
||||
mut mod_name := 'main'
|
||||
if is_module_file {
|
||||
mod_name = filepath.filename(mod_folder)
|
||||
}
|
||||
if use_tmp_main_program {
|
||||
// TODO: remove the need for this
|
||||
// This makes a small program that imports the module,
|
||||
// so that the module files will get processed by the
|
||||
// vfmt implementation.
|
||||
mod_folder_parent = filepath.basedir(mod_folder)
|
||||
mut main_program_content := 'import ${mod_name} \n fn main(){}'
|
||||
if fcontent.contains('module builtin\n') {
|
||||
main_program_content = 'fn main(){}'
|
||||
}
|
||||
main_program_file := filepath.join(tmpfolder,'vfmt_tmp_${mod_name}_program.v')
|
||||
if os.exists(main_program_file) {
|
||||
os.rm(main_program_file)
|
||||
}
|
||||
os.write_file(main_program_file, main_program_content)
|
||||
cfile = main_program_file
|
||||
compiler_params << ['-user_mod_path', mod_folder_parent]
|
||||
}
|
||||
compiler_params << cfile
|
||||
if foptions.is_verbose {
|
||||
eprintln('vfmt format_file: file: $file')
|
||||
eprintln('vfmt format_file: cfile: $cfile')
|
||||
eprintln('vfmt format_file: is_test_file: $is_test_file')
|
||||
eprintln('vfmt format_file: is_module_file: $is_module_file')
|
||||
eprintln('vfmt format_file: mod_name: $mod_name')
|
||||
eprintln('vfmt format_file: mod_folder: $mod_folder')
|
||||
eprintln('vfmt format_file: mod_folder_parent: $mod_folder_parent')
|
||||
eprintln('vfmt format_file: use_tmp_main_program: $use_tmp_main_program')
|
||||
eprintln('vfmt format_file: compiler_params: $compiler_params')
|
||||
eprintln('-------------------------------------------')
|
||||
}
|
||||
formatted_file_path := foptions.compile_file(file, compiler_params)
|
||||
if use_tmp_main_program {
|
||||
os.rm(cfile)
|
||||
}
|
||||
if formatted_file_path.len == 0 {
|
||||
return
|
||||
}
|
||||
v.compile()
|
||||
formatted_file_path := os.getenv('VFMT_FILE_RESULT')
|
||||
// eprintln('File: $file .')
|
||||
// eprintln('Formatted file is: $formatted_file_path .')
|
||||
if foptions.is_diff {
|
||||
if find_diff:=os.exec('diff -v'){
|
||||
os.system('diff "$formatted_file_path" "$file" ')
|
||||
diff_cmd := find_working_diff_command() or {
|
||||
eprintln('No working "diff" CLI command found.')
|
||||
return
|
||||
}
|
||||
eprintln('No working "diff" CLI command found.')
|
||||
os.system('$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$file" "$formatted_file_path" ')
|
||||
return
|
||||
}
|
||||
if foptions.is_w {
|
||||
@@ -92,10 +165,36 @@ fn format_file(file string, foptions FormatOptions) {
|
||||
}
|
||||
|
||||
fn usage() {
|
||||
print('Usage: tools/vfmt [flags] path_to_source.v [path_to_other_source.v]
|
||||
print('Usage: tools/vfmt [flags] fmt path_to_source.v [path_to_other_source.v]
|
||||
Formats the given V source files, and prints their formatted source to stdout.
|
||||
Options:
|
||||
-diff display only diffs between the formatted source and the original source.
|
||||
-w write result to (source) file(s) instead of to stdout.
|
||||
')
|
||||
}
|
||||
|
||||
fn find_working_diff_command() ?string {
|
||||
for diffcmd in ['colordiff', 'diff', 'colordiff.exe', 'diff.exe'] {
|
||||
p := os.exec('$diffcmd --version') or {
|
||||
continue
|
||||
}
|
||||
if p.exit_code == 0 {
|
||||
return diffcmd
|
||||
}
|
||||
}
|
||||
return error('no working diff command found')
|
||||
}
|
||||
|
||||
fn (foptions &FormatOptions) compile_file(file string, compiler_params []string) string {
|
||||
mut v := compiler.new_v_compiler_with_args(compiler_params)
|
||||
v.v_fmt_file = file
|
||||
if foptions.is_all {
|
||||
v.v_fmt_all = true
|
||||
}
|
||||
v.compile()
|
||||
return v.v_fmt_file_result
|
||||
}
|
||||
|
||||
pub fn (f FormatOptions) str() string {
|
||||
return 'FormatOptions{ ' + ' is_w: $f.is_w' + ' is_diff: $f.is_diff' + ' is_verbose: $f.is_verbose' + ' is_all: $f.is_all' + ' is_worker: $f.is_worker' + ' }'
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ module main
|
||||
|
||||
import (
|
||||
os
|
||||
os.cmdline
|
||||
testing
|
||||
)
|
||||
|
||||
@@ -20,18 +21,18 @@ pub fn main() {
|
||||
return
|
||||
}
|
||||
|
||||
args_string := args[1..].join(' ')
|
||||
args_before := args_string.all_before('test ')
|
||||
args_after := args_string.all_after('test ')
|
||||
args_to_executable := args[1..]
|
||||
args_before := cmdline.before(args_to_executable, ['test'])
|
||||
args_after := cmdline.after(args_to_executable, ['test'])
|
||||
|
||||
if args_after == 'v' {
|
||||
if args_after.join(' ') == 'v' {
|
||||
eprintln('`v test v` has been deprecated.')
|
||||
eprintln('Use `v test-compiler` instead.')
|
||||
exit(1)
|
||||
}
|
||||
|
||||
mut ts := testing.new_test_session(args_before)
|
||||
for targ in args_after.split(' ') {
|
||||
mut ts := testing.new_test_session(args_before.join(' '))
|
||||
for targ in args_after {
|
||||
if os.exists(targ) && targ.ends_with('_test.v') {
|
||||
ts.files << targ
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user