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,502 @@
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
+ from functools import reduce
18
+ from typing import Any, Dict, List, Optional, Set, Union
19
+ import logging
20
+
21
+ from jaclang.vendor.pygls.lsprotocol.types import (
22
+ INLAY_HINT_RESOLVE,
23
+ TEXT_DOCUMENT_CODE_ACTION,
24
+ TEXT_DOCUMENT_CODE_LENS,
25
+ TEXT_DOCUMENT_COMPLETION,
26
+ TEXT_DOCUMENT_DECLARATION,
27
+ TEXT_DOCUMENT_DEFINITION,
28
+ TEXT_DOCUMENT_DIAGNOSTIC,
29
+ TEXT_DOCUMENT_DOCUMENT_COLOR,
30
+ TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT,
31
+ TEXT_DOCUMENT_DOCUMENT_LINK,
32
+ TEXT_DOCUMENT_DOCUMENT_SYMBOL,
33
+ TEXT_DOCUMENT_FOLDING_RANGE,
34
+ TEXT_DOCUMENT_FORMATTING,
35
+ TEXT_DOCUMENT_HOVER,
36
+ TEXT_DOCUMENT_IMPLEMENTATION,
37
+ TEXT_DOCUMENT_INLAY_HINT,
38
+ TEXT_DOCUMENT_INLINE_VALUE,
39
+ TEXT_DOCUMENT_ON_TYPE_FORMATTING,
40
+ TEXT_DOCUMENT_RANGE_FORMATTING,
41
+ TEXT_DOCUMENT_REFERENCES,
42
+ TEXT_DOCUMENT_RENAME,
43
+ TEXT_DOCUMENT_SELECTION_RANGE,
44
+ TEXT_DOCUMENT_SIGNATURE_HELP,
45
+ TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY,
46
+ TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY,
47
+ TEXT_DOCUMENT_DID_CLOSE,
48
+ TEXT_DOCUMENT_DID_OPEN,
49
+ TEXT_DOCUMENT_DID_SAVE,
50
+ TEXT_DOCUMENT_LINKED_EDITING_RANGE,
51
+ TEXT_DOCUMENT_MONIKER,
52
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
53
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA,
54
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE,
55
+ TEXT_DOCUMENT_WILL_SAVE,
56
+ TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL,
57
+ TEXT_DOCUMENT_TYPE_DEFINITION,
58
+ WORKSPACE_DIAGNOSTIC,
59
+ WORKSPACE_DID_CREATE_FILES,
60
+ WORKSPACE_DID_DELETE_FILES,
61
+ WORKSPACE_DID_RENAME_FILES,
62
+ WORKSPACE_SYMBOL,
63
+ WORKSPACE_SYMBOL_RESOLVE,
64
+ WORKSPACE_WILL_CREATE_FILES,
65
+ WORKSPACE_WILL_DELETE_FILES,
66
+ WORKSPACE_WILL_RENAME_FILES,
67
+ InlayHintOptions,
68
+ PositionEncodingKind,
69
+ )
70
+ from jaclang.vendor.pygls.lsprotocol.types import (
71
+ ClientCapabilities,
72
+ CodeLensOptions,
73
+ CompletionOptions,
74
+ DocumentLinkOptions,
75
+ ExecuteCommandOptions,
76
+ ImplementationOptions,
77
+ NotebookDocumentSyncOptions,
78
+ SemanticTokensOptions,
79
+ SemanticTokensRegistrationOptions,
80
+ SemanticTokensOptionsFullType1,
81
+ ServerCapabilities,
82
+ ServerCapabilitiesWorkspaceType,
83
+ SignatureHelpOptions,
84
+ TextDocumentSyncKind,
85
+ TextDocumentSyncOptions,
86
+ TypeDefinitionOptions,
87
+ FileOperationOptions,
88
+ WorkspaceFoldersServerCapabilities,
89
+ )
90
+
91
+ logger = logging.getLogger(__name__)
92
+
93
+
94
+ def get_capability(
95
+ client_capabilities: ClientCapabilities, field: str, default: Any = None
96
+ ) -> Any:
97
+ """Check if ClientCapabilities has some nested value without raising
98
+ AttributeError.
99
+ e.g. get_capability('text_document.synchronization.will_save')
100
+ """
101
+ try:
102
+ value = reduce(getattr, field.split("."), client_capabilities)
103
+ except AttributeError:
104
+ return default
105
+
106
+ # If we reach the desired leaf value but it's None, return the default.
107
+ return default if value is None else value
108
+
109
+
110
+ class ServerCapabilitiesBuilder:
111
+ """Create `ServerCapabilities` instance depending on builtin and user registered
112
+ features.
113
+ """
114
+
115
+ def __init__(
116
+ self,
117
+ client_capabilities: ClientCapabilities,
118
+ features: Set[str],
119
+ feature_options: Dict[str, Any],
120
+ commands: List[str],
121
+ text_document_sync_kind: TextDocumentSyncKind,
122
+ notebook_document_sync: Optional[NotebookDocumentSyncOptions] = None,
123
+ ):
124
+ self.client_capabilities = client_capabilities
125
+ self.features = features
126
+ self.feature_options = feature_options
127
+ self.commands = commands
128
+ self.text_document_sync_kind = text_document_sync_kind
129
+ self.notebook_document_sync = notebook_document_sync
130
+
131
+ self.server_cap = ServerCapabilities()
132
+
133
+ def _provider_options(self, feature, default=True):
134
+ if feature in self.features:
135
+ return self.feature_options.get(feature, default)
136
+ return None
137
+
138
+ def _with_text_document_sync(self):
139
+ open_close = (
140
+ TEXT_DOCUMENT_DID_OPEN in self.features
141
+ or TEXT_DOCUMENT_DID_CLOSE in self.features
142
+ )
143
+ will_save = (
144
+ get_capability(
145
+ self.client_capabilities, "text_document.synchronization.will_save"
146
+ )
147
+ and TEXT_DOCUMENT_WILL_SAVE in self.features
148
+ )
149
+ will_save_wait_until = (
150
+ get_capability(
151
+ self.client_capabilities,
152
+ "text_document.synchronization.will_save_wait_until",
153
+ )
154
+ and TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL in self.features
155
+ )
156
+ if TEXT_DOCUMENT_DID_SAVE in self.features:
157
+ save = self.feature_options.get(TEXT_DOCUMENT_DID_SAVE, True)
158
+ else:
159
+ save = False
160
+
161
+ self.server_cap.text_document_sync = TextDocumentSyncOptions(
162
+ open_close=open_close,
163
+ change=self.text_document_sync_kind,
164
+ will_save=will_save,
165
+ will_save_wait_until=will_save_wait_until,
166
+ save=save,
167
+ )
168
+
169
+ return self
170
+
171
+ def _with_notebook_document_sync(self):
172
+ if self.client_capabilities.notebook_document is None:
173
+ return self
174
+
175
+ self.server_cap.notebook_document_sync = self.notebook_document_sync
176
+ return self
177
+
178
+ def _with_completion(self):
179
+ value = self._provider_options(
180
+ TEXT_DOCUMENT_COMPLETION, default=CompletionOptions()
181
+ )
182
+ if value is not None:
183
+ self.server_cap.completion_provider = value
184
+ return self
185
+
186
+ def _with_hover(self):
187
+ value = self._provider_options(TEXT_DOCUMENT_HOVER)
188
+ if value is not None:
189
+ self.server_cap.hover_provider = value
190
+ return self
191
+
192
+ def _with_signature_help(self):
193
+ value = self._provider_options(
194
+ TEXT_DOCUMENT_SIGNATURE_HELP, default=SignatureHelpOptions()
195
+ )
196
+ if value is not None:
197
+ self.server_cap.signature_help_provider = value
198
+ return self
199
+
200
+ def _with_declaration(self):
201
+ value = self._provider_options(TEXT_DOCUMENT_DECLARATION)
202
+ if value is not None:
203
+ self.server_cap.declaration_provider = value
204
+ return self
205
+
206
+ def _with_definition(self):
207
+ value = self._provider_options(TEXT_DOCUMENT_DEFINITION)
208
+ if value is not None:
209
+ self.server_cap.definition_provider = value
210
+ return self
211
+
212
+ def _with_type_definition(self):
213
+ value = self._provider_options(
214
+ TEXT_DOCUMENT_TYPE_DEFINITION, default=TypeDefinitionOptions()
215
+ )
216
+ if value is not None:
217
+ self.server_cap.type_definition_provider = value
218
+ return self
219
+
220
+ def _with_inlay_hints(self):
221
+ value = self._provider_options(
222
+ TEXT_DOCUMENT_INLAY_HINT, default=InlayHintOptions()
223
+ )
224
+ if value is not None:
225
+ value.resolve_provider = INLAY_HINT_RESOLVE in self.features
226
+ self.server_cap.inlay_hint_provider = value
227
+ return self
228
+
229
+ def _with_implementation(self):
230
+ value = self._provider_options(
231
+ TEXT_DOCUMENT_IMPLEMENTATION, default=ImplementationOptions()
232
+ )
233
+ if value is not None:
234
+ self.server_cap.implementation_provider = value
235
+ return self
236
+
237
+ def _with_references(self):
238
+ value = self._provider_options(TEXT_DOCUMENT_REFERENCES)
239
+ if value is not None:
240
+ self.server_cap.references_provider = value
241
+ return self
242
+
243
+ def _with_document_highlight(self):
244
+ value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT)
245
+ if value is not None:
246
+ self.server_cap.document_highlight_provider = value
247
+ return self
248
+
249
+ def _with_document_symbol(self):
250
+ value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_SYMBOL)
251
+ if value is not None:
252
+ self.server_cap.document_symbol_provider = value
253
+ return self
254
+
255
+ def _with_code_action(self):
256
+ value = self._provider_options(TEXT_DOCUMENT_CODE_ACTION)
257
+ if value is not None:
258
+ self.server_cap.code_action_provider = value
259
+ return self
260
+
261
+ def _with_code_lens(self):
262
+ value = self._provider_options(
263
+ TEXT_DOCUMENT_CODE_LENS, default=CodeLensOptions()
264
+ )
265
+ if value is not None:
266
+ self.server_cap.code_lens_provider = value
267
+ return self
268
+
269
+ def _with_document_link(self):
270
+ value = self._provider_options(
271
+ TEXT_DOCUMENT_DOCUMENT_LINK, default=DocumentLinkOptions()
272
+ )
273
+ if value is not None:
274
+ self.server_cap.document_link_provider = value
275
+ return self
276
+
277
+ def _with_color(self):
278
+ value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_COLOR)
279
+ if value is not None:
280
+ self.server_cap.color_provider = value
281
+ return self
282
+
283
+ def _with_document_formatting(self):
284
+ value = self._provider_options(TEXT_DOCUMENT_FORMATTING)
285
+ if value is not None:
286
+ self.server_cap.document_formatting_provider = value
287
+ return self
288
+
289
+ def _with_document_range_formatting(self):
290
+ value = self._provider_options(TEXT_DOCUMENT_RANGE_FORMATTING)
291
+ if value is not None:
292
+ self.server_cap.document_range_formatting_provider = value
293
+ return self
294
+
295
+ def _with_document_on_type_formatting(self):
296
+ value = self._provider_options(TEXT_DOCUMENT_ON_TYPE_FORMATTING)
297
+ if value is not None:
298
+ self.server_cap.document_on_type_formatting_provider = value
299
+ return self
300
+
301
+ def _with_rename(self):
302
+ value = self._provider_options(TEXT_DOCUMENT_RENAME)
303
+ if value is not None:
304
+ self.server_cap.rename_provider = value
305
+ return self
306
+
307
+ def _with_folding_range(self):
308
+ value = self._provider_options(TEXT_DOCUMENT_FOLDING_RANGE)
309
+ if value is not None:
310
+ self.server_cap.folding_range_provider = value
311
+ return self
312
+
313
+ def _with_execute_command(self):
314
+ self.server_cap.execute_command_provider = ExecuteCommandOptions(
315
+ commands=self.commands
316
+ )
317
+ return self
318
+
319
+ def _with_selection_range(self):
320
+ value = self._provider_options(TEXT_DOCUMENT_SELECTION_RANGE)
321
+ if value is not None:
322
+ self.server_cap.selection_range_provider = value
323
+ return self
324
+
325
+ def _with_call_hierarchy(self):
326
+ value = self._provider_options(TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY)
327
+ if value is not None:
328
+ self.server_cap.call_hierarchy_provider = value
329
+ return self
330
+
331
+ def _with_type_hierarchy(self):
332
+ value = self._provider_options(TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY)
333
+ if value is not None:
334
+ self.server_cap.type_hierarchy_provider = value
335
+ return self
336
+
337
+ def _with_semantic_tokens(self):
338
+ providers = [
339
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
340
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA,
341
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE,
342
+ ]
343
+
344
+ for provider in providers:
345
+ value = self._provider_options(provider, None)
346
+ if value:
347
+ break
348
+
349
+ if value is None:
350
+ return self
351
+
352
+ if isinstance(value, SemanticTokensRegistrationOptions):
353
+ self.server_cap.semantic_tokens_provider = value
354
+ return self
355
+
356
+ full_support: Union[bool, SemanticTokensOptionsFullType1] = (
357
+ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL in self.features
358
+ )
359
+
360
+ if TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA in self.features:
361
+ full_support = SemanticTokensOptionsFullType1(delta=True)
362
+
363
+ options = SemanticTokensOptions(
364
+ legend=value,
365
+ full=full_support or None,
366
+ range=TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE in self.features or None,
367
+ )
368
+
369
+ if options.full or options.range:
370
+ self.server_cap.semantic_tokens_provider = options
371
+
372
+ return self
373
+
374
+ def _with_linked_editing_range(self):
375
+ value = self._provider_options(TEXT_DOCUMENT_LINKED_EDITING_RANGE)
376
+ if value is not None:
377
+ self.server_cap.linked_editing_range_provider = value
378
+ return self
379
+
380
+ def _with_moniker(self):
381
+ value = self._provider_options(TEXT_DOCUMENT_MONIKER)
382
+ if value is not None:
383
+ self.server_cap.moniker_provider = value
384
+ return self
385
+
386
+ def _with_workspace_symbol(self):
387
+ value = self._provider_options(WORKSPACE_SYMBOL)
388
+ if value is not None:
389
+ value.resolve_provider = self._provider_options(WORKSPACE_SYMBOL_RESOLVE)
390
+ self.server_cap.workspace_symbol_provider = value
391
+ return self
392
+
393
+ def _with_workspace_capabilities(self):
394
+ # File operations
395
+ file_operations = FileOperationOptions()
396
+ operations = [
397
+ (WORKSPACE_WILL_CREATE_FILES, "will_create"),
398
+ (WORKSPACE_DID_CREATE_FILES, "did_create"),
399
+ (WORKSPACE_WILL_DELETE_FILES, "will_delete"),
400
+ (WORKSPACE_DID_DELETE_FILES, "did_delete"),
401
+ (WORKSPACE_WILL_RENAME_FILES, "will_rename"),
402
+ (WORKSPACE_DID_RENAME_FILES, "did_rename"),
403
+ ]
404
+
405
+ for method_name, capability_name in operations:
406
+ client_supports_method = get_capability(
407
+ self.client_capabilities, f"workspace.file_operations.{capability_name}"
408
+ )
409
+
410
+ if client_supports_method:
411
+ value = self._provider_options(method_name, None)
412
+ setattr(file_operations, capability_name, value)
413
+
414
+ self.server_cap.workspace = ServerCapabilitiesWorkspaceType(
415
+ workspace_folders=WorkspaceFoldersServerCapabilities(
416
+ supported=True,
417
+ change_notifications=True,
418
+ ),
419
+ file_operations=file_operations,
420
+ )
421
+ return self
422
+
423
+ def _with_diagnostic_provider(self):
424
+ value = self._provider_options(TEXT_DOCUMENT_DIAGNOSTIC)
425
+ if value is not None:
426
+ value.workspace_diagnostics = self._provider_options(WORKSPACE_DIAGNOSTIC)
427
+ self.server_cap.diagnostic_provider = value
428
+ return self
429
+
430
+ def _with_inline_value_provider(self):
431
+ value = self._provider_options(TEXT_DOCUMENT_INLINE_VALUE)
432
+ if value is not None:
433
+ self.server_cap.inline_value_provider = value
434
+ return self
435
+
436
+ def _with_position_encodings(self):
437
+ self.server_cap.position_encoding = PositionEncodingKind.Utf16
438
+
439
+ general = self.client_capabilities.general
440
+ if general is None:
441
+ return self
442
+
443
+ encodings = general.position_encodings
444
+ if encodings is None:
445
+ return self
446
+
447
+ if PositionEncodingKind.Utf16 in encodings:
448
+ return self
449
+
450
+ if PositionEncodingKind.Utf32 in encodings:
451
+ self.server_cap.position_encoding = PositionEncodingKind.Utf32
452
+ return self
453
+
454
+ if PositionEncodingKind.Utf8 in encodings:
455
+ self.server_cap.position_encoding = PositionEncodingKind.Utf8
456
+ return self
457
+
458
+ logger.warning(f"Unknown `PositionEncoding`s: {encodings}")
459
+
460
+ return self
461
+
462
+ def _build(self):
463
+ return self.server_cap
464
+
465
+ def build(self):
466
+ return (
467
+ self._with_text_document_sync()
468
+ ._with_notebook_document_sync()
469
+ ._with_completion()
470
+ ._with_hover()
471
+ ._with_signature_help()
472
+ ._with_declaration()
473
+ ._with_definition()
474
+ ._with_type_definition()
475
+ ._with_inlay_hints()
476
+ ._with_implementation()
477
+ ._with_references()
478
+ ._with_document_highlight()
479
+ ._with_document_symbol()
480
+ ._with_code_action()
481
+ ._with_code_lens()
482
+ ._with_document_link()
483
+ ._with_color()
484
+ ._with_document_formatting()
485
+ ._with_document_range_formatting()
486
+ ._with_document_on_type_formatting()
487
+ ._with_rename()
488
+ ._with_folding_range()
489
+ ._with_execute_command()
490
+ ._with_selection_range()
491
+ ._with_call_hierarchy()
492
+ ._with_type_hierarchy()
493
+ ._with_semantic_tokens()
494
+ ._with_linked_editing_range()
495
+ ._with_moniker()
496
+ ._with_workspace_symbol()
497
+ ._with_workspace_capabilities()
498
+ ._with_diagnostic_provider()
499
+ ._with_inline_value_provider()
500
+ ._with_position_encodings()
501
+ ._build()
502
+ )
@@ -0,0 +1,176 @@
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 logging
19
+ import re
20
+ from threading import Event
21
+ from typing import Any
22
+ from typing import Callable
23
+ from typing import List
24
+ from typing import Optional
25
+ from typing import Type
26
+ from typing import Union
27
+
28
+ from cattrs import Converter
29
+
30
+ from jaclang.vendor.pygls.exceptions import PyglsError, JsonRpcException
31
+ from jaclang.vendor.pygls.protocol import JsonRPCProtocol, default_converter
32
+
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ async def aio_readline(stop_event, reader, message_handler):
38
+ CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$")
39
+
40
+ # Initialize message buffer
41
+ message = []
42
+ content_length = 0
43
+
44
+ while not stop_event.is_set():
45
+ # Read a header line
46
+ header = await reader.readline()
47
+ if not header:
48
+ break
49
+ message.append(header)
50
+
51
+ # Extract content length if possible
52
+ if not content_length:
53
+ match = CONTENT_LENGTH_PATTERN.fullmatch(header)
54
+ if match:
55
+ content_length = int(match.group(1))
56
+ logger.debug("Content length: %s", content_length)
57
+
58
+ # Check if all headers have been read (as indicated by an empty line \r\n)
59
+ if content_length and not header.strip():
60
+ # Read body
61
+ body = await reader.readexactly(content_length)
62
+ if not body:
63
+ break
64
+ message.append(body)
65
+
66
+ # Pass message to protocol
67
+ message_handler(b"".join(message))
68
+
69
+ # Reset the buffer
70
+ message = []
71
+ content_length = 0
72
+
73
+
74
+ class JsonRPCClient:
75
+ """Base JSON-RPC client."""
76
+
77
+ def __init__(
78
+ self,
79
+ protocol_cls: Type[JsonRPCProtocol] = JsonRPCProtocol,
80
+ converter_factory: Callable[[], Converter] = default_converter,
81
+ ):
82
+ # Strictly speaking `JsonRPCProtocol` wants a `LanguageServer`, not a
83
+ # `JsonRPCClient`. However there similar enough for our purposes, which is
84
+ # that this client will mostly be used in testing contexts.
85
+ self.protocol = protocol_cls(self, converter_factory()) # type: ignore
86
+
87
+ self._server: Optional[asyncio.subprocess.Process] = None
88
+ self._stop_event = Event()
89
+ self._async_tasks: List[asyncio.Task] = []
90
+
91
+ @property
92
+ def stopped(self) -> bool:
93
+ """Return ``True`` if the client has been stopped."""
94
+ return self._stop_event.is_set()
95
+
96
+ def feature(
97
+ self,
98
+ feature_name: str,
99
+ options: Optional[Any] = None,
100
+ ):
101
+ """Decorator used to register LSP features.
102
+
103
+ Example
104
+ -------
105
+ ::
106
+
107
+ import logging
108
+ from jaclang.vendor.pygls.client import JsonRPCClient
109
+
110
+ ls = JsonRPCClient()
111
+
112
+ @ls.feature('window/logMessage')
113
+ def completions(ls, params):
114
+ logging.info("%s", params.message)
115
+ """
116
+ return self.protocol.fm.feature(feature_name, options)
117
+
118
+ async def start_io(self, cmd: str, *args, **kwargs):
119
+ """Start the given server and communicate with it over stdio."""
120
+
121
+ logger.debug("Starting server process: %s", " ".join([cmd, *args]))
122
+ server = await asyncio.create_subprocess_exec(
123
+ cmd,
124
+ *args,
125
+ stdout=asyncio.subprocess.PIPE,
126
+ stdin=asyncio.subprocess.PIPE,
127
+ stderr=asyncio.subprocess.PIPE,
128
+ **kwargs,
129
+ )
130
+
131
+ self.protocol.connection_made(server.stdin) # type: ignore
132
+ connection = asyncio.create_task(
133
+ aio_readline(self._stop_event, server.stdout, self.protocol.data_received)
134
+ )
135
+ notify_exit = asyncio.create_task(self._server_exit())
136
+
137
+ self._server = server
138
+ self._async_tasks.extend([connection, notify_exit])
139
+
140
+ async def _server_exit(self):
141
+ if self._server is not None:
142
+ await self._server.wait()
143
+ logger.debug(
144
+ "Server process %s exited with return code: %s",
145
+ self._server.pid,
146
+ self._server.returncode,
147
+ )
148
+ await self.server_exit(self._server)
149
+ self._stop_event.set()
150
+
151
+ async def server_exit(self, server: asyncio.subprocess.Process):
152
+ """Called when the server process exits."""
153
+
154
+ def _report_server_error(
155
+ self, error: Exception, source: Union[PyglsError, JsonRpcException]
156
+ ):
157
+ try:
158
+ self.report_server_error(error, source)
159
+ except Exception:
160
+ logger.error("Unable to report error", exc_info=True)
161
+
162
+ def report_server_error(
163
+ self, error: Exception, source: Union[PyglsError, JsonRpcException]
164
+ ):
165
+ """Called when the server does something unexpected e.g. respond with malformed
166
+ JSON."""
167
+
168
+ async def stop(self):
169
+ self._stop_event.set()
170
+
171
+ if self._server is not None and self._server.returncode is None:
172
+ logger.debug("Terminating server process: %s", self._server.pid)
173
+ self._server.terminate()
174
+
175
+ if len(self._async_tasks) > 0:
176
+ await asyncio.gather(*self._async_tasks)
@@ -0,0 +1,26 @@
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
+
18
+ # Dynamically assigned attributes
19
+ ATTR_EXECUTE_IN_THREAD = "execute_in_thread"
20
+ ATTR_COMMAND_TYPE = "command"
21
+ ATTR_FEATURE_TYPE = "feature"
22
+ ATTR_REGISTERED_NAME = "reg_name"
23
+ ATTR_REGISTERED_TYPE = "reg_type"
24
+
25
+ # Parameters
26
+ PARAM_LS = "ls"