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

parser: add warning for s.$field.name without brackets (#8411)

This commit is contained in:
Nick Treleaven 2021-01-30 11:56:10 +00:00 committed by GitHub
parent 97cb7687a2
commit c0685eeefc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 30 additions and 33 deletions

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/comptime_field_selector_not_in_for_err.vv:9:5: error: expected selector expression e.g. `$(field.name)` vlib/v/checker/tests/comptime_field_selector_not_in_for_err.vv:9:6: error: expected selector expression e.g. `$(field.name)`
7 | mut t := T{} 7 | mut t := T{}
8 | name := 'test' 8 | name := 'test'
9 | t.$name = '3' 9 | t.$(name) = '3'
| ~~~~ | ~~~~
10 | } 10 | }
11 | 11 |

View File

@ -6,7 +6,7 @@ struct Foo {
fn test<T>() { fn test<T>() {
mut t := T{} mut t := T{}
name := 'test' name := 'test'
t.$name = '3' t.$(name) = '3'
} }
fn main() { fn main() {

View File

@ -1,21 +1,21 @@
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:10:7: error: expected `string` instead of `FieldData` (e.g. `field.name`) vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:10:8: error: expected `string` instead of `FieldData` (e.g. `field.name`)
8 | $for f in T.fields { 8 | $for f in T.fields {
9 | $if f.typ is string { 9 | $if f.typ is string {
10 | t.$f = '3' 10 | t.$(f) = '3'
| ^ | ^
11 | fv := Foo{} 11 | fv := Foo{}
12 | _ = t.$fv.name 12 | _ = t.$(fv.name)
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:12:11: error: unknown `$for` variable `fv` vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:12:12: error: unknown `$for` variable `fv`
10 | t.$f = '3' 10 | t.$(f) = '3'
11 | fv := Foo{} 11 | fv := Foo{}
12 | _ = t.$fv.name 12 | _ = t.$(fv.name)
| ~~ | ~~
13 | } 13 | }
14 | } 14 | }
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:9: error: compile time field access can only be used when iterating over `T.fields` vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:10: error: compile time field access can only be used when iterating over `T.fields`
13 | } 13 | }
14 | } 14 | }
15 | _ = t.$f.name 15 | _ = t.$(f.name)
| ^ | ^
16 | } 16 | }
17 | 17 |

View File

@ -7,12 +7,12 @@ fn test<T>() {
mut t := T{} mut t := T{}
$for f in T.fields { $for f in T.fields {
$if f.typ is string { $if f.typ is string {
t.$f = '3' t.$(f) = '3'
fv := Foo{} fv := Foo{}
_ = t.$fv.name _ = t.$(fv.name)
} }
} }
_ = t.$f.name _ = t.$(f.name)
} }
fn main() { fn main() {

View File

@ -1156,8 +1156,7 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
} }
pub fn (mut f Fmt) comptime_selector(node ast.ComptimeSelector) { pub fn (mut f Fmt) comptime_selector(node ast.ComptimeSelector) {
field_expr := if node.has_parens { '($node.field_expr)' } else { node.field_expr.str() } f.write('${node.left}.\$($node.field_expr)')
f.write('${node.left}.$$field_expr')
} }
pub fn (mut f Fmt) concat_expr(node ast.ConcatExpr) { pub fn (mut f Fmt) concat_expr(node ast.ConcatExpr) {

View File

@ -13,7 +13,7 @@ fn test<T>() {
t.name = '2' t.name = '2'
$for f in T.fields { $for f in T.fields {
$if f.typ is string { $if f.typ is string {
println(t.$f.name) println(t.$(f.name))
} }
} }
} }

View File

@ -256,17 +256,9 @@ fn (mut p Parser) at() ast.AtExpr {
fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr { fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr {
p.check(.dollar) p.check(.dollar)
mut has_parens := false
if p.tok.kind == .lpar {
p.check(.lpar)
has_parens = true
}
if p.peek_tok.kind == .lpar { if p.peek_tok.kind == .lpar {
method_name := p.check_name() method_name := p.check_name()
// `app.$action()` (`action` is a string) // `app.$action()` (`action` is a string)
if has_parens {
p.check(.rpar)
}
p.check(.lpar) p.check(.lpar)
mut args_var := '' mut args_var := ''
if p.tok.kind == .name { if p.tok.kind == .name {
@ -279,12 +271,18 @@ fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr {
p.check(.lcbr) p.check(.lcbr)
} }
return ast.ComptimeCall{ return ast.ComptimeCall{
has_parens: has_parens
left: left left: left
method_name: method_name method_name: method_name
args_var: args_var args_var: args_var
} }
} }
mut has_parens := false
if p.tok.kind == .lpar {
p.check(.lpar)
has_parens = true
} else {
p.warn_with_pos('use brackets instead e.g. `s.$(field.name)` - run vfmt', p.tok.position())
}
expr := p.expr(0) expr := p.expr(0)
if has_parens { if has_parens {
p.check(.rpar) p.check(.rpar)

View File

@ -12,7 +12,7 @@ fn comptime_field_selector_read<T>() []string {
mut value_list := []string{} mut value_list := []string{}
$for f in T.fields { $for f in T.fields {
$if f.typ is string { $if f.typ is string {
value_list << t.$f.name value_list << t.$(f.name)
} }
} }
return value_list return value_list
@ -26,10 +26,10 @@ fn comptime_field_selector_write<T>() T {
mut t := T{} mut t := T{}
$for f in T.fields { $for f in T.fields {
$if f.typ is string { $if f.typ is string {
t.$f.name = '1' t.$(f.name) = '1'
} }
$if f.typ is int { $if f.typ is int {
t.$f.name = 1 t.$(f.name) = 1
} }
} }
return t return t