From 2b30c487701110d8f6ba8e4627f8c7386ae41e03 Mon Sep 17 00:00:00 2001 From: Enzo Date: Wed, 27 Jan 2021 13:54:33 +0100 Subject: [PATCH] checker: fix ctdefine check in non-main modules (#8332) --- vlib/v/checker/checker.v | 58 +++++++++++++------------------ vlib/v/checker/tests/ctdefine.out | 12 +++++++ vlib/v/checker/tests/ctdefine.vv | 6 ++++ 3 files changed, 43 insertions(+), 33 deletions(-) create mode 100644 vlib/v/checker/tests/ctdefine.out create mode 100644 vlib/v/checker/tests/ctdefine.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 431c00e067..1096931850 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -148,7 +148,7 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) { if file.mod.name == 'main' { files_from_main_module << file has_main_mod_file = true - if c.check_file_in_main(file) { + if c.file_has_main_fn(file) { has_main_fn = true } } @@ -205,44 +205,27 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) { // do checks specific to files in main module // returns `true` if a main function is in the file -fn (mut c Checker) check_file_in_main(file ast.File) bool { +fn (mut c Checker) file_has_main_fn(file ast.File) bool { mut has_main_fn := false for stmt in file.stmts { - match stmt { - ast.FnDecl { - if stmt.name == 'main.main' { - if has_main_fn { - c.error('function `main` is already defined', stmt.pos) - } - has_main_fn = true - if stmt.params.len > 0 { - c.error('function `main` cannot have arguments', stmt.pos) - } - if stmt.return_type != table.void_type { - c.error('function `main` cannot return values', stmt.pos) - } - if stmt.no_body { - c.error('function `main` must declare a body', stmt.pos) - } - } else { - for attr in stmt.attrs { - if attr.name == 'console' { - c.error('only `main` can have the `[console]` attribute', - stmt.pos) - } - } + if stmt is ast.FnDecl { + if stmt.name == 'main.main' { + if has_main_fn { + c.error('function `main` is already defined', stmt.pos) + } + has_main_fn = true + if stmt.params.len > 0 { + c.error('function `main` cannot have arguments', stmt.pos) } if stmt.return_type != table.void_type { - for attr in stmt.attrs { - if attr.is_ctdefine { - c.error('only functions that do NOT return values can have `[if $attr.name]` tags', - stmt.pos) - break - } - } + c.error('function `main` cannot return values', stmt.pos) } + if stmt.no_body { + c.error('function `main` must declare a body', stmt.pos) + } + } else if stmt.attrs.contains('console') { + c.error('only `main` can have the `[console]` attribute', stmt.pos) } - else {} } } return has_main_fn @@ -5270,6 +5253,15 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { if node.language == .v && !c.is_builtin_mod { c.check_valid_snake_case(node.name, 'function name', node.pos) } + if node.return_type != table.void_type { + for attr in node.attrs { + if attr.is_ctdefine { + c.error('only functions that do NOT return values can have `[if $attr.name]` tags', + node.pos) + break + } + } + } if node.is_method { mut sym := c.table.get_type_symbol(node.receiver.typ) if sym.kind == .array && !c.is_builtin_mod && node.name == 'map' { diff --git a/vlib/v/checker/tests/ctdefine.out b/vlib/v/checker/tests/ctdefine.out new file mode 100644 index 0000000000..008a7d63dc --- /dev/null +++ b/vlib/v/checker/tests/ctdefine.out @@ -0,0 +1,12 @@ +vlib/v/checker/tests/ctdefine.vv:4:1: error: only functions that do NOT return values can have `[if test]` tags + 2 | + 3 | [if test] + 4 | fn only_called_in_test() string { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 5 | return 'bah' + 6 | } +vlib/v/checker/tests/ctdefine.vv:1:1: error: project must include a `main` module or be a shared library (compile with `v -shared`) + 1 | module notmain + | ^ + 2 | + 3 | [if test] diff --git a/vlib/v/checker/tests/ctdefine.vv b/vlib/v/checker/tests/ctdefine.vv new file mode 100644 index 0000000000..20d1eb010b --- /dev/null +++ b/vlib/v/checker/tests/ctdefine.vv @@ -0,0 +1,6 @@ +module notmain + +[if test] +fn only_called_in_test() string { + return 'bah' +}