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

checker: fix missing or_block check for left expr of CallExpr(fix #19061) (#19074)

This commit is contained in:
shove 2023-08-08 14:06:03 +08:00 committed by GitHub
parent 3b3395d93b
commit f4859ffb11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 12 deletions

View File

@ -32,17 +32,17 @@ const (
fn test_search_tag_by_type() {
mut dom := parse(html.html)
tag := dom.get_tag('body')[0]
assert tag.get_tag('div') or { assert false }.attributes['id'] == '1st'
assert tag.get_tag_by_attribute('href') or { assert false }.content == 'V'
tag := dom.get_tags(GetTagsOptions{'body'})[0]
assert tag.get_tag('div')?.attributes['id'] == '1st'
assert tag.get_tag_by_attribute('href')?.content == 'V'
// TODO: update after improved parsing to not add trailing white space to attribute values
assert tag.get_tag_by_attribute_value('id', '3rd') or { assert false }.str() == '<div id="3rd" ></div>'
assert tag.get_tag_by_class_name('foo') or { assert false }.attributes['class'] == 'foo bar'
assert tag.get_tag_by_attribute_value('id', '3rd')?.str() == '<div id="3rd" ></div>'
assert tag.get_tag_by_class_name('foo')?.attributes['class'] == 'foo bar'
}
fn test_search_tags_by_type() {
mut dom := parse(html.html)
tag := dom.get_tag_by_attribute_value('id', '2nd')[0]
tag := dom.get_tags_by_attribute_value('id', '2nd')[0]
assert tag.get_tags('div').len == 5
assert tag.get_tags_by_attribute('href')[2].content == 'vpm'
assert tag.get_tags_by_attribute_value('class', 'bar').len == 3
@ -65,7 +65,7 @@ fn generate_temp_html_with_classes() string {
fn test_search_by_class() {
mut dom := parse(generate_temp_html_with_classes())
tag := dom.get_tag('body')[0]
tag := dom.get_tags(GetTagsOptions{'body'})[0]
single_class_tags := tag.get_tags_by_class_name('single')
common_class_tags := tag.get_tags_by_class_name('common')
complex_class_tags := tag.get_tags_by_class_name('complex-0', 'complex-1', 'complex-2')

View File

@ -1146,6 +1146,8 @@ fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type ast.Type) ast.Typ
c.check_expr_opt_call(expr.expr, ret_type)
} else if expr is ast.AsCast {
c.check_expr_opt_call(expr.expr, ret_type)
} else if expr is ast.ParExpr {
c.check_expr_opt_call(expr.expr, ret_type)
}
return ret_type
}

View File

@ -490,6 +490,9 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
c.error('unknown function: ${node.name}', node.pos)
}
}
// If the left expr has an or_block, it needs to be checked for legal or_block statement.
return_type := c.expr(mut node.left)
c.check_expr_opt_call(node.left, return_type)
// TODO merge logic from method_call and fn_call
// First check everything that applies to both fns and methods
old_inside_fn_arg := c.inside_fn_arg

View File

@ -5,6 +5,13 @@ vlib/v/checker/tests/generics_struct_init_err.vv:14:2: notice: uninitialized `fn
| ~~~~~~~~~~~~~~~~~
15 | }
16 |
vlib/v/checker/tests/generics_struct_init_err.vv:58:8: error: cannot initialize builtin type `FnHolder1[neg]`
56 | ret = holder_call_12(neg, 3)
57 | assert ret == -3
58 | ret = FnHolder1{neg}.call(4)
| ~~~~~~~~~~~~~~
59 | assert ret == -4
60 |
vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: could not infer generic type `T` in generic struct `FnHolder2[T]`
65 | ret = holder_call_22(neg, 5)
66 | assert ret == -5

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/option_type_call_err.vv:4:5: error: Result type cannot be called directly
vlib/v/checker/tests/option_type_call_err.vv:4:5: error: os.ls() returns a Result, so it should have either an `or {}` block, or `!` at the end
2 |
3 | fn main() {
4 | os.ls('.').filter(it.ends_with('.v')) or { return }

View File

@ -0,0 +1,27 @@
vlib/v/checker/tests/or_block_check_err.vv:6:36: error: assignment requires a non empty `or {}` block
4 |
5 | fn main() {
6 | _ = callexpr_with_or_block_call() or {}.replace('a', 'b')
| ~~~~~
7 | _ = (callexpr_with_or_block_call() or {}).replace('a', 'b')
8 |
vlib/v/checker/tests/or_block_check_err.vv:7:37: error: assignment requires a non empty `or {}` block
5 | fn main() {
6 | _ = callexpr_with_or_block_call() or {}.replace('a', 'b')
7 | _ = (callexpr_with_or_block_call() or {}).replace('a', 'b')
| ~~~~~
8 |
9 | _ = callexpr_with_or_block_call() or { eprintln('error') }.replace('a', 'b')
vlib/v/checker/tests/or_block_check_err.vv:9:41: error: `or` block must provide a default value of type `string`, or return/continue/break or call a [noreturn] function like panic(err) or exit(1)
7 | _ = (callexpr_with_or_block_call() or {}).replace('a', 'b')
8 |
9 | _ = callexpr_with_or_block_call() or { eprintln('error') }.replace('a', 'b')
| ~~~~~~~~~~~~~~~~~
10 | _ = (callexpr_with_or_block_call() or { eprintln('error') }).replace('a', 'b')
11 | }
vlib/v/checker/tests/or_block_check_err.vv:10:42: error: `or` block must provide a default value of type `string`, or return/continue/break or call a [noreturn] function like panic(err) or exit(1)
8 |
9 | _ = callexpr_with_or_block_call() or { eprintln('error') }.replace('a', 'b')
10 | _ = (callexpr_with_or_block_call() or { eprintln('error') }).replace('a', 'b')
| ~~~~~~~~~~~~~~~~~
11 | }

View File

@ -0,0 +1,11 @@
fn callexpr_with_or_block_call() !string {
return error('')
}
fn main() {
_ = callexpr_with_or_block_call() or {}.replace('a', 'b')
_ = (callexpr_with_or_block_call() or {}).replace('a', 'b')
_ = callexpr_with_or_block_call() or { eprintln('error') }.replace('a', 'b')
_ = (callexpr_with_or_block_call() or { eprintln('error') }).replace('a', 'b')
}

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/result_type_call_err.vv:12:2: error: Result type cannot be called directly
vlib/v/checker/tests/result_type_call_err.vv:12:2: error: new_foo() returns a Result, so it should have either an `or {}` block, or `!` at the end
10 |
11 | fn main() {
12 | new_foo().foo()