jaclang 0.8.1__py3-none-any.whl → 0.8.3__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 (84) hide show
  1. jaclang/__init__.py +6 -0
  2. jaclang/cli/cli.py +21 -50
  3. jaclang/compiler/codeinfo.py +0 -1
  4. jaclang/compiler/constant.py +2 -0
  5. jaclang/compiler/jac.lark +17 -10
  6. jaclang/compiler/larkparse/jac_parser.py +2 -2
  7. jaclang/compiler/parser.py +34 -10
  8. jaclang/compiler/passes/main/__init__.py +2 -14
  9. jaclang/compiler/passes/main/annex_pass.py +2 -8
  10. jaclang/compiler/passes/main/cfg_build_pass.py +38 -12
  11. jaclang/compiler/passes/main/import_pass.py +3 -11
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +246 -592
  13. jaclang/compiler/passes/main/sem_def_match_pass.py +67 -0
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +8 -0
  15. jaclang/compiler/passes/main/sym_tab_link_pass.py +2 -5
  16. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.impl.jac +12 -0
  17. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.jac +31 -0
  18. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +2 -8
  19. jaclang/compiler/passes/main/tests/test_decl_impl_match_pass.py +7 -8
  20. jaclang/compiler/passes/main/tests/test_import_pass.py +5 -18
  21. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -6
  22. jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +38 -0
  23. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
  24. jaclang/compiler/passes/main/tests/test_sym_tab_link_pass.py +20 -17
  25. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +259 -106
  26. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -0
  27. jaclang/compiler/passes/tool/tests/fixtures/archetype_frmt.jac +14 -0
  28. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +5 -4
  29. jaclang/compiler/passes/tool/tests/fixtures/has_frmt.jac +13 -0
  30. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +6 -0
  31. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +9 -0
  33. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +25 -3
  34. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +2 -2
  35. jaclang/compiler/program.py +23 -60
  36. jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +2 -8
  37. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +1 -5
  38. jaclang/compiler/tests/test_importer.py +10 -13
  39. jaclang/compiler/unitree.py +88 -16
  40. jaclang/langserve/__init__.jac +1 -1
  41. jaclang/langserve/engine.jac +113 -108
  42. jaclang/langserve/server.jac +17 -2
  43. jaclang/langserve/tests/server_test/test_lang_serve.py +138 -46
  44. jaclang/langserve/tests/server_test/utils.py +35 -9
  45. jaclang/langserve/tests/test_sem_tokens.py +1 -1
  46. jaclang/langserve/tests/test_server.py +3 -7
  47. jaclang/runtimelib/archetype.py +127 -5
  48. jaclang/runtimelib/importer.py +51 -94
  49. jaclang/runtimelib/machine.py +391 -268
  50. jaclang/runtimelib/meta_importer.py +86 -0
  51. jaclang/runtimelib/tests/fixtures/graph_purger.jac +24 -26
  52. jaclang/runtimelib/tests/fixtures/other_root_access.jac +25 -16
  53. jaclang/runtimelib/tests/test_jaseci.py +3 -1
  54. jaclang/tests/fixtures/arch_rel_import_creation.jac +23 -23
  55. jaclang/tests/fixtures/async_ability.jac +43 -10
  56. jaclang/tests/fixtures/async_function.jac +18 -0
  57. jaclang/tests/fixtures/async_walker.jac +17 -12
  58. jaclang/tests/fixtures/create_dynamic_archetype.jac +25 -28
  59. jaclang/tests/fixtures/deep/deeper/deep_outer_import.jac +7 -4
  60. jaclang/tests/fixtures/deep/deeper/snd_lev.jac +2 -2
  61. jaclang/tests/fixtures/deep/deeper/snd_lev_dup.jac +6 -0
  62. jaclang/tests/fixtures/deep/one_lev.jac +2 -2
  63. jaclang/tests/fixtures/deep/one_lev_dup.jac +4 -3
  64. jaclang/tests/fixtures/dynamic_archetype.jac +19 -12
  65. jaclang/tests/fixtures/foo.jac +14 -22
  66. jaclang/tests/fixtures/jac_from_py.py +1 -1
  67. jaclang/tests/fixtures/jp_importer.jac +6 -6
  68. jaclang/tests/fixtures/jp_importer_auto.jac +5 -3
  69. jaclang/tests/fixtures/unicode_strings.jac +24 -0
  70. jaclang/tests/fixtures/walker_update.jac +5 -7
  71. jaclang/tests/test_language.py +138 -140
  72. jaclang/tests/test_reference.py +9 -4
  73. jaclang/tests/test_typecheck.py +13 -26
  74. jaclang/utils/lang_tools.py +7 -5
  75. jaclang/utils/module_resolver.py +23 -0
  76. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/METADATA +1 -1
  77. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/RECORD +79 -72
  78. jaclang/compiler/passes/main/tests/fixtures/main_err.jac +0 -6
  79. jaclang/compiler/passes/main/tests/fixtures/second_err.jac +0 -4
  80. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +0 -644
  81. jaclang/compiler/passes/tool/tests/test_doc_ir_gen_pass.py +0 -29
  82. jaclang/tests/fixtures/deep/deeper/__init__.jac +0 -1
  83. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/WHEEL +0 -0
  84. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,6 @@ import from typing { Callable , Optional }
8
8
 
9
9
  import jaclang.compiler.unitree as uni;
10
10
  import from jaclang { JacMachineInterface as Jac }
11
- import from jaclang.compiler.passes.main { CompilerMode as CMode }
12
11
  import from jaclang.compiler.program { JacProgram }
13
12
  import from jaclang.compiler.unitree { UniScopeNode }
14
13
  import from sem_manager { SemTokManager }
@@ -33,9 +32,9 @@ class ModuleManager {
33
32
  ) -> None {
34
33
  file_path = file_path.removeprefix('file://');
35
34
  self.program.mod.hub[file_path] = build;
36
- self.sem_managers[file_path] = SemTokManager(ir=build);
37
35
  if update_annexed {
38
- for (p,mod) in self.program.mod.hub.items() { if p != file_path {
36
+ self.sem_managers[file_path] = SemTokManager(ir=build);
37
+ for (p, mod) in self.program.mod.hub.items() { if p != file_path {
39
38
  self.sem_managers[p] = SemTokManager(ir=mod);
40
39
  } }
41
40
  }
@@ -43,8 +42,10 @@ class ModuleManager {
43
42
 
44
43
  """Remove errors and warnings for a specific file from the lists."""
45
44
  def clear_alerts_for_file(self: ModuleManager, file_path_fs: str) -> None {
46
- self.program.errors_had = [ e for e in self.program.errors_had if e.loc.mod_path != file_path_fs ];
47
- self.program.warnings_had = [ w for w in self.program.warnings_had if w.loc.mod_path != file_path_fs ];
45
+ self.program.errors_had =
46
+ [ e for e in self.program.errors_had if e.loc.mod_path != file_path_fs ];
47
+ self.program.warnings_had =
48
+ [ w for w in self.program.warnings_had if w.loc.mod_path != file_path_fs ];
48
49
  }
49
50
  }
50
51
 
@@ -56,16 +57,17 @@ class JacLangServer ( JacProgram , LanguageServer ) {
56
57
  LanguageServer.init(self, 'jac-lsp', 'v0.1');
57
58
  JacProgram.init(self);
58
59
  self.executor = ThreadPoolExecutor();
59
- self.tasks: <>dict[(str,asyncio.Task)] = {};
60
- self.sem_managers: <>dict[(str,SemTokManager)] = {};
60
+ self.tasks: <>dict[(str, asyncio.Task)] = {} ;
61
+ self.sem_managers: <>dict[(str, SemTokManager)] = {} ;
61
62
  self.module_manager = ModuleManager(self, self.sem_managers);
62
63
  }
63
64
 
64
65
  """Return diagnostics for all files as a dict {uri: diagnostics}."""
65
66
  @ property
66
67
  def diagnostics(self: JacLangServer, ) -> <>dict[str, <>list] {
67
- result = {};
68
- for file_path in self.mod.hub { uri = uris.from_fs_path(file_path); result[uri] = utils.gen_diagnostics(uri, self.errors_had, self.warnings_had); }
68
+ result = {} ;
69
+ for file_path in self.mod.hub { uri = uris.from_fs_path(file_path); result[uri] =
70
+ utils.gen_diagnostics(uri, self.errors_had, self.warnings_had); }
69
71
  return result;
70
72
  }
71
73
 
@@ -90,28 +92,30 @@ class JacLangServer ( JacProgram , LanguageServer ) {
90
92
 
91
93
  """Rebuild a file (syntax only)."""
92
94
  def quick_check(self: JacLangServer, file_path: str) -> bool {
93
- try { file_path_fs = file_path.removeprefix('file://'); document = self.workspace.get_text_document(file_path); self._clear_alerts_for_file(file_path_fs); build = self.compile_from_str(
94
- source_str=document.source, file_path=document.path, mode=CMode.PARSE
95
- ); self.update_modules(file_path_fs, build, need=False); self.publish_diagnostics(
95
+ try { file_path_fs = file_path.removeprefix('file://'); document =
96
+ self.workspace.get_text_document(file_path); self._clear_alerts_for_file(file_path_fs); build =
97
+ self.compile(use_str=document.source, file_path=document.path); self.update_modules(file_path_fs, build, need=False); self.publish_diagnostics(
96
98
  file_path, utils.gen_diagnostics(
97
99
  file_path, self.errors_had, self.warnings_had
98
100
  )
99
- ); return len(self.errors_had) == 0; } except Exception as e { self.log_error(f"'Error during syntax check: '{e}"); return False; }
101
+ ); build_errors =
102
+ [ e for e in self.errors_had if e.loc.mod_path == file_path_fs ]; return len(build_errors) == 0; } except Exception as e { self.log_error(f"'Error during syntax check: '{e}"); return False; }
100
103
  }
101
104
 
102
105
  """Rebuild a file and its dependencies (typecheck)."""
103
106
  def deep_check(
104
107
  self: JacLangServer, file_path: str, annex_view: Optional[str] = None
105
108
  ) -> bool {
106
- try { start_time = time.time(); file_path_fs = file_path.removeprefix('file://'); document = self.workspace.get_text_document(file_path); self._clear_alerts_for_file(file_path_fs); build = self.compile_from_str(
107
- source_str=document.source, file_path=document.path, mode=CMode.TYPECHECK
108
- ); self.update_modules(file_path_fs, build); if build.annexable_by {
109
+ try { start_time = time.time(); file_path_fs =
110
+ file_path.removeprefix('file://'); document =
111
+ self.workspace.get_text_document(file_path); self._clear_alerts_for_file(file_path_fs); build =
112
+ self.build(use_str=document.source, file_path=document.path); self.update_modules(file_path_fs, build); if build.annexable_by {
109
113
  return self.deep_check(
110
114
  uris.from_fs_path(build.annexable_by), annex_view=file_path
111
115
  );
112
116
  } self.publish_diagnostics(
113
- annex_view if annex_view else file_path , utils.gen_diagnostics(
114
- annex_view if annex_view else file_path , self.errors_had, self.warnings_had
117
+ annex_view if annex_view else file_path, utils.gen_diagnostics(
118
+ annex_view if annex_view else file_path, self.errors_had, self.warnings_had
115
119
  )
116
120
  ); if annex_view {
117
121
  self.publish_diagnostics(
@@ -121,12 +125,12 @@ class JacLangServer ( JacProgram , LanguageServer ) {
121
125
  );
122
126
  } self.log_py(
123
127
  f"'PROFILE: Deep check took '{(time.time() - start_time)}' seconds.'"
124
- ); return len(self.errors_had) == 0; } except Exception as e { self.log_error(f"'Error during deep check: '{e}"); return False; }
128
+ ); return len(self.errors_had) == 0; } except Exception as e { self.log_py(f"'Error during deep check: '{e}"); return False; }
125
129
  }
126
130
 
127
131
  """Analyze and publish diagnostics."""
128
- async def launch_quick_check(self: JacLangServer, uri: str) -> None {
129
- await asyncio.get_event_loop().run_in_executor(
132
+ async def launch_quick_check(self: JacLangServer, uri: str) -> bool {
133
+ return await asyncio.get_event_loop().run_in_executor(
130
134
  self.executor, self.quick_check, uri
131
135
  );
132
136
  }
@@ -134,7 +138,7 @@ class JacLangServer ( JacProgram , LanguageServer ) {
134
138
  """Analyze and publish diagnostics."""
135
139
  async def launch_deep_check(self: JacLangServer, uri: str) -> None {
136
140
  async def run_in_executor(
137
- func: Callable[([str,Optional[str]],bool)], file_path: str, annex_view: Optional[str] = None
141
+ func: Callable[([str, Optional[str]], bool)], file_path: str, annex_view: Optional[str] = None
138
142
  ) -> None {
139
143
  loop = asyncio.get_event_loop();
140
144
  await loop.run_in_executor(self.executor, func, file_path, annex_view);
@@ -142,7 +146,7 @@ class JacLangServer ( JacProgram , LanguageServer ) {
142
146
  if uri in self.tasks and not self.tasks[uri].done() {
143
147
  self.log_py(f"'Canceling '{uri}' deep check...'");
144
148
  self.tasks[uri].cancel();
145
- del (self.tasks[uri],) ;
149
+ del (self.tasks[uri], ) ;
146
150
  }
147
151
  self.log_py(f"'Analyzing '{uri}'...'");
148
152
  task = asyncio.create_task(run_in_executor(self.deep_check, uri));
@@ -154,49 +158,42 @@ class JacLangServer ( JacProgram , LanguageServer ) {
154
158
  def get_completion(
155
159
  self: JacLangServer, file_path: str, position: lspt.Position, completion_trigger: Optional[str]
156
160
  ) -> lspt.CompletionList {
157
- document = self.workspace.get_text_document(file_path);
158
- mod_ir = self.get_ir(file_path);
159
- if not mod_ir {
161
+ try { document = self.workspace.get_text_document(file_path); mod_ir =
162
+ self.get_ir(file_path); if not mod_ir {
160
163
  return lspt.CompletionList(is_incomplete=False, items=[]);
161
- }
162
- current_line = document.lines[position.line];
163
- current_pos = position.character;
164
- current_symbol_path = utils.parse_symbol_path(current_line, current_pos);
165
- builtin_mod = next(
166
- ( mod for (name,mod) in self.mod.hub.items() if 'builtins' in name )
167
- );
168
- builtin_tab = builtin_mod.sym_tab;
169
- assert isinstance(builtin_tab, UniScopeNode) ;
170
- completion_items = [];
171
- node_selected = utils.find_deepest_symbol_node_at_pos(
172
- mod_ir, position.line, (position.character - 2)
173
- );
174
- mod_tab = mod_ir.sym_tab if not node_selected else node_selected.sym_tab ;
175
- current_symbol_table = mod_tab;
176
- if completion_trigger == '.' {
164
+ } current_line = document.lines[position.line]; current_pos =
165
+ position.character; current_symbol_path =
166
+ utils.parse_symbol_path(current_line, current_pos); builtin_mod =
167
+ next(( mod for (name, mod) in self.mod.hub.items() if 'builtins' in name )); builtin_tab =
168
+ builtin_mod.sym_tab; assert isinstance(builtin_tab, UniScopeNode) ; completion_items =
169
+ []; node_selected =
170
+ utils.find_deepest_symbol_node_at_pos(
171
+ mod_ir, position.line, (position.character - 2)
172
+ ); mod_tab = mod_ir.sym_tab if not node_selected else node_selected.sym_tab; current_symbol_table =
173
+ mod_tab; if completion_trigger == '.' {
177
174
  if current_symbol_path {
178
175
  temp_tab = mod_tab;
179
176
  for symbol in current_symbol_path { if symbol == 'self' {
180
- is_ability_def = temp_tab
181
- if isinstance(temp_tab, uni.ImplDef)
182
- else temp_tab.find_parent_of_type(uni.ImplDef)
183
- ;
177
+ is_ability_def =
178
+ temp_tab
179
+ if isinstance(temp_tab, uni.ImplDef)
180
+ else temp_tab.find_parent_of_type(uni.ImplDef);
184
181
  if not is_ability_def {
185
182
  archi_owner = mod_tab.find_parent_of_type(uni.Archetype);
186
- temp_tab = archi_owner.sym_tab
187
- if archi_owner and archi_owner.sym_tab
188
- else mod_tab
189
- ;
183
+ temp_tab =
184
+ archi_owner.sym_tab
185
+ if archi_owner and archi_owner.sym_tab
186
+ else mod_tab;
190
187
  continue;
191
188
  } else {
192
- archi_owner = is_ability_def.decl_link.find_parent_of_type(uni.Archetype)
193
- if is_ability_def.decl_link
194
- else None
195
- ;
196
- temp_tab = archi_owner.sym_tab
197
- if archi_owner and archi_owner.sym_tab
198
- else temp_tab
199
- ;
189
+ archi_owner =
190
+ is_ability_def.decl_link.find_parent_of_type(uni.Archetype)
191
+ if is_ability_def.decl_link
192
+ else None;
193
+ temp_tab =
194
+ archi_owner.sym_tab
195
+ if archi_owner and archi_owner.sym_tab
196
+ else temp_tab;
200
197
  continue;
201
198
  }
202
199
  } symb = temp_tab.lookup(symbol); if symb {
@@ -204,14 +201,14 @@ class JacLangServer ( JacProgram , LanguageServer ) {
204
201
  if fetc_tab {
205
202
  temp_tab = fetc_tab;
206
203
  } else {
207
- temp_tab = symb.defn[0].type_sym_tab
208
- if symb.defn[0].type_sym_tab
209
- else temp_tab
210
- ;
204
+ temp_tab =
205
+ symb.defn[0].type_sym_tab
206
+ if symb.defn[0].type_sym_tab
207
+ else temp_tab;
211
208
  }
212
209
  } else {
213
210
  break;
214
- } }
211
+ } }
215
212
  completion_items += utils.collect_all_symbols_in_scope(
216
213
  temp_tab, up_tree=False
217
214
  );
@@ -230,11 +227,14 @@ class JacLangServer ( JacProgram , LanguageServer ) {
230
227
  } elif node_selected and node_selected.find_parent_of_type(uni.Archetype)
231
228
  or node_selected.find_parent_of_type(uni.ImplDef)
232
229
  {
233
- self_symbol = [lspt.CompletionItem(label='self', kind=lspt.CompletionItemKind.Variable)];
230
+ self_symbol =
231
+
232
+ [lspt.CompletionItem(
233
+ label='self', kind=lspt.CompletionItemKind.Variable
234
+ )];
234
235
  } else {
235
236
  self_symbol = [];
236
- }
237
- return lspt.CompletionList(is_incomplete=False, items=completion_items);
237
+ } return lspt.CompletionList(is_incomplete=False, items=completion_items); } except Exception as e { self.log_py(f"'Error during completion: '{e}"); return lspt.CompletionList(is_incomplete=False, items=[]); }
238
238
  }
239
239
 
240
240
  """Rename module."""
@@ -242,27 +242,30 @@ class JacLangServer ( JacProgram , LanguageServer ) {
242
242
  if old_path in self.mod.hub and new_path != old_path {
243
243
  self.mod.hub[new_path] = self.mod.hub[old_path];
244
244
  self.sem_managers[new_path] = self.sem_managers[old_path];
245
- del (self.mod.hub[old_path],) ;
246
- del (self.sem_managers[old_path],) ;
245
+ del (self.mod.hub[old_path], ) ;
246
+ del (self.sem_managers[old_path], ) ;
247
247
  }
248
248
  }
249
249
 
250
250
  """Delete module."""
251
251
  def delete_module(self: JacLangServer, uri: str) -> None {
252
252
  if uri in self.mod.hub {
253
- del (self.mod.hub[uri],) ;
253
+ del (self.mod.hub[uri], ) ;
254
254
  }
255
255
  if uri in self.sem_managers {
256
- del (self.sem_managers[uri],) ;
256
+ del (self.sem_managers[uri], ) ;
257
257
  }
258
258
  }
259
259
 
260
260
  """Return formatted jac."""
261
261
  def formatted_jac(self: JacLangServer, file_path: str) -> <>list[lspt.TextEdit] {
262
- try { document = self.workspace.get_text_document(file_path); formatted_text = JacProgram.jac_str_formatter(
263
- source_str=document.source, file_path=document.path
264
- ); } except Exception as e { self.log_error(f"'Error during formatting: '{e}"); formatted_text = document.source; }
265
- return [lspt.TextEdit(
262
+ try { document = self.workspace.get_text_document(file_path); formatted_text =
263
+ JacProgram.jac_str_formatter(
264
+ source_str=document.source, file_path=document.path
265
+ ); } except Exception as e { self.log_error(f"'Error during formatting: '{e}"); formatted_text =
266
+ document.source; }
267
+ return
268
+ [lspt.TextEdit(
266
269
  range=lspt.Range(
267
270
  start=lspt.Position(line=0, character=0), end=lspt.Position(
268
271
  line=(len(document.source.splitlines()) + 1), character=0
@@ -283,14 +286,13 @@ class JacLangServer ( JacProgram , LanguageServer ) {
283
286
  if not sem_mgr {
284
287
  return None;
285
288
  }
286
- token_index = utils.find_index(
287
- sem_mgr.sem_tokens, position.line, position.character
288
- );
289
+ token_index =
290
+ utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
289
291
  if token_index is None {
290
292
  return None;
291
293
  }
292
294
  node_selected = sem_mgr.static_sem_tokens[token_index][3];
293
- value = self.get_node_info(node_selected) if node_selected else None ;
295
+ value = self.get_node_info(node_selected) if node_selected else None;
294
296
  if value {
295
297
  return lspt.Hover(
296
298
  contents=lspt.MarkupContent(
@@ -305,7 +307,8 @@ class JacLangServer ( JacProgram , LanguageServer ) {
305
307
  def get_node_info(self: JacLangServer, <>node: uni.AstSymbolNode) -> Optional[str] {
306
308
  try { if isinstance(<>node, uni.NameAtom) {
307
309
  <>node = <>node.name_of;
308
- } access = (<>node.sym.access.value + ' ') if <>node.sym else None ; node_info = f"'('{access if access else '' }{<>node.sym_category.value}') '{<>node.sym_name}"; if <>node.name_spec.clean_type {
310
+ } access = (<>node.sym.access.value + ' ') if <>node.sym else None; node_info =
311
+ f"'('{access if access else ''}{<>node.sym_category.value}') '{<>node.sym_name}"; if <>node.name_spec.clean_type {
309
312
  node_info += f"': '{<>node.name_spec.clean_type}";
310
313
  } if isinstance(<>node, uni.AstDocNode) and <>node.doc {
311
314
  node_info += f"'\n'{<>node.doc.value}";
@@ -338,9 +341,8 @@ class JacLangServer ( JacProgram , LanguageServer ) {
338
341
  if not sem_mgr {
339
342
  return None;
340
343
  }
341
- token_index = utils.find_index(
342
- sem_mgr.sem_tokens, position.line, position.character
343
- );
344
+ token_index =
345
+ utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
344
346
  if token_index is None {
345
347
  return None;
346
348
  }
@@ -352,7 +354,7 @@ class JacLangServer ( JacProgram , LanguageServer ) {
352
354
  {
353
355
  spec = node_selected.parent.parent.abs_path;
354
356
  if spec {
355
- spec = spec[ 5 : ] if spec.startswith('File:') else spec ;
357
+ spec = spec[ 5 : ] if spec.startswith('File:') else spec;
356
358
  return lspt.Location(
357
359
  uri=uris.from_fs_path(spec), range=lspt.Range(
358
360
  start=lspt.Position(line=0, character=0), end=lspt.Position(line=0, character=0)
@@ -364,12 +366,13 @@ class JacLangServer ( JacProgram , LanguageServer ) {
364
366
  } elif node_selected.parent
365
367
  and isinstance(node_selected.parent, uni.ModuleItem)
366
368
  {
367
- path = node_selected.parent.abs_path
368
- or node_selected.parent.from_mod_path.abs_path
369
- ;
370
- loc_range = (0,0,0,0);
369
+ path =
370
+ node_selected.parent.abs_path
371
+ or node_selected.parent.from_mod_path.abs_path
372
+ ;
373
+ loc_range = (0, 0, 0, 0);
371
374
  if path and loc_range {
372
- path = path[ 5 : ] if path.startswith('File:') else path ;
375
+ path = path[ 5 : ] if path.startswith('File:') else path;
373
376
  return lspt.Location(
374
377
  uri=uris.from_fs_path(path), range=lspt.Range(
375
378
  start=lspt.Position(
@@ -381,16 +384,15 @@ class JacLangServer ( JacProgram , LanguageServer ) {
381
384
  } elif isinstance(node_selected, uni.ElementStmt) {
382
385
  return None;
383
386
  }
384
- decl_node = node_selected.parent.body.target
385
- if node_selected.parent
386
- and isinstance(node_selected.parent, uni.AstImplNeedingNode)
387
- and isinstance(node_selected.parent.body, uni.ImplDef)
388
-
389
- else node_selected.sym.decl
390
- if node_selected.sym and node_selected.sym.decl
391
- else node_selected
392
-
393
- ;
387
+ decl_node =
388
+ node_selected.parent.body.target
389
+ if node_selected.parent
390
+ and isinstance(node_selected.parent, uni.AstImplNeedingNode)
391
+ and isinstance(node_selected.parent.body, uni.ImplDef)
392
+
393
+ else node_selected.sym.decl
394
+ if node_selected.sym and node_selected.sym.decl
395
+ else node_selected;
394
396
  if isinstance(decl_node, list) {
395
397
  valid_path = decl_node[0].loc.mod_path;
396
398
  } else {
@@ -402,7 +404,7 @@ class JacLangServer ( JacProgram , LanguageServer ) {
402
404
  } else {
403
405
  valid_range = decl_node.loc;
404
406
  }
405
- try { decl_range = utils.create_range(valid_range); } except ValueError { return None; }
407
+ try { decl_range = utils.create_range(valid_range); } except ValueError { return None; }
406
408
  decl_location = lspt.Location(uri=decl_uri, range=decl_range);
407
409
  return decl_location;
408
410
  } else {
@@ -422,15 +424,17 @@ class JacLangServer ( JacProgram , LanguageServer ) {
422
424
  if not sem_mgr {
423
425
  return [];
424
426
  }
425
- index1 = utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
427
+ index1 =
428
+ utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
426
429
  if index1 is None {
427
430
  return [];
428
431
  }
429
432
  node_selected = sem_mgr.static_sem_tokens[index1][3];
430
433
  if node_selected and node_selected.sym {
431
- list_of_references: <>list[lspt.Location] = [ lspt.Location(
432
- uri=uris.from_fs_path(<>node.loc.mod_path), range=utils.create_range(<>node.loc)
433
- ) for <>node in node_selected.sym.uses ];
434
+ list_of_references: <>list[lspt.Location] =
435
+ [ lspt.Location(
436
+ uri=uris.from_fs_path(<>node.loc.mod_path), range=utils.create_range(<>node.loc)
437
+ ) for <>node in node_selected.sym.uses ];
434
438
  return list_of_references;
435
439
  }
436
440
  return [];
@@ -448,16 +452,17 @@ class JacLangServer ( JacProgram , LanguageServer ) {
448
452
  if not sem_mgr {
449
453
  return None;
450
454
  }
451
- index1 = utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
455
+ index1 =
456
+ utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
452
457
  if index1 is None {
453
458
  return None;
454
459
  }
455
460
  node_selected = sem_mgr.static_sem_tokens[index1][3];
456
461
  if node_selected and node_selected.sym {
457
- changes: <>dict[(str,<>list[lspt.TextEdit])] = {};
458
- for <>node in [*node_selected.sym.uses,node_selected.sym.defn[0]] { key = uris.from_fs_path(<>node.loc.mod_path); new_edit = lspt.TextEdit(
459
- range=utils.create_range(<>node.loc), new_text=new_name
460
- ); utils.add_unique_text_edit(changes, key, new_edit); }
462
+ changes: <>dict[(str, <>list[lspt.TextEdit])] = {} ;
463
+ for <>node in [*node_selected.sym.uses, node_selected.sym.defn[0]] { key =
464
+ uris.from_fs_path(<>node.loc.mod_path); new_edit =
465
+ lspt.TextEdit(range=utils.create_range(<>node.loc), new_text=new_name); utils.add_unique_text_edit(changes, key, new_edit); }
461
466
  return lspt.WorkspaceEdit(changes=changes);
462
467
  }
463
468
  return None;
@@ -30,6 +30,10 @@ async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) ->
30
30
  @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
31
31
  async def did_save(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None {
32
32
  file_path = params.text_document.uri;
33
+ quick_check_passed = await ls.launch_quick_check(file_path);
34
+ if not quick_check_passed {
35
+ return;
36
+ }
33
37
  await ls.launch_deep_check(file_path);
34
38
  ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
35
39
  }
@@ -42,8 +46,19 @@ async def did_change(
42
46
  params: lspt.DidChangeTextDocumentParams
43
47
  ) -> None {
44
48
  file_path = params.text_document.uri;
45
- await ls.launch_quick_check(file_path);
46
- ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
49
+ quick_check_passed = await ls.launch_quick_check(file_path);
50
+
51
+ if quick_check_passed {
52
+ document = ls.workspace.get_text_document(file_path);
53
+ lines = document.source.splitlines();
54
+ sem_manager = ls.sem_managers[file_path.removeprefix('file://')];
55
+ sem_manager.update_sem_tokens(
56
+ params,sem_manager.sem_tokens,lines
57
+ );
58
+ ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
59
+ await ls.launch_deep_check(file_path);
60
+ ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
61
+ }
47
62
  }
48
63
 
49
64