mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
Merge branch 'vlang:master' into sqlite_return_type_consistency
This commit is contained in:
commit
881fbb6183
@ -324,8 +324,8 @@ fn vpm_install_from_vcs(module_names []string, vcs_key string) {
|
||||
eprintln('Removing module "${minfo.final_module_path}" ...')
|
||||
os.rmdir_all(minfo.final_module_path) or {
|
||||
errors++
|
||||
println('Errors while removing "${minfo.final_module_path}" :')
|
||||
println(err)
|
||||
eprintln('Errors while removing "${minfo.final_module_path}" :')
|
||||
eprintln(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -342,6 +342,14 @@ fn vpm_install_from_vcs(module_names []string, vcs_key string) {
|
||||
continue
|
||||
}
|
||||
println('Module "${name}" relocated to "${vmod_.name}" successfully.')
|
||||
publisher_dir := final_module_path.all_before_last(os.path_separator)
|
||||
if os.is_dir_empty(publisher_dir) {
|
||||
os.rmdir(publisher_dir) or {
|
||||
errors++
|
||||
eprintln('Errors while removing "${publisher_dir}" :')
|
||||
eprintln(err)
|
||||
}
|
||||
}
|
||||
final_module_path = minfo.final_module_path
|
||||
}
|
||||
name = vmod_.name
|
||||
|
@ -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')
|
||||
|
@ -5,34 +5,34 @@ fn test_custom_format() {
|
||||
assert date.custom_format('YYYY-MM-DD HH:mm') == date.format()
|
||||
assert date.custom_format('MMM') == date.smonth()
|
||||
|
||||
test_str := 'M MM Mo MMM MMMM\nD DD DDD DDDD\nd dd ddd dddd\nYY YYYY a A\nH HH h hh k kk e\nm mm s ss Z ZZ ZZZ\nDo DDDo Q Qo QQ\nN NN w wo ww\nM/D/YYYY N-HH:mm:ss Qo?a'
|
||||
test_str := 'M MM Mo MMM MMMM\nD DD DDD DDDD\nd dd ddd dddd\nYY YYYY a A\nH HH h hh k kk i ii e\nm mm s ss Z ZZ ZZZ\nDo DDDo Q Qo QQ\nN NN w wo ww\nM/D/YYYY N-HH:mm:ss Qo?a'
|
||||
|
||||
println(date.custom_format(test_str))
|
||||
}
|
||||
|
||||
fn test_hours() {
|
||||
assert time.parse('2023-08-04 00:00:45')!.custom_format('hh A h a') == '00 AM 0 am'
|
||||
assert time.parse('2023-08-04 01:00:45')!.custom_format('hh A h a') == '01 AM 1 am'
|
||||
assert time.parse('2023-08-04 02:00:45')!.custom_format('hh A h a') == '02 AM 2 am'
|
||||
assert time.parse('2023-08-04 03:00:45')!.custom_format('hh A h a') == '03 AM 3 am'
|
||||
assert time.parse('2023-08-04 04:00:45')!.custom_format('hh A h a') == '04 AM 4 am'
|
||||
assert time.parse('2023-08-04 05:00:45')!.custom_format('hh A h a') == '05 AM 5 am'
|
||||
assert time.parse('2023-08-04 06:00:45')!.custom_format('hh A h a') == '06 AM 6 am'
|
||||
assert time.parse('2023-08-04 07:00:45')!.custom_format('hh A h a') == '07 AM 7 am'
|
||||
assert time.parse('2023-08-04 08:00:45')!.custom_format('hh A h a') == '08 AM 8 am'
|
||||
assert time.parse('2023-08-04 09:00:45')!.custom_format('hh A h a') == '09 AM 9 am'
|
||||
assert time.parse('2023-08-04 10:00:45')!.custom_format('hh A h a') == '10 AM 10 am'
|
||||
assert time.parse('2023-08-04 11:00:45')!.custom_format('hh A h a') == '11 AM 11 am'
|
||||
assert time.parse('2023-08-04 12:00:45')!.custom_format('hh A h a') == '12 PM 12 pm'
|
||||
assert time.parse('2023-08-04 13:00:45')!.custom_format('hh A h a') == '01 PM 1 pm'
|
||||
assert time.parse('2023-08-04 14:00:45')!.custom_format('hh A h a') == '02 PM 2 pm'
|
||||
assert time.parse('2023-08-04 15:00:45')!.custom_format('hh A h a') == '03 PM 3 pm'
|
||||
assert time.parse('2023-08-04 16:00:45')!.custom_format('hh A h a') == '04 PM 4 pm'
|
||||
assert time.parse('2023-08-04 17:00:45')!.custom_format('hh A h a') == '05 PM 5 pm'
|
||||
assert time.parse('2023-08-04 18:00:45')!.custom_format('hh A h a') == '06 PM 6 pm'
|
||||
assert time.parse('2023-08-04 19:00:45')!.custom_format('hh A h a') == '07 PM 7 pm'
|
||||
assert time.parse('2023-08-04 20:00:45')!.custom_format('hh A h a') == '08 PM 8 pm'
|
||||
assert time.parse('2023-08-04 21:00:45')!.custom_format('hh A h a') == '09 PM 9 pm'
|
||||
assert time.parse('2023-08-04 22:00:45')!.custom_format('hh A h a') == '10 PM 10 pm'
|
||||
assert time.parse('2023-08-04 23:00:45')!.custom_format('hh A h a') == '11 PM 11 pm'
|
||||
assert time.parse('2023-08-04 00:00:45')!.custom_format('ii A i a hh A h a') == '00 AM 0 am 12 AM 12 am'
|
||||
assert time.parse('2023-08-04 01:00:45')!.custom_format('ii A i a hh A h a') == '01 AM 1 am 01 AM 1 am'
|
||||
assert time.parse('2023-08-04 02:00:45')!.custom_format('ii A i a hh A h a') == '02 AM 2 am 02 AM 2 am'
|
||||
assert time.parse('2023-08-04 03:00:45')!.custom_format('ii A i a hh A h a') == '03 AM 3 am 03 AM 3 am'
|
||||
assert time.parse('2023-08-04 04:00:45')!.custom_format('ii A i a hh A h a') == '04 AM 4 am 04 AM 4 am'
|
||||
assert time.parse('2023-08-04 05:00:45')!.custom_format('ii A i a hh A h a') == '05 AM 5 am 05 AM 5 am'
|
||||
assert time.parse('2023-08-04 06:00:45')!.custom_format('ii A i a hh A h a') == '06 AM 6 am 06 AM 6 am'
|
||||
assert time.parse('2023-08-04 07:00:45')!.custom_format('ii A i a hh A h a') == '07 AM 7 am 07 AM 7 am'
|
||||
assert time.parse('2023-08-04 08:00:45')!.custom_format('ii A i a hh A h a') == '08 AM 8 am 08 AM 8 am'
|
||||
assert time.parse('2023-08-04 09:00:45')!.custom_format('ii A i a hh A h a') == '09 AM 9 am 09 AM 9 am'
|
||||
assert time.parse('2023-08-04 10:00:45')!.custom_format('ii A i a hh A h a') == '10 AM 10 am 10 AM 10 am'
|
||||
assert time.parse('2023-08-04 11:00:45')!.custom_format('ii A i a hh A h a') == '11 AM 11 am 11 AM 11 am'
|
||||
assert time.parse('2023-08-04 12:00:45')!.custom_format('ii A i a hh A h a') == '12 PM 12 pm 12 PM 12 pm'
|
||||
assert time.parse('2023-08-04 13:00:45')!.custom_format('ii A i a hh A h a') == '01 PM 1 pm 01 PM 1 pm'
|
||||
assert time.parse('2023-08-04 14:00:45')!.custom_format('ii A i a hh A h a') == '02 PM 2 pm 02 PM 2 pm'
|
||||
assert time.parse('2023-08-04 15:00:45')!.custom_format('ii A i a hh A h a') == '03 PM 3 pm 03 PM 3 pm'
|
||||
assert time.parse('2023-08-04 16:00:45')!.custom_format('ii A i a hh A h a') == '04 PM 4 pm 04 PM 4 pm'
|
||||
assert time.parse('2023-08-04 17:00:45')!.custom_format('ii A i a hh A h a') == '05 PM 5 pm 05 PM 5 pm'
|
||||
assert time.parse('2023-08-04 18:00:45')!.custom_format('ii A i a hh A h a') == '06 PM 6 pm 06 PM 6 pm'
|
||||
assert time.parse('2023-08-04 19:00:45')!.custom_format('ii A i a hh A h a') == '07 PM 7 pm 07 PM 7 pm'
|
||||
assert time.parse('2023-08-04 20:00:45')!.custom_format('ii A i a hh A h a') == '08 PM 8 pm 08 PM 8 pm'
|
||||
assert time.parse('2023-08-04 21:00:45')!.custom_format('ii A i a hh A h a') == '09 PM 9 pm 09 PM 9 pm'
|
||||
assert time.parse('2023-08-04 22:00:45')!.custom_format('ii A i a hh A h a') == '10 PM 10 pm 10 PM 10 pm'
|
||||
assert time.parse('2023-08-04 23:00:45')!.custom_format('ii A i a hh A h a') == '11 PM 11 pm 11 PM 11 pm'
|
||||
}
|
||||
|
@ -20,14 +20,6 @@ pub fn (t Time) format_ss_milli() string {
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}.${(t.nanosecond / 1_000_000):03d}'
|
||||
}
|
||||
|
||||
// format_rfc3339 returns a date string in "YYYY-MM-DDTHH:mm:ss.123Z" format (24 hours, see https://www.rfc-editor.org/rfc/rfc3339.html)
|
||||
// RFC3339 is an Internet profile, based on the ISO 8601 standard for for representation of dates and times using the Gregorian calendar.
|
||||
// It is intended to improve consistency and interoperability, when representing and using date and time in Internet protocols.
|
||||
pub fn (t Time) format_rfc3339() string {
|
||||
u := t.local_to_utc()
|
||||
return '${u.year:04d}-${u.month:02d}-${u.day:02d}T${u.hour:02d}:${u.minute:02d}:${u.second:02d}.${(u.nanosecond / 1_000_000):03d}Z'
|
||||
}
|
||||
|
||||
// format_ss_micro returns a date string in "YYYY-MM-DD HH:mm:ss.123456" format (24h).
|
||||
pub fn (t Time) format_ss_micro() string {
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}.${(t.nanosecond / 1_000):06d}'
|
||||
@ -38,6 +30,20 @@ pub fn (t Time) format_ss_nano() string {
|
||||
return '${t.year:04d}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}.${t.nanosecond:09d}'
|
||||
}
|
||||
|
||||
// format_rfc3339 returns a date string in "YYYY-MM-DDTHH:mm:ss.123Z" format (24 hours, see https://www.rfc-editor.org/rfc/rfc3339.html)
|
||||
// RFC3339 is an Internet profile, based on the ISO 8601 standard for for representation of dates and times using the Gregorian calendar.
|
||||
// It is intended to improve consistency and interoperability, when representing and using date and time in Internet protocols.
|
||||
pub fn (t Time) format_rfc3339() string {
|
||||
u := t.local_to_utc()
|
||||
return '${u.year:04d}-${u.month:02d}-${u.day:02d}T${u.hour:02d}:${u.minute:02d}:${u.second:02d}.${(u.nanosecond / 1_000_000):03d}Z'
|
||||
}
|
||||
|
||||
// format_rfc3339_nano returns a date string in "YYYY-MM-DDTHH:mm:ss.123456789Z" format (24 hours, see https://www.rfc-editor.org/rfc/rfc3339.html)
|
||||
pub fn (t Time) format_rfc3339_nano() string {
|
||||
u := t.local_to_utc()
|
||||
return '${u.year:04d}-${u.month:02d}-${u.day:02d}T${u.hour:02d}:${u.minute:02d}:${u.second:02d}.${(u.nanosecond):09d}Z'
|
||||
}
|
||||
|
||||
// hhmm returns a date string in "HH:mm" format (24h).
|
||||
pub fn (t Time) hhmm() string {
|
||||
return '${t.hour:02d}:${t.minute:02d}'
|
||||
@ -90,8 +96,8 @@ fn ordinal_suffix(n int) string {
|
||||
}
|
||||
|
||||
const (
|
||||
tokens_2 = ['MM', 'Mo', 'DD', 'Do', 'YY', 'ss', 'kk', 'NN', 'mm', 'hh', 'HH', 'ZZ', 'dd', 'Qo',
|
||||
'QQ', 'wo', 'ww']
|
||||
tokens_2 = ['MM', 'Mo', 'DD', 'Do', 'YY', 'ss', 'kk', 'NN', 'mm', 'hh', 'HH', 'ii', 'ZZ', 'dd',
|
||||
'Qo', 'QQ', 'wo', 'ww']
|
||||
tokens_3 = ['MMM', 'DDD', 'ZZZ', 'ddd']
|
||||
tokens_4 = ['MMMM', 'DDDD', 'DDDo', 'dddd', 'YYYY']
|
||||
)
|
||||
@ -132,6 +138,8 @@ const (
|
||||
// | | HH | 00 01 ... 22 23 |
|
||||
// | | h | 1 2 ... 11 12 |
|
||||
// | | hh | 01 02 ... 11 12 |
|
||||
// | | i | 0 1 ... 11 12 1 ... 11 |
|
||||
// | | ii | 00 01 ... 11 12 01 ... 11 |
|
||||
// | | k | 1 2 ... 23 24 |
|
||||
// | | kk | 01 02 ... 23 24 |
|
||||
// | **Minute** | m | 0 1 ... 58 59 |
|
||||
@ -226,10 +234,18 @@ pub fn (t Time) custom_format(s string) string {
|
||||
sb.write_string('${t.hour:02}')
|
||||
}
|
||||
'h' {
|
||||
h := if t.hour > 12 { t.hour - 12 } else { t.hour }
|
||||
h := (t.hour + 11) % 12 + 1
|
||||
sb.write_string(h.str())
|
||||
}
|
||||
'hh' {
|
||||
h := (t.hour + 11) % 12 + 1
|
||||
sb.write_string('${h:02}')
|
||||
}
|
||||
'i' {
|
||||
h := if t.hour > 12 { t.hour - 12 } else { t.hour }
|
||||
sb.write_string(h.str())
|
||||
}
|
||||
'ii' {
|
||||
h := if t.hour > 12 { t.hour - 12 } else { t.hour }
|
||||
sb.write_string('${h:02}')
|
||||
}
|
||||
|
@ -89,6 +89,13 @@ fn test_format_rfc3339() {
|
||||
assert res.contains('T')
|
||||
}
|
||||
|
||||
fn test_format_rfc3339_nano() {
|
||||
res := time_to_test.format_rfc3339_nano()
|
||||
assert res.ends_with('23:42.123456789Z')
|
||||
assert res.starts_with('1980-07-1')
|
||||
assert res.contains('T')
|
||||
}
|
||||
|
||||
fn test_format_ss() {
|
||||
assert '11.07.1980 21:23:42' == time_to_test.get_fmt_str(.dot, .hhmmss24, .ddmmyyyy)
|
||||
}
|
||||
|
@ -526,6 +526,9 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) {
|
||||
// type Sum = int | Alias
|
||||
// type Alias = Sum
|
||||
}
|
||||
.none_ {
|
||||
c.error('cannot create a type alias of `none` as it is a value', node.type_pos)
|
||||
}
|
||||
// The rest of the parent symbol kinds are also allowed, since they are either primitive types,
|
||||
// that in turn do not allow recursion, or are abstract enough so that they can not be checked at comptime:
|
||||
else {}
|
||||
@ -1143,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
|
||||
}
|
||||
@ -1774,9 +1779,6 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
|
||||
useen << uval
|
||||
}
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
dump(field.expr)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
// Handle `enum Foo { x = 1 + 2 }`
|
||||
c.infix_expr(mut field.expr)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
vlib/v/checker/tests/option_type_call_err.vv:4:5: error: Result type cannot be called directly
|
||||
2 |
|
||||
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 }
|
||||
| ~~~~~~~
|
||||
5 | }
|
||||
5 | }
|
||||
|
27
vlib/v/checker/tests/or_block_check_err.out
Normal file
27
vlib/v/checker/tests/or_block_check_err.out
Normal 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 | }
|
11
vlib/v/checker/tests/or_block_check_err.vv
Normal file
11
vlib/v/checker/tests/or_block_check_err.vv
Normal 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')
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
vlib/v/checker/tests/result_type_call_err.vv:12:2: error: Result type cannot be called directly
|
||||
10 |
|
||||
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()
|
||||
| ~~~~~~~~~
|
||||
|
3
vlib/v/checker/tests/type_alias_none_parent_type_err.out
Normal file
3
vlib/v/checker/tests/type_alias_none_parent_type_err.out
Normal file
@ -0,0 +1,3 @@
|
||||
vlib/v/checker/tests/type_alias_none_parent_type_err.vv:1:13: error: cannot create a type alias of `none` as it is a value
|
||||
1 | type None = none
|
||||
| ~~~~
|
1
vlib/v/checker/tests/type_alias_none_parent_type_err.vv
Normal file
1
vlib/v/checker/tests/type_alias_none_parent_type_err.vv
Normal file
@ -0,0 +1 @@
|
||||
type None = none
|
@ -648,7 +648,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||
}
|
||||
// End of $var, start next string
|
||||
if s.is_inter_end {
|
||||
if s.text[s.pos] == s.quote {
|
||||
if s.text[s.pos] == s.quote || (s.text[s.pos] == s.inter_quote && s.is_enclosed_inter) {
|
||||
s.is_inter_end = false
|
||||
return s.new_token(.string, '', 1)
|
||||
}
|
||||
@ -1472,17 +1472,23 @@ fn (mut s Scanner) ident_char() string {
|
||||
u := c.runes()
|
||||
if u.len != 1 {
|
||||
if escaped_hex || escaped_unicode {
|
||||
s.error('invalid character literal `${orig}` => `${c}` (${u}) (escape sequence did not refer to a singular rune)')
|
||||
s.error_with_pos('invalid character literal `${orig}` => `${c}` (${u}) (escape sequence did not refer to a singular rune)',
|
||||
lspos)
|
||||
} else if u.len == 0 {
|
||||
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
|
||||
lspos)
|
||||
s.error('invalid empty character literal `${orig}`')
|
||||
s.error_with_pos('invalid empty character literal `${orig}`', lspos)
|
||||
} else {
|
||||
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
|
||||
lspos)
|
||||
s.error('invalid character literal `${orig}` => `${c}` (${u}) (more than one character)')
|
||||
s.error_with_pos('invalid character literal `${orig}` => `${c}` (${u}) (more than one character)',
|
||||
lspos)
|
||||
}
|
||||
}
|
||||
} else if c == '\n' {
|
||||
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
|
||||
lspos)
|
||||
s.error_with_pos('invalid character literal, use \`\\n\` instead', lspos)
|
||||
}
|
||||
// Escapes a `'` character
|
||||
if c == "'" {
|
||||
@ -1566,15 +1572,19 @@ fn (mut s Scanner) eat_details() string {
|
||||
}
|
||||
|
||||
pub fn (mut s Scanner) warn(msg string) {
|
||||
if s.pref.warns_are_errors {
|
||||
s.error(msg)
|
||||
return
|
||||
}
|
||||
pos := token.Pos{
|
||||
line_nr: s.line_nr
|
||||
pos: s.pos
|
||||
col: s.current_column() - 1
|
||||
}
|
||||
s.warn_with_pos(msg, pos)
|
||||
}
|
||||
|
||||
pub fn (mut s Scanner) warn_with_pos(msg string, pos token.Pos) {
|
||||
if s.pref.warns_are_errors {
|
||||
s.error_with_pos(msg, pos)
|
||||
return
|
||||
}
|
||||
details := s.eat_details()
|
||||
if s.pref.output_mode == .stdout && !s.pref.check_only {
|
||||
util.show_compiler_message('warning:',
|
||||
@ -1604,6 +1614,10 @@ pub fn (mut s Scanner) error(msg string) {
|
||||
pos: s.pos
|
||||
col: s.current_column() - 1
|
||||
}
|
||||
s.error_with_pos(msg, pos)
|
||||
}
|
||||
|
||||
pub fn (mut s Scanner) error_with_pos(msg string, pos token.Pos) {
|
||||
details := s.eat_details()
|
||||
if s.pref.output_mode == .stdout && !s.pref.check_only {
|
||||
util.show_compiler_message('error:',
|
||||
|
@ -1,10 +1,10 @@
|
||||
vlib/v/scanner/tests/empty_character_literal_err.vv:2:8: error: invalid empty character literal ``
|
||||
vlib/v/scanner/tests/empty_character_literal_err.vv:2:7: error: invalid empty character literal ``
|
||||
1 | fn main() {
|
||||
2 | a := ``
|
||||
| ^
|
||||
| ^
|
||||
3 | println(a)
|
||||
4 | }
|
||||
Details:
|
||||
Details:
|
||||
vlib/v/scanner/tests/empty_character_literal_err.vv:2:7: details: use quotes for strings, backticks for characters
|
||||
1 | fn main() {
|
||||
2 | a := ``
|
||||
|
13
vlib/v/scanner/tests/newline_character_literal_err.out
Normal file
13
vlib/v/scanner/tests/newline_character_literal_err.out
Normal file
@ -0,0 +1,13 @@
|
||||
vlib/v/scanner/tests/newline_character_literal_err.vv:2:7: error: invalid character literal, use `\n` instead
|
||||
1 | fn main() {
|
||||
2 | a := `
|
||||
| ^
|
||||
3 | `
|
||||
4 | println(a)
|
||||
Details:
|
||||
vlib/v/scanner/tests/newline_character_literal_err.vv:2:7: details: use quotes for strings, backticks for characters
|
||||
1 | fn main() {
|
||||
2 | a := `
|
||||
| ^
|
||||
3 | `
|
||||
4 | println(a)
|
5
vlib/v/scanner/tests/newline_character_literal_err.vv
Normal file
5
vlib/v/scanner/tests/newline_character_literal_err.vv
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
a := `
|
||||
`
|
||||
println(a)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:5] 2 + 2: 4
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:6] 2 * 3 + 50 / 5: 16
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:7] 3.14 + 0.1: 3.24
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:8] 'abc' + 'a': abca
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:9] 'a' + 'b' + 'c': abc
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:10] true || (false && true): true
|
||||
[vlib/v/slow_tests/inout/dump_expressions_with_literals.vv:11] 2 == 4: false
|
12
vlib/v/slow_tests/inout/dump_expressions_with_literals.vv
Normal file
12
vlib/v/slow_tests/inout/dump_expressions_with_literals.vv
Normal file
@ -0,0 +1,12 @@
|
||||
// Note: dump expressions should not get optimised out by the transformer stage,
|
||||
// even though they could normally, when they are composed of literals, i.e.
|
||||
// the value of the expression is known at compile time.
|
||||
fn main() {
|
||||
dump(2 + 2)
|
||||
dump(2 * 3 + 50 / 5)
|
||||
dump(3.14 + 0.1)
|
||||
dump('abc' + 'a')
|
||||
dump('a' + 'b' + 'c')
|
||||
dump(true || (false && true))
|
||||
dump(2 == 4)
|
||||
}
|
32
vlib/v/tests/string_interpolation_with_inner_quotes_test.v
Normal file
32
vlib/v/tests/string_interpolation_with_inner_quotes_test.v
Normal file
@ -0,0 +1,32 @@
|
||||
fn f(x int, s string) string {
|
||||
return 'label ${s}: ${x}'
|
||||
}
|
||||
|
||||
// vfmt off
|
||||
fn test_string_interp_with_inner_quotes() {
|
||||
x := 'hi'
|
||||
println('abc ${f(123, 'def')} xyz')
|
||||
assert 'abc ${f(123, 'def')} xyz' == 'abc label def: 123 xyz'
|
||||
|
||||
println('abc ${f(123, "def")} xyz')
|
||||
assert 'abc ${f(123, "def")} xyz' == 'abc label def: 123 xyz'
|
||||
|
||||
println("abc ${f(123, 'def')} xyz")
|
||||
assert "abc ${f(123, 'def')} xyz" == 'abc label def: 123 xyz'
|
||||
|
||||
println("abc ${f(123, "def")} xyz")
|
||||
assert "abc ${f(123, "def")} xyz" == 'abc label def: 123 xyz'
|
||||
|
||||
println("abc ${f(123, "$x $x")} xyz")
|
||||
assert "abc ${f(123, "$x $x")} xyz" == 'abc label hi hi: 123 xyz'
|
||||
|
||||
println('abc ${f(123, '$x $x')} xyz')
|
||||
assert 'abc ${f(123, '$x $x')} xyz' == 'abc label hi hi: 123 xyz'
|
||||
|
||||
println('abc ${f(123, "$x $x")} xyz')
|
||||
assert 'abc ${f(123, "$x $x")} xyz' == 'abc label hi hi: 123 xyz'
|
||||
|
||||
println("abc ${f(123, '$x $x')} xyz")
|
||||
assert "abc ${f(123, '$x $x')} xyz" == 'abc label hi hi: 123 xyz'
|
||||
}
|
||||
// vfmt on
|
@ -10,7 +10,8 @@ pub mut:
|
||||
index &IndexState
|
||||
table &ast.Table = unsafe { nil }
|
||||
mut:
|
||||
is_assert bool
|
||||
is_assert bool
|
||||
inside_dump bool
|
||||
}
|
||||
|
||||
pub fn new_transformer(pref_ &pref.Preferences) &Transformer {
|
||||
@ -513,6 +514,9 @@ pub fn (mut t Transformer) interface_decl(mut node ast.InterfaceDecl) ast.Stmt {
|
||||
}
|
||||
|
||||
pub fn (mut t Transformer) expr(mut node ast.Expr) ast.Expr {
|
||||
if t.inside_dump {
|
||||
return node
|
||||
}
|
||||
match mut node {
|
||||
ast.AnonFn {
|
||||
node.decl = t.stmt(mut node.decl) as ast.FnDecl
|
||||
@ -563,7 +567,10 @@ pub fn (mut t Transformer) expr(mut node ast.Expr) ast.Expr {
|
||||
}
|
||||
}
|
||||
ast.DumpExpr {
|
||||
old_inside_dump := t.inside_dump
|
||||
t.inside_dump = true
|
||||
node.expr = t.expr(mut node.expr)
|
||||
t.inside_dump = old_inside_dump
|
||||
}
|
||||
ast.GoExpr {
|
||||
node.call_expr = t.expr(mut node.call_expr) as ast.CallExpr
|
||||
|
Loading…
Reference in New Issue
Block a user