1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

tools: add tests for v where; improve usability (#15059)

This commit is contained in:
Sebastian Atlántico 2022-07-15 01:59:11 -03:00 committed by GitHub
parent 89a757aba0
commit 4f997feee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 356 additions and 56 deletions

View File

@ -8,40 +8,49 @@ import os.cmdline
// Finder is entity that contains all the logic
struct Finder {
mut:
symbol Symbol
visib Visibility
mutab Mutability
name string
modul string
mth_of string
dirs []string
matches []Match
symbol Symbol
visib Visibility
mutab Mutability
name string
modul string
receiver string
dirs []string
matches []Match
}
fn (mut fdr Finder) configure_from_arguments() {
fn (mut fdr Finder) configure_from_arguments(args []string) {
match args.len {
1 {
fdr.name = args[0]
}
2 {
fdr.symbol.set_from_str(args[0])
fdr.name = args[1]
}
else {
fdr.symbol.set_from_str(args[0])
fdr.name = args[1]
if fdr.symbol == .method && !args[1].contains('.') {
make_and_print_error('method require a special notation:', [
'Receiver.method',
], '${args[1]}')
} else if fdr.symbol == .method {
temp_args := args[1].split('.')
fdr.receiver = temp_args[0]
fdr.name = temp_args[1]
} else {
fdr.name = args[1]
}
if fdr.name.contains('-') {
make_and_print_error('It seems you forgot positional arg name:', [], fdr.name)
}
fdr.visib.set_from_str(cmdline.option(args, '-vis', '${Visibility.all}'))
if fdr.symbol == .var && fdr.visib != .all {
make_and_print_error('-vis $fdr.visib just can be setted with symbol_type:',
['fn', 'method', 'const', 'struct', 'enum', 'interface', 'regexp'],
'$fdr.symbol')
}
fdr.mutab.set_from_str(cmdline.option(args, '-mut', '${Mutability.any}'))
if fdr.symbol != .var && fdr.mutab != .any {
make_and_print_error('-mut $fdr.mutab just can be setted with symbol_type:',
['var'], '$fdr.symbol')
}
fdr.modul = cmdline.option(args, '-mod', '')
fdr.mth_of = cmdline.option(args, '-m-of', '')
if fdr.symbol !in [.@fn, .regexp] && fdr.mth_of != '' {
make_and_print_error('-m-of $fdr.mth_of just can be setted with symbol_types:',
['fn', 'regexp'], '$fdr.symbol')
}
fdr.dirs = cmdline.options(args, '-dir')
}
}
@ -53,24 +62,32 @@ fn (mut fdr Finder) search_for_matches() {
mut paths_to_search := []string{}
if fdr.dirs.len == 0 && fdr.modul == '' {
paths_to_search << [current_dir, vmod_dir]
if vroot !in paths_to_search {
paths_to_search << vroot
if vlib_dir !in paths_to_search {
paths_to_search << vlib_dir
}
paths_to_search << vmod_paths
} else if fdr.dirs.len == 0 && fdr.modul != '' {
paths_to_search << if fdr.modul == 'main' { current_dir } else { fdr.modul }
paths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {
panic(err)} }
} else if fdr.dirs.len != 0 && fdr.modul == '' {
recursive = false
paths_to_search << fdr.dirs
paths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })
} else {
recursive = false
paths_to_search << if fdr.modul == 'main' { current_dir } else { fdr.modul }
paths_to_search << fdr.dirs
paths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {
panic(err)} }
paths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })
}
// for p in paths_to_search {
// println(p)
// }
mut files_to_search := []string{}
for path in paths_to_search {
files_to_search << collect_v_files(path, recursive) or { panic(err) }
}
// for f in files_to_search {
// println(f)
// }
// Auxiliar rgx
sp := r'\s*'
@ -79,12 +96,15 @@ fn (mut fdr Finder) search_for_matches() {
// Build regex query
sy := '$fdr.symbol'
st := if fdr.mth_of != '' { '$sp$op$sp[a-z].*$sp$fdr.mth_of$cp$sp' } else { '.*' }
st := if fdr.receiver != '' { '$sp$op$sp[a-z].*$sp$fdr.receiver$cp$sp' } else { '.*' }
na := '$fdr.name'
query := match fdr.symbol {
.@fn {
'.*$sy$st$na$sp${op}.*${cp}.*'
'.*$sy$sp$na$sp${op}.*${cp}.*'
}
.method {
'.*fn$st$na$sp${op}.*${cp}.*'
}
.var {
'.*$na$sp:=.*'
@ -129,16 +149,16 @@ fn (mut fdr Finder) search_within_file(file string, query string) {
}
}
if re.matches_string(line) && (const_found || line.contains('const')) {
words := line.split(' ').map(it.trim('\t'))
words := line.split(' ').filter(it != '').map(it.trim('\t'))
match fdr.visib {
.all {}
.@pub {
if 'pub' !in words {
if 'pub' !in words && fdr.symbol != .@const {
continue
}
}
.pri {
if 'pub' in words {
if 'pub' in words && fdr.symbol != .@const {
continue
}
}
@ -156,7 +176,10 @@ fn (mut fdr Finder) search_within_file(file string, query string) {
}
}
}
fdr.matches << Match{file, n_line, line.replace(' {', '').trim('\t')}
fdr.matches << Match{file, n_line, words.join(' ').trim(' {')}
}
if line.starts_with(')') && fdr.symbol == .@const {
const_found = false
}
n_line++
}
@ -182,7 +205,7 @@ fn (fdr Finder) show_results() {
fn (fdr Finder) str() string {
v := maybe_color(term.bright_red, '$fdr.visib')
m := maybe_color(term.bright_red, '$fdr.mutab')
st := if fdr.mth_of != '' { ' ( _ $fdr.mth_of)' } else { '' }
st := if fdr.receiver != '' { ' ( _ $fdr.receiver)' } else { '' }
s := maybe_color(term.bright_magenta, '$fdr.symbol')
n := maybe_color(term.bright_cyan, '$fdr.name')

View File

@ -8,6 +8,7 @@ import os.cmdline
// Symbol type to search
enum Symbol {
@fn
method
@struct
@interface
@enum
@ -31,12 +32,13 @@ enum Mutability {
}
const (
args = os.args[2..]
verbose = '-v' in cmdline.only_options(args)
header = '-h' in cmdline.only_options(args)
format = '-f' in cmdline.only_options(args)
_args = os.args
verbose = '-v' in cmdline.only_options(_args)
header = '-h' in cmdline.only_options(_args)
format = '-f' in cmdline.only_options(_args)
symbols = {
'fn': Symbol.@fn
'method': .method
'struct': .@struct
'interface': .@interface
'enum': .@enum
@ -55,7 +57,7 @@ const (
'not': .not
}
vexe = pref.vexe_path()
vroot = os.dir(vexe)
vlib_dir = os.join_path(os.dir(vexe), 'vlib')
vmod_dir = os.vmodules_dir()
vmod_paths = os.vmodules_paths()[1..]
current_dir = os.abs_path('.')
@ -106,12 +108,12 @@ fn invalid_option(invalid ParamOption, arg string) {
}
}
fn valid_args_quantity_or_show_help() {
fn valid_args_quantity_or_show_help(args []string) {
if true in [
args.len < 1,
'-help' in os.args,
'--help' in os.args,
os.args[1..] == ['where', 'help'],
'-help' in args,
'--help' in args,
args == ['help'],
] {
os.system('${os.quoted_path(vexe)} help where')
exit(0)
@ -119,11 +121,19 @@ fn valid_args_quantity_or_show_help() {
}
fn make_and_print_error(msg string, opts []string, arg string) {
eprintln('\n' + maybe_color(term.bright_yellow, msg))
if opts.len > 0 {
eprint(opts.map(maybe_color(term.bright_green, it)).join(' | '))
if verbose || format {
eprintln('\n' + maybe_color(term.bright_yellow, msg))
if opts.len > 0 {
eprint(opts.map(maybe_color(term.bright_green, it)).join(' | '))
}
eprintln(' ...can not be ${maybe_color(term.bright_red, arg)}')
} else {
eprint(maybe_color(term.bright_yellow, msg) + ' ')
if opts.len > 0 {
eprint(opts.map(maybe_color(term.bright_green, it)).join(' | '))
}
eprintln(' ...can not be ${maybe_color(term.bright_red, arg)}')
}
eprintln(' ...can not be ${maybe_color(term.bright_red, arg)}')
exit(1)
}
@ -158,3 +168,15 @@ fn collect_v_files(path string, recursive bool) ?[]string {
}
return all_files
}
fn resolve_module(path string) ?string {
if os.is_dir(path) {
return path
} else if os.is_dir(os.join_path(vmod_dir, path)) {
return os.join_path(vmod_dir, path)
} else if os.is_dir(os.join_path(vlib_dir, path)) {
return os.join_path(vlib_dir, path)
} else {
return error('Path: $path not found')
}
}

View File

@ -0,0 +1,28 @@
module test
// Test declarations
fn main() {
p_1 := Programmer{'Programmer', 'Inmutable'}
mut p_2 := Programmer{'Programmer', 'Mutable'}
}
struct Programmer {
f_name string
l_name string
}
fn (p Programmer) drink(cups int) string {
return 'drink coffee, return program'
}
pub struct Brogrammer {
f_name string
life []Stories
}
pub fn (p Brogrammer) drink(glasses int) string {
return 'drink beer, return script cluster'
}
struct Stories {}

View File

@ -0,0 +1,29 @@
module test
const (
x = 10
y = 100
z = 1000
)
pub enum Public {
importable
shareable
}
enum Private {
storable
donwloadable
}
interface Drinker {
drink(int) string
}
pub fn sprint(dkr Drinker) {
println(drk.drink(6))
}
fn some_function_name(foo string, bar int) string {
return 'baz'
}

View File

@ -0,0 +1,7 @@
module nested_mod
pub const (
a = 30
b = 60
c = 120
)

View File

@ -1,9 +1,14 @@
module main
import os
fn main() {
valid_args_quantity_or_show_help()
args := os.args[2..]
valid_args_quantity_or_show_help(args)
mut fdr := Finder{}
fdr.configure_from_arguments()
fdr.configure_from_arguments(args)
fdr.search_for_matches()
fdr.show_results()
}

View File

@ -0,0 +1,186 @@
module main
import os
const test_dir = os.join_path(os.dir(vexe), 'cmd', 'tools', 'vwhere', 'test')
fn test_create_finder() {
mut fdr := Finder{}
fdr.configure_from_arguments(['some'])
assert fdr.symbol == .@fn
assert fdr.name == 'some'
assert fdr.visib == .all
assert fdr.mutab == .any
fdr.configure_from_arguments(['fn', 'some', '-vis', 'pub'])
assert fdr.symbol == .@fn
assert fdr.name == 'some'
assert fdr.visib == .@pub
fdr.configure_from_arguments(['method', 'Some.some', '-vis', 'pri'])
assert fdr.symbol == .method
assert fdr.receiver == 'Some'
assert fdr.name == 'some'
assert fdr.visib == .pri
fdr.configure_from_arguments(['struct', 'Some', '-mod', 'foo'])
assert fdr.symbol == .@struct
assert fdr.name == 'Some'
assert fdr.modul == 'foo'
fdr.configure_from_arguments(['interface', 'Some', '-mod', 'foo', '-dir', 'bar'])
assert fdr.symbol == .@interface
assert fdr.name == 'Some'
assert fdr.modul == 'foo'
assert fdr.dirs == ['bar']
fdr.configure_from_arguments(['enum', 'Some', '-dir', 'bar', '-dir', 'baz'])
assert fdr.symbol == .@enum
assert fdr.name == 'Some'
assert fdr.dirs == ['bar', 'baz']
fdr.configure_from_arguments(['const', 'some'])
assert fdr.symbol == .@const
assert fdr.name == 'some'
fdr.configure_from_arguments(['var', 'some', '-mut', 'yes'])
assert fdr.symbol == .var
assert fdr.name == 'some'
assert fdr.mutab == .yes
fdr.configure_from_arguments(['var', 'some', '-mut', 'not'])
assert fdr.symbol == .var
assert fdr.name == 'some'
assert fdr.mutab == .not
fdr.configure_from_arguments(['regexp', '.*some.*'])
assert fdr.symbol == .regexp
assert fdr.name == '.*some.*'
}
fn test_find_mut_var() {
args := ['var', 'p_2', '-mut', 'yes', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_one.v')
line: 7
text: "mut p_2 := Programmer{'Programmer', 'Mutable'}"
},
]
}
fn test_find_non_mut_var() {
args := ['var', 'p_1', '-mut', 'not', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_one.v')
line: 6
text: "p_1 := Programmer{'Programmer', 'Inmutable'}"
},
]
}
fn test_find_method() {
args := ['method', 'Programmer.drink', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_one.v')
line: 15
text: 'fn (p Programmer) drink(cups int) string'
},
]
}
fn test_find_pub_method() {
args := ['method', 'Brogrammer.drink', '-vis', 'pub', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_one.v')
line: 24
text: 'pub fn (p Brogrammer) drink(glasses int) string'
},
]
}
fn test_find_pri_const() {
args := ['const', 'y', '-vis', 'pri', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_two.v')
line: 5
text: 'y = 100'
},
]
}
fn test_find_pub_enum() {
args := ['enum', 'Public', '-vis', 'pub', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_two.v')
line: 9
text: 'pub enum Public'
},
]
}
fn test_find_pri_enum() {
args := ['enum', 'Private', '-vis', 'pri', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_two.v')
line: 14
text: 'enum Private'
},
]
}
fn test_find_fn() {
args := ['fn', 'some_function_name', '-dir', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'file_two.v')
line: 27
text: 'fn some_function_name(foo string, bar int) string'
},
]
}
fn test_find_pub_const_with_mod() {
args := ['const', 'b', '-vis', 'pub', '-mod', test_dir]
mut fdr := Finder{}
fdr.configure_from_arguments(args)
fdr.search_for_matches()
assert fdr.matches == [
Match{
path: os.join_path(test_dir, 'nested_mod', 'nested_file.v')
line: 5
text: 'b = 60'
},
]
}

View File

@ -1,11 +1,11 @@
Usage:
v where [symbol_type] [symbol_name] [params]
v where symbol_type symbol_name [params]
Examples:
v where fn main
v where struct User
v where fn say_hello -mod Person
v where fn area -m-of Square
v where method Square.area
v where fn pow -mod math
v where interface callable -dir some -dir other
--------------------------------------------------------------------------------
@ -13,7 +13,8 @@ Prints the location of the searched symbols in the scope of the current project.
--------------------------------------------------------------------------------
symbol_name can be:
fn (by default if omit [symbol_type])
fn by default if omit symbol_type (don't omit preferably)
method require Struct.method notation
struct
interface
enum
@ -23,19 +24,18 @@ symbol_name can be:
params:
-mod [mod_name] Restrict to search recursively only within of the given
module, if not provided search in entire v scope.
module, if not provided search in entire v scope
(use -mod main to search inside all your project).
-dir [dir_path] Restrict to search non recursively within the given
folder/s, if not provided, search in entire v scope.
-vis [visibility] Can be: all, pub, pri (all by default if not provided).
Restrict to search symbols with the given visibility.
-mut [mutability] Can be: any, yes, not (any by default if not provided).
Restrict to search symbols with the given mutability.
-m-of [struct_name] (just for fn symbol_name).
Restrict to search fn as method of the given struct.
flags:
-h Include header
-h include Header
-f Format output (each match uses 3 lines)
-v For both above
-v for both above (more Verbose)
Note:
This tool is inspired by the vdoc tool and its design. However, this is