mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
vfmt: automate transition from the old [attribute]
to the new @[attribute]
syntax (#19912)
This commit is contained in:
parent
157d603e5c
commit
f7b9e4eafd
@ -707,12 +707,14 @@ fn (t Tree) attr(node ast.Attr) &Node {
|
|||||||
obj.add_terse('ast_type', t.string_node('Attr'))
|
obj.add_terse('ast_type', t.string_node('Attr'))
|
||||||
obj.add_terse('name', t.string_node(node.name))
|
obj.add_terse('name', t.string_node(node.name))
|
||||||
obj.add_terse('has_arg', t.bool_node(node.has_arg))
|
obj.add_terse('has_arg', t.bool_node(node.has_arg))
|
||||||
|
obj.add_terse('arg', t.string_node(node.arg))
|
||||||
obj.add_terse('kind', t.enum_node(node.kind))
|
obj.add_terse('kind', t.enum_node(node.kind))
|
||||||
obj.add_terse('ct_expr', t.expr(node.ct_expr))
|
|
||||||
obj.add_terse('ct_opt', t.bool_node(node.ct_opt))
|
obj.add_terse('ct_opt', t.bool_node(node.ct_opt))
|
||||||
|
obj.add_terse('has_at', t.bool_node(node.has_at))
|
||||||
|
obj.add_terse('ct_expr', t.expr(node.ct_expr))
|
||||||
obj.add_terse('ct_evaled', t.bool_node(node.ct_evaled))
|
obj.add_terse('ct_evaled', t.bool_node(node.ct_evaled))
|
||||||
obj.add_terse('ct_skip', t.bool_node(node.ct_skip))
|
obj.add_terse('ct_skip', t.bool_node(node.ct_skip))
|
||||||
obj.add_terse('arg', t.string_node(node.arg))
|
obj.add('pos', t.pos(node.pos))
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
doc/docs.md
16
doc/docs.md
@ -2271,7 +2271,7 @@ It's also possible to define custom default values.
|
|||||||
|
|
||||||
```v
|
```v
|
||||||
struct Foo {
|
struct Foo {
|
||||||
n int [required]
|
n int @[required]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -4389,12 +4389,12 @@ struct User {
|
|||||||
// If a field is not [required], but is missing, it will be assumed
|
// If a field is not [required], but is missing, it will be assumed
|
||||||
// to have its default value, like 0 for numbers, or '' for strings,
|
// to have its default value, like 0 for numbers, or '' for strings,
|
||||||
// and decoding will not fail.
|
// and decoding will not fail.
|
||||||
name string [required]
|
name string @[required]
|
||||||
age int
|
age int
|
||||||
// Use the `skip` attribute to skip certain fields
|
// Use the `skip` attribute to skip certain fields
|
||||||
foo Foo [skip]
|
foo Foo @[skip]
|
||||||
// If the field name is different in JSON, it can be specified
|
// If the field name is different in JSON, it can be specified
|
||||||
last_name string [json: lastName]
|
last_name string @[json: lastName]
|
||||||
}
|
}
|
||||||
|
|
||||||
data := '{ "name": "Frodo", "lastName": "Baggins", "age": 25 }'
|
data := '{ "name": "Frodo", "lastName": "Baggins", "age": 25 }'
|
||||||
@ -4976,10 +4976,10 @@ import db.sqlite
|
|||||||
// sets a custom table name. Default is struct name (case-sensitive)
|
// sets a custom table name. Default is struct name (case-sensitive)
|
||||||
@[table: 'customers']
|
@[table: 'customers']
|
||||||
struct Customer {
|
struct Customer {
|
||||||
id int [primary; sql: serial] // a field named `id` of integer type must be the first field
|
id int @[primary; sql: serial] // a field named `id` of integer type must be the first field
|
||||||
name string [nonull]
|
name string @[nonull]
|
||||||
nr_orders int
|
nr_orders int
|
||||||
country string [nonull]
|
country string @[nonull]
|
||||||
}
|
}
|
||||||
|
|
||||||
db := sqlite.connect('customers.db')!
|
db := sqlite.connect('customers.db')!
|
||||||
@ -5385,7 +5385,7 @@ module abc
|
|||||||
pub struct Xyz {
|
pub struct Xyz {
|
||||||
pub mut:
|
pub mut:
|
||||||
a int
|
a int
|
||||||
d int [deprecated: 'use Xyz.a instead'; deprecated_after: '2999-03-01']
|
d int @[deprecated: 'use Xyz.a instead'; deprecated_after: '2999-03-01']
|
||||||
// the tags above, will produce a notice, since the deprecation date is in the far future
|
// the tags above, will produce a notice, since the deprecation date is in the far future
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -11,7 +11,7 @@ struct App {
|
|||||||
@[table: 'benchmark']
|
@[table: 'benchmark']
|
||||||
struct Task {
|
struct Task {
|
||||||
mut:
|
mut:
|
||||||
id u32 [primary; serial; sql: serial]
|
id u32 @[primary; serial; sql: serial]
|
||||||
title string
|
title string
|
||||||
status string
|
status string
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ Create a new file `article.v`:
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
struct Article {
|
struct Article {
|
||||||
id int [primary; sql: serial]
|
id int @[primary; sql: serial]
|
||||||
title string
|
title string
|
||||||
text string
|
text string
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ enum JobTitle {
|
|||||||
struct Employee {
|
struct Employee {
|
||||||
mut:
|
mut:
|
||||||
name string
|
name string
|
||||||
family string [json: '-'] // this field will be skipped
|
family string @[json: '-'] // this field will be skipped
|
||||||
age int
|
age int
|
||||||
salary f32
|
salary f32
|
||||||
title JobTitle [json: 'ETitle'] // the key for this field will be 'ETitle', not 'title'
|
title JobTitle @[json: 'ETitle'] // the key for this field will be 'ETitle', not 'title'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -4,8 +4,8 @@ struct PostTag {
|
|||||||
id string
|
id string
|
||||||
parent ?&PostTag
|
parent ?&PostTag
|
||||||
visibility string
|
visibility string
|
||||||
created_at string [json: 'createdAt']
|
created_at string @[json: 'createdAt']
|
||||||
metadata string [raw]
|
metadata string @[raw]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_main() {
|
fn test_main() {
|
||||||
|
@ -101,7 +101,7 @@ fn (db MockDB) last_id() int {
|
|||||||
@[table: 'foo']
|
@[table: 'foo']
|
||||||
struct Foo {
|
struct Foo {
|
||||||
mut:
|
mut:
|
||||||
id u64 [primary; sql: serial]
|
id u64 @[primary; sql: serial]
|
||||||
a string
|
a string
|
||||||
// b string [default: '"yes"']
|
// b string [default: '"yes"']
|
||||||
c ?string
|
c ?string
|
||||||
@ -222,7 +222,7 @@ fn test_option_struct_fields_and_none() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Bar {
|
struct Bar {
|
||||||
id u64 [primary; sql: serial]
|
id u64 @[primary; sql: serial]
|
||||||
name ?string
|
name ?string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ pub fn (t &Table) fn_type_source_signature(f &Fn) string {
|
|||||||
sig += ' ?'
|
sig += ' ?'
|
||||||
} else if f.return_type == rvoid_type {
|
} else if f.return_type == rvoid_type {
|
||||||
sig += ' !'
|
sig += ' !'
|
||||||
} else if f.return_type != void_type {
|
} else if f.return_type != void_type && f.return_type != 0 {
|
||||||
return_type_sym := t.sym(f.return_type)
|
return_type_sym := t.sym(f.return_type)
|
||||||
if f.return_type.has_flag(.option) {
|
if f.return_type.has_flag(.option) {
|
||||||
sig += ' ?${return_type_sym.name}'
|
sig += ' ?${return_type_sym.name}'
|
||||||
|
@ -17,10 +17,7 @@ pub fn (mut f Fmt) attrs(attrs []ast.Attr) {
|
|||||||
f.single_line_attrs(sorted_attrs[i..])
|
f.single_line_attrs(sorted_attrs[i..])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if attr.has_at {
|
f.writeln('@[${attr}]')
|
||||||
f.write('@')
|
|
||||||
}
|
|
||||||
f.writeln('[${attr}]')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,10 +35,7 @@ pub fn (mut f Fmt) single_line_attrs(attrs []ast.Attr, options AttrsOptions) {
|
|||||||
if options.same_line {
|
if options.same_line {
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
}
|
}
|
||||||
if attrs[0].has_at {
|
f.write('@[')
|
||||||
f.write('@')
|
|
||||||
}
|
|
||||||
f.write('[')
|
|
||||||
for i, attr in sorted_attrs {
|
for i, attr in sorted_attrs {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
f.write('; ')
|
f.write('; ')
|
||||||
|
@ -30,7 +30,7 @@ fn test_fmt() {
|
|||||||
}
|
}
|
||||||
vroot := os.dir(vexe)
|
vroot := os.dir(vexe)
|
||||||
os.chdir(vroot) or {}
|
os.chdir(vroot) or {}
|
||||||
basepath := os.join_path(vroot, '')
|
basepath := vroot + '/'
|
||||||
tmpfolder := os.temp_dir()
|
tmpfolder := os.temp_dir()
|
||||||
diff_cmd := diff.find_working_diff_command() or { '' }
|
diff_cmd := diff.find_working_diff_command() or { '' }
|
||||||
mut fmt_bench := benchmark.new_benchmark()
|
mut fmt_bench := benchmark.new_benchmark()
|
||||||
@ -40,6 +40,7 @@ fn test_fmt() {
|
|||||||
input_files << keep_input_files
|
input_files << keep_input_files
|
||||||
input_files << expected_input_files
|
input_files << expected_input_files
|
||||||
input_files = vtest.filter_vtest_only(input_files, basepath: vroot)
|
input_files = vtest.filter_vtest_only(input_files, basepath: vroot)
|
||||||
|
input_files.sort()
|
||||||
fmt_bench.set_total_expected_steps(input_files.len + 1)
|
fmt_bench.set_total_expected_steps(input_files.len + 1)
|
||||||
prepare_bin2v_file(mut fmt_bench)
|
prepare_bin2v_file(mut fmt_bench)
|
||||||
for istep, ipath in input_files {
|
for istep, ipath in input_files {
|
||||||
|
@ -124,7 +124,8 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
|
|||||||
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
|
||||||
has_at := if has_attrs { field.attrs[0].has_at } else { false }
|
// has_at := if has_attrs { field.attrs[0].has_at } else { false }
|
||||||
|
has_at := true
|
||||||
// TODO: this will get removed in next stage
|
// TODO: this will get removed in next stage
|
||||||
if has_attrs && !has_at {
|
if has_attrs && !has_at {
|
||||||
f.write(strings.repeat(` `, field_align.max_type_len - field_types[i].len))
|
f.write(strings.repeat(` `, field_align.max_type_len - field_types[i].len))
|
||||||
|
26
vlib/v/fmt/tests/old_attrs_to_new_expected.vv
Normal file
26
vlib/v/fmt/tests/old_attrs_to_new_expected.vv
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
@[export: 'Java_io_vlang_V_callStaticMethods']
|
||||||
|
@[tom: 'jerry']
|
||||||
|
@[direct_array_access; inline; unsafe]
|
||||||
|
fn heavily_tagged() {}
|
||||||
|
|
||||||
|
// a console attribute to force-open a console for easier diagnostics on windows
|
||||||
|
// also it's not safe to use
|
||||||
|
@[a_console; unsafe]
|
||||||
|
fn dangerous_console() {}
|
||||||
|
|
||||||
|
@[attribute_on_struct]
|
||||||
|
struct Generic[T] {
|
||||||
|
x T @[required]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
f fn () int = fn () int {
|
||||||
|
return 456 + os.args.len
|
||||||
|
} @[atr1; atr2]
|
||||||
|
//
|
||||||
|
g Generic[int] = Generic[int]{123} @[atr3; atr4]
|
||||||
|
}
|
23
vlib/v/fmt/tests/old_attrs_to_new_input.vv
Normal file
23
vlib/v/fmt/tests/old_attrs_to_new_input.vv
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module main
|
||||||
|
import os
|
||||||
|
[inline]
|
||||||
|
[export: 'Java_io_vlang_V_callStaticMethods']
|
||||||
|
[direct_array_access]
|
||||||
|
[unsafe]
|
||||||
|
[tom: 'jerry']
|
||||||
|
fn heavily_tagged() {}
|
||||||
|
|
||||||
|
[a_console] // a console attribute to force-open a console for easier diagnostics on windows
|
||||||
|
[unsafe] // also it's not safe to use
|
||||||
|
fn dangerous_console() {}
|
||||||
|
|
||||||
|
[attribute_on_struct]
|
||||||
|
struct Generic[T] {
|
||||||
|
x T [required]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
f fn () int [atr1] = fn () int { return 456 + os.args.len } @[atr2]
|
||||||
|
//
|
||||||
|
g Generic[int] [atr3] = Generic[int] { 123 } @[atr4]
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
enum Color {
|
enum Color {
|
||||||
red = 1 + 1 [json: 'Red']
|
red = 1 + 1 @[json: 'Red']
|
||||||
blue = 10 / 2 [json: 'Blue']
|
blue = 10 / 2 @[json: 'Blue']
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_main() {
|
fn test_main() {
|
||||||
|
@ -21,7 +21,7 @@ pub fn (ar &Vec[T]) iter() Iter[T] {
|
|||||||
|
|
||||||
pub struct Iter[T] {
|
pub struct Iter[T] {
|
||||||
mut:
|
mut:
|
||||||
v &Vec[T] [required]
|
v &Vec[T] @[required]
|
||||||
pos usize
|
pos usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
struct Fns {
|
struct Fns {
|
||||||
f1 fn () [required]
|
f1 fn () @[required]
|
||||||
f2 fn () [attr1; required]
|
f2 fn () @[attr1; required]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func() {
|
fn func() {
|
||||||
|
@ -360,8 +360,8 @@ fn test_struct_with_default_values_no_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct FieldsWithOptionVoidReturnType {
|
struct FieldsWithOptionVoidReturnType {
|
||||||
f fn () ! [required]
|
f fn () ! @[required]
|
||||||
g fn () ? [required]
|
g fn () ? @[required]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_fields_anon_fn_with_option_void_return_type() {
|
fn test_fields_anon_fn_with_option_void_return_type() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user