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

checker: check option fn returning error (fix #17423) (#17438)

This commit is contained in:
yuyi 2023-03-02 21:49:50 +08:00 committed by GitHub
parent 8f7c35552d
commit 17000ef7b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 129 additions and 106 deletions

View File

@ -95,7 +95,7 @@ pub fn chdir(path string) {
}
}
pub fn mkdir(path string) ? {
pub fn mkdir(path string) ! {
verbose_trace_strong(modfn(@MOD, @FN), 'mkdir ${path}')
os.mkdir(path) or {
verbose_trace(modfn(@MOD, @FN), '## failed.')
@ -103,7 +103,7 @@ pub fn mkdir(path string) ? {
}
}
pub fn mkdir_all(path string) ? {
pub fn mkdir_all(path string) ! {
verbose_trace_strong(modfn(@MOD, @FN), 'mkdir -p ${path}')
os.mkdir_all(path) or {
verbose_trace(modfn(@MOD, @FN), '## failed.')
@ -123,7 +123,7 @@ pub fn rmrf(path string) {
}
// execute a command, and return a result, or an error, if it failed in any way.
pub fn exec(cmd string) ?os.Result {
pub fn exec(cmd string) !os.Result {
verbose_trace_strong(modfn(@MOD, @FN), cmd)
x := os.execute(cmd)
if x.exit_code != 0 {

View File

@ -721,7 +721,7 @@ pub fn get_test_details(file string) TestDetails {
return res
}
pub fn find_started_process(pname string) ?string {
pub fn find_started_process(pname string) !string {
for line in testing.all_processes {
if line.contains(pname) {
return line

View File

@ -169,7 +169,7 @@ Try ${tool_name} -h for more help...')
}
}
fn validate_options(options Options) ? {
fn validate_options(options Options) ! {
if options.patch && options.major {
return error('Cannot specify both --patch and --major.')
}

View File

@ -213,7 +213,7 @@ fn (mut foptions FormatOptions) find_diff_cmd() string {
return foptions.diff_cmd
}
fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_path string) ? {
fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_path string) ! {
if formatted_file_path.len == 0 {
return
}
@ -307,7 +307,7 @@ fn file_to_mod_name_and_is_module_file(file string) (string, bool) {
return mod_name, is_module_file
}
fn read_source_lines(file string) ?[]string {
fn read_source_lines(file string) ![]string {
source_lines := os.read_lines(file) or { return error('can not read ${file}') }
return source_lines
}

View File

@ -414,7 +414,7 @@ fn vpm_update(m []string) {
}
}
fn get_outdated() ?[]string {
fn get_outdated() ![]string {
module_names := get_installed_modules()
mut outdated := []string{}
for name in module_names {
@ -720,7 +720,7 @@ fn verbose_println(s string) {
}
}
fn get_mod_by_url(name string) ?Mod {
fn get_mod_by_url(name string) !Mod {
if purl := urllib.parse(name) {
verbose_println('purl: ${purl}')
mod := Mod{
@ -733,7 +733,7 @@ fn get_mod_by_url(name string) ?Mod {
return error('invalid url: ${name}')
}
fn get_module_meta_info(name string) ?Mod {
fn get_module_meta_info(name string) !Mod {
if mod := get_mod_by_url(name) {
return mod
}

View File

@ -576,7 +576,7 @@ fn cleanup_files(file string) {
}
}
fn repl_run_vfile(file string) ?os.Result {
fn repl_run_vfile(file string) !os.Result {
$if trace_repl_temp_files ? {
eprintln('>> repl_run_vfile file: ${file}')
}

View File

@ -152,7 +152,7 @@ fn warn_and_exit(err string) {
}
// get the system environment registry handle
fn get_reg_sys_env_handle() ?voidptr {
fn get_reg_sys_env_handle() !voidptr {
$if windows { // wrap for cross-compile compat
// open the registry key
reg_key_path := 'Environment'
@ -166,7 +166,7 @@ fn get_reg_sys_env_handle() ?voidptr {
}
// get a value from a given $key
fn get_reg_value(reg_env_key voidptr, key string) ?string {
fn get_reg_value(reg_env_key voidptr, key string) !string {
$if windows {
// query the value (shortcut the sizing step)
reg_value_size := u32(4095) // this is the max length (not for the registry, but for the system %PATH%)
@ -180,7 +180,7 @@ fn get_reg_value(reg_env_key voidptr, key string) ?string {
}
// sets the value for the given $key to the given $value
fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
fn set_reg_value(reg_key voidptr, key string, value string) !bool {
$if windows {
if C.RegSetValueExW(reg_key, key.to_wide(), 0, C.REG_EXPAND_SZ, value.to_wide(),
value.len * 2) != 0 {
@ -193,7 +193,7 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
// Broadcasts a message to all listening windows (explorer.exe in particular)
// letting them know that the system environment has changed and should be reloaded
fn send_setting_change_msg(message_data string) ?bool {
fn send_setting_change_msg(message_data string) !bool {
$if windows {
if C.SendMessageTimeoutW(os.hwnd_broadcast, os.wm_settingchange, 0, unsafe { &u32(message_data.to_wide()) },
os.smto_abortifhung, 5000, 0) == 0 {

View File

@ -69,7 +69,7 @@ fn new_app() &App {
}
['/'; get]
pub fn (mut app App) controller_get_all_task() ?vweb.Result {
pub fn (mut app App) controller_get_all_task() !vweb.Result {
v_version := version.full_v_version(true)
orm_stmt_kinds := ['insert', 'select', 'update']

View File

@ -25,7 +25,7 @@ fn (mut app App) service_add_product(product_name string, user_id int) ! {
}
}
fn (mut app App) service_get_all_products_from(user_id int) ?[]Product {
fn (mut app App) service_get_all_products_from(user_id int) ![]Product {
mut db := databases.create_db_connection() or {
println(err)
return err

View File

@ -30,7 +30,7 @@ fn (mut app App) service_add_user(username string, password string) ! {
}
}
fn (mut app App) service_get_all_user() ?[]User {
fn (mut app App) service_get_all_user() ![]User {
mut db := databases.create_db_connection() or {
println(err)
return err
@ -47,7 +47,7 @@ fn (mut app App) service_get_all_user() ?[]User {
return results
}
fn (mut app App) service_get_user(id int) ?User {
fn (mut app App) service_get_user(id int) !User {
mut db := databases.create_db_connection() or {
println(err)
return err

View File

@ -3,7 +3,7 @@ module main
import crypto.bcrypt
import databases
fn (mut app App) service_add_user(username string, password string) ?User {
fn (mut app App) service_add_user(username string, password string) !User {
mut db := databases.create_db_connection() or {
eprintln(err)
return err
@ -38,7 +38,7 @@ fn (mut app App) service_add_user(username string, password string) ?User {
return result
}
fn (mut app App) service_get_user_by_id(user_id int) ?User {
fn (mut app App) service_get_user_by_id(user_id int) !User {
mut db := databases.create_db_connection() or {
println(err)
return err
@ -55,7 +55,7 @@ fn (mut app App) service_get_user_by_id(user_id int) ?User {
return results
}
fn (mut app App) service_get_all_user() ?[]User {
fn (mut app App) service_get_all_user() ![]User {
mut db := databases.create_db_connection() or {
println(err)
return err
@ -72,7 +72,7 @@ fn (mut app App) service_get_all_user() ?[]User {
return results
}
fn (mut app App) service_get_by_username(username string) ?User {
fn (mut app App) service_get_by_username(username string) !User {
mut db := databases.create_db_connection() or {
println(err)
return err

View File

@ -562,8 +562,8 @@ pub fn (b []u8) bytestr() string {
// from utf8 to utf32 and return the result as a rune
// it will produce an error if there are more than
// four bytes in the array.
pub fn (b []u8) byterune() ?rune {
r := b.utf8_to_utf32()?
pub fn (b []u8) byterune() !rune {
r := b.utf8_to_utf32()!
return rune(r)
}

View File

@ -910,7 +910,7 @@ pub fn (s string) substr(start int, end int) string {
// version of `substr()` that is used in `a[start..end] or {`
// return an error when the index is out of range
[direct_array_access]
pub fn (s string) substr_with_check(start int, end int) ?string {
pub fn (s string) substr_with_check(start int, end int) !string {
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
return error('substr(${start}, ${end}) out of bounds (len=${s.len})')
}
@ -1606,7 +1606,7 @@ fn (s string) at(idx int) byte {
// return an error when the index is out of range
fn (s string) at_with_check(idx int) ?u8 {
if idx < 0 || idx >= s.len {
return error('string index out of range')
return none
}
unsafe {
return s.str[idx]

View File

@ -98,7 +98,7 @@ pub fn (_rune string) utf32_code() int {
// convert array of utf8 bytes to single utf32 value
// will error if more than 4 bytes are submitted
pub fn (_bytes []u8) utf8_to_utf32() ?rune {
pub fn (_bytes []u8) utf8_to_utf32() !rune {
if _bytes.len == 0 {
return 0
}

View File

@ -43,14 +43,14 @@ const magic_cipher_data = [u8(0x4f), 0x72, 0x70, 0x68, 0x65, 0x61, 0x6e, 0x42, 0
0x6c, 0x64, 0x65, 0x72, 0x53, 0x63, 0x72, 0x79, 0x44, 0x6f, 0x75, 0x62, 0x74]
// generate_from_password return a bcrypt string from Hashed struct.
pub fn generate_from_password(password []u8, cost int) ?string {
pub fn generate_from_password(password []u8, cost int) !string {
mut p := new_from_password(password, cost) or { return error('Error: ${err}') }
x := p.hash_u8()
return x.bytestr()
}
// compare_hash_and_password compares a bcrypt hashed password with its possible hashed version.
pub fn compare_hash_and_password(password []u8, hashed_password []u8) ? {
pub fn compare_hash_and_password(password []u8, hashed_password []u8) ! {
mut p := new_from_hash(hashed_password) or { return error('Error: ${err}') }
p.salt << `=`
p.salt << `=`
@ -76,7 +76,7 @@ pub fn generate_salt() string {
}
// new_from_password converting from password to a Hashed struct with bcrypt.
fn new_from_password(password []u8, cost int) ?&Hashed {
fn new_from_password(password []u8, cost int) !&Hashed {
mut cost_ := cost
if cost < bcrypt.min_cost {
cost_ = bcrypt.default_cost
@ -98,7 +98,7 @@ fn new_from_password(password []u8, cost int) ?&Hashed {
}
// new_from_hash converting from hashed data to a Hashed struct.
fn new_from_hash(hashed_secret []u8) ?&Hashed {
fn new_from_hash(hashed_secret []u8) !&Hashed {
mut tmp := hashed_secret.clone()
if tmp.len < bcrypt.min_hash_size {
return error('hash to short')
@ -118,7 +118,7 @@ fn new_from_hash(hashed_secret []u8) ?&Hashed {
}
// bcrypt hashing passwords.
fn bcrypt(password []u8, cost int, salt []u8) ?[]u8 {
fn bcrypt(password []u8, cost int, salt []u8) ![]u8 {
mut cipher_data := []u8{len: 72 - bcrypt.magic_cipher_data.len, init: 0}
cipher_data << bcrypt.magic_cipher_data
@ -135,7 +135,7 @@ fn bcrypt(password []u8, cost int, salt []u8) ?[]u8 {
}
// expensive_blowfish_setup generate a Blowfish cipher, given key, cost and salt.
fn expensive_blowfish_setup(key []u8, cost u32, salt []u8) ?&blowfish.Blowfish {
fn expensive_blowfish_setup(key []u8, cost u32, salt []u8) !&blowfish.Blowfish {
csalt := base64.decode(salt.bytestr())
// Bug compatibility with C bcrypt implementations, which use the trailing NULL in the key string during expansion.
// See https://cs.opensource.google/go/x/crypto/+/master:bcrypt/bcrypt.go;l=226
@ -180,7 +180,7 @@ fn (mut h Hashed) hash_u8() []u8 {
}
// decode_version decode bcrypt version.
fn (mut h Hashed) decode_version(sbytes []u8) ?int {
fn (mut h Hashed) decode_version(sbytes []u8) !int {
if sbytes[0] != `$` {
return error("bcrypt hashes must start with '$'")
}
@ -197,7 +197,7 @@ fn (mut h Hashed) decode_version(sbytes []u8) ?int {
}
// decode_cost extracts the value of cost and returns the next index in the array.
fn (mut h Hashed) decode_cost(sbytes []u8) ?int {
fn (mut h Hashed) decode_cost(sbytes []u8) !int {
cost := sbytes[0..2].bytestr().int()
check_cost(cost) or { return err }
h.cost = cost
@ -205,7 +205,7 @@ fn (mut h Hashed) decode_cost(sbytes []u8) ?int {
}
// check_cost check for reasonable quantities.
fn check_cost(cost int) ? {
fn check_cost(cost int) ! {
if cost < bcrypt.min_cost || cost > bcrypt.max_cost {
return error('invalid cost')
}

View File

@ -8,7 +8,7 @@ pub mut:
// new_cipher creates and returns a new Blowfish cipher.
// The key argument should be the Blowfish key, from 1 to 56 bytes.
pub fn new_cipher(key []u8) ?Blowfish {
pub fn new_cipher(key []u8) !Blowfish {
mut bf := Blowfish{}
unsafe { vmemcpy(&bf.p[0], &p[0], int(sizeof(bf.p))) }
unsafe { vmemcpy(&bf.s[0], &s[0], int(sizeof(bf.s))) }
@ -21,7 +21,7 @@ pub fn new_cipher(key []u8) ?Blowfish {
}
// new_salted_cipher returns a new Blowfish cipher that folds a salt into its key schedule.
pub fn new_salted_cipher(key []u8, salt []u8) ?Blowfish {
pub fn new_salted_cipher(key []u8, salt []u8) !Blowfish {
if salt.len == 0 {
return new_cipher(key)
}

View File

@ -76,7 +76,7 @@ fn random_number() string {
return s.substr(1, s.len)
}
fn prefix_and_suffix(pattern string) ?(string, string) {
fn prefix_and_suffix(pattern string) !(string, string) {
mut pat := pattern
if pat.contains(os.path_separator) {
return error('pattern cannot contain path separators (${os.path_separator}).')

View File

@ -131,7 +131,7 @@ pub fn norm_path(path string) string {
// existing_path returns the existing part of the given `path`.
// An error is returned if there is no existing part of the given `path`.
pub fn existing_path(path string) ?string {
pub fn existing_path(path string) !string {
err := error('path does not exist')
if path.len == 0 {
return err

View File

@ -77,7 +77,7 @@ mut:
}
[inline]
fn setup_sock(fd int) ? {
fn setup_sock(fd int) ! {
flag := 1
if C.setsockopt(fd, C.IPPROTO_TCP, C.TCP_NODELAY, &flag, sizeof(int)) < 0 {
return error('setup_sock.setup_sock failed')

View File

@ -3,7 +3,7 @@ module regex
import strings
// compile_opt compile RE pattern string
pub fn (mut re RE) compile_opt(pattern string) ? {
pub fn (mut re RE) compile_opt(pattern string) ! {
re_err, err_pos := re.impl_compile(pattern)
if re_err != compile_ok {
@ -34,7 +34,7 @@ pub fn new() RE {
}
// regex_opt create new RE object from RE pattern string
pub fn regex_opt(pattern string) ?RE {
pub fn regex_opt(pattern string) !RE {
// init regex
mut re := RE{}
re.prog = []Token{len: pattern.len + 1} // max program length, can not be longer then the pattern
@ -47,7 +47,7 @@ pub fn regex_opt(pattern string) ?RE {
re.group_data = []int{len: re.group_max, init: -1}
// compile the pattern
re.compile_opt(pattern)?
re.compile_opt(pattern)!
return re
}

View File

@ -53,7 +53,7 @@ fn (ver RawVersion) is_missing(typ int) bool {
return typ >= ver.raw_ints.len - 1
}
fn (raw_ver RawVersion) coerce() ?Version {
fn (raw_ver RawVersion) coerce() !Version {
ver := raw_ver.complete()
if !is_valid_number(ver.raw_ints[semver.ver_major]) {
return error('Invalid major version: ${ver.raw_ints}[ver_major]')

View File

@ -69,7 +69,7 @@ fn (c Comparator) satisfies(ver Version) bool {
return false
}
fn parse_range(input string) ?Range {
fn parse_range(input string) !Range {
raw_comparator_sets := input.split(semver.comparator_set_sep)
mut comparator_sets := []ComparatorSet{}
for raw_comp_set in raw_comparator_sets {
@ -84,7 +84,7 @@ fn parse_range(input string) ?Range {
return Range{comparator_sets}
}
fn parse_comparator_set(input string) ?ComparatorSet {
fn parse_comparator_set(input string) !ComparatorSet {
raw_comparators := input.split(semver.comparator_sep)
if raw_comparators.len > 2 {
return &InvalidComparatorFormatError{

View File

@ -38,7 +38,7 @@ pub fn (err InvalidVersionFormatError) msg() string {
// * Constructor.
// from returns a `Version` structure parsed from `input` `string`.
pub fn from(input string) ?Version {
pub fn from(input string) !Version {
if input.len == 0 {
return &EmptyInputError{}
}
@ -114,7 +114,7 @@ import semver
v := semver.coerce('1.3-RC1-b2') or { semver.Version{} }
assert v.satisfies('>1.0 <2.0') == true // 1.3.0
*/
pub fn coerce(input string) ?Version {
pub fn coerce(input string) !Version {
return coerce_version(input)
}

View File

@ -8,7 +8,7 @@ fn is_version_valid(input string) bool {
}
[inline]
fn coerce_version(input string) ?Version {
fn coerce_version(input string) !Version {
raw_ver := parse(input)
ver := raw_ver.coerce() or { return error('Invalid version for input "${input}"') }
return ver

View File

@ -285,7 +285,7 @@ pub fn is_leap_year(year int) bool {
}
// days_in_month returns a number of days in a given month.
pub fn days_in_month(month int, year int) ?int {
pub fn days_in_month(month int, year int) !int {
if month > 12 || month < 1 {
return error('Invalid month: ${month}')
}

View File

@ -368,7 +368,7 @@ pub fn module_path(mod string) string {
// TODO: try to merge this & util.module functions to create a
// reliable multi use function. see comments in util/module.v
pub fn (b &Builder) find_module_path(mod string, fpath string) ?string {
pub fn (b &Builder) find_module_path(mod string, fpath string) !string {
// support @VROOT/v.mod relative paths:
mut mcache := vmod.get_cache()
vmod_file_location := mcache.get_by_file(fpath)

View File

@ -194,7 +194,7 @@ fn (c Checker) check_multiple_ptr_match(got ast.Type, expected ast.Type, param a
return true
}
fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ? {
fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ! {
if got == 0 {
return error('unexpected 0 type')
}

View File

@ -96,6 +96,12 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
option_type_idx := c.table.type_idxs['_option']
result_type_idx := c.table.type_idxs['_result']
got_types_0_idx := got_types[0].idx()
if exp_is_option && got_types_0_idx == ast.error_type_idx {
c.warn('Option and Result types have been split, use `!Foo` to return errors',
node.pos)
} else if exp_is_result && got_types_0_idx == ast.none_type_idx {
c.warn('Option and Result types have been split, use `?Foo` to return none', node.pos)
}
if (exp_is_option
&& got_types_0_idx in [ast.none_type_idx, ast.error_type_idx, option_type_idx])
|| (exp_is_result && got_types_0_idx in [ast.error_type_idx, result_type_idx]) {

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/error_fn_with_0_args.vv:2:9: error: expected 1 arguments, but got 0
1 | fn abc() ? {
1 | fn abc() ! {
2 | return error()
| ~~~~~~~
3 | }

View File

@ -1,3 +1,3 @@
fn abc() ? {
fn abc() ! {
return error()
}

View File

@ -1,4 +1,4 @@
fn return_option(fail bool) ?string {
fn return_option(fail bool) !string {
if fail {
return error('nope')
}

View File

@ -1,14 +1,14 @@
vlib/v/checker/tests/invalid_parameter_name_err.vv:4:24: error: invalid use of reserved type `char` as a parameter name
2 | }
3 |
4 | fn (mut b Buffer) put8(char u8) ? {
4 | fn (mut b Buffer) put8(char u8) ! {
| ~~~~
5 | return error('-')
6 | }
vlib/v/checker/tests/invalid_parameter_name_err.vv:10:6: error: invalid use of reserved type `char` as a parameter name
8 | interface Writer {
9 | mut:
10 | put(char u8)?
10 | put(char u8) !
| ~~~~
11 | }
12 |

View File

@ -1,13 +1,13 @@
struct Buffer {
}
fn (mut b Buffer) put8(char u8) ? {
fn (mut b Buffer) put8(char u8) ! {
return error('-')
}
interface Writer {
mut:
put(char u8)?
put(char u8) !
}
fn main() {

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/option_fn_return_error.vv:2:2: warning: Option and Result types have been split, use `!Foo` to return errors
1 | fn func() ?int {
2 | return error('Some error')
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
3 | }
4 |

View File

@ -0,0 +1,11 @@
fn func() ?int {
return error('Some error')
}
fn main() {
mut a := ?int(5)
a = 1
a = none
a = func()
println(a)
}

View File

@ -1,4 +1,4 @@
fn test_option(fail bool) ?string {
fn test_option(fail bool) !string {
if fail {
return error('false')
}

View File

@ -12,17 +12,17 @@ Details: vlib/v/checker/tests/option_propagate_nested.vv:9:14: details: prepend
| ~~~~~~
10 | s := ret(raise()?)
11 | return s
vlib/v/checker/tests/option_propagate_nested.vv:28:21: error: to propagate the option call, `aa_propagate` must return an option
vlib/v/checker/tests/option_propagate_nested.vv:28:21: error: to propagate the result call, `aa_propagate` must return a result
26 |
27 | fn (mut s St) aa_propagate() {
28 | f := retf(s.raise()?)
28 | f := retf(s.raise()!)
| ^
29 | s.z = 7.5
30 | println(f)
Details: vlib/v/checker/tests/option_propagate_nested.vv:27:30: details: prepend ? before the declaration of the return type of `aa_propagate`
Details: vlib/v/checker/tests/option_propagate_nested.vv:27:30: details: prepend ! before the declaration of the return type of `aa_propagate`
25 | }
26 |
27 | fn (mut s St) aa_propagate() {
| ^
28 | f := retf(s.raise()?)
29 | s.z = 7.5
28 | f := retf(s.raise()!)
29 | s.z = 7.5

View File

@ -16,7 +16,7 @@ mut:
z f64
}
fn (mut s St) raise() ?f64 {
fn (mut s St) raise() !f64 {
return error('some error')
}
@ -25,7 +25,7 @@ fn retf(f f64) f64 {
}
fn (mut s St) aa_propagate() {
f := retf(s.raise()?)
f := retf(s.raise()!)
s.z = 7.5
println(f)
}

View File

@ -1,4 +1,4 @@
fn abc() ?int {
fn abc() !int {
return error('oh no')
}

View File

@ -7,7 +7,7 @@ fn (mut t Test) zz_exit() {
exit(0)
}
fn option() ?int {
fn option() !int {
return error('oh no')
}

View File

@ -1,4 +1,4 @@
fn return_err() ?int {
fn return_err() !int {
return error('')
}

View File

@ -49,7 +49,7 @@ pub enum Platform {
}
// copy of pref.os_from_string
pub fn platform_from_string(platform_str string) ?Platform {
pub fn platform_from_string(platform_str string) !Platform {
match platform_str {
'all', 'cross' { return .cross }
'linux' { return .linux }
@ -177,7 +177,7 @@ pub fn new(input_path string) Doc {
// stmt reads the data of an `ast.Stmt` node and returns a `DocNode`.
// An option error is thrown if the symbol is not exposed to the public
// (when `pub_only` is enabled) or the content's of the AST node is empty.
pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) ?DocNode {
pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) !DocNode {
mut name := d.stmt_name(stmt)
if name in d.common_symbols {
return error('already documented')
@ -421,7 +421,7 @@ pub fn (mut d Doc) file_ast_with_pos(file_ast ast.File, pos int) map[string]DocN
// generate is a `Doc` method that will start documentation
// process based on a file path provided.
pub fn (mut d Doc) generate() ? {
pub fn (mut d Doc) generate() ! {
// get all files
d.base_path = if os.is_dir(d.base_path) {
d.base_path
@ -451,7 +451,7 @@ pub fn (mut d Doc) generate() ? {
// file_asts has the same function as the `file_ast` function but
// accepts an array of `ast.File` and throws an error if necessary.
pub fn (mut d Doc) file_asts(file_asts []ast.File) ? {
pub fn (mut d Doc) file_asts(file_asts []ast.File) ! {
mut fname_has_set := false
d.orig_mod_name = file_asts[0].mod.name
for i, file_ast in file_asts {
@ -506,7 +506,7 @@ pub fn (mut d Doc) file_asts(file_asts []ast.File) ? {
// generate documents a certain file directory and returns an
// instance of `Doc` if it is successful. Otherwise, it will throw an error.
pub fn generate(input_path string, pub_only bool, with_comments bool, platform Platform, filter_symbol_names ...string) ?Doc {
pub fn generate(input_path string, pub_only bool, with_comments bool, platform Platform, filter_symbol_names ...string) !Doc {
if platform == .js {
return error('vdoc: Platform `${platform}` is not supported.')
}
@ -519,19 +519,19 @@ pub fn generate(input_path string, pub_only bool, with_comments bool, platform P
} else {
unsafe { pref.OS(int(platform)) }
}
doc.generate()?
doc.generate()!
return doc
}
// generate_with_pos has the same function as the `generate` function but
// accepts an offset-based position and enables the comments by default.
pub fn generate_with_pos(input_path string, filename string, pos int) ?Doc {
pub fn generate_with_pos(input_path string, filename string, pos int) !Doc {
mut doc := new(input_path)
doc.pub_only = false
doc.with_comments = true
doc.with_pos = true
doc.filename = filename
doc.pos = pos
doc.generate()?
doc.generate()!
return doc
}

View File

@ -13,7 +13,7 @@ import v.pref
// Note: calling this is expensive, so keep the result, instead of recomputing it.
// TODO: turn this to a Doc method, so that the new_vdoc_preferences call here can
// be removed.
fn get_parent_mod(input_dir string) ?string {
fn get_parent_mod(input_dir string) !string {
// windows root path is C: or D:
if input_dir.len == 2 && input_dir[1] == `:` {
return error('root folder reached')
@ -56,7 +56,7 @@ fn get_parent_mod(input_dir string) ?string {
// lookup_module_with_path looks up the path of a given module name.
// Throws an error if the module was not found.
pub fn lookup_module_with_path(mod string, base_path string) ?string {
pub fn lookup_module_with_path(mod string, base_path string) !string {
vexe := pref.vexe_path()
vroot := os.dir(vexe)
mod_path := mod.replace('.', os.path_separator)
@ -79,12 +79,12 @@ pub fn lookup_module_with_path(mod string, base_path string) ?string {
// lookup_module returns the result of the `lookup_module_with_path`
// but with the current directory as the provided base lookup path.
pub fn lookup_module(mod string) ?string {
pub fn lookup_module(mod string) !string {
return lookup_module_with_path(mod, os.dir('.'))
}
// generate_from_mod generates a documentation from a specific module.
pub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) ?Doc {
mod_path := lookup_module(module_name)?
pub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) !Doc {
mod_path := lookup_module(module_name)!
return generate(mod_path, pub_only, with_comments, .auto)
}

View File

@ -1,6 +1,6 @@
module doc
pub fn (nodes []DocNode) find(symname string) ?DocNode {
pub fn (nodes []DocNode) find(symname string) !DocNode {
for node in nodes {
if node.name != symname {
continue

View File

@ -835,7 +835,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
g.writeln('}// \$for')
}
fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) ?string {
fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) !string {
match name {
// platforms/os-es:
'windows' {
@ -991,5 +991,5 @@ fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) ?strin
return error('bad os ifdef name "${name}"') // should never happen, caught in the checker
}
}
return none
return error('none')
}

View File

@ -72,7 +72,7 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) {
tmp_opt = g.new_tmp_var()
cur_line = g.go_before_stmt(0)
g.out.write_string(util.tabs(g.indent))
opt_elem_type := g.typ(ast.string_type.set_flag(.option))
opt_elem_type := g.typ(ast.string_type.set_flag(.result))
g.write('${opt_elem_type} ${tmp_opt} = string_substr_with_check(')
} else {
g.write('string_substr(')
@ -165,7 +165,7 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) {
if gen_or {
if !node.is_option {
g.or_block(tmp_opt, node.or_expr, ast.string_type)
g.or_block(tmp_opt, node.or_expr, ast.string_type.set_flag(.result))
}
g.write('\n${cur_line}*(string*)&${tmp_opt}.data')

View File

@ -34,7 +34,7 @@ struct MainOptions {
args []string
}
fn desc(mod string) ?string {
fn desc(mod string) !string {
options := Options{
only_description: true
}
@ -42,7 +42,7 @@ fn desc(mod string) ?string {
return pc.description
}
pub fn main(args []string) ?&Main {
pub fn main(args []string) !&Main {
mut fp := flag.new_flag_parser(args)
fp.application('pkgconfig')
fp.version(version)
@ -72,7 +72,7 @@ pub fn main(args []string) ?&Main {
return m
}
pub fn (mut m Main) run() ?string {
pub fn (mut m Main) run() !string {
options := Options{
debug: m.opt.debug
}
@ -94,7 +94,7 @@ pub fn (mut m Main) run() ?string {
res += pcdep.description
}
if unsafe { pc != 0 } {
pc.extend(pcdep)?
pc.extend(pcdep)!
} else {
pc = pcdep
}

View File

@ -140,7 +140,7 @@ fn (mut pc PkgConfig) parse(file string) bool {
return true
}
fn (mut pc PkgConfig) resolve(pkgname string) ?string {
fn (mut pc PkgConfig) resolve(pkgname string) !string {
if pkgname.ends_with('.pc') {
if os.exists(pkgname) {
return pkgname
@ -171,7 +171,7 @@ pub fn (mut pc PkgConfig) atleast(v string) bool {
return v0.gt(v1)
}
pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) ?string {
pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) !string {
for flag in pcdep.cflags {
if pc.cflags.index(flag) == -1 {
pc.cflags << flag
@ -187,19 +187,19 @@ pub fn (mut pc PkgConfig) extend(pcdep &PkgConfig) ?string {
pc.libs_private << lib
}
}
return none
return error('')
}
fn (mut pc PkgConfig) load_requires() ? {
fn (mut pc PkgConfig) load_requires() ! {
for dep in pc.requires {
pc.load_require(dep)?
pc.load_require(dep)!
}
for dep in pc.requires_private {
pc.load_require(dep)?
pc.load_require(dep)!
}
}
fn (mut pc PkgConfig) load_require(dep string) ? {
fn (mut pc PkgConfig) load_require(dep string) ! {
if dep in pc.loaded {
return
}
@ -218,9 +218,9 @@ fn (mut pc PkgConfig) load_require(dep string) ? {
return error('required file "${depfile}" could not be parsed')
}
if !pc.options.norecurse {
pcdep.load_requires()?
pcdep.load_requires()!
}
pc.extend(pcdep)?
pc.extend(pcdep) or {}
}
fn (mut pc PkgConfig) add_path(path string) {
@ -267,7 +267,7 @@ fn (mut pc PkgConfig) load_paths() {
}
}
pub fn load(pkgname string, options Options) ?&PkgConfig {
pub fn load(pkgname string, options Options) !&PkgConfig {
mut pc := &PkgConfig{
modname: pkgname
options: options
@ -278,7 +278,7 @@ pub fn load(pkgname string, options Options) ?&PkgConfig {
return error('file "${file}" could not be parsed')
}
if !options.norecurse {
pc.load_requires()?
pc.load_requires()!
}
return pc
}

View File

@ -48,5 +48,5 @@ fn test_propagation() {
x := get_propagate(s, 2) or { '${err}' }
y := get_propagate(s, 5) or { '${err}' }
assert x == 'got `c`'
assert y == 'string index out of range'
assert y == 'none'
}