parser: add support for multiple struct field attributes

pull/4788/head
Ned Palacios 2020-05-08 21:09:42 +08:00 committed by GitHub
parent c29f76454e
commit 5b47ec49af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 15 deletions

View File

@ -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

View File

@ -109,7 +109,7 @@ pub:
comment Comment
default_expr Expr
has_default_expr bool
attr string
attrs []string
mut:
typ table.Type
}

View File

@ -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 {}
| ~~

View File

@ -0,0 +1,2 @@
[inline;deprecated]
fn foo(name string) string {}

View File

@ -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 | }

View File

@ -0,0 +1,4 @@
struct User {
name string
jobs []string [json:jobss;]
}

View File

@ -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

View File

@ -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

View File

@ -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')
}

View File

@ -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