mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: attr for enum fields (+ json encode/decode) (#18163)
This commit is contained in:
parent
8482bc4626
commit
47761a42e9
@ -111,6 +111,7 @@ pub struct EnumData {
|
||||
pub:
|
||||
name string
|
||||
value i64
|
||||
attrs []string
|
||||
}
|
||||
|
||||
// FieldData holds information about a field. Fields reside on structs.
|
||||
|
@ -1296,6 +1296,7 @@ pub:
|
||||
comments []Comment // comment after Enumfield in the same line
|
||||
next_comments []Comment // comments between current EnumField and next EnumField
|
||||
has_expr bool // true, when .expr has a value
|
||||
attrs []Attr
|
||||
pub mut:
|
||||
expr Expr // the value of current EnumField; 123 in `ename = 123`
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ pub fn (x Expr) str() string {
|
||||
return "'${x.val}'"
|
||||
}
|
||||
TypeNode {
|
||||
return 'TypeNode(${x.typ})'
|
||||
return 'TypeNode(${global_table.type_str(x.typ)})'
|
||||
}
|
||||
TypeOf {
|
||||
if x.is_type {
|
||||
|
@ -193,6 +193,7 @@ pub:
|
||||
is_multi_allowed bool
|
||||
uses_exprs bool
|
||||
typ Type
|
||||
attrs map[string][]Attr
|
||||
}
|
||||
|
||||
[minify]
|
||||
|
@ -986,6 +986,10 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) {
|
||||
f.write(' = ')
|
||||
f.expr(field.expr)
|
||||
}
|
||||
if field.attrs.len > 0 {
|
||||
f.write(' ')
|
||||
f.single_line_attrs(field.attrs, inline: true)
|
||||
}
|
||||
f.comments(field.comments, inline: true, has_nl: false, level: .indent)
|
||||
f.writeln('')
|
||||
f.comments(field.next_comments, inline: false, has_nl: true, level: .indent)
|
||||
|
@ -942,6 +942,15 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
|
||||
} else {
|
||||
g.writeln('${g.typ(g.comptime_for_field_type)}__${g.comptime_enum_field_value};')
|
||||
}
|
||||
enum_attrs := sym.info.attrs[val]
|
||||
if enum_attrs.len == 0 {
|
||||
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
|
||||
} else {
|
||||
attrs := cgen_attrs(enum_attrs)
|
||||
g.writeln(
|
||||
'\t${node.val_var}.attrs = new_array_from_c_array(${attrs.len}, ${attrs.len}, sizeof(string), _MOV((string[${attrs.len}]){' +
|
||||
attrs.join(', ') + '}));\n')
|
||||
}
|
||||
g.stmts(node.stmts)
|
||||
g.writeln('}')
|
||||
i++
|
||||
|
@ -205,7 +205,15 @@ fn (mut g Gen) gen_enum_to_str(utyp ast.Type, sym ast.TypeSymbol, enum_var strin
|
||||
enc.writeln('${ident}switch (${enum_var}) {')
|
||||
for val in (sym.info as ast.Enum).vals {
|
||||
enc.write_string('${ident}\tcase ${enum_prefix}${val}:\t')
|
||||
enc.writeln('${result_var} = json__encode_string(_SLIT("${val}")); break;')
|
||||
// read [json:] attr from the Enum value
|
||||
attr := g.table.enum_decls[sym.name].fields.filter(it.name == val)[0].attrs.find_first('json') or {
|
||||
ast.Attr{}
|
||||
}
|
||||
if attr.has_arg {
|
||||
enc.writeln('${result_var} = json__encode_string(_SLIT("${attr.arg}")); break;')
|
||||
} else {
|
||||
enc.writeln('${result_var} = json__encode_string(_SLIT("${val}")); break;')
|
||||
}
|
||||
}
|
||||
enc.writeln('${ident}}')
|
||||
}
|
||||
@ -215,11 +223,19 @@ fn (mut g Gen) gen_str_to_enum(utyp ast.Type, sym ast.TypeSymbol, val_var string
|
||||
enum_prefix := g.gen_enum_prefix(utyp.clear_flag(.option))
|
||||
is_option := utyp.has_flag(.option)
|
||||
for k, val in (sym.info as ast.Enum).vals {
|
||||
if k == 0 {
|
||||
dec.write_string('${ident}if (string__eq(_SLIT("${val}"), ${val_var}))\t')
|
||||
} else {
|
||||
dec.write_string('${ident}else if (string__eq(_SLIT("${val}"), ${val_var}))\t')
|
||||
// read [json:] attr from the Enum value
|
||||
attr := g.table.enum_decls[sym.name].fields.filter(it.name == val)[0].attrs.find_first('json') or {
|
||||
ast.Attr{}
|
||||
}
|
||||
if k == 0 {
|
||||
dec.write_string('${ident}if (string__eq(_SLIT("${val}"), ${val_var})')
|
||||
} else {
|
||||
dec.write_string('${ident}else if (string__eq(_SLIT("${val}"), ${val_var})')
|
||||
}
|
||||
if attr.has_arg {
|
||||
dec.write_string(' || string__eq(_SLIT("${attr.arg}"), ${val_var})')
|
||||
}
|
||||
dec.write_string(')\t')
|
||||
if is_option {
|
||||
base_typ := g.base_type(utyp)
|
||||
dec.writeln('_option_ok(&(${base_typ}[]){ ${enum_prefix}${val} }, ${result_var}, sizeof(${base_typ}));')
|
||||
|
@ -3922,6 +3922,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
// mut default_exprs := []ast.Expr{}
|
||||
mut fields := []ast.EnumField{}
|
||||
mut uses_exprs := false
|
||||
mut enum_attrs := map[string][]ast.Attr{}
|
||||
for p.tok.kind != .eof && p.tok.kind != .rcbr {
|
||||
pos := p.tok.pos()
|
||||
val := p.check_name()
|
||||
@ -3935,6 +3936,13 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
has_expr = true
|
||||
uses_exprs = true
|
||||
}
|
||||
mut attrs := []ast.Attr{}
|
||||
if p.tok.kind == .lsbr {
|
||||
p.attributes()
|
||||
attrs << p.attrs
|
||||
enum_attrs[val] = attrs
|
||||
p.attrs = []
|
||||
}
|
||||
fields << ast.EnumField{
|
||||
name: val
|
||||
pos: pos
|
||||
@ -3942,6 +3950,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
has_expr: has_expr
|
||||
comments: p.eat_comments(same_line: true)
|
||||
next_comments: p.eat_comments()
|
||||
attrs: attrs
|
||||
}
|
||||
}
|
||||
p.top_level_statement_end()
|
||||
@ -3983,6 +3992,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
is_multi_allowed: is_multi_allowed
|
||||
uses_exprs: uses_exprs
|
||||
typ: enum_type
|
||||
attrs: enum_attrs
|
||||
}
|
||||
is_pub: is_pub
|
||||
})
|
||||
|
37
vlib/v/tests/enum_attr_test.v
Normal file
37
vlib/v/tests/enum_attr_test.v
Normal file
@ -0,0 +1,37 @@
|
||||
import json
|
||||
|
||||
enum Foo {
|
||||
yay [json: 'A'; yay]
|
||||
foo [foo; json: 'B']
|
||||
}
|
||||
|
||||
struct FooStruct {
|
||||
item Foo
|
||||
}
|
||||
|
||||
fn test_comptime() {
|
||||
$for f in Foo.values {
|
||||
println(f)
|
||||
if f.value == Foo.yay {
|
||||
assert f.attrs[0] == 'json: A'
|
||||
assert f.attrs[1] == 'yay'
|
||||
}
|
||||
if f.value == Foo.foo {
|
||||
assert f.attrs[1] == 'json: B'
|
||||
assert f.attrs[0] == 'foo'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_json_encode() {
|
||||
assert dump(json.encode(Foo.yay)) == '"A"'
|
||||
assert dump(json.encode(Foo.foo)) == '"B"'
|
||||
|
||||
assert dump(json.encode(FooStruct{ item: Foo.yay })) == '{"item":"A"}'
|
||||
assert dump(json.encode(FooStruct{ item: Foo.foo })) == '{"item":"B"}'
|
||||
}
|
||||
|
||||
fn test_json_decode() {
|
||||
dump(json.decode(FooStruct, '{"item": "A"}')!)
|
||||
dump(json.decode(FooStruct, '{"item": "B"}')!)
|
||||
}
|
Loading…
Reference in New Issue
Block a user