parser: add support for multiple struct field attributes
parent
c29f76454e
commit
5b47ec49af
|
@ -27,10 +27,11 @@ struct User {
|
|||
last_name string [json:lastName]
|
||||
is_registered bool [json:IsRegistered]
|
||||
typ int [json:'type']
|
||||
pets string [raw; json:'pet_animals']
|
||||
}
|
||||
|
||||
fn test_parse_user() {
|
||||
s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true}'
|
||||
s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true, "pet_animals": {"name": "Bob", "animal": "Dog"}}'
|
||||
u2 := json.decode(User2, s) or {
|
||||
exit(1)
|
||||
}
|
||||
|
@ -47,11 +48,12 @@ fn test_parse_user() {
|
|||
assert u.nums[1] == 2
|
||||
assert u.nums[2] == 3
|
||||
assert u.typ == 1
|
||||
assert u.pets == '{"name":"Bob","animal":"Dog"}'
|
||||
}
|
||||
|
||||
fn test_encode_user(){
|
||||
usr := User{ age: 10, nums: [1,2,3], last_name: 'Johnson', is_registered: true, typ: 0}
|
||||
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0}'
|
||||
usr := User{ age: 10, nums: [1,2,3], last_name: 'Johnson', is_registered: true, typ: 0, pets: 'foo'}
|
||||
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"foo"}'
|
||||
out := json.encode(usr)
|
||||
println(out)
|
||||
assert out == expected
|
||||
|
|
|
@ -109,7 +109,7 @@ pub:
|
|||
comment Comment
|
||||
default_expr Expr
|
||||
has_default_expr bool
|
||||
attr string
|
||||
attrs []string
|
||||
mut:
|
||||
typ table.Type
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
vlib/v/checker/tests/multiple_fn_attributes.v:2:1: error: multiple attributes detected
|
||||
1 | [inline;deprecated]
|
||||
2 | fn foo(name string) string {}
|
||||
| ~~
|
|
@ -0,0 +1,2 @@
|
|||
[inline;deprecated]
|
||||
fn foo(name string) string {}
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/trailing_comma_struct_attr.v:3:31: error: unexpected `]`, expecting `name`
|
||||
1 | struct User {
|
||||
2 | name string
|
||||
3 | jobs []string [json:jobss;]
|
||||
| ^
|
||||
4 | }
|
|
@ -0,0 +1,4 @@
|
|||
struct User {
|
||||
name string
|
||||
jobs []string [json:jobss;]
|
||||
}
|
|
@ -70,13 +70,19 @@ cJSON* ${enc_fn_name}($styp val) {
|
|||
}
|
||||
info := sym.info as table.Struct
|
||||
for field in info.fields {
|
||||
if field.attr == 'skip' {
|
||||
if 'skip' in field.attrs {
|
||||
continue
|
||||
}
|
||||
name := if field.attr.starts_with('json:') { field.attr[5..] } else { field.name }
|
||||
mut name := field.name
|
||||
for attr in field.attrs {
|
||||
if attr.starts_with('json:') {
|
||||
name = attr[5..]
|
||||
break
|
||||
}
|
||||
}
|
||||
field_type := g.typ(field.typ)
|
||||
enc_name := js_enc_name(field_type)
|
||||
if field.attr == 'raw' {
|
||||
if 'raw' in field.attrs {
|
||||
dec.writeln(' res . $field.name = tos2(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
|
||||
} else {
|
||||
// Now generate decoders for all field types in this struct
|
||||
|
|
|
@ -310,7 +310,12 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
|||
}
|
||||
}
|
||||
.lsbr {
|
||||
return p.attribute()
|
||||
attrs := p.attributes()
|
||||
|
||||
if attrs.len > 1 {
|
||||
p.error('multiple attributes detected')
|
||||
}
|
||||
return attrs[0]
|
||||
}
|
||||
.key_interface {
|
||||
return p.interface_decl()
|
||||
|
@ -481,8 +486,29 @@ pub fn (mut p Parser) stmt() ast.Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) attribute() ast.Attr {
|
||||
fn (mut p Parser) attributes() []ast.Attr {
|
||||
mut attrs := []ast.Attr{}
|
||||
|
||||
p.check(.lsbr)
|
||||
for p.tok.kind != .rsbr {
|
||||
attr := p.parse_attr()
|
||||
attrs << attr
|
||||
if p.tok.kind != .semicolon {
|
||||
expected := `;`
|
||||
if p.tok.kind == .rsbr {
|
||||
p.next()
|
||||
break
|
||||
}
|
||||
|
||||
p.error('unexpected `${p.tok.kind.str()}`, expecting `${expected.str()}`')
|
||||
}
|
||||
p.next()
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_attr() ast.Attr {
|
||||
mut is_if_attr := false
|
||||
if p.tok.kind == .key_if {
|
||||
p.next()
|
||||
|
@ -499,7 +525,6 @@ fn (mut p Parser) attribute() ast.Attr {
|
|||
p.next()
|
||||
}
|
||||
}
|
||||
p.check(.rsbr)
|
||||
p.attr = name
|
||||
if is_if_attr {
|
||||
p.attr_ctdefine = name
|
||||
|
|
|
@ -117,9 +117,12 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
}
|
||||
has_default_expr = true
|
||||
}
|
||||
mut attr := ast.Attr{}
|
||||
mut attrs := []string{}
|
||||
if p.tok.kind == .lsbr {
|
||||
attr = p.attribute()
|
||||
parsed_attrs := p.attributes()
|
||||
for attr in parsed_attrs {
|
||||
attrs << attr.name
|
||||
}
|
||||
}
|
||||
if p.tok.kind == .comment {
|
||||
comment = p.comment()
|
||||
|
@ -132,7 +135,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
comment: comment
|
||||
default_expr: default_expr
|
||||
has_default_expr: has_default_expr
|
||||
attr: attr.name
|
||||
attrs: attrs
|
||||
}
|
||||
fields << table.Field{
|
||||
name: field_name
|
||||
|
@ -142,7 +145,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
is_pub: is_field_pub
|
||||
is_mut: is_field_mut
|
||||
is_global: is_field_global
|
||||
attr: attr.name
|
||||
attrs: attrs
|
||||
}
|
||||
// println('struct field $ti.name $field_name')
|
||||
}
|
||||
|
|
|
@ -564,7 +564,7 @@ mut:
|
|||
default_expr FExpr
|
||||
has_default_expr bool
|
||||
default_val string
|
||||
attr string
|
||||
attrs []string
|
||||
is_pub bool
|
||||
is_mut bool
|
||||
is_global bool
|
||||
|
|
Loading…
Reference in New Issue