mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
flag: fix assigning to @[tail]
field when no fields has been matched yet in flag.parse[T]()
(#22043)
This commit is contained in:
parent
198d4f49ef
commit
21339fe167
@ -524,8 +524,9 @@ pub fn (mut fm FlagMapper) parse[T]() ! {
|
||||
}
|
||||
}
|
||||
|
||||
// Extract any tail according to config
|
||||
// Extract any tail(s) according to config
|
||||
if pos >= pos_last_flag + 1 {
|
||||
trace_dbg_println('${@FN}: (tail) looking for tail match for position "${pos}"...')
|
||||
pos_is_handled = pos in fm.handled_pos
|
||||
if pos_is_handled {
|
||||
trace_dbg_println('${@FN}: (tail) skipping position "${pos}". Already handled')
|
||||
@ -542,27 +543,27 @@ pub fn (mut fm FlagMapper) parse[T]() ! {
|
||||
continue
|
||||
}
|
||||
if field.hints.has(.has_tail) {
|
||||
if last_handled_pos := fm.handled_pos[fm.handled_pos.len - 1] {
|
||||
trace_println('${@FN}: (tail) flag `${arg}` last_handled_pos: ${last_handled_pos} pos: ${pos}')
|
||||
if pos == last_handled_pos + 1 {
|
||||
if field.hints.has(.is_array) {
|
||||
fm.array_field_map_flag[field.name] << FlagData{
|
||||
raw: arg
|
||||
field_name: field.name
|
||||
arg: ?string(arg) // .arg is used when assigning at comptime to []XYZ
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
fm.field_map_flag[field.name] = FlagData{
|
||||
raw: arg
|
||||
field_name: field.name
|
||||
arg: ?string(arg)
|
||||
pos: pos
|
||||
}
|
||||
trace_dbg_println('${@FN}: (tail) field "${field.name}" has a tail attribute. fm.handled_pos.len: ${fm.handled_pos.len}')
|
||||
last_handled_pos := fm.handled_pos[fm.handled_pos.len - 1] or { 0 }
|
||||
trace_println('${@FN}: (tail) flag `${arg}` last_handled_pos: ${last_handled_pos} pos: ${pos}')
|
||||
if pos == last_handled_pos + 1 || pos == pos_last_flag + 1 {
|
||||
if field.hints.has(.is_array) {
|
||||
fm.array_field_map_flag[field.name] << FlagData{
|
||||
raw: arg
|
||||
field_name: field.name
|
||||
arg: ?string(arg) // .arg is used when assigning at comptime to []XYZ
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
fm.field_map_flag[field.name] = FlagData{
|
||||
raw: arg
|
||||
field_name: field.name
|
||||
arg: ?string(arg)
|
||||
pos: pos
|
||||
}
|
||||
fm.handled_pos << pos
|
||||
continue
|
||||
}
|
||||
fm.handled_pos << pos
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -900,6 +901,10 @@ pub fn (fm FlagMapper) to_struct[T](defaults ?T) !T {
|
||||
}
|
||||
result.$(field.name) = true
|
||||
} $else $if field.typ is string {
|
||||
trace_dbg_println('${@FN}: assigning (string) ${struct_name}.${field.name} = ${f.arg or {
|
||||
'ERROR'
|
||||
}
|
||||
.str()}')
|
||||
result.$(field.name) = f.arg or {
|
||||
return error('failed appending ${f.raw} to ${field.name}')
|
||||
}
|
||||
|
62
vlib/flag/flag_to_tail_test.v
Normal file
62
vlib/flag/flag_to_tail_test.v
Normal file
@ -0,0 +1,62 @@
|
||||
import flag
|
||||
|
||||
const posix_and_gnu_args_no_tail = ['-f']
|
||||
|
||||
const posix_and_gnu_args_tail = ['-f', 'tail']
|
||||
const posix_and_gnu_args_tails = ['-f', 'tail0', 'tail1', 'tail2']
|
||||
|
||||
const skip_posix_and_gnu_args_tail = ['skipme', '-f', 'tail']
|
||||
const skip_posix_and_gnu_args_tails = ['skipme', '-f', 'tail0', 'tail1', 'tail2']
|
||||
|
||||
struct ConfigTail {
|
||||
mix bool
|
||||
path string @[tail]
|
||||
}
|
||||
|
||||
struct ConfigTails {
|
||||
mix bool
|
||||
paths []string @[tail]
|
||||
}
|
||||
|
||||
fn test_flag_tail() {
|
||||
// Test `@[tail]` edge-cases
|
||||
config1, no_matches1 := flag.to_struct[ConfigTail](posix_and_gnu_args_tail)!
|
||||
assert config1.mix == false
|
||||
assert config1.path == 'tail'
|
||||
assert no_matches1 == ['-f']
|
||||
|
||||
config2, no_matches2 := flag.to_struct[ConfigTails](posix_and_gnu_args_tails)!
|
||||
assert config2.mix == false
|
||||
assert config2.paths == ['tail0', 'tail1', 'tail2']
|
||||
assert no_matches2 == ['-f']
|
||||
|
||||
config3, no_matches3 := flag.to_struct[ConfigTail](skip_posix_and_gnu_args_tail, skip: 1)!
|
||||
assert config3.mix == false
|
||||
assert config3.path == 'tail'
|
||||
assert no_matches3 == ['-f']
|
||||
|
||||
config4, no_matches4 := flag.to_struct[ConfigTails](skip_posix_and_gnu_args_tails, skip: 1)!
|
||||
assert config4.mix == false
|
||||
assert config4.paths == ['tail0', 'tail1', 'tail2']
|
||||
assert no_matches4 == ['-f']
|
||||
|
||||
config5, no_matches5 := flag.to_struct[ConfigTail](posix_and_gnu_args_tail, skip: 1)!
|
||||
assert config5.mix == false
|
||||
assert config5.path == 'tail'
|
||||
assert no_matches5 == []
|
||||
|
||||
config6, no_matches6 := flag.to_struct[ConfigTails](posix_and_gnu_args_tails, skip: 1)!
|
||||
assert config6.mix == false
|
||||
assert config6.paths == ['tail0', 'tail1', 'tail2']
|
||||
assert no_matches6 == []
|
||||
|
||||
config7, no_matches7 := flag.to_struct[ConfigTail](posix_and_gnu_args_no_tail)!
|
||||
assert config7.mix == false
|
||||
assert config7.path == ''
|
||||
assert no_matches7 == ['-f']
|
||||
|
||||
config8, no_matches8 := flag.to_struct[ConfigTail](posix_and_gnu_args_no_tail, skip: 1)!
|
||||
assert config8.mix == false
|
||||
assert config8.path == ''
|
||||
assert no_matches8 == []
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user