jaclang 0.0.5__py3-none-any.whl → 0.0.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (94) hide show
  1. jaclang/__init__.py +2 -1
  2. jaclang/cli/__jac_gen__/__init__.py +0 -0
  3. jaclang/cli/__jac_gen__/cli.py +175 -0
  4. jaclang/cli/__jac_gen__/cmds.py +132 -0
  5. jaclang/cli/cli.jac +2 -2
  6. jaclang/cli/cmds.jac +8 -2
  7. jaclang/cli/impl/__jac_gen__/__init__.py +0 -0
  8. jaclang/cli/impl/__jac_gen__/cli_impl.py +16 -0
  9. jaclang/cli/impl/__jac_gen__/cmds_impl.py +26 -0
  10. jaclang/cli/impl/cli_impl.jac +25 -8
  11. jaclang/cli/impl/cmds_impl.jac +35 -6
  12. jaclang/core/__jac_gen__/__init__.py +0 -0
  13. jaclang/core/__jac_gen__/primitives.py +567 -0
  14. jaclang/core/impl/__jac_gen__/__init__.py +0 -0
  15. jaclang/core/impl/__jac_gen__/arch_impl.py +24 -0
  16. jaclang/core/impl/__jac_gen__/element_impl.py +26 -0
  17. jaclang/core/impl/__jac_gen__/exec_ctx_impl.py +12 -0
  18. jaclang/core/impl/__jac_gen__/memory_impl.py +14 -0
  19. jaclang/core/impl/element_impl.jac +3 -3
  20. jaclang/core/impl/exec_ctx_impl.jac +3 -6
  21. jaclang/core/primitives.jac +4 -3
  22. jaclang/jac/absyntree.py +555 -180
  23. jaclang/jac/constant.py +6 -0
  24. jaclang/jac/importer.py +34 -56
  25. jaclang/jac/langserve.py +26 -0
  26. jaclang/jac/lexer.py +35 -3
  27. jaclang/jac/parser.py +146 -115
  28. jaclang/jac/passes/blue/__init__.py +8 -3
  29. jaclang/jac/passes/blue/ast_build_pass.py +454 -305
  30. jaclang/jac/passes/blue/blue_pygen_pass.py +112 -74
  31. jaclang/jac/passes/blue/decl_def_match_pass.py +49 -277
  32. jaclang/jac/passes/blue/import_pass.py +1 -1
  33. jaclang/jac/passes/blue/pyout_pass.py +74 -0
  34. jaclang/jac/passes/blue/semantic_check_pass.py +37 -0
  35. jaclang/jac/passes/blue/sym_tab_build_pass.py +1045 -0
  36. jaclang/jac/passes/blue/tests/test_ast_build_pass.py +2 -2
  37. jaclang/jac/passes/blue/tests/test_blue_pygen_pass.py +9 -28
  38. jaclang/jac/passes/blue/tests/test_decl_def_match_pass.py +13 -22
  39. jaclang/jac/passes/blue/tests/test_sym_tab_build_pass.py +22 -0
  40. jaclang/jac/passes/ir_pass.py +8 -6
  41. jaclang/jac/passes/purple/__jac_gen__/__init__.py +0 -0
  42. jaclang/jac/passes/purple/__jac_gen__/analyze_pass.py +37 -0
  43. jaclang/jac/passes/purple/__jac_gen__/purple_pygen_pass.py +305 -0
  44. jaclang/jac/passes/purple/impl/__jac_gen__/__init__.py +0 -0
  45. jaclang/jac/passes/purple/impl/__jac_gen__/purple_pygen_pass_impl.py +23 -0
  46. jaclang/jac/passes/purple/impl/purple_pygen_pass_impl.jac +2 -5
  47. jaclang/jac/symtable.py +154 -0
  48. jaclang/jac/tests/fixtures/__jac_gen__/__init__.py +0 -0
  49. jaclang/jac/tests/fixtures/__jac_gen__/hello_world.py +16 -0
  50. jaclang/jac/tests/fixtures/fam.jac +7 -8
  51. jaclang/jac/tests/fixtures/mod_doc_test.jac +1 -0
  52. jaclang/jac/tests/test_parser.py +8 -0
  53. jaclang/jac/transform.py +41 -14
  54. jaclang/jac/transpiler.py +18 -9
  55. jaclang/utils/fstring_parser.py +2 -2
  56. jaclang/utils/helpers.py +41 -0
  57. jaclang/utils/lang_tools.py +12 -2
  58. jaclang/utils/test.py +41 -0
  59. jaclang/vendor/__init__.py +1 -0
  60. jaclang/vendor/pygls/__init__.py +25 -0
  61. jaclang/vendor/pygls/capabilities.py +502 -0
  62. jaclang/vendor/pygls/client.py +176 -0
  63. jaclang/vendor/pygls/constants.py +26 -0
  64. jaclang/vendor/pygls/exceptions.py +220 -0
  65. jaclang/vendor/pygls/feature_manager.py +241 -0
  66. jaclang/vendor/pygls/lsp/__init__.py +139 -0
  67. jaclang/vendor/pygls/lsp/client.py +2224 -0
  68. jaclang/vendor/pygls/lsprotocol/__init__.py +2 -0
  69. jaclang/vendor/pygls/lsprotocol/_hooks.py +1233 -0
  70. jaclang/vendor/pygls/lsprotocol/converters.py +17 -0
  71. jaclang/vendor/pygls/lsprotocol/types.py +12820 -0
  72. jaclang/vendor/pygls/lsprotocol/validators.py +47 -0
  73. jaclang/vendor/pygls/progress.py +79 -0
  74. jaclang/vendor/pygls/protocol.py +1184 -0
  75. jaclang/vendor/pygls/server.py +620 -0
  76. jaclang/vendor/pygls/uris.py +184 -0
  77. jaclang/vendor/pygls/workspace/__init__.py +81 -0
  78. jaclang/vendor/pygls/workspace/position.py +204 -0
  79. jaclang/vendor/pygls/workspace/text_document.py +234 -0
  80. jaclang/vendor/pygls/workspace/workspace.py +311 -0
  81. {jaclang-0.0.5.dist-info → jaclang-0.0.8.dist-info}/METADATA +1 -1
  82. jaclang-0.0.8.dist-info/RECORD +118 -0
  83. jaclang/core/jaclang.jac +0 -62
  84. jaclang/jac/passes/blue/tests/test_type_analyze_pass.py +0 -53
  85. jaclang/jac/passes/blue/type_analyze_pass.py +0 -728
  86. jaclang/jac/sym_table.py +0 -127
  87. jaclang-0.0.5.dist-info/RECORD +0 -73
  88. /jaclang/{utils → vendor}/sly/__init__.py +0 -0
  89. /jaclang/{utils → vendor}/sly/docparse.py +0 -0
  90. /jaclang/{utils → vendor}/sly/lex.py +0 -0
  91. /jaclang/{utils → vendor}/sly/yacc.py +0 -0
  92. {jaclang-0.0.5.dist-info → jaclang-0.0.8.dist-info}/WHEEL +0 -0
  93. {jaclang-0.0.5.dist-info → jaclang-0.0.8.dist-info}/entry_points.txt +0 -0
  94. {jaclang-0.0.5.dist-info → jaclang-0.0.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,620 @@
1
+ ############################################################################
2
+ # Copyright(c) Open Law Library. All rights reserved. #
3
+ # See ThirdPartyNotices.txt in the project root for additional notices. #
4
+ # #
5
+ # Licensed under the Apache License, Version 2.0 (the "License") #
6
+ # you may not use this file except in compliance with the License. #
7
+ # You may obtain a copy of the License at #
8
+ # #
9
+ # http: // www.apache.org/licenses/LICENSE-2.0 #
10
+ # #
11
+ # Unless required by applicable law or agreed to in writing, software #
12
+ # distributed under the License is distributed on an "AS IS" BASIS, #
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14
+ # See the License for the specific language governing permissions and #
15
+ # limitations under the License. #
16
+ ############################################################################
17
+ import asyncio
18
+ import json
19
+ import logging
20
+ import re
21
+ import sys
22
+ from concurrent.futures import Future, ThreadPoolExecutor
23
+ from threading import Event
24
+ from typing import (
25
+ Any,
26
+ Callable,
27
+ List,
28
+ Optional,
29
+ TextIO,
30
+ Type,
31
+ TypeVar,
32
+ Union,
33
+ )
34
+
35
+ import cattrs
36
+ from jaclang.vendor.pygls import IS_PYODIDE
37
+ from jaclang.vendor.pygls.lsp import ConfigCallbackType, ShowDocumentCallbackType
38
+ from jaclang.vendor.pygls.exceptions import (
39
+ FeatureNotificationError,
40
+ JsonRpcInternalError,
41
+ PyglsError,
42
+ JsonRpcException,
43
+ FeatureRequestError,
44
+ )
45
+ from jaclang.vendor.pygls.lsprotocol.types import (
46
+ ClientCapabilities,
47
+ Diagnostic,
48
+ MessageType,
49
+ NotebookDocumentSyncOptions,
50
+ RegistrationParams,
51
+ ServerCapabilities,
52
+ ShowDocumentParams,
53
+ TextDocumentSyncKind,
54
+ UnregistrationParams,
55
+ WorkspaceApplyEditResponse,
56
+ WorkspaceEdit,
57
+ WorkspaceConfigurationParams,
58
+ )
59
+ from jaclang.vendor.pygls.progress import Progress
60
+ from jaclang.vendor.pygls.protocol import (
61
+ JsonRPCProtocol,
62
+ LanguageServerProtocol,
63
+ default_converter,
64
+ )
65
+ from jaclang.vendor.pygls.workspace import Workspace
66
+
67
+ if not IS_PYODIDE:
68
+ from multiprocessing.pool import ThreadPool
69
+
70
+
71
+ logger = logging.getLogger(__name__)
72
+
73
+ F = TypeVar("F", bound=Callable)
74
+
75
+ ServerErrors = Union[
76
+ PyglsError,
77
+ JsonRpcException,
78
+ Type[JsonRpcInternalError],
79
+ Type[FeatureNotificationError],
80
+ Type[FeatureRequestError],
81
+ ]
82
+
83
+
84
+ async def aio_readline(loop, executor, stop_event, rfile, proxy):
85
+ """Reads data from stdin in separate thread (asynchronously)."""
86
+
87
+ CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$")
88
+
89
+ # Initialize message buffer
90
+ message = []
91
+ content_length = 0
92
+
93
+ while not stop_event.is_set() and not rfile.closed:
94
+ # Read a header line
95
+ header = await loop.run_in_executor(executor, rfile.readline)
96
+ if not header:
97
+ break
98
+ message.append(header)
99
+
100
+ # Extract content length if possible
101
+ if not content_length:
102
+ match = CONTENT_LENGTH_PATTERN.fullmatch(header)
103
+ if match:
104
+ content_length = int(match.group(1))
105
+ logger.debug("Content length: %s", content_length)
106
+
107
+ # Check if all headers have been read (as indicated by an empty line \r\n)
108
+ if content_length and not header.strip():
109
+ # Read body
110
+ body = await loop.run_in_executor(executor, rfile.read, content_length)
111
+ if not body:
112
+ break
113
+ message.append(body)
114
+
115
+ # Pass message to language server protocol
116
+ proxy(b"".join(message))
117
+
118
+ # Reset the buffer
119
+ message = []
120
+ content_length = 0
121
+
122
+
123
+ class StdOutTransportAdapter:
124
+ """Protocol adapter which overrides write method.
125
+
126
+ Write method sends data to stdout.
127
+ """
128
+
129
+ def __init__(self, rfile, wfile):
130
+ self.rfile = rfile
131
+ self.wfile = wfile
132
+
133
+ def close(self):
134
+ self.rfile.close()
135
+ self.wfile.close()
136
+
137
+ def write(self, data):
138
+ self.wfile.write(data)
139
+ self.wfile.flush()
140
+
141
+
142
+ class PyodideTransportAdapter:
143
+ """Protocol adapter which overrides write method.
144
+
145
+ Write method sends data to stdout.
146
+ """
147
+
148
+ def __init__(self, wfile):
149
+ self.wfile = wfile
150
+
151
+ def close(self):
152
+ self.wfile.close()
153
+
154
+ def write(self, data):
155
+ self.wfile.write(data)
156
+ self.wfile.flush()
157
+
158
+
159
+ class WebSocketTransportAdapter:
160
+ """Protocol adapter which calls write method.
161
+
162
+ Write method sends data via the WebSocket interface.
163
+ """
164
+
165
+ def __init__(self, ws, loop):
166
+ self._ws = ws
167
+ self._loop = loop
168
+
169
+ def close(self) -> None:
170
+ """Stop the WebSocket server."""
171
+ self._ws.close()
172
+
173
+ def write(self, data: Any) -> None:
174
+ """Create a task to write specified data into a WebSocket."""
175
+ asyncio.ensure_future(self._ws.send(data))
176
+
177
+
178
+ class Server:
179
+ """Base server class
180
+
181
+ Parameters
182
+ ----------
183
+ protocol_cls
184
+ Protocol implementation that must be derive from :class:`~pygls.protocol.JsonRPCProtocol`
185
+
186
+ converter_factory
187
+ Factory function to use when constructing a cattrs converter.
188
+
189
+ loop
190
+ The asyncio event loop
191
+
192
+ max_workers
193
+ Maximum number of workers for `ThreadPool` and `ThreadPoolExecutor`
194
+
195
+ """
196
+
197
+ def __init__(
198
+ self,
199
+ protocol_cls: Type[JsonRPCProtocol],
200
+ converter_factory: Callable[[], cattrs.Converter],
201
+ loop: Optional[asyncio.AbstractEventLoop] = None,
202
+ max_workers: int = 2,
203
+ sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
204
+ ):
205
+ if not issubclass(protocol_cls, asyncio.Protocol):
206
+ raise TypeError("Protocol class should be subclass of asyncio.Protocol")
207
+
208
+ self._max_workers = max_workers
209
+ self._server = None
210
+ self._stop_event: Optional[Event] = None
211
+ self._thread_pool: Optional[ThreadPool] = None
212
+ self._thread_pool_executor: Optional[ThreadPoolExecutor] = None
213
+
214
+ if sync_kind is not None:
215
+ self.text_document_sync_kind = sync_kind
216
+
217
+ if loop is None:
218
+ loop = asyncio.new_event_loop()
219
+ asyncio.set_event_loop(loop)
220
+ self._owns_loop = True
221
+ else:
222
+ self._owns_loop = False
223
+
224
+ self.loop = loop
225
+
226
+ # TODO: Will move this to `LanguageServer` soon
227
+ self.lsp = protocol_cls(self, converter_factory()) # type: ignore
228
+
229
+ def shutdown(self):
230
+ """Shutdown server."""
231
+ logger.info("Shutting down the server")
232
+
233
+ if self._stop_event is not None:
234
+ self._stop_event.set()
235
+
236
+ if self._thread_pool:
237
+ self._thread_pool.terminate()
238
+ self._thread_pool.join()
239
+
240
+ if self._thread_pool_executor:
241
+ self._thread_pool_executor.shutdown()
242
+
243
+ if self._server:
244
+ self._server.close()
245
+ self.loop.run_until_complete(self._server.wait_closed())
246
+
247
+ if self._owns_loop and not self.loop.is_closed():
248
+ logger.info("Closing the event loop.")
249
+ self.loop.close()
250
+
251
+ def start_io(self, stdin: Optional[TextIO] = None, stdout: Optional[TextIO] = None):
252
+ """Starts IO server."""
253
+ logger.info("Starting IO server")
254
+
255
+ self._stop_event = Event()
256
+ transport = StdOutTransportAdapter(
257
+ stdin or sys.stdin.buffer, stdout or sys.stdout.buffer
258
+ )
259
+ self.lsp.connection_made(transport) # type: ignore[arg-type]
260
+
261
+ try:
262
+ self.loop.run_until_complete(
263
+ aio_readline(
264
+ self.loop,
265
+ self.thread_pool_executor,
266
+ self._stop_event,
267
+ stdin or sys.stdin.buffer,
268
+ self.lsp.data_received,
269
+ )
270
+ )
271
+ except BrokenPipeError:
272
+ logger.error("Connection to the client is lost! Shutting down the server.")
273
+ except (KeyboardInterrupt, SystemExit):
274
+ pass
275
+ finally:
276
+ self.shutdown()
277
+
278
+ def start_pyodide(self):
279
+ logger.info("Starting Pyodide server")
280
+
281
+ # Note: We don't actually start anything running as the main event
282
+ # loop will be handled by the web platform.
283
+ transport = PyodideTransportAdapter(sys.stdout)
284
+ self.lsp.connection_made(transport) # type: ignore[arg-type]
285
+ self.lsp._send_only_body = True # Don't send headers within the payload
286
+
287
+ def start_tcp(self, host: str, port: int) -> None:
288
+ """Starts TCP server."""
289
+ logger.info("Starting TCP server on %s:%s", host, port)
290
+
291
+ self._stop_event = Event()
292
+ self._server = self.loop.run_until_complete( # type: ignore[assignment]
293
+ self.loop.create_server(self.lsp, host, port)
294
+ )
295
+ try:
296
+ self.loop.run_forever()
297
+ except (KeyboardInterrupt, SystemExit):
298
+ pass
299
+ finally:
300
+ self.shutdown()
301
+
302
+ def start_ws(self, host: str, port: int) -> None:
303
+ """Starts WebSocket server."""
304
+ try:
305
+ from websockets.server import serve
306
+ except ImportError:
307
+ logger.error("Run `pip install pygls[ws]` to install `websockets`.")
308
+ sys.exit(1)
309
+
310
+ logger.info("Starting WebSocket server on {}:{}".format(host, port))
311
+
312
+ self._stop_event = Event()
313
+ self.lsp._send_only_body = True # Don't send headers within the payload
314
+
315
+ async def connection_made(websocket, _):
316
+ """Handle new connection wrapped in the WebSocket."""
317
+ self.lsp.transport = WebSocketTransportAdapter(websocket, self.loop)
318
+ async for message in websocket:
319
+ self.lsp._procedure_handler(
320
+ json.loads(message, object_hook=self.lsp._deserialize_message)
321
+ )
322
+
323
+ start_server = serve(connection_made, host, port, loop=self.loop)
324
+ self._server = start_server.ws_server # type: ignore[assignment]
325
+ self.loop.run_until_complete(start_server)
326
+
327
+ try:
328
+ self.loop.run_forever()
329
+ except (KeyboardInterrupt, SystemExit):
330
+ pass
331
+ finally:
332
+ self._stop_event.set()
333
+ self.shutdown()
334
+
335
+ if not IS_PYODIDE:
336
+
337
+ @property
338
+ def thread_pool(self) -> ThreadPool:
339
+ """Returns thread pool instance (lazy initialization)."""
340
+ if not self._thread_pool:
341
+ self._thread_pool = ThreadPool(processes=self._max_workers)
342
+
343
+ return self._thread_pool
344
+
345
+ @property
346
+ def thread_pool_executor(self) -> ThreadPoolExecutor:
347
+ """Returns thread pool instance (lazy initialization)."""
348
+ if not self._thread_pool_executor:
349
+ self._thread_pool_executor = ThreadPoolExecutor(
350
+ max_workers=self._max_workers
351
+ )
352
+
353
+ return self._thread_pool_executor
354
+
355
+
356
+ class LanguageServer(Server):
357
+ """The default LanguageServer
358
+
359
+ This class can be extended and it can be passed as a first argument to
360
+ registered commands/features.
361
+
362
+ .. |ServerInfo| replace:: :class:`~lsprotocol.types.InitializeResultServerInfoType`
363
+
364
+ Parameters
365
+ ----------
366
+ name
367
+ Name of the server, used to populate |ServerInfo| which is sent to
368
+ the client during initialization
369
+
370
+ version
371
+ Version of the server, used to populate |ServerInfo| which is sent to
372
+ the client during initialization
373
+
374
+ protocol_cls
375
+ The :class:`~pygls.protocol.LanguageServerProtocol` class definition, or any
376
+ subclass of it.
377
+
378
+ max_workers
379
+ Maximum number of workers for ``ThreadPool`` and ``ThreadPoolExecutor``
380
+
381
+ text_document_sync_kind
382
+ Text document synchronization method
383
+
384
+ None
385
+ No synchronization
386
+
387
+ :attr:`~lsprotocol.types.TextDocumentSyncKind.Full`
388
+ Send entire document text with each update
389
+
390
+ :attr:`~lsprotocol.types.TextDocumentSyncKind.Incremental`
391
+ Send only the region of text that changed with each update
392
+
393
+ notebook_document_sync
394
+ Advertise :lsp:`NotebookDocument` support to the client.
395
+ """
396
+
397
+ lsp: LanguageServerProtocol
398
+
399
+ default_error_message = (
400
+ "Unexpected error in LSP server, see server's logs for details"
401
+ )
402
+ """
403
+ The default error message sent to the user's editor when this server encounters an uncaught
404
+ exception.
405
+ """
406
+
407
+ def __init__(
408
+ self,
409
+ name: str,
410
+ version: str,
411
+ loop=None,
412
+ protocol_cls: Type[LanguageServerProtocol] = LanguageServerProtocol,
413
+ converter_factory=default_converter,
414
+ text_document_sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
415
+ notebook_document_sync: Optional[NotebookDocumentSyncOptions] = None,
416
+ max_workers: int = 2,
417
+ ):
418
+ if not issubclass(protocol_cls, LanguageServerProtocol):
419
+ raise TypeError(
420
+ "Protocol class should be subclass of LanguageServerProtocol"
421
+ )
422
+
423
+ self.name = name
424
+ self.version = version
425
+ self._text_document_sync_kind = text_document_sync_kind
426
+ self._notebook_document_sync = notebook_document_sync
427
+ self.process_id: Optional[Union[int, None]] = None
428
+ super().__init__(protocol_cls, converter_factory, loop, max_workers)
429
+
430
+ def apply_edit(
431
+ self, edit: WorkspaceEdit, label: Optional[str] = None
432
+ ) -> WorkspaceApplyEditResponse:
433
+ """Sends apply edit request to the client."""
434
+ return self.lsp.apply_edit(edit, label)
435
+
436
+ def apply_edit_async(
437
+ self, edit: WorkspaceEdit, label: Optional[str] = None
438
+ ) -> WorkspaceApplyEditResponse:
439
+ """Sends apply edit request to the client. Should be called with `await`"""
440
+ return self.lsp.apply_edit_async(edit, label)
441
+
442
+ def command(self, command_name: str) -> Callable[[F], F]:
443
+ """Decorator used to register custom commands.
444
+
445
+ Example
446
+ -------
447
+ ::
448
+
449
+ @ls.command('myCustomCommand')
450
+ def my_cmd(ls, a, b, c):
451
+ pass
452
+ """
453
+ return self.lsp.fm.command(command_name)
454
+
455
+ @property
456
+ def client_capabilities(self) -> ClientCapabilities:
457
+ """The client's capabilities."""
458
+ return self.lsp.client_capabilities
459
+
460
+ def feature(
461
+ self,
462
+ feature_name: str,
463
+ options: Optional[Any] = None,
464
+ ) -> Callable[[F], F]:
465
+ """Decorator used to register LSP features.
466
+
467
+ Example
468
+ -------
469
+ ::
470
+
471
+ @ls.feature('textDocument/completion', CompletionOptions(trigger_characters=['.']))
472
+ def completions(ls, params: CompletionParams):
473
+ return CompletionList(is_incomplete=False, items=[CompletionItem("Completion 1")])
474
+ """
475
+ return self.lsp.fm.feature(feature_name, options)
476
+
477
+ def get_configuration(
478
+ self,
479
+ params: WorkspaceConfigurationParams,
480
+ callback: Optional[ConfigCallbackType] = None,
481
+ ) -> Future:
482
+ """Gets the configuration settings from the client."""
483
+ return self.lsp.get_configuration(params, callback)
484
+
485
+ def get_configuration_async(
486
+ self, params: WorkspaceConfigurationParams
487
+ ) -> asyncio.Future:
488
+ """Gets the configuration settings from the client. Should be called with `await`"""
489
+ return self.lsp.get_configuration_async(params)
490
+
491
+ def log_trace(self, message: str, verbose: Optional[str] = None) -> None:
492
+ """Sends trace notification to the client."""
493
+ self.lsp.log_trace(message, verbose)
494
+
495
+ @property
496
+ def progress(self) -> Progress:
497
+ """Gets the object to manage client's progress bar."""
498
+ return self.lsp.progress
499
+
500
+ def publish_diagnostics(
501
+ self,
502
+ uri: str,
503
+ diagnostics: Optional[List[Diagnostic]] = None,
504
+ version: Optional[int] = None,
505
+ **kwargs
506
+ ):
507
+ """
508
+ Sends diagnostic notification to the client.
509
+ """
510
+ params = self.lsp._construct_publish_diagnostic_type(
511
+ uri, diagnostics, version, **kwargs
512
+ )
513
+ self.lsp.publish_diagnostics(params, **kwargs)
514
+
515
+ def register_capability(
516
+ self, params: RegistrationParams, callback: Optional[Callable[[], None]] = None
517
+ ) -> Future:
518
+ """Register a new capability on the client."""
519
+ return self.lsp.register_capability(params, callback)
520
+
521
+ def register_capability_async(self, params: RegistrationParams) -> asyncio.Future:
522
+ """Register a new capability on the client. Should be called with `await`"""
523
+ return self.lsp.register_capability_async(params)
524
+
525
+ def semantic_tokens_refresh(
526
+ self, callback: Optional[Callable[[], None]] = None
527
+ ) -> Future:
528
+ """Request a refresh of all semantic tokens."""
529
+ return self.lsp.semantic_tokens_refresh(callback)
530
+
531
+ def semantic_tokens_refresh_async(self) -> asyncio.Future:
532
+ """Request a refresh of all semantic tokens. Should be called with `await`"""
533
+ return self.lsp.semantic_tokens_refresh_async()
534
+
535
+ def send_notification(self, method: str, params: object = None) -> None:
536
+ """Sends notification to the client."""
537
+ self.lsp.notify(method, params)
538
+
539
+ @property
540
+ def server_capabilities(self) -> ServerCapabilities:
541
+ """Return server capabilities."""
542
+ return self.lsp.server_capabilities
543
+
544
+ def show_document(
545
+ self,
546
+ params: ShowDocumentParams,
547
+ callback: Optional[ShowDocumentCallbackType] = None,
548
+ ) -> Future:
549
+ """Display a particular document in the user interface."""
550
+ return self.lsp.show_document(params, callback)
551
+
552
+ def show_document_async(self, params: ShowDocumentParams) -> asyncio.Future:
553
+ """Display a particular document in the user interface. Should be called with `await`"""
554
+ return self.lsp.show_document_async(params)
555
+
556
+ def show_message(self, message, msg_type=MessageType.Info) -> None:
557
+ """Sends message to the client to display message."""
558
+ self.lsp.show_message(message, msg_type)
559
+
560
+ def show_message_log(self, message, msg_type=MessageType.Log) -> None:
561
+ """Sends message to the client's output channel."""
562
+ self.lsp.show_message_log(message, msg_type)
563
+
564
+ def _report_server_error(
565
+ self,
566
+ error: Exception,
567
+ source: ServerErrors,
568
+ ):
569
+ # Prevent recursive error reporting
570
+ try:
571
+ self.report_server_error(error, source)
572
+ except Exception:
573
+ logger.warning("Failed to report error to client")
574
+
575
+ def report_server_error(self, error: Exception, source: ServerErrors):
576
+ """
577
+ Sends error to the client for displaying.
578
+
579
+ By default this fucntion does not handle LSP request errors. This is because LSP requests
580
+ require direct responses and so already have a mechanism for including unexpected errors
581
+ in the response body.
582
+
583
+ All other errors are "out of band" in the sense that the client isn't explicitly waiting
584
+ for them. For example diagnostics are returned as notifications, not responses to requests,
585
+ and so can seemingly be sent at random. Also for example consider JSON RPC serialization
586
+ and deserialization, if a payload cannot be parsed then the whole request/response cycle
587
+ cannot be completed and so one of these "out of band" error messages is sent.
588
+
589
+ These "out of band" error messages are not a requirement of the LSP spec. Pygls simply
590
+ offers this behaviour as a recommended default. It is perfectly reasonble to override this
591
+ default.
592
+ """
593
+
594
+ if source == FeatureRequestError:
595
+ return
596
+
597
+ self.show_message(self.default_error_message, msg_type=MessageType.Error)
598
+
599
+ def thread(self) -> Callable[[F], F]:
600
+ """Decorator that mark function to execute it in a thread."""
601
+ return self.lsp.thread()
602
+
603
+ def unregister_capability(
604
+ self,
605
+ params: UnregistrationParams,
606
+ callback: Optional[Callable[[], None]] = None,
607
+ ) -> Future:
608
+ """Unregister a new capability on the client."""
609
+ return self.lsp.unregister_capability(params, callback)
610
+
611
+ def unregister_capability_async(
612
+ self, params: UnregistrationParams
613
+ ) -> asyncio.Future:
614
+ """Unregister a new capability on the client. Should be called with `await`"""
615
+ return self.lsp.unregister_capability_async(params)
616
+
617
+ @property
618
+ def workspace(self) -> Workspace:
619
+ """Returns in-memory workspace."""
620
+ return self.lsp.workspace