fmt: prevent code corruption with struct update syntax as trailing function arg (#9091)

pull/9111/head
Lukas Neubert 2021-03-04 11:44:17 +01:00 committed by GitHub
parent 28fc91acb7
commit 8ce53b8b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 22 deletions

View File

@ -2116,14 +2116,14 @@ pub fn (mut f Fmt) map_init(it ast.MapInit) {
f.write('}') f.write('}')
} }
pub fn (mut f Fmt) struct_init(it ast.StructInit) { pub fn (mut f Fmt) struct_init(node ast.StructInit) {
struct_init_save := f.is_struct_init struct_init_save := f.is_struct_init
f.is_struct_init = true f.is_struct_init = true
defer { defer {
f.is_struct_init = struct_init_save f.is_struct_init = struct_init_save
} }
type_sym := f.table.get_type_symbol(it.typ) type_sym := f.table.get_type_symbol(node.typ)
// f.write('<old name: $type_sym.name>') // f.write('<old name: $type_sym.name>')
mut name := type_sym.name mut name := type_sym.name
if !name.starts_with('C.') { if !name.starts_with('C.') {
@ -2132,38 +2132,38 @@ pub fn (mut f Fmt) struct_init(it ast.StructInit) {
if name == 'void' { if name == 'void' {
name = '' name = ''
} }
if it.fields.len == 0 && !it.has_update_expr { if node.fields.len == 0 && !node.has_update_expr {
// `Foo{}` on one line if there are no fields or comments // `Foo{}` on one line if there are no fields or comments
if it.pre_comments.len == 0 { if node.pre_comments.len == 0 {
f.write('$name{}') f.write('$name{}')
} else { } else {
f.writeln('$name{') f.writeln('$name{')
f.comments(it.pre_comments, inline: true, has_nl: true, level: .indent) f.comments(node.pre_comments, inline: true, has_nl: true, level: .indent)
f.write('}') f.write('}')
} }
f.mark_import_as_used(name) f.mark_import_as_used(name)
} else if it.is_short { } else if node.is_short {
// `Foo{1,2,3}` (short syntax ) // `Foo{1,2,3}` (short syntax )
f.write('$name{') f.write('$name{')
f.mark_import_as_used(name) f.mark_import_as_used(name)
if it.has_update_expr { if node.has_update_expr {
f.write('...') f.write('...')
f.expr(it.update_expr) f.expr(node.update_expr)
f.write(', ') f.write(', ')
} }
for i, field in it.fields { for i, field in node.fields {
f.prefix_expr_cast_expr(field.expr) f.prefix_expr_cast_expr(field.expr)
if i < it.fields.len - 1 { if i < node.fields.len - 1 {
f.write(', ') f.write(', ')
} }
} }
f.write('}') f.write('}')
} else { } else {
use_short_args := f.use_short_fn_args use_short_args := f.use_short_fn_args && !node.has_update_expr
f.use_short_fn_args = false f.use_short_fn_args = false
mut single_line_fields := f.single_line_fields mut single_line_fields := f.single_line_fields
f.single_line_fields = false f.single_line_fields = false
if it.pos.line_nr < it.pos.last_line || it.pre_comments.len > 0 { if node.pos.line_nr < node.pos.last_line || node.pre_comments.len > 0 {
single_line_fields = false single_line_fields = false
} }
if !use_short_args { if !use_short_args {
@ -2179,19 +2179,25 @@ pub fn (mut f Fmt) struct_init(it ast.StructInit) {
f.writeln('') f.writeln('')
f.indent++ f.indent++
} }
f.comments(it.pre_comments, inline: true, has_nl: true, level: .keep) f.comments(node.pre_comments, inline: true, has_nl: true, level: .keep)
if it.has_update_expr { if node.has_update_expr {
f.write('...') f.write('...')
f.expr(it.update_expr) f.expr(node.update_expr)
f.writeln('') if single_line_fields {
f.comments(it.update_expr_comments, inline: true, has_nl: true, level: .keep) if node.fields.len > 0 {
f.write(', ')
}
} else {
f.writeln('')
}
f.comments(node.update_expr_comments, inline: true, has_nl: true, level: .keep)
} }
for i, field in it.fields { for i, field in node.fields {
f.write('$field.name: ') f.write('$field.name: ')
f.prefix_expr_cast_expr(field.expr) f.prefix_expr_cast_expr(field.expr)
f.comments(field.comments, inline: true, has_nl: false, level: .indent) f.comments(field.comments, inline: true, has_nl: false, level: .indent)
if single_line_fields { if single_line_fields {
if i < it.fields.len - 1 { if i < node.fields.len - 1 {
f.write(', ') f.write(', ')
} }
} else { } else {

View File

@ -11,6 +11,9 @@ struct Baz {
x string x string
} }
fn bar_func(bar Bar) {}
fn foo_func(f Foo) {}
fn main() { fn main() {
bar_func(x: 'bar', y: 13, z: 42) bar_func(x: 'bar', y: 13, z: 42)
bar_func( bar_func(
@ -47,6 +50,7 @@ fn main() {
) )
} }
fn bar_func(bar Bar) {} fn trailing_struct_with_update_expr() {
c.error('duplicate const `$field.name`', { ...field.pos, len: name_len })
fn foo_func(f Foo) {} c.error('duplicate const `$field.name`', Position{ ...field.pos, len: name_len })
}