mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
fmt: handle anon structs; tests: bring back anon struct test
This commit is contained in:
parent
972bba66d1
commit
f5001192f9
@ -316,6 +316,7 @@ pub mut:
|
|||||||
default_expr_typ Type
|
default_expr_typ Type
|
||||||
name string
|
name string
|
||||||
typ Type
|
typ Type
|
||||||
|
anon_struct_decl StructDecl // only if the field is an anonymous struct
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (f &StructField) equals(o &StructField) bool {
|
pub fn (f &StructField) equals(o &StructField) bool {
|
||||||
|
@ -1121,7 +1121,7 @@ pub mut:
|
|||||||
parent_type Type
|
parent_type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// human readable type name
|
// human readable type name, also used by vfmt
|
||||||
pub fn (t &Table) type_to_str(typ Type) string {
|
pub fn (t &Table) type_to_str(typ Type) string {
|
||||||
return t.type_to_str_using_aliases(typ, map[string]string{})
|
return t.type_to_str_using_aliases(typ, map[string]string{})
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||||||
f.sql_stmt(node)
|
f.sql_stmt(node)
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
f.struct_decl(node)
|
f.struct_decl(node, false)
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
ast.TypeDecl {
|
||||||
f.type_decl(node)
|
f.type_decl(node)
|
||||||
|
@ -6,7 +6,7 @@ module fmt
|
|||||||
import strings
|
import strings
|
||||||
import v.ast
|
import v.ast
|
||||||
|
|
||||||
pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
|
||||||
f.attrs(node.attrs)
|
f.attrs(node.attrs)
|
||||||
if node.is_pub {
|
if node.is_pub {
|
||||||
f.write('pub ')
|
f.write('pub ')
|
||||||
@ -18,7 +18,9 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
|||||||
}
|
}
|
||||||
f.write_language_prefix(node.language)
|
f.write_language_prefix(node.language)
|
||||||
name := node.name.after('.') // strip prepended module
|
name := node.name.after('.') // strip prepended module
|
||||||
|
if !is_anon {
|
||||||
f.write(name)
|
f.write(name)
|
||||||
|
}
|
||||||
f.write_generic_types(node.generic_types)
|
f.write_generic_types(node.generic_types)
|
||||||
if node.fields.len == 0 && node.embeds.len == 0 && node.pos.line_nr == node.pos.last_line {
|
if node.fields.len == 0 && node.embeds.len == 0 && node.pos.line_nr == node.pos.last_line {
|
||||||
f.writeln(' {}')
|
f.writeln(' {}')
|
||||||
@ -28,8 +30,11 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
|||||||
mut comment_aligns := []AlignInfo{}
|
mut comment_aligns := []AlignInfo{}
|
||||||
mut default_expr_aligns := []AlignInfo{}
|
mut default_expr_aligns := []AlignInfo{}
|
||||||
mut field_types := []string{cap: node.fields.len}
|
mut field_types := []string{cap: node.fields.len}
|
||||||
|
// Calculate the alignments first
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias))
|
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias))
|
||||||
|
// Handle anon structs recursively
|
||||||
|
sym := f.table.sym(field.typ)
|
||||||
field_types << ft
|
field_types << ft
|
||||||
attrs_len := inline_attrs_len(field.attrs)
|
attrs_len := inline_attrs_len(field.attrs)
|
||||||
end_pos := field.pos.pos + field.pos.len
|
end_pos := field.pos.pos + field.pos.len
|
||||||
@ -68,6 +73,7 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
|||||||
f.comments(comments, level: .indent)
|
f.comments(comments, level: .indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Now handle each field
|
||||||
mut field_align_i := 0
|
mut field_align_i := 0
|
||||||
mut comment_align_i := 0
|
mut comment_align_i := 0
|
||||||
mut default_expr_align_i := 0
|
mut default_expr_align_i := 0
|
||||||
@ -125,7 +131,21 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
|||||||
field_align = field_aligns[field_align_i]
|
field_align = field_aligns[field_align_i]
|
||||||
}
|
}
|
||||||
f.write(strings.repeat(` `, field_align.max_len - field.name.len - comments_len))
|
f.write(strings.repeat(` `, field_align.max_len - field.name.len - comments_len))
|
||||||
|
// Handle anon structs recursively
|
||||||
|
mut field_is_anon := false
|
||||||
|
sym := f.table.sym(field.typ)
|
||||||
|
if sym.kind == .struct_ {
|
||||||
|
info := sym.info as ast.Struct
|
||||||
|
field_is_anon = info.is_anon
|
||||||
|
}
|
||||||
|
if field_is_anon {
|
||||||
|
f.indent++
|
||||||
|
f.struct_decl(field.anon_struct_decl, true)
|
||||||
|
f.indent--
|
||||||
|
} else {
|
||||||
|
// If it's not an anon struct, just write the type of the field
|
||||||
f.write(field_types[i])
|
f.write(field_types[i])
|
||||||
|
}
|
||||||
f.mark_types_import_as_used(field.typ)
|
f.mark_types_import_as_used(field.typ)
|
||||||
attrs_len := inline_attrs_len(field.attrs)
|
attrs_len := inline_attrs_len(field.attrs)
|
||||||
has_attrs := field.attrs.len > 0
|
has_attrs := field.attrs.len > 0
|
||||||
@ -174,7 +194,11 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.comments_after_last_field(node.end_comments)
|
f.comments_after_last_field(node.end_comments)
|
||||||
|
if is_anon {
|
||||||
|
f.write('}')
|
||||||
|
} else {
|
||||||
f.writeln('}\n')
|
f.writeln('}\n')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut f Fmt) struct_init(node ast.StructInit) {
|
pub fn (mut f Fmt) struct_init(node ast.StructInit) {
|
||||||
|
@ -26,7 +26,17 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
|||||||
defer {
|
defer {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
|
|
||||||
|
mut is_anon := false
|
||||||
|
if sym.kind == .struct_ {
|
||||||
|
mut info := sym.info as ast.Struct
|
||||||
|
|
||||||
|
is_anon = info.is_anon
|
||||||
|
}
|
||||||
|
if is_anon {
|
||||||
|
// No name needed for anon structs, C figures it out on its own.
|
||||||
|
g.writeln('{')
|
||||||
|
} else if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
|
||||||
mut shared_typ := node.typ.set_flag(.shared_f)
|
mut shared_typ := node.typ.set_flag(.shared_f)
|
||||||
shared_styp = g.typ(shared_typ)
|
shared_styp = g.typ(shared_typ)
|
||||||
g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
|
g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =($styp){')
|
||||||
|
@ -199,6 +199,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||||||
mut typ := ast.Type(0)
|
mut typ := ast.Type(0)
|
||||||
mut type_pos := token.Pos{}
|
mut type_pos := token.Pos{}
|
||||||
mut field_pos := token.Pos{}
|
mut field_pos := token.Pos{}
|
||||||
|
mut anon_struct_decl := ast.StructDecl{}
|
||||||
if is_embed {
|
if is_embed {
|
||||||
// struct embedding
|
// struct embedding
|
||||||
type_pos = p.tok.pos()
|
type_pos = p.tok.pos()
|
||||||
@ -237,7 +238,16 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.inside_struct_field_decl = true
|
p.inside_struct_field_decl = true
|
||||||
|
if p.tok.kind == .key_struct {
|
||||||
|
// Anon structs
|
||||||
|
if p.tok.kind == .key_struct {
|
||||||
|
anon_struct_decl = p.struct_decl(true)
|
||||||
|
// Find the registered anon struct type, it was registered above in `p.struct_decl()`
|
||||||
|
typ = p.table.find_type_idx(anon_struct_decl.name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
typ = p.parse_type()
|
typ = p.parse_type()
|
||||||
|
}
|
||||||
p.inside_struct_field_decl = false
|
p.inside_struct_field_decl = false
|
||||||
if typ.idx() == 0 {
|
if typ.idx() == 0 {
|
||||||
// error is set in parse_type
|
// error is set in parse_type
|
||||||
@ -287,6 +297,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||||||
is_global: is_field_global
|
is_global: is_field_global
|
||||||
is_volatile: is_field_volatile
|
is_volatile: is_field_volatile
|
||||||
is_deprecated: is_field_deprecated
|
is_deprecated: is_field_deprecated
|
||||||
|
anon_struct_decl: anon_struct_decl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// save embeds as table fields too, it will be used in generation phase
|
// save embeds as table fields too, it will be used in generation phase
|
||||||
|
@ -413,16 +413,18 @@ fn test_struct_update() {
|
|||||||
assert c2.name == 'test'
|
assert c2.name == 'test'
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Test anon structs
|
// Test anon structs
|
||||||
struct Book {
|
struct Book {
|
||||||
x Foo
|
x Foo
|
||||||
title string
|
|
||||||
author struct {
|
author struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
title string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_anon() {}
|
fn test_anon() {
|
||||||
*/
|
// book := Book{author:struct{'sdf', 23}}
|
||||||
|
// println(book.author.age)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user