changeset 14437:ceb9b6bf0f4a v8.1.0232

patch 8.1.0232: Ruby error does not include backtrace commit https://github.com/vim/vim/commit/f711cb2f12458d32e082c0e3d4103e2b072947c3 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 1 18:42:13 2018 +0200 patch 8.1.0232: Ruby error does not include backtrace Problem: Ruby error does not include backtrace. Solution: Add an error backtrace. (Masataka Pocke Kuwabara, closes https://github.com/vim/vim/issues/3267)
author Christian Brabandt <cb@256bit.org>
date Wed, 01 Aug 2018 18:45:05 +0200
parents c5b4768f5224
children af83b1cb4702
files src/if_ruby.c src/version.c
diffstat 2 files changed, 56 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -93,6 +93,11 @@
 # define RUBY20_OR_LATER 1
 #endif
 
+#if (defined(RUBY_VERSION) && RUBY_VERSION >= 21) \
+    || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 21)
+# define RUBY21_OR_LATER 1
+#endif
+
 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
 /* Ruby 1.9 defines a number of static functions which use rb_num2long and
  * rb_int2big */
@@ -238,11 +243,21 @@ static void ruby_vim_init(void);
 # define rb_eRuntimeError		(*dll_rb_eRuntimeError)
 # define rb_eStandardError		(*dll_rb_eStandardError)
 # define rb_eval_string_protect		dll_rb_eval_string_protect
+# ifdef RUBY21_OR_LATER
+#  define rb_funcallv			dll_rb_funcallv
+# else
+#  define rb_funcall2			dll_rb_funcall2
+# endif
 # define rb_global_variable		dll_rb_global_variable
 # define rb_hash_aset			dll_rb_hash_aset
 # define rb_hash_new			dll_rb_hash_new
 # define rb_inspect			dll_rb_inspect
 # define rb_int2inum			dll_rb_int2inum
+# ifdef RUBY19_OR_LATER
+#  define rb_intern2			dll_rb_intern2
+# else
+#  define rb_intern			dll_rb_intern
+# endif
 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18
 #   define rb_fix2int			dll_rb_fix2int
@@ -367,11 +382,21 @@ static VALUE *dll_rb_eIndexError;
 static VALUE *dll_rb_eRuntimeError;
 static VALUE *dll_rb_eStandardError;
 static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
+# ifdef RUBY21_OR_LATER
+static VALUE (*dll_rb_funcallv) (VALUE, ID, int, const VALUE*);
+# else
+static VALUE (*dll_rb_funcall2) (VALUE, ID, int, const VALUE*);
+# endif
 static void (*dll_rb_global_variable) (VALUE*);
 static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
 static VALUE (*dll_rb_hash_new) (void);
 static VALUE (*dll_rb_inspect) (VALUE);
 static VALUE (*dll_rb_int2inum) (long);
+# ifdef RUBY19_OR_LATER
+static ID (*dll_rb_intern2) (const char*, long);
+# else
+static ID (*dll_rb_intern) (const char*);
+# endif
 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
 static long (*dll_rb_fix2int) (VALUE);
 static long (*dll_rb_num2int) (VALUE);
@@ -561,11 +586,21 @@ static struct
     {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
     {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
     {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
+# ifdef RUBY21_OR_LATER
+    {"rb_funcallv", (RUBY_PROC*)&dll_rb_funcallv},
+# else
+    {"rb_funcall2", (RUBY_PROC*)&dll_rb_funcall2},
+# endif
     {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
     {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
     {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
     {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
     {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
+# ifdef RUBY19_OR_LATER
+    {"rb_intern2", (RUBY_PROC*)&dll_rb_intern2},
+# else
+    {"rb_intern", (RUBY_PROC*)&dll_rb_intern},
+# endif
 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
     {"rb_fix2int", (RUBY_PROC*)&dll_rb_fix2int},
     {"rb_num2int", (RUBY_PROC*)&dll_rb_num2int},
@@ -926,9 +961,13 @@ static void error_print(int state)
     RUBYEXTERN VALUE ruby_errinfo;
 #endif
 #endif
+    VALUE error;
     VALUE eclass;
     VALUE einfo;
+    VALUE bt;
+    int attr;
     char buff[BUFSIZ];
+    long i;
 
 #define TAG_RETURN	0x1
 #define TAG_BREAK	0x2
@@ -960,12 +999,12 @@ static void error_print(int state)
     case TAG_RAISE:
     case TAG_FATAL:
 #ifdef RUBY19_OR_LATER
-	eclass = CLASS_OF(rb_errinfo());
-	einfo = rb_obj_as_string(rb_errinfo());
+	error = rb_errinfo();
 #else
-	eclass = CLASS_OF(ruby_errinfo);
-	einfo = rb_obj_as_string(ruby_errinfo);
+	error = ruby_errinfo;
 #endif
+	eclass = CLASS_OF(error);
+	einfo = rb_obj_as_string(error);
 	if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0)
 	{
 	    EMSG(_("E272: unhandled exception"));
@@ -982,6 +1021,17 @@ static void error_print(int state)
 	    if (p) *p = '\0';
 	    EMSG(buff);
 	}
+
+	attr = syn_name2attr((char_u *)"Error");
+# ifdef RUBY21_OR_LATER
+	bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
+	for (i = 0; i < RARRAY_LEN(bt); i++)
+	    msg_attr((char_u *)RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
+# else
+	bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0);
+	for (i = 0; i < RARRAY_LEN(bt); i++)
+	    msg_attr((char_u *)RSTRING_PTR(RARRAY_PTR(bt)[i]), attr);
+# endif
 	break;
     default:
 	vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    232,
+/**/
     231,
 /**/
     230,