Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json: allow anon struct as decode type #22228

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions vlib/json/json_decode_anon_struct_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import json

fn test_main() {
json_text := '{ "a": "b" }'
b := json.decode(struct {
a string
}, json_text)!.a
assert dump(b) == 'b'
}
1 change: 1 addition & 0 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub:
pos token.Pos
pub mut:
typ Type
stmt Stmt = empty_stmt // for anon struct
end_comments []Comment // comments that after current type node
}

Expand Down
3 changes: 3 additions & 0 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -3088,6 +3088,9 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
&& c.table.cur_fn.generic_names.len == 0 {
c.error('unexpected generic variable in non-generic function `${c.table.cur_fn.name}`',
node.pos)
} else if node.stmt != ast.empty_stmt && node.typ == ast.void_type {
c.stmt(mut node.stmt)
node.typ = c.table.find_type_idx((node.stmt as ast.StructDecl).name)
}
return node.typ
}
Expand Down
5 changes: 3 additions & 2 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -837,8 +837,9 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
node.pos)
return ast.void_type
}
expr := node.args[0].expr
if expr is ast.TypeNode {
mut expr := node.args[0].expr
if mut expr is ast.TypeNode {
expr.typ = c.expr(mut expr)
mut unwrapped_typ := c.unwrap_generic(expr.typ)
if c.needs_unwrap_generic_type(expr.typ) {
unwrapped_typ = c.table.unwrap_generic_type(expr.typ, c.table.cur_fn.generic_names,
Expand Down
9 changes: 7 additions & 2 deletions vlib/v/fmt/fmt.v
Original file line number Diff line number Diff line change
Expand Up @@ -3215,8 +3215,13 @@ pub fn (mut f Fmt) string_inter_literal(node ast.StringInterLiteral) {
}

pub fn (mut f Fmt) type_expr(node ast.TypeNode) {
f.mark_types_import_as_used(node.typ)
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
if node.stmt == ast.empty_stmt {
f.mark_types_import_as_used(node.typ)
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
} else {
f.struct_decl(ast.StructDecl{ fields: (node.stmt as ast.StructDecl).fields },
true)
}
}

pub fn (mut f Fmt) type_of(node ast.TypeOf) {
Expand Down
16 changes: 13 additions & 3 deletions vlib/v/parser/expr.v
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,19 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
}
else {
if p.tok.kind == .key_struct && p.peek_tok.kind == .lcbr {
// Anonymous struct
p.next()
return p.struct_init('', .anon, false)
if p.expecting_type && p.inside_call_args {
// Anonymous struct for json.decode
tok_pos := p.tok.pos()
return ast.TypeNode{
stmt: p.struct_decl(true)
pos: tok_pos
typ: ast.void_type
}
} else {
// Anonymous struct
p.next()
return p.struct_init('', .anon, false)
}
}
if p.tok.kind != .eof && !(p.tok.kind == .rsbr && p.inside_asm) {
// eof should be handled where it happens
Expand Down
Loading