diff options
author | zeertzjq <zeertzjq@outlook.com> | 2025-01-03 20:12:15 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2025-01-07 09:15:10 +0800 |
commit | d5308637bf1aac2b97fccf73a0ffdef304eaa1d6 (patch) | |
tree | acb03c837290a225f1fcb7f73b4ae1306d1e7589 /src/nvim/runtime.c | |
parent | 06ff5480ce274daf3b7ad9950a587099200dc8ff (diff) | |
download | rneovim-d5308637bf1aac2b97fccf73a0ffdef304eaa1d6.tar.gz rneovim-d5308637bf1aac2b97fccf73a0ffdef304eaa1d6.tar.bz2 rneovim-d5308637bf1aac2b97fccf73a0ffdef304eaa1d6.zip |
vim-patch:9.1.0984: exception handling can be improved
Problem: exception handling can be improved
Solution: add v:stacktrace and getstacktrace()
closes: vim/vim#16360
https://github.com/vim/vim/commit/663d18d6102f40d14e36096ec590445e61026ed6
Co-authored-by: ichizok <gclient.gaap@gmail.com>
Co-authored-by: Naruhiko Nishino <naru123456789@gmail.com>
Diffstat (limited to 'src/nvim/runtime.c')
-rw-r--r-- | src/nvim/runtime.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index d849a18879..cdedf86977 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -228,6 +228,72 @@ char *estack_sfile(estack_arg_T which) return (char *)ga.ga_data; } +static void stacktrace_push_item(list_T *const l, ufunc_T *const fp, const char *const event, + const linenr_T lnum, char *const filepath, + const bool filepath_alloced) +{ + dict_T *const d = tv_dict_alloc_lock(VAR_FIXED); + typval_T tv = { + .v_type = VAR_DICT, + .v_lock = VAR_LOCKED, + .vval.v_dict = d, + }; + + if (fp != NULL) { + tv_dict_add_func(d, S_LEN("funcref"), fp); + } + if (event != NULL) { + tv_dict_add_str(d, S_LEN("event"), event); + } + tv_dict_add_nr(d, S_LEN("lnum"), lnum); + if (filepath_alloced) { + tv_dict_add_allocated_str(d, S_LEN("filepath"), filepath); + } else { + tv_dict_add_str(d, S_LEN("filepath"), filepath); + } + + tv_list_append_tv(l, &tv); +} + +/// Create the stacktrace from exestack. +list_T *stacktrace_create(void) +{ + list_T *const l = tv_list_alloc(exestack.ga_len); + + for (int i = 0; i < exestack.ga_len; i++) { + estack_T *const entry = &((estack_T *)exestack.ga_data)[i]; + linenr_T lnum = entry->es_lnum; + + if (entry->es_type == ETYPE_SCRIPT) { + stacktrace_push_item(l, NULL, NULL, lnum, entry->es_name, false); + } else if (entry->es_type == ETYPE_UFUNC) { + ufunc_T *const fp = entry->es_info.ufunc; + const sctx_T sctx = fp->uf_script_ctx; + bool filepath_alloced = false; + char *filepath = sctx.sc_sid > 0 + ? get_scriptname((LastSet){ .script_ctx = sctx }, + &filepath_alloced) : ""; + lnum += sctx.sc_lnum; + stacktrace_push_item(l, fp, NULL, lnum, filepath, filepath_alloced); + } else if (entry->es_type == ETYPE_AUCMD) { + const sctx_T sctx = entry->es_info.aucmd->script_ctx; + bool filepath_alloced = false; + char *filepath = sctx.sc_sid > 0 + ? get_scriptname((LastSet){ .script_ctx = sctx }, + &filepath_alloced) : ""; + lnum += sctx.sc_lnum; + stacktrace_push_item(l, NULL, entry->es_name, lnum, filepath, filepath_alloced); + } + } + return l; +} + +/// getstacktrace() function +void f_getstacktrace(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_set_ret(rettv, stacktrace_create()); +} + static bool runtime_search_path_valid = false; static int *runtime_search_path_ref = NULL; static RuntimeSearchPath runtime_search_path; |