1
1
import asyncio
2
+ import logging
2
3
import threading
3
4
from threading import Event
4
5
from typing import Any , ClassVar , Final , List , Optional , Set , Union
15
16
InitializeParamsClientInfoType ,
16
17
InitializeResult ,
17
18
InitializeResultServerInfoType ,
19
+ LogMessageParams ,
20
+ LogTraceParams ,
21
+ MessageType ,
18
22
PositionEncodingKind ,
19
23
ProgressToken ,
20
24
Registration ,
29
33
UnregistrationParams ,
30
34
WorkspaceFolder ,
31
35
)
32
- from robotcode .core .utils .logging import LoggingDescriptor
36
+ from robotcode .core .utils .logging import TRACE , LoggingDescriptor
33
37
from robotcode .core .utils .process import pid_exists
34
38
from robotcode .jsonrpc2 .protocol import (
35
39
JsonRPCErrorException ,
36
40
JsonRPCErrors ,
37
41
JsonRPCException ,
42
+ JsonRPCMessage ,
38
43
JsonRPCProtocol ,
39
44
ProtocolPartDescriptor ,
40
45
rpc_method ,
@@ -74,6 +79,34 @@ class LanguageServerException(JsonRPCException):
74
79
pass
75
80
76
81
82
+ class LanguageServerLogHandler (logging .Handler ):
83
+ MAPPING = {
84
+ logging .INFO : MessageType .INFO ,
85
+ logging .WARNING : MessageType .WARNING ,
86
+ logging .ERROR : MessageType .ERROR ,
87
+ TRACE : MessageType .LOG ,
88
+ }
89
+
90
+ def __init__ (self , protocol : "LanguageServerProtocol" ):
91
+ super ().__init__ ()
92
+ self .protocol = protocol
93
+ self .trace : TraceValues = TraceValues .OFF
94
+
95
+ def emit (self , record : logging .LogRecord ) -> None :
96
+ if record .levelno == TRACE :
97
+ if self .trace != TraceValues .OFF :
98
+ self .protocol .log_trace (record .getMessage ())
99
+
100
+ type = self .MAPPING .get (record .levelno , None )
101
+ if type is None :
102
+ type = MessageType .LOG
103
+
104
+ self .protocol .window_log_message (
105
+ type = type ,
106
+ message = record .getMessage (),
107
+ )
108
+
109
+
77
110
class LanguageServerProtocol (JsonRPCProtocol ):
78
111
__logger = LoggingDescriptor ()
79
112
@@ -131,8 +164,13 @@ def __init__(self, server: JsonRPCServer[Any]):
131
164
)
132
165
133
166
self ._trace = TraceValues .OFF
167
+ self ._trace_loghandler : Optional [LanguageServerLogHandler ] = None
168
+
134
169
self .is_initialized = Event ()
135
170
171
+ def __del__ (self ) -> None :
172
+ self .trace = TraceValues .OFF
173
+
136
174
@event
137
175
def on_shutdown (sender ) -> None : # pragma: no cover, NOSONAR
138
176
...
@@ -149,6 +187,9 @@ def trace(self) -> TraceValues:
149
187
def trace (self , value : TraceValues ) -> None :
150
188
self ._trace = value
151
189
190
+ if self ._trace_loghandler :
191
+ self ._trace_loghandler .trace = value
192
+
152
193
@property
153
194
def workspace (self ) -> Workspace :
154
195
if self ._workspace is None :
@@ -210,7 +251,14 @@ def _initialize(
210
251
if self .parent_process_id and pid_exists (self .parent_process_id ):
211
252
self .start_parent_process_watcher ()
212
253
254
+ logger = logging .getLogger ()
255
+
256
+ if self ._trace_loghandler is None :
257
+ self ._trace_loghandler = LanguageServerLogHandler (self )
258
+ logger .addHandler (self ._trace_loghandler )
259
+
213
260
self .trace = trace or TraceValues .OFF
261
+
214
262
self .client_info = client_info
215
263
216
264
self .client_capabilities = capabilities
@@ -292,6 +340,13 @@ def _shutdown(self, *args: Any, **kwargs: Any) -> None:
292
340
293
341
self .shutdown_received = True
294
342
343
+ logger = logging .getLogger ()
344
+
345
+ if self ._trace_loghandler in logger .handlers :
346
+ logging .getLogger ().removeHandler (self ._trace_loghandler )
347
+ del self ._trace_loghandler
348
+ self ._trace_loghandler = None
349
+
295
350
try :
296
351
self .cancel_all_received_request ()
297
352
except BaseException as e :
@@ -311,6 +366,16 @@ def _exit(self, *args: Any, **kwargs: Any) -> None:
311
366
def _set_trace (self , value : TraceValues , * args : Any , ** kwargs : Any ) -> None :
312
367
self .trace = value
313
368
369
+ def window_log_message (self , type : MessageType , message : str ) -> None :
370
+ self .send_notification ("window/logMessage" , LogMessageParams (type = type , message = message ))
371
+
372
+ def log_trace (self , message : str , verbose : Optional [str ] = None ) -> None :
373
+ self .send_notification ("$/logTrace" , LogTraceParams (message = message , verbose = verbose ))
374
+
375
+ def _do_trace_message (self , message : JsonRPCMessage , msg : bytes ) -> None :
376
+ if getattr (message , "method" , None ) not in ["$/logTrace" , "window/logMessage" ]:
377
+ self ._data_logger .trace (lambda : f"JSON send: { msg .decode ()!r} " )
378
+
314
379
@rpc_method (name = "$/cancelRequest" , param_type = CancelParams )
315
380
@__logger .call
316
381
def _cancel_request (self , id : Union [int , str ], ** kwargs : Any ) -> None :
0 commit comments