1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, parser, fmt: implement inline comments (#19012)

This commit is contained in:
yuyi 2023-08-01 02:22:51 +08:00 committed by GitHub
parent 0f861db9b0
commit 8861538c66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 294 additions and 113 deletions

View File

@ -536,6 +536,7 @@ pub:
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv
name_pos token.Pos
body_pos token.Pos // function bodys position
file string
generic_names []string
@ -635,6 +636,7 @@ pub:
is_hidden bool // interface first arg
pub mut:
typ Type
comments []Comment
}
pub fn (p &Param) specifier() string {
@ -1195,6 +1197,7 @@ pub:
val_var string
is_range bool
pos token.Pos
kv_pos token.Pos
comments []Comment
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
// and the array cannot be indexed inside the loop

View File

@ -218,7 +218,7 @@ struct StringifyModReplacement {
weight int
}
fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
pub fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
if m2a.len == 0 || -1 == input.index_u8(`.`) {
// a simple typename, like `string` or `[]bool`; no module aliasings apply,
// (or there just are not any mappings)

View File

@ -14,14 +14,12 @@ pub enum CommentsLevel {
// - has_nl: adds an newline at the end of a list of comments
// - inline: line comments will be on the same line as the last statement
// - level: either .keep (don't indent), or .indent (increment indentation)
// - iembed: a /* ... */ block comment used inside expressions; // comments the whole line
// - prev_line: the line number of the previous token to save linebreaks
[minify; params]
pub struct CommentsOptions {
has_nl bool = true
inline bool
level CommentsLevel
iembed bool
prev_line int = -1
}
@ -44,7 +42,7 @@ pub fn (mut f Fmt) comment(node ast.Comment, options CommentsOptions) {
if options.level == .indent {
f.indent++
}
if options.iembed {
if node.is_inline && !node.is_multi {
x := node.text.trim_left('\x01').trim_space()
if x.contains('\n') {
f.writeln('/*')
@ -105,7 +103,9 @@ pub fn (mut f Fmt) comments(comments []ast.Comment, options CommentsOptions) {
f.write(' ')
}
f.comment(c, options)
if !options.iembed && (i < comments.len - 1 || options.has_nl) {
if c.is_inline && i < comments.len - 1 && !c.is_multi {
f.write(' ')
} else if (!c.is_inline || c.is_multi) && (i < comments.len - 1 || options.has_nl) {
f.writeln('')
}
prev_line = c.pos.last_line

View File

@ -813,8 +813,14 @@ pub fn (mut f Fmt) assert_stmt(node ast.AssertStmt) {
}
pub fn (mut f Fmt) assign_stmt(node ast.AssignStmt) {
f.comments(node.comments)
mut sum_len := 0
for i, left in node.left {
pre_comments := node.comments[sum_len..].filter(it.pos.pos < left.pos().pos)
sum_len += pre_comments.len
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
f.expr(left)
if i < node.left.len - 1 {
f.write(', ')
@ -823,6 +829,12 @@ pub fn (mut f Fmt) assign_stmt(node ast.AssignStmt) {
f.is_assign = true
f.write(' ${node.op.str()} ')
for i, val in node.right {
pre_comments := node.comments[sum_len..].filter(it.pos.pos < val.pos().pos)
sum_len += pre_comments.len
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
f.expr(val)
if i < node.right.len - 1 {
f.write(', ')
@ -1007,7 +1019,7 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) {
pub fn (mut f Fmt) fn_decl(node ast.FnDecl) {
f.attrs(node.attrs)
f.write(node.stringify_fn_decl(f.table, f.cur_mod, f.mod2alias)) // `Expr` instead of `ast.Expr` in mod ast
f.fn_header(node)
// Handle trailing comments after fn header declarations
if node.no_body && node.end_comments.len > 0 {
first_comment := node.end_comments[0]
@ -1031,6 +1043,136 @@ pub fn (mut f Fmt) fn_decl(node ast.FnDecl) {
f.fn_body(node)
}
pub fn (mut f Fmt) fn_header(node ast.FnDecl) {
if node.is_pub {
f.write('pub ')
}
f.write('fn ')
pre_comments := node.comments.filter(it.pos.pos < node.name_pos.pos)
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
if node.is_method {
f.write('(')
mut styp := util.no_cur_mod(f.table.type_to_code(node.receiver.typ.clear_flag(.shared_f)),
f.cur_mod)
if node.rec_mut {
f.write(node.receiver.typ.share().str() + ' ')
styp = styp[1..] // remove &
}
f.write(node.receiver.name + ' ')
styp = util.no_cur_mod(styp, f.cur_mod)
if node.params[0].is_auto_rec {
styp = styp.trim('&')
}
f.write(styp + ') ')
} else if node.is_static_type_method {
mut styp := util.no_cur_mod(f.table.type_to_code(node.receiver.typ.clear_flag(.shared_f)),
f.cur_mod)
f.write(styp + '.')
}
mut name := if !node.is_method && node.language == .v {
node.name.all_after_last('.')
} else {
node.name
}
if node.is_static_type_method {
name = name.after('__static__')
}
f.write(name)
if name in ['+', '-', '*', '/', '%', '<', '>', '==', '!=', '>=', '<='] {
f.write(' ')
}
mut add_para_types := true
if node.generic_names.len > 0 {
if node.is_method {
sym := f.table.sym(node.params[0].typ)
if sym.info is ast.Struct {
generic_names := sym.info.generic_types.map(f.table.sym(it).name)
if generic_names == node.generic_names {
add_para_types = false
}
}
}
if add_para_types {
f.write('[')
for i, gname in node.generic_names {
is_last := i == node.generic_names.len - 1
f.write(gname)
if !is_last {
f.write(', ')
}
}
f.write(']')
}
}
f.write('(')
for i, arg in node.params {
before_comments := arg.comments.filter(it.pos.pos < arg.pos.pos)
if before_comments.len > 0 {
f.comments(before_comments, level: .indent)
}
// skip receiver
if node.is_method && i == 0 {
continue
}
if arg.is_hidden {
continue
}
is_last_arg := i == node.params.len - 1
is_type_only := arg.name == ''
should_add_type := true
if arg.is_mut {
f.write(arg.typ.share().str() + ' ')
}
f.write(arg.name)
arg_sym := f.table.sym(arg.typ)
if arg_sym.kind == .struct_ && (arg_sym.info as ast.Struct).is_anon {
f.write(' struct {')
struct_ := arg_sym.info as ast.Struct
for field in struct_.fields {
f.write(' ${field.name} ${f.table.type_to_str(field.typ)}')
if field.has_default_expr {
f.write(' = ${field.default_expr}')
}
}
if struct_.fields.len > 0 {
f.write(' ')
}
f.write('}')
} else {
mut s := f.table.type_to_str(arg.typ.clear_flag(.shared_f))
if arg.is_mut {
if s.starts_with('&') && ((!arg_sym.is_number() && arg_sym.kind != .bool)
|| node.language != .v) {
s = s[1..]
}
}
s = util.no_cur_mod(s, f.cur_mod)
s = ast.shorten_full_name_based_on_aliases(s, f.mod2alias)
if should_add_type {
if !is_type_only {
f.write(' ')
}
if node.is_variadic && is_last_arg {
f.write('...')
}
f.write(s)
}
}
if !is_last_arg {
f.write(', ')
}
}
f.write(')')
if node.return_type != ast.void_type {
sreturn_type := util.no_cur_mod(f.table.type_to_str(node.return_type), f.cur_mod)
short_sreturn_type := ast.shorten_full_name_based_on_aliases(sreturn_type, f.mod2alias)
f.write(' ${short_sreturn_type}')
}
}
pub fn (mut f Fmt) anon_fn(node ast.AnonFn) {
f.write(node.stringify_anon_decl(f.table, f.cur_mod, f.mod2alias)) // `Expr` instead of `ast.Expr` in mod ast
f.fn_body(node.decl)
@ -1045,9 +1187,11 @@ fn (mut f Fmt) fn_body(node ast.FnDecl) {
if node.language == .v {
if !node.no_body {
f.write(' {')
f.comments(node.comments, inline: true)
pre_comments := node.comments.filter(it.pos.pos < node.name_pos.pos)
body_comments := node.comments[pre_comments.len..]
f.comments(body_comments, inline: true)
if node.stmts.len > 0 || node.pos.line_nr < node.pos.last_line {
if node.comments.len == 0 {
if body_comments.len == 0 {
f.writeln('')
}
f.stmts(node.stmts)
@ -1090,20 +1234,39 @@ pub fn (mut f Fmt) for_c_stmt(node ast.ForCStmt) {
if node.label.len > 0 {
f.write('${node.label}: ')
}
if node.comments.len > 0 {
f.comments(node.comments)
}
init_comments := node.comments.filter(it.pos.pos < node.init.pos.pos)
cond_comments := node.comments[init_comments.len..].filter(it.pos.pos < node.cond.pos().pos)
inc_comments := node.comments[(init_comments.len + cond_comments.len)..].filter(it.pos.pos < node.inc.pos.pos)
after_inc_comments := node.comments[(init_comments.len + cond_comments.len + inc_comments.len)..]
f.write('for ')
if node.has_init {
if init_comments.len > 0 {
f.comments(init_comments)
f.write(' ')
}
f.single_line_if = true // to keep all for ;; exprs on the same line
f.stmt(node.init)
f.single_line_if = false
}
f.write('; ')
if cond_comments.len > 0 {
f.comments(cond_comments)
f.write(' ')
}
f.expr(node.cond)
f.write('; ')
if inc_comments.len > 0 {
f.comments(inc_comments)
f.write(' ')
}
f.stmt(node.inc)
f.remove_new_line()
if after_inc_comments.len > 0 {
f.comments(after_inc_comments)
}
if f.out.len > 1 && !f.out.last_n(1)[0].is_space() {
f.write(' ')
}
f.write('{')
if node.stmts.len > 0 || node.pos.line_nr < node.pos.last_line {
f.writeln('')
@ -1116,10 +1279,14 @@ pub fn (mut f Fmt) for_in_stmt(node ast.ForInStmt) {
if node.label.len > 0 {
f.write('${node.label}: ')
}
if node.comments.len > 0 {
f.comments(node.comments)
}
kv_comments := node.comments.filter(it.pos.pos < node.kv_pos.pos)
cond_comments := node.comments[kv_comments.len..].filter(it.pos.pos < node.cond.pos().pos)
after_comments := node.comments[(kv_comments.len + cond_comments.len)..]
f.write('for ')
if kv_comments.len > 0 {
f.comments(kv_comments)
f.write(' ')
}
if node.key_var != '' {
f.write(node.key_var)
}
@ -1133,11 +1300,21 @@ pub fn (mut f Fmt) for_in_stmt(node ast.ForInStmt) {
f.write(node.val_var)
}
f.write(' in ')
if cond_comments.len > 0 {
f.comments(cond_comments)
f.write(' ')
}
f.expr(node.cond)
if node.is_range {
f.write(' .. ')
f.expr(node.high)
}
if after_comments.len > 0 {
f.comments(after_comments)
}
if f.out.len > 1 && !f.out.last_n(1)[0].is_space() {
f.write(' ')
}
f.write('{')
if node.stmts.len > 0 || node.pos.line_nr < node.pos.last_line {
f.writeln('')
@ -1150,12 +1327,12 @@ pub fn (mut f Fmt) for_stmt(node ast.ForStmt) {
if node.label.len > 0 {
f.write('${node.label}: ')
}
f.write('for ')
if node.comments.len > 0 {
f.comments(node.comments)
}
f.write('for ')
f.expr(node.cond)
if !node.is_inf {
if f.out.len > 1 && !f.out.last_n(1)[0].is_space() {
f.write(' ')
}
f.write('{')
@ -1334,12 +1511,18 @@ pub fn (mut f Fmt) module_stmt(mod ast.Module) {
}
pub fn (mut f Fmt) return_stmt(node ast.Return) {
f.comments(node.comments)
f.write('return')
if node.exprs.len > 0 {
f.write(' ')
mut sum_len := 0
// Loop over all return values. In normal returns this will only run once.
for i, expr in node.exprs {
pre_comments := node.comments[sum_len..].filter(it.pos.pos < expr.pos().pos)
sum_len += pre_comments.len
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
if expr is ast.ParExpr {
f.expr(expr.expr)
} else {
@ -1591,7 +1774,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
f.comment(c, level: .indent)
f.writeln('')
} else {
f.comment(c, level: .indent, iembed: true)
f.comment(c, level: .indent)
f.write(' ')
}
} else {
@ -1606,7 +1789,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
f.writeln('')
}
} else {
f.comment(c, level: .indent, iembed: true)
f.comment(c, level: .indent)
if node.exprs.len > 0 {
f.write(' ')
}
@ -1688,18 +1871,13 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
set_comma = true
}
}
mut next_pos := expr_pos
if i + 1 < node.exprs.len {
next_pos = node.exprs[i + 1].pos()
}
if cmt.pos.line_nr > expr_pos.last_line {
embed := i + 1 < node.exprs.len && next_pos.line_nr == cmt.pos.last_line
f.writeln('')
f.comment(cmt, iembed: embed)
f.comment(cmt)
} else {
if cmt.is_inline {
f.write(' ')
f.comment(cmt, iembed: true)
f.comment(cmt)
if !set_comma && cmt.pos.line_nr == expr_pos.last_line
&& cmt.pos.pos < expr_pos.pos {
f.write(',')
@ -1717,7 +1895,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
set_comma = true
}
f.write(' ')
f.comment(cmt, iembed: false)
f.comment(cmt)
}
}
last_comment_was_inline = cmt.is_inline
@ -1793,10 +1971,6 @@ pub fn (mut f Fmt) at_expr(node ast.AtExpr) {
}
pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
for arg in node.args {
f.comments(arg.comments)
}
mut is_method_newline := false
if node.is_method {
if node.name in ['map', 'filter', 'all', 'any'] {
@ -1893,6 +2067,12 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
f.use_short_fn_args = old_short_arg_state
}
for i, arg in args {
pre_comments := arg.comments.filter(it.pos.pos < arg.expr.pos().pos)
post_comments := arg.comments[pre_comments.len..]
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
if i == args.len - 1 && arg.expr is ast.StructInit {
if arg.expr.typ == ast.void_type {
f.use_short_fn_args = true
@ -1905,6 +2085,10 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
f.wrap_long_line(3, true)
}
f.expr(arg.expr)
if post_comments.len > 0 {
f.comments(post_comments)
f.write(' ')
}
if i < args.len - 1 {
f.write(', ')
}
@ -2133,14 +2317,16 @@ pub fn (mut f Fmt) if_expr(node ast.IfExpr) {
start_len := f.line_len
for {
for i, branch in node.branches {
if i == 0 {
// first `if`
f.comments(branch.comments)
} else {
mut sum_len := 0
if i > 0 {
// `else`, close previous branch
if branch.comments.len > 0 {
f.writeln('}')
f.comments(branch.comments)
pre_comments := branch.comments.filter(it.pos.pos < branch.pos.pos)
sum_len += pre_comments.len
if pre_comments.len > 0 {
f.comments(pre_comments)
}
} else {
f.write('} ')
}
@ -2149,7 +2335,18 @@ pub fn (mut f Fmt) if_expr(node ast.IfExpr) {
if i < node.branches.len - 1 || !node.has_else {
f.write('${dollar}if ')
cur_pos := f.out.len
pre_comments := branch.comments[sum_len..].filter(it.pos.pos < branch.cond.pos().pos)
sum_len += pre_comments.len
post_comments := branch.comments[sum_len..]
if pre_comments.len > 0 {
f.comments(pre_comments)
f.write(' ')
}
f.expr(branch.cond)
if post_comments.len > 0 {
f.comments(post_comments)
f.write(' ')
}
cond_len := f.out.len - cur_pos
is_cond_wrapped := cond_len > 0 && branch.cond in [ast.IfGuardExpr, ast.CallExpr]
&& f.out.last_n(cond_len).contains('\n')
@ -2255,7 +2452,7 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
f.expr(node.left)
}
if node.before_op_comments.len > 0 {
f.comments(node.before_op_comments, iembed: node.before_op_comments[0].is_inline)
f.comments(node.before_op_comments)
}
is_one_val_array_init := node.op in [.key_in, .not_in] && node.right is ast.ArrayInit
&& node.right.exprs.len == 1
@ -2270,7 +2467,7 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
f.write(' ${node.op.str()} ')
}
if node.after_op_comments.len > 0 {
f.comments(node.after_op_comments, iembed: node.after_op_comments[0].is_inline)
f.comments(node.after_op_comments)
f.write(' ')
}
if is_one_val_array_init && !f.inside_comptime_if {
@ -2515,7 +2712,7 @@ fn (mut f Fmt) match_branch(branch ast.MatchBranch, single_line bool) {
f.write(estr)
if j < branch.ecmnts.len && branch.ecmnts[j].len > 0 {
f.write(' ')
f.comments(branch.ecmnts[j], iembed: true)
f.comments(branch.ecmnts[j])
}
if j < branch.exprs.len - 1 {
f.write(', ')

View File

@ -135,7 +135,7 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
f.write('\t${volatile_prefix}${field.name} ')
// Handle comments between field name and type
before_len := f.line_len
f.comments(between_comments, iembed: true, has_nl: false)
f.comments(between_comments, has_nl: false)
comments_len := f.line_len - before_len
if field_aligns[field_align_i].line_nr < field.pos.line_nr {
field_align_i++

View File

@ -5,5 +5,5 @@ v := [
// 2-3
3, // 3
// 4
// 5
/* 5 */
]

View File

@ -6,26 +6,23 @@ comment
*/
fn fun() int {
// comment zero
return 0 // another comment
return /* comment zero */ 0 // another comment
}
fn mr_fun() (int, int) {
// one comment
// another comment
return 1, 2
return /* one comment */ 1, /* another comment */ 2
}
fn single_line_blocks() {
// 1
/* 1 */
println('')
// 2
/* 2 */
println('')
// 3
// 4
/* 3 */
/* 4 */
println('')
// 5
// 6
/* 6 */
}
fn main() {
@ -38,38 +35,28 @@ fn main() {
/*
block3
*/
// this is a comment
a := 1
// and another comment
// just to make it worse
b, c := a, 2
a := /* this is a comment */ 1
b, c := /* and another comment */ a, /* just to make it worse */ 2
d := c // and an extra one
e := c
// more comments = more good
arr := [
// block foo bar
/* block foo bar */
// inline foo bar
0,
]
// before arg comment
// after arg comment
println('this is a test')
// before if expr
// after if expr
if true {
println( /* before arg comment */ 'this is a test' /* after arg comment */ )
if /* before if expr */ true /* after if expr */ {
println('if')
}
// before else if
// between else if
else if false {
else if /* between else if */ false {
println('else if')
}
// before else
// after else
else {
println('else')
}
// empty return
return
}
@ -104,47 +91,37 @@ fn between_if_branches() {
}
}
// comments
for {
for // comments
{
break
}
// comments
for {
for /* comments */ {
break
}
// comments
for i := 0; i < 1; i++ {
for i := 0; i < 1; i++ // comments
{
break
}
// comments
for i := 0; i < 1; i++ {
for i := 0; i < 1; i++ /* comments */ {
break
}
// comments1
// comments2
// comments3
// comments4
for i := 0; i < 1; i++ {
for /* comments1 */ i := 0; /* comments2 */ i < 1; /* comments3 */ i++ /* comments4 */ {
break
}
// comments
for _ in [1, 2] {
for _ in [1, 2] /* comments */ {
break
}
// comments
for _ in [1, 2] {
for _ in [1, 2] // comments
{
break
}
// comments1
// comments2
// comments3
for _ in [1, 2] {
for /* comments1 */ _ in /* comments2 */ [1, 2] /* comments3 */ {
break
}

View File

@ -1,3 +1,2 @@
// comments
if true {
if true /* comments */ {
}

View File

@ -9,7 +9,7 @@ const two = 2
move
*/
const three = 3 // rewrite and leave
const three = 3 /* rewrite and leave */
// leave
const four = 4 // leave

View File

@ -1,12 +1,12 @@
fn C.Mix_LoadMUS1(file byteptr) voidptr // *Mix_Music
fn C.Mix_LoadMUS2(file byteptr) voidptr //*Mix_Music
fn C.Mix_LoadMUS2(file byteptr) voidptr /* *Mix_Music */
fn C.Mix_LoadMUS3(file byteptr) voidptr // 1
fn C.Mix_LoadMUS3(file byteptr) voidptr /* 1 */
// 2
/* 2 */
// 3
/* 3 */
// Loads music
fn C.Mix_LoadMUS4(file byteptr) voidptr

View File

@ -1,7 +1,8 @@
fn main() { // main
fn /* main */ main() {
return
}
fn print_hi() { // hi
fn // hi
print_hi() {
println('hi')
}

View File

@ -1,13 +1,12 @@
fn main() {
a, b := true, true
// a
if a || b {
if a || b // a
{
println('hi')
}
// a
if a || b {
if a || b /* a */ {
println('hi')
}
}

View File

@ -41,10 +41,7 @@ struct SomeStruct {
mut:
// 2
// 3
somefield /* 4 */ /* 5 */ int // 6
// 7
// 8
/*
somefield /* 4 */ /* 5 */ int /* 6 */ /* 7 */ /* 8 */ /*
9
10
*/

View File

@ -620,6 +620,7 @@ run them via `v file.v` instead',
language: language
no_body: no_body
pos: start_pos.extend_with_last_line(end_pos, p.prev_tok.line_nr)
name_pos: name_pos
body_pos: body_start_pos
file: p.file_name
is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts
@ -867,6 +868,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
if types_only {
mut arg_no := 1
for p.tok.kind != .rpar {
mut comments := p.eat_comments()
if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.tok.pos())
return []ast.Param{}, false, false
@ -926,6 +928,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
p.error_with_pos('expecting `)`', p.prev_tok.pos())
return []ast.Param{}, false, false
}
comments << p.eat_comments()
if p.tok.kind == .comma {
if is_variadic {
@ -954,6 +957,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
}
} else {
for p.tok.kind != .rpar {
mut comments := p.eat_comments()
if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.tok.pos())
return []ast.Param{}, false, false
@ -966,6 +970,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
}
mut arg_pos := [p.tok.pos()]
name := p.check_name()
comments << p.eat_comments()
mut arg_names := [name]
if name.len > 0 && p.fn_language == .v && name[0].is_capital() {
p.error_with_pos('parameter name must not begin with upper case letter (`${arg_names[0]}`)',
@ -1031,6 +1036,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
// derive flags, however nr_muls only needs to be set on the array elem type, so clear it on the arg type
typ = ast.new_type(p.table.find_or_register_array(typ)).derive(typ).set_nr_muls(0).set_flag(.variadic)
}
comments << p.eat_comments()
for i, arg_name in arg_names {
alanguage := p.table.sym(typ).language
if alanguage != .v {
@ -1044,6 +1050,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
is_shared: is_shared
typ: typ
type_pos: type_pos[i]
comments: comments
}
// if typ.typ.kind == .variadic && p.tok.kind == .comma {
if is_variadic && p.tok.kind == .comma && p.peek_tok.kind != .rpar {

View File

@ -198,6 +198,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
high: high_expr
is_range: is_range
pos: pos
kv_pos: key_var_pos
comments: comments
val_is_mut: val_is_mut
scope: p.scope