Skip to content

Commit

Permalink
vfmt: automate transition from the old [attribute] to the new `@[at…
Browse files Browse the repository at this point in the history
…tribute]` syntax (#19912)
  • Loading branch information
spytheman committed Nov 17, 2023
1 parent 157d603 commit f7b9e4e
Show file tree
Hide file tree
Showing 17 changed files with 86 additions and 39 deletions.
6 changes: 4 additions & 2 deletions cmd/tools/vast/vast.v
Expand Up @@ -707,12 +707,14 @@ fn (t Tree) attr(node ast.Attr) &Node {
obj.add_terse('ast_type', t.string_node('Attr'))
obj.add_terse('name', t.string_node(node.name))
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('ct_expr', t.expr(node.ct_expr))
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_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
}

Expand Down
18 changes: 9 additions & 9 deletions doc/docs.md
Expand Up @@ -2271,7 +2271,7 @@ It's also possible to define custom default values.

```v
struct Foo {
n int [required]
n int @[required]
}
```

Expand Down Expand Up @@ -4389,12 +4389,12 @@ struct User {
// 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,
// and decoding will not fail.
name string [required]
name string @[required]
age int
// 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
last_name string [json: lastName]
last_name string @[json: lastName]
}
data := '{ "name": "Frodo", "lastName": "Baggins", "age": 25 }'
Expand Down Expand Up @@ -4976,10 +4976,10 @@ import db.sqlite
// sets a custom table name. Default is struct name (case-sensitive)
@[table: 'customers']
struct Customer {
id int [primary; sql: serial] // a field named `id` of integer type must be the first field
name string [nonull]
id int @[primary; sql: serial] // a field named `id` of integer type must be the first field
name string @[nonull]
nr_orders int
country string [nonull]
country string @[nonull]
}
db := sqlite.connect('customers.db')!
Expand Down Expand Up @@ -5385,7 +5385,7 @@ module abc
pub struct Xyz {
pub mut:
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
}
```
Expand Down Expand Up @@ -7111,4 +7111,4 @@ Assignment Operators
+= -= *= /= %=
&= |= ^=
>>= <<= >>>=
```
```
2 changes: 1 addition & 1 deletion examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v
Expand Up @@ -11,7 +11,7 @@ struct App {
@[table: 'benchmark']
struct Task {
mut:
id u32 [primary; serial; sql: serial]
id u32 @[primary; serial; sql: serial]
title string
status string
}
Expand Down
4 changes: 2 additions & 2 deletions tutorials/building_a_simple_web_blog_with_vweb/README.md
Expand Up @@ -234,7 +234,7 @@ Create a new file `article.v`:
module main
struct Article {
id int [primary; sql: serial]
id int @[primary; sql: serial]
title string
text string
}
Expand Down Expand Up @@ -411,4 +411,4 @@ app is run you will see the articles created from the previous executions

To be continued...

For an example of a more sophisticated web app written in V, check out Vorum: https://github.com/vlang/vorum
For an example of a more sophisticated web app written in V, check out Vorum: https://github.com/vlang/vorum
6 changes: 3 additions & 3 deletions vlib/json/README.md
Expand Up @@ -21,10 +21,10 @@ enum JobTitle {
struct Employee {
mut:
name string
family string [json: '-'] // this field will be skipped
family string @[json: '-'] // this field will be skipped
age int
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() {
Expand All @@ -43,4 +43,4 @@ fn main() {
println('JSON encoding of employee y: ${ss}')
assert ss == s
}
```
```
4 changes: 2 additions & 2 deletions vlib/json/json_encode_recursive_ptr_test.v
Expand Up @@ -4,8 +4,8 @@ struct PostTag {
id string
parent ?&PostTag
visibility string
created_at string [json: 'createdAt']
metadata string [raw]
created_at string @[json: 'createdAt']
metadata string @[raw]
}

fn test_main() {
Expand Down
4 changes: 2 additions & 2 deletions vlib/orm/orm_null_test.v
Expand Up @@ -101,7 +101,7 @@ fn (db MockDB) last_id() int {
@[table: 'foo']
struct Foo {
mut:
id u64 [primary; sql: serial]
id u64 @[primary; sql: serial]
a string
// b string [default: '"yes"']
c ?string
Expand Down Expand Up @@ -222,7 +222,7 @@ fn test_option_struct_fields_and_none() {
}

struct Bar {
id u64 [primary; sql: serial]
id u64 @[primary; sql: serial]
name ?string
age int
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/ast/table.v
Expand Up @@ -153,7 +153,7 @@ pub fn (t &Table) fn_type_source_signature(f &Fn) string {
sig += ' ?'
} else if f.return_type == rvoid_type {
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)
if f.return_type.has_flag(.option) {
sig += ' ?${return_type_sym.name}'
Expand Down
10 changes: 2 additions & 8 deletions vlib/v/fmt/attrs.v
Expand Up @@ -17,10 +17,7 @@ pub fn (mut f Fmt) attrs(attrs []ast.Attr) {
f.single_line_attrs(sorted_attrs[i..])
break
}
if attr.has_at {
f.write('@')
}
f.writeln('[${attr}]')
f.writeln('@[${attr}]')
}
}

Expand All @@ -38,10 +35,7 @@ pub fn (mut f Fmt) single_line_attrs(attrs []ast.Attr, options AttrsOptions) {
if options.same_line {
f.write(' ')
}
if attrs[0].has_at {
f.write('@')
}
f.write('[')
f.write('@[')
for i, attr in sorted_attrs {
if i > 0 {
f.write('; ')
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/fmt/fmt_keep_test.v
Expand Up @@ -30,7 +30,7 @@ fn test_fmt() {
}
vroot := os.dir(vexe)
os.chdir(vroot) or {}
basepath := os.join_path(vroot, '')
basepath := vroot + '/'
tmpfolder := os.temp_dir()
diff_cmd := diff.find_working_diff_command() or { '' }
mut fmt_bench := benchmark.new_benchmark()
Expand All @@ -40,6 +40,7 @@ fn test_fmt() {
input_files << keep_input_files
input_files << expected_input_files
input_files = vtest.filter_vtest_only(input_files, basepath: vroot)
input_files.sort()
fmt_bench.set_total_expected_steps(input_files.len + 1)
prepare_bin2v_file(mut fmt_bench)
for istep, ipath in input_files {
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/fmt/struct.v
Expand Up @@ -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)
attrs_len := inline_attrs_len(field.attrs)
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
if has_attrs && !has_at {
f.write(strings.repeat(` `, field_align.max_type_len - field_types[i].len))
Expand Down
26 changes: 26 additions & 0 deletions vlib/v/fmt/tests/old_attrs_to_new_expected.vv
@@ -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 changes: 23 additions & 0 deletions vlib/v/fmt/tests/old_attrs_to_new_input.vv
@@ -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]
}
4 changes: 2 additions & 2 deletions vlib/v/tests/enum_attr_2_test.v
@@ -1,6 +1,6 @@
enum Color {
red = 1 + 1 [json: 'Red']
blue = 10 / 2 [json: 'Blue']
red = 1 + 1 @[json: 'Red']
blue = 10 / 2 @[json: 'Blue']
}

fn test_main() {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/tests/generics_for_in_iterate_test.v
Expand Up @@ -21,7 +21,7 @@ pub fn (ar &Vec[T]) iter() Iter[T] {

pub struct Iter[T] {
mut:
v &Vec[T] [required]
v &Vec[T] @[required]
pos usize
}

Expand Down
4 changes: 2 additions & 2 deletions vlib/v/tests/struct_fields_required_test.v
@@ -1,6 +1,6 @@
struct Fns {
f1 fn () [required]
f2 fn () [attr1; required]
f1 fn () @[required]
f2 fn () @[attr1; required]
}

fn func() {
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/tests/struct_test.v
Expand Up @@ -360,8 +360,8 @@ fn test_struct_with_default_values_no_init() {
}

struct FieldsWithOptionVoidReturnType {
f fn () ! [required]
g fn () ? [required]
f fn () ! @[required]
g fn () ? @[required]
}

fn test_fields_anon_fn_with_option_void_return_type() {
Expand Down

0 comments on commit f7b9e4e

Please sign in to comment.