jaclang 0.7.18__py3-none-any.whl → 0.7.21__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 (45) hide show
  1. jaclang/cli/cli.py +2 -2
  2. jaclang/compiler/absyntree.py +1 -1
  3. jaclang/compiler/jac.lark +14 -14
  4. jaclang/compiler/parser.py +71 -59
  5. jaclang/compiler/passes/ir_pass.py +2 -0
  6. jaclang/compiler/passes/main/__init__.py +1 -1
  7. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +50 -13
  8. jaclang/compiler/passes/main/import_pass.py +29 -1
  9. jaclang/compiler/passes/main/py_collect_dep_pass.py +8 -0
  10. jaclang/compiler/passes/main/registry_pass.py +4 -0
  11. jaclang/compiler/passes/main/sym_tab_build_pass.py +0 -18
  12. jaclang/compiler/passes/main/tests/fixtures/mod_type_assign.jac +7 -0
  13. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -0
  14. jaclang/compiler/passes/main/tests/test_import_pass.py +10 -10
  15. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  16. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +23 -1
  17. jaclang/compiler/passes/main/type_check_pass.py +4 -4
  18. jaclang/compiler/passes/tool/jac_formatter_pass.py +61 -31
  19. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/line_spacing.jac +57 -0
  20. jaclang/compiler/semtable.py +4 -4
  21. jaclang/compiler/symtable.py +5 -0
  22. jaclang/langserve/engine.py +68 -7
  23. jaclang/langserve/tests/test_server.py +3 -3
  24. jaclang/langserve/utils.py +0 -113
  25. jaclang/plugin/tests/test_jaseci.py +23 -4
  26. jaclang/runtimelib/architype.py +20 -2
  27. jaclang/runtimelib/importer.py +3 -0
  28. jaclang/runtimelib/machine.py +92 -4
  29. jaclang/runtimelib/memory.py +1 -1
  30. jaclang/settings.py +4 -0
  31. jaclang/tests/fixtures/bar.jac +1 -1
  32. jaclang/tests/fixtures/builtins_test.jac +16 -0
  33. jaclang/tests/fixtures/dynamic_architype.jac +34 -0
  34. jaclang/tests/fixtures/entry_exit.jac +36 -0
  35. jaclang/tests/fixtures/foo.jac +0 -1
  36. jaclang/tests/fixtures/match_multi_ex.jac +12 -0
  37. jaclang/tests/fixtures/trailing_comma.jac +88 -0
  38. jaclang/tests/fixtures/walker_update.jac +19 -0
  39. jaclang/tests/test_cli.py +29 -2
  40. jaclang/tests/test_language.py +131 -2
  41. jaclang/utils/treeprinter.py +1 -1
  42. {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/METADATA +4 -2
  43. {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/RECORD +45 -36
  44. {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/WHEEL +0 -0
  45. {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,7 @@
1
+ import:jac blip;
2
+
3
+
4
+ with entry{
5
+ kl = blip;
6
+ l1 = l2 = blip;
7
+ }
@@ -0,0 +1,3 @@
1
+ from .display import *
2
+ from .color import *
3
+ from .constants import *
@@ -70,19 +70,19 @@ class ImportPassPassTests(TestCase):
70
70
  )
71
71
  assert isinstance(build.ir, ast.Module)
72
72
  p = {
73
- "math": "jaclang/jaclang/vendor/mypy/typeshed/stdlib/math.pyi",
74
- "pygame_mock": "pygame_mock/__init__.py",
75
- "pygame_mock.color": "pygame_mock/color.py",
76
- "pygame_mock.constants": "pygame_mock/constants.py",
77
- "argparse": "jaclang/vendor/mypy/typeshed/stdlib/argparse.pyi",
78
- "builtins": "jaclang/vendor/mypy/typeshed/stdlib/builtins.pyi",
79
- "pygame_mock.display": "pygame_mock/display.py",
80
- "os": "jaclang/vendor/mypy/typeshed/stdlib/os/__init__.pyi",
81
- "genericpath": "jaclang/vendor/mypy/typeshed/stdlib/genericpath.pyi",
73
+ "math": r"jaclang/vendor/mypy/typeshed/stdlib/math.pyi$",
74
+ "pygame_mock": r"pygame_mock/__init__.pyi$",
75
+ "pygame_mock.color": r"pygame_mock/color.py$",
76
+ "pygame_mock.constants": r"pygame_mock/constants.py$",
77
+ "argparse": r"jaclang/vendor/mypy/typeshed/stdlib/argparse.pyi$",
78
+ "builtins": r"jaclang/vendor/mypy/typeshed/stdlib/builtins.pyi$",
79
+ "pygame_mock.display": r"pygame_mock/display.py$",
80
+ "os": r"jaclang/vendor/mypy/typeshed/stdlib/os/__init__.pyi$",
81
+ "genericpath": r"jaclang/vendor/mypy/typeshed/stdlib/genericpath.pyi$",
82
82
  }
83
83
  for i in p:
84
84
  self.assertIn(i, build.ir.py_raise_map)
85
- self.assertIn(p[i], re.sub(r".*fixtures/", "", build.ir.py_raise_map[i]))
85
+ self.assertRegex(re.sub(r".*fixtures/", "", build.ir.py_raise_map[i]), p[i])
86
86
 
87
87
  def test_py_raised_mods(self) -> None:
88
88
  """Basic test for pass."""
@@ -59,6 +59,6 @@ class MypyTypeCheckPassTests(TestCase):
59
59
  self.assertIn("HasVar - species - Type: builtins.str", out)
60
60
  self.assertIn("myDog - Type: type_info.Dog", out)
61
61
  self.assertIn("Body - Type: type_info.Dog.Body", out)
62
- self.assertEqual(out.count("Type: builtins.str"), 28)
62
+ self.assertEqual(out.count("Type: builtins.str"), 34)
63
63
  for i in lis:
64
64
  self.assertNotIn(i, out)
@@ -1,7 +1,29 @@
1
1
  """Test pass module."""
2
2
 
3
+ from jaclang.compiler.compile import jac_file_to_pass
4
+ from jaclang.compiler.passes.main.fuse_typeinfo_pass import FuseTypeInfoPass
5
+ from jaclang.compiler.passes.main.schedules import py_code_gen_typed
3
6
  from jaclang.utils.test import TestCase
4
7
 
5
8
 
6
9
  class TestFuseTypeInfo(TestCase):
7
- """Test pass module."""
10
+ """Test FuseTypeInfoPass module."""
11
+
12
+ def setUp(self) -> None:
13
+ """Set up test."""
14
+ return super().setUp()
15
+
16
+ def test_mod_type_assign(self) -> None:
17
+ """Test module type assignment."""
18
+ gen_ast = jac_file_to_pass(
19
+ self.fixture_abs_path("mod_type_assign.jac"),
20
+ FuseTypeInfoPass,
21
+ schedule=py_code_gen_typed,
22
+ ).ir.pp()
23
+ type_info_list = [
24
+ "kl - Type: types.ModuleType, SymbolTable: blip",
25
+ "l1 - Type: types.ModuleType, SymbolTable: blip",
26
+ "l2 - Type: types.ModuleType, SymbolTable: blip",
27
+ ]
28
+ for type_info in type_info_list:
29
+ self.assertIn(type_info, str(gen_ast))
@@ -51,10 +51,10 @@ class JacTypeCheckPass(Pass):
51
51
  options.ignore_missing_imports = True
52
52
  options.cache_dir = Con.JAC_MYPY_CACHE
53
53
  options.mypy_path = [
54
- str(
55
- pathlib.Path(os.path.dirname(__file__)).parent.parent.parent.parent
56
- / "stubs"
57
- )
54
+ # str( # TODO: Remove me, this was the wrong way to point to stubs
55
+ # pathlib.Path(os.path.dirname(__file__)).parent.parent.parent.parent
56
+ # / "stubs"
57
+ # )
58
58
  ]
59
59
  if top_module_path != "":
60
60
  options.mypy_path.append(top_module_path)
@@ -126,11 +126,14 @@ class JacFormatPass(Pass):
126
126
  last_element = None
127
127
  for counter, i in enumerate(node.body):
128
128
  counter += 1
129
+ if last_element and (
130
+ i.loc.first_line - last_element.loc.last_line > 1
131
+ and not last_element.gen.jac.endswith("\n\n")
132
+ ):
133
+ self.emit_ln(node, "")
129
134
  if isinstance(i, ast.Import):
130
135
  self.emit_ln(node, i.gen.jac)
131
136
  else:
132
- if isinstance(last_element, ast.Import):
133
- self.emit_ln(node, "")
134
137
  if last_element and (
135
138
  isinstance(i, ast.Architype)
136
139
  and isinstance(last_element, ast.Architype)
@@ -140,21 +143,6 @@ class JacFormatPass(Pass):
140
143
  self.emit_ln(node, "")
141
144
  self.emit_ln(node, i.gen.jac)
142
145
 
143
- if counter <= len(node.body) - 1:
144
- if (
145
- isinstance(i, ast.Ability)
146
- and isinstance(node.body[counter], ast.Ability)
147
- and i.gen.jac.endswith(";")
148
- or (
149
- isinstance(i, ast.Architype)
150
- and len(node.body[counter].kid[-1].kid) == 2
151
- and len(node.body[counter - 1].kid[-1].kid) == 2
152
- )
153
- and node.gen.jac.endswith("\n")
154
- ):
155
- self.emit(node, "")
156
- else:
157
- self.emit_ln(node, "")
158
146
  last_element = i
159
147
 
160
148
  def exit_global_vars(self, node: ast.GlobalVars) -> None:
@@ -222,6 +210,20 @@ class JacFormatPass(Pass):
222
210
  """
223
211
  prev_token = None
224
212
  for stmt in node.kid:
213
+ line_emiited = False
214
+ if prev_token and stmt.loc.first_line - prev_token.loc.last_line > 1:
215
+ if (
216
+ stmt.kid
217
+ and isinstance(stmt.kid[-1], ast.SubNodeList)
218
+ and not isinstance(stmt.kid[-1].kid[-1], ast.CommentToken)
219
+ ):
220
+ self.emit(node, "")
221
+
222
+ else:
223
+ line_emiited = True
224
+ self.indent_level -= 1
225
+ self.emit_ln(node, "")
226
+ self.indent_level += 1
225
227
  if isinstance(node.parent, (ast.EnumDef, ast.Enum)) and stmt.gen.jac == ",":
226
228
  self.indent_level -= 1
227
229
  self.emit_ln(node, f"{stmt.gen.jac}")
@@ -266,9 +268,10 @@ class JacFormatPass(Pass):
266
268
  self.indent_level += 1
267
269
  else:
268
270
  self.emit(node, f" {stmt.gen.jac}")
269
- self.indent_level -= 1
270
- self.emit_ln(node, "")
271
- self.indent_level += 1
271
+ if not line_emiited:
272
+ self.indent_level -= 1
273
+ self.emit_ln(node, "")
274
+ self.indent_level += 1
272
275
  else:
273
276
  if not node.gen.jac.endswith("\n"):
274
277
  self.indent_level -= 1
@@ -279,12 +282,21 @@ class JacFormatPass(Pass):
279
282
  if prev_token and isinstance(prev_token, ast.Ability):
280
283
  self.emit(node, f"{stmt.gen.jac}")
281
284
  else:
282
- self.emit(node, stmt.gen.jac)
283
- if not stmt.gen.jac.endswith("postinit;"):
285
+ token_before = self.token_before(stmt)
286
+ if (
287
+ token_before is not None
288
+ and isinstance(token_before, ast.Token)
289
+ and token_before.name == Tok.LBRACE
290
+ and stmt.loc.first_line - token_before.loc.last_line > 1
291
+ ):
284
292
  self.indent_level -= 1
285
- self.emit_ln(stmt, "")
286
293
  self.emit_ln(node, "")
287
294
  self.indent_level += 1
295
+ self.emit(node, stmt.gen.jac)
296
+ self.indent_level -= 1
297
+ self.emit_ln(stmt, "")
298
+ self.emit_ln(node, "")
299
+ self.indent_level += 1
288
300
  elif stmt.gen.jac == ",":
289
301
  self.emit(node, f"{stmt.value} ")
290
302
  elif stmt.value == "=":
@@ -304,10 +316,29 @@ class JacFormatPass(Pass):
304
316
  isinstance(prev_token, ast.Ability)
305
317
  and isinstance(stmt, (ast.Ability, ast.AbilityDef))
306
318
  ):
307
- if not isinstance(prev_token.kid[-1], ast.CommentToken):
308
- self.indent_level -= 1
309
- self.emit_ln(node, "")
310
- self.indent_level += 1
319
+ if (
320
+ not isinstance(prev_token.kid[-1], ast.CommentToken)
321
+ and not line_emiited
322
+ ):
323
+ if (
324
+ prev_token.kid
325
+ and isinstance(prev_token.kid[-1], ast.SubNodeList)
326
+ and isinstance(prev_token.kid[-1].kid[-1], ast.CommentToken)
327
+ ):
328
+ if (
329
+ prev_token
330
+ and stmt.loc.first_line - prev_token.kid[-1].kid[-1].line_no
331
+ > 1
332
+ ):
333
+ self.indent_level -= 1
334
+ self.emit_ln(node, "")
335
+ self.indent_level += 1
336
+ else:
337
+ self.emit(node, "")
338
+ else:
339
+ self.indent_level -= 1
340
+ self.emit_ln(node, "")
341
+ self.indent_level += 1
311
342
  self.emit(node, stmt.gen.jac)
312
343
  else:
313
344
  if prev_token and prev_token.gen.jac.strip() == "{":
@@ -373,7 +404,9 @@ class JacFormatPass(Pass):
373
404
  indented = True
374
405
  for count, j in enumerate(i.kid):
375
406
  if j.gen.jac == ",":
376
- if i.kid[count + 1].gen.jac.startswith("#"):
407
+ if len(i.kid) > count + 1 and i.kid[
408
+ count + 1
409
+ ].gen.jac.startswith("#"):
377
410
  self.indent_level -= 1
378
411
  self.emit(node, f"{j.gen.jac} ")
379
412
  self.indent_level += 1
@@ -907,8 +940,6 @@ class JacFormatPass(Pass):
907
940
  """Check if the length of the current generated code exceeds the max line length."""
908
941
  if max_line_length == 0:
909
942
  max_line_length = self.MAX_LINE_LENGTH
910
- # print(content)
911
- # print(len(content))
912
943
  return len(content) > max_line_length
913
944
 
914
945
  def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
@@ -958,7 +989,6 @@ class JacFormatPass(Pass):
958
989
  self.error(
959
990
  f"Binary operator {node.op.value} not supported in bootstrap Jac"
960
991
  )
961
- # print(node.gen)
962
992
  if isinstance(
963
993
  node.kid[-1], (ast.Semi, ast.CommentToken)
964
994
  ) and not node.gen.jac.endswith("\n"):
@@ -0,0 +1,57 @@
1
+ import:py math;
2
+
3
+ glob RAD = 5;
4
+
5
+ glob DIA = 10;
6
+
7
+ # this comment is for walker
8
+
9
+ walker decorator_walk {
10
+ can hash(func: Any) {
11
+ can inner(a: Any) {
12
+ print(("#" * 20));
13
+ func(a);
14
+ print(("#" * 20));
15
+ }
16
+ return inner;
17
+ }
18
+
19
+ can exclaim(func: Any) {
20
+ can inner(b: Any) {
21
+ print(("!" * 20));
22
+ func(b);
23
+ print(("!" * 20));
24
+ }
25
+ return inner;
26
+ }
27
+
28
+ can tilde(func: Any) {
29
+ can inner(c: Any) {
30
+ print(("~" * 20));
31
+ func(c);
32
+ print(("~" * 20));
33
+ }
34
+ return inner;
35
+ }
36
+
37
+ can greeter(name: Any) {
38
+ print("Hello, " + name + "!");
39
+ }
40
+
41
+ # Entry point for the walker
42
+
43
+ can start with entry {
44
+
45
+ # Apply decorators to greeter
46
+ decorated_greeter = hash(exclaim(tilde(greeter)));
47
+
48
+ # Call the decorated greeter function
49
+ decorated_greeter("World");
50
+
51
+ # this is another comment
52
+ }
53
+ }
54
+
55
+ with entry {
56
+ root spawn decorator_walk();
57
+ }
@@ -19,13 +19,13 @@ class SemInfo:
19
19
  self,
20
20
  node: ast.AstNode,
21
21
  name: str,
22
- type: Optional[str] = None,
22
+ type_str: Optional[str] = None,
23
23
  semstr: str = "",
24
24
  ) -> None:
25
25
  """Initialize the class."""
26
- self.node = node
26
+ self.node_type = type(node)
27
27
  self.name = name
28
- self.type = type
28
+ self.type = type_str
29
29
  self.semstr = semstr
30
30
 
31
31
  def __repr__(self) -> str:
@@ -40,7 +40,7 @@ class SemInfo:
40
40
  self_scope = str(scope) + f".{self.name}({self.type})"
41
41
  _, children = sem_registry.lookup(scope=SemScope.get_scope_from_str(self_scope))
42
42
  if filter and children and isinstance(children, list):
43
- return [i for i in children if isinstance(i.node, filter)]
43
+ return [i for i in children if i.node_type == filter]
44
44
  return children if children and isinstance(children, list) else []
45
45
 
46
46
 
@@ -54,6 +54,11 @@ class Symbol:
54
54
  out.reverse()
55
55
  return ".".join(out)
56
56
 
57
+ @property
58
+ def fetch_sym_tab(self) -> Optional[SymbolTable]:
59
+ """Get symbol table."""
60
+ return self.parent_tab.find_scope(self.sym_name)
61
+
57
62
  def add_defn(self, node: ast.NameAtom) -> None:
58
63
  """Add defn."""
59
64
  self.defn.append(node)
@@ -25,7 +25,6 @@ from jaclang.langserve.utils import (
25
25
  get_location_range,
26
26
  get_symbols_for_outline,
27
27
  parse_symbol_path,
28
- resolve_completion_symbol_table,
29
28
  )
30
29
  from jaclang.vendor.pygls import uris
31
30
  from jaclang.vendor.pygls.server import LanguageServer
@@ -188,14 +187,73 @@ class JacLangServer(LanguageServer):
188
187
  if not node_selected
189
188
  else node_selected.sym_tab
190
189
  )
191
- current_tab = self.modules[file_path].ir._sym_tab
192
190
  current_symbol_table = mod_tab
193
191
 
194
192
  if completion_trigger == ".":
195
193
  if current_symbol_path:
196
- completion_items = resolve_completion_symbol_table(
197
- mod_tab, current_symbol_path, current_tab
198
- )
194
+ temp_tab = mod_tab
195
+ for symbol in current_symbol_path:
196
+ if symbol == "self":
197
+ is_ability_def = (
198
+ temp_tab.owner
199
+ if isinstance(temp_tab.owner, ast.AbilityDef)
200
+ else temp_tab.owner.find_parent_of_type(ast.AbilityDef)
201
+ )
202
+ if not is_ability_def:
203
+ archi_owner = mod_tab.owner.find_parent_of_type(
204
+ ast.Architype
205
+ )
206
+ temp_tab = (
207
+ archi_owner._sym_tab
208
+ if archi_owner and archi_owner._sym_tab
209
+ else mod_tab
210
+ )
211
+ continue
212
+ else:
213
+ archi_owner = (
214
+ (
215
+ is_ability_def.decl_link.find_parent_of_type(
216
+ ast.Architype
217
+ )
218
+ )
219
+ if is_ability_def.decl_link
220
+ else None
221
+ )
222
+ temp_tab = (
223
+ archi_owner.sym_tab
224
+ if archi_owner and archi_owner.sym_tab
225
+ else temp_tab
226
+ )
227
+ continue
228
+ symb = temp_tab.lookup(symbol)
229
+ if symb:
230
+ fetc_tab = symb.fetch_sym_tab
231
+ if fetc_tab:
232
+ temp_tab = fetc_tab
233
+ else:
234
+ temp_tab = (
235
+ symb.defn[0].type_sym_tab
236
+ if symb.defn[0].type_sym_tab
237
+ else temp_tab
238
+ )
239
+ else:
240
+ break
241
+ completion_items = collect_all_symbols_in_scope(temp_tab, up_tree=False)
242
+ if (
243
+ isinstance(temp_tab.owner, ast.Architype)
244
+ and temp_tab.owner.base_classes
245
+ ):
246
+ base = []
247
+ for base_name in temp_tab.owner.base_classes.items:
248
+ if isinstance(base_name, ast.Name) and base_name.sym:
249
+ base.append(base_name.sym)
250
+ for base_class_symbol in base:
251
+ if base_class_symbol.fetch_sym_tab:
252
+ completion_items += collect_all_symbols_in_scope(
253
+ base_class_symbol.fetch_sym_tab,
254
+ up_tree=False,
255
+ )
256
+
199
257
  else:
200
258
  completion_items = []
201
259
  else:
@@ -349,7 +407,10 @@ class JacLangServer(LanguageServer):
349
407
  elif node_selected.parent and isinstance(
350
408
  node_selected.parent, ast.ModuleItem
351
409
  ):
352
- path = node_selected.parent.from_mod_path.abs_path
410
+ path = (
411
+ node_selected.parent.abs_path
412
+ or node_selected.parent.from_mod_path.abs_path
413
+ )
353
414
  try: # TODO: Get rid of this when 'from' import is fixed
354
415
  loc_range = tuple(
355
416
  loc - 1 if loc > 0 else loc
@@ -371,7 +432,7 @@ class JacLangServer(LanguageServer):
371
432
  ),
372
433
  ),
373
434
  )
374
- elif isinstance(node_selected, (ast.ElementStmt, ast.BuiltinType)):
435
+ elif isinstance(node_selected, ast.ElementStmt):
375
436
  return None
376
437
  decl_node = (
377
438
  node_selected.parent.body.target
@@ -218,9 +218,9 @@ class TestJacLangServer(TestCase):
218
218
  )
219
219
  lsp.deep_check(import_file)
220
220
  positions = [
221
- (6, 39, "/pygame_mock/__init__.py:2:0-2:0"),
221
+ (6, 39, "/pygame_mock/__init__.pyi:2:0-2:0"),
222
222
  (6, 45, "/pygame_mock/constants.py:3:0-4:1"),
223
- (7, 31, "/pygame_mock/__init__.py:2:0-2:0"),
223
+ (7, 31, "/pygame_mock/__init__.pyi:2:0-2:0"),
224
224
  (7, 35, "/pygame_mock/constants.py:3:0-4:1"),
225
225
  (20, 51, "/py_imp_test.jac:6:4-6:11"),
226
226
  (20, 64, "/pygame_mock/constants.py:4:3-4:15"),
@@ -282,7 +282,7 @@ class TestJacLangServer(TestCase):
282
282
  ),
283
283
  (
284
284
  "<JacSemTokenType.FUNCTION: 12>, <JacSemTokenModifier.DECLARATION: 1>,",
285
- 6,
285
+ 8,
286
286
  ),
287
287
  ("<JacSemTokenType.METHOD: 13>, <JacSemTokenModifier.DECLARATION: 1>", 6),
288
288
  ("<JacSemTokenType.ENUM: 3>, <JacSemTokenModifier.DECLARATION: 1>,", 4),
@@ -332,119 +332,6 @@ def parse_symbol_path(text: str, dot_position: int) -> list[str]:
332
332
  return all_words
333
333
 
334
334
 
335
- def resolve_symbol_path(sym_name: str, node_tab: SymbolTable) -> str:
336
- """Resolve symbol path."""
337
- visited = set()
338
- current_tab: Optional[SymbolTable] = node_tab
339
-
340
- while current_tab is not None and current_tab not in visited:
341
- visited.add(current_tab)
342
- for name, symbol in current_tab.tab.items():
343
- if name not in dir(builtins) and name == sym_name:
344
- path = symbol.defn[0]._sym_type
345
- if symbol.sym_type == SymbolType.ENUM_ARCH:
346
- if isinstance(current_tab.owner, ast.Module):
347
- return current_tab.owner.name + "." + sym_name
348
- elif isinstance(current_tab.owner, ast.AstSymbolNode):
349
- return current_tab.owner.name_spec._sym_type + "." + sym_name
350
- return path
351
- current_tab = current_tab.parent if current_tab.parent != current_tab else None
352
- return ""
353
-
354
-
355
- def find_symbol_table(path: str, current_tab: Optional[SymbolTable]) -> SymbolTable:
356
- """Find symbol table."""
357
- path = path.lstrip(".")
358
- current_table = current_tab
359
- if current_table:
360
- for segment in path.split("."):
361
- current_table = next(
362
- (
363
- child_table
364
- for child_table in current_table.kid
365
- if child_table.name == segment
366
- ),
367
- current_table,
368
- )
369
- if current_table:
370
- return current_table
371
- raise ValueError(f"Symbol table not found for path {path}")
372
-
373
-
374
- def resolve_completion_symbol_table(
375
- mod_tab: SymbolTable,
376
- current_symbol_path: list[str],
377
- current_tab: Optional[SymbolTable],
378
- ) -> list[lspt.CompletionItem]:
379
- """Resolve symbol table for completion items."""
380
- current_symbol_table = mod_tab
381
- for obj in current_symbol_path:
382
- if obj == "self":
383
- try:
384
- try:
385
- is_abilitydef = (
386
- mod_tab.owner
387
- if isinstance(mod_tab.owner, ast.AbilityDef)
388
- else mod_tab.owner.parent_of_type(ast.AbilityDef)
389
- )
390
- archi_owner = (
391
- (is_abilitydef.decl_link.parent_of_type(ast.Architype))
392
- if is_abilitydef.decl_link
393
- else None
394
- )
395
- current_symbol_table = (
396
- archi_owner._sym_tab
397
- if archi_owner and archi_owner._sym_tab
398
- else mod_tab
399
- )
400
- continue
401
-
402
- except ValueError:
403
- pass
404
- archi_owner = mod_tab.owner.parent_of_type(ast.Architype)
405
- current_symbol_table = (
406
- archi_owner._sym_tab
407
- if archi_owner and archi_owner._sym_tab
408
- else mod_tab
409
- )
410
- except ValueError:
411
- pass
412
- else:
413
- path: str = resolve_symbol_path(obj, current_symbol_table)
414
- if path:
415
- current_symbol_table = find_symbol_table(path, current_tab)
416
- else:
417
- if (
418
- isinstance(current_symbol_table.owner, ast.Architype)
419
- and current_symbol_table.owner.base_classes
420
- ):
421
- for base_name in current_symbol_table.owner.base_classes.items:
422
- if isinstance(base_name, ast.Name) and base_name.sym:
423
- path = base_name.sym.sym_dotted_name + "." + obj
424
- current_symbol_table = find_symbol_table(path, current_tab)
425
- if (
426
- isinstance(current_symbol_table.owner, ast.Architype)
427
- and current_symbol_table.owner.base_classes
428
- ):
429
- base = []
430
- for base_name in current_symbol_table.owner.base_classes.items:
431
- if isinstance(base_name, ast.Name) and base_name.sym:
432
- base.append(base_name.sym.sym_dotted_name)
433
- for base_ in base:
434
- completion_items = collect_all_symbols_in_scope(
435
- find_symbol_table(base_, current_tab),
436
- up_tree=False,
437
- )
438
- else:
439
- completion_items = []
440
- if isinstance(current_symbol_table.owner, (ast.Ability, ast.AbilityDef)):
441
- return completion_items
442
- completion_items.extend(
443
- collect_all_symbols_in_scope(current_symbol_table, up_tree=False)
444
- )
445
- return completion_items
446
-
447
-
448
335
  def get_token_start(
449
336
  token_index: int | None, sem_tokens: list[int]
450
337
  ) -> tuple[int, int, int]:
@@ -337,8 +337,8 @@ class TestJaseciPlugin(TestCase):
337
337
 
338
338
  # --------- NO UPDATE SHOULD HAPPEN -------- #
339
339
 
340
- self.assertTrue(archs[0], "A(val=2)")
341
- self.assertTrue(archs[1], "A(val=1)")
340
+ self.assertEqual(archs[0], "A(val=2)")
341
+ self.assertEqual(archs[1], "A(val=1)")
342
342
 
343
343
  self._output2buffer()
344
344
  cli.enter(
@@ -435,8 +435,8 @@ class TestJaseciPlugin(TestCase):
435
435
 
436
436
  # --------- UPDATE SHOULD HAPPEN -------- #
437
437
 
438
- self.assertTrue(archs[0], "A(val=20)")
439
- self.assertTrue(archs[1], "A(val=10)")
438
+ self.assertEqual(archs[0], "A(val=20)")
439
+ self.assertEqual(archs[1], "A(val=10)")
440
440
 
441
441
  self._output2buffer()
442
442
  cli.enter(
@@ -474,6 +474,25 @@ class TestJaseciPlugin(TestCase):
474
474
  )
475
475
  self.assertFalse(self.capturedOutput.getvalue().strip())
476
476
 
477
+ # --------- ROOTS RESET OWN NODE -------- #
478
+
479
+ cli.enter(
480
+ filename=self.fixture_abs_path("other_root_access.jac"),
481
+ entrypoint="update_node",
482
+ args=[1],
483
+ session=session,
484
+ root=self.roots[0],
485
+ node=self.nodes[0],
486
+ )
487
+ cli.enter(
488
+ filename=self.fixture_abs_path("other_root_access.jac"),
489
+ entrypoint="update_node",
490
+ args=[2],
491
+ session=session,
492
+ root=self.roots[1],
493
+ node=self.nodes[1],
494
+ )
495
+
477
496
  def test_other_root_access(self) -> None:
478
497
  """Test filtering on node, then visit."""
479
498
  global session