5
5
import logging
6
6
import os
7
7
import os .path
8
+ import re
8
9
9
10
from traceback import format_exc
10
11
11
12
from ..api import DecodeHook
12
13
from ..compat import IS_PYTHON3 , find_module
14
+ from ..msgpack_rpc import ErrorResponse
13
15
14
16
__all__ = ('Host' )
15
17
@@ -31,6 +33,7 @@ def __init__(self, nvim):
31
33
self .nvim = nvim
32
34
self ._specs = {}
33
35
self ._loaded = {}
36
+ self ._load_errors = {}
34
37
self ._notification_handlers = {}
35
38
self ._request_handlers = {
36
39
'poll' : lambda : 'ok' ,
@@ -58,9 +61,9 @@ def _on_request(self, name, args):
58
61
name = name .decode (self ._nvim_encoding )
59
62
handler = self ._request_handlers .get (name , None )
60
63
if not handler :
61
- msg = 'no request handler registered for "%s"' % name
62
- warn (msg )
63
- raise Exception (msg )
64
+ msg = self . _missing_handler_error ( name , ' request' )
65
+ error (msg )
66
+ raise ErrorResponse (msg )
64
67
65
68
debug ('calling request handler for "%s", args: "%s"' , name , args )
66
69
rv = handler (* args )
@@ -73,7 +76,9 @@ def _on_notification(self, name, args):
73
76
name = name .decode (self ._nvim_encoding )
74
77
handler = self ._notification_handlers .get (name , None )
75
78
if not handler :
76
- warn ('no notification handler registered for "%s"' , name )
79
+ msg = self ._missing_handler_error (name , 'notification' )
80
+ error (msg )
81
+ self .nvim .err_write (msg + "\n " )
77
82
return
78
83
79
84
debug ('calling notification handler for "%s", args: "%s"' , name , args )
@@ -85,8 +90,18 @@ def _on_notification(self, name, args):
85
90
self .nvim .err_write (msg , async = True )
86
91
raise
87
92
93
+ def _missing_handler_error (self , name , kind ):
94
+ msg = 'no {} handler registered for "{}"' .format (kind , name )
95
+ pathmatch = re .match (r'(.+):[^:]+:[^:]+' , name )
96
+ if pathmatch :
97
+ loader_error = self ._load_errors .get (pathmatch .group (1 ))
98
+ if loader_error is not None :
99
+ msg = msg + "\n " + loader_error
100
+ return msg
101
+
88
102
def _load (self , plugins ):
89
103
for path in plugins :
104
+ err = None
90
105
if path in self ._loaded :
91
106
error ('{0} is already loaded' .format (path ))
92
107
continue
@@ -105,12 +120,11 @@ def _load(self, plugins):
105
120
error ('{0} exports no handlers' .format (path ))
106
121
continue
107
122
self ._loaded [path ] = {'handlers' : handlers , 'module' : module }
108
- except (ImportError , SyntaxError ) as e :
109
- error (('Encountered import error loading '
110
- 'plugin at {0}: {1}' ).format (path , e ))
111
123
except Exception as e :
112
- error ('Error loading plugin at {0} {1}: {2}' .format (
113
- path , type (e ).__name__ , e ))
124
+ err = ('Encountered {} loading plugin at {}: {}\n {}'
125
+ .format (type (e ).__name__ , path , e , format_exc (5 )))
126
+ error (err )
127
+ self ._load_errors [path ] = err
114
128
115
129
def _unload (self ):
116
130
for path , plugin in self ._loaded .items ():
@@ -183,6 +197,8 @@ def _copy_attributes(self, fn, fn2):
183
197
def _on_specs_request (self , path ):
184
198
if IS_PYTHON3 and isinstance (path , bytes ):
185
199
path = path .decode (self ._nvim_encoding )
200
+ if path in self ._load_errors :
201
+ self .nvim .out_write (self ._load_errors [path ] + '\n ' )
186
202
return self ._specs .get (path , 0 )
187
203
188
204
def _decodehook_for (self , encoding ):
0 commit comments