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

checker: fix ctdefine check in non-main modules (#8332)

This commit is contained in:
Enzo 2021-01-27 13:54:33 +01:00 committed by GitHub
parent cb885d30b4
commit 2b30c48770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 33 deletions

View File

@ -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' {

View File

@ -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]

View File

@ -0,0 +1,6 @@
module notmain
[if test]
fn only_called_in_test() string {
return 'bah'
}