Merge pull request #592 from seletskiy/show-backtrace-on-error

Show backtrace on error in the scratch buffer.
This commit is contained in:
Holger Rapp 2015-10-22 07:45:51 +02:00
commit 1ce44ac9c8
4 changed files with 130 additions and 3 deletions

View File

@ -6,6 +6,7 @@
import re
import vim
import textwrap
from UltiSnips import _vim
from UltiSnips.compatibility import as_unicode
@ -116,7 +117,31 @@ class SnippetDefinition(object):
snip = SnippetUtilForAction(locals)
exec(code, {'snip': snip})
try:
exec(code, {'snip': snip})
except Exception as e:
e.snippet_info = textwrap.dedent("""
Defined in: {}
Trigger: {}
Description: {}
Context: {}
Pre-expand: {}
Post-expand: {}
""").format(
self._location,
self._trigger,
self._description,
self._context_code if self._context_code else '<none>',
self._actions['pre_expand'] if 'pre_expand' in self._actions
else '<none>',
self._actions['post_expand'] if 'post_expand' in self._actions
else '<none>',
code,
)
e.snippet_code = code
raise
return snip

View File

@ -8,7 +8,9 @@ from functools import wraps
import os
import platform
import traceback
import sys
import vim
import re
from contextlib import contextmanager
from UltiSnips import _vim
@ -57,7 +59,7 @@ def err_to_scratch_buffer(func):
def wrapper(self, *args, **kwds):
try:
return func(self, *args, **kwds)
except: # pylint: disable=bare-except
except Exception as e: # pylint: disable=bare-except
msg = \
"""An error occured. This is either a bug in UltiSnips or a bug in a
snippet definition. If you think this is a bug, please report it to
@ -65,7 +67,28 @@ https://github.com/SirVer/ultisnips/issues/new.
Following is the full stack trace:
"""
msg += traceback.format_exc()
if hasattr(e, 'snippet_info'):
msg += "\nSnippet, caused error:\n"
msg += re.sub(
'^(?=\S)', ' ', e.snippet_info, flags=re.MULTILINE
)
# snippet_code comes from _python_code.py, it's set manually for
# providing error message with stacktrace of failed python code
# inside of the snippet.
if hasattr(e, 'snippet_code'):
_, _, tb = sys.exc_info()
tb_top = traceback.extract_tb(tb)[-1]
msg += "\nExecuted snippet code:\n"
lines = e.snippet_code.split("\n")
for number, line in enumerate(lines, 1):
msg += str(number).rjust(3)
prefix = " " if line else ""
if tb_top[1] == number:
prefix = " > "
msg += prefix + line + "\n"
# Vim sends no WinLeave msg here.
self._leaving_buffer() # pylint:disable=protected-access
_vim.new_scratch_buffer(msg)

View File

@ -267,7 +267,11 @@ class PythonCode(NoneditableTextObject):
self._snip._reset(ct) # pylint:disable=protected-access
for code in self._codes:
exec(code, self._locals) # pylint:disable=exec-used
try:
exec(code, self._locals) # pylint:disable=exec-used
except Exception as e:
e.snippet_code = code
raise
rv = as_unicode(
self._snip.rv if self._snip._rv_changed # pylint:disable=protected-access

View File

@ -239,3 +239,78 @@ endsnippet
"""}
keys = 'ab' + EX
wanted = 'x first a bob b y'
class ParseSnippets_PrintPythonStacktrace(_VimTest):
files = { 'us/all.snippets': r"""
snippet test
`!p abc()`
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = " > abc"
class ParseSnippets_PrintPythonStacktraceMultiline(_VimTest):
files = { 'us/all.snippets': r"""
snippet test
`!p if True:
qwe()`
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = " > \s+qwe"
class ParseSnippets_PrintErroneousSnippet(_VimTest):
files = { 'us/all.snippets': r"""
snippet test "asd()" e
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = "Trigger: test"
class ParseSnippets_PrintErroneousSnippetContext(_VimTest):
files = { 'us/all.snippets': r"""
snippet test "asd()" e
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = "Context: asd"
class ParseSnippets_PrintErroneousSnippetPreAction(_VimTest):
files = { 'us/all.snippets': r"""
pre_expand "asd()"
snippet test
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = "Pre-expand: asd"
class ParseSnippets_PrintErroneousSnippetPostAction(_VimTest):
files = { 'us/all.snippets': r"""
post_expand "asd()"
snippet test
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = "Post-expand: asd"
class ParseSnippets_PrintErroneousSnippetLocation(_VimTest):
files = { 'us/all.snippets': r"""
post_expand "asd()"
snippet test
endsnippet
"""}
keys = 'test' + EX
wanted = keys
expected_error = "Defined in: .*/all.snippets"