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.
- jaclang/cli/cli.py +2 -2
- jaclang/compiler/absyntree.py +1 -1
- jaclang/compiler/jac.lark +14 -14
- jaclang/compiler/parser.py +71 -59
- jaclang/compiler/passes/ir_pass.py +2 -0
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +50 -13
- jaclang/compiler/passes/main/import_pass.py +29 -1
- jaclang/compiler/passes/main/py_collect_dep_pass.py +8 -0
- jaclang/compiler/passes/main/registry_pass.py +4 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +0 -18
- jaclang/compiler/passes/main/tests/fixtures/mod_type_assign.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +10 -10
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +23 -1
- jaclang/compiler/passes/main/type_check_pass.py +4 -4
- jaclang/compiler/passes/tool/jac_formatter_pass.py +61 -31
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/line_spacing.jac +57 -0
- jaclang/compiler/semtable.py +4 -4
- jaclang/compiler/symtable.py +5 -0
- jaclang/langserve/engine.py +68 -7
- jaclang/langserve/tests/test_server.py +3 -3
- jaclang/langserve/utils.py +0 -113
- jaclang/plugin/tests/test_jaseci.py +23 -4
- jaclang/runtimelib/architype.py +20 -2
- jaclang/runtimelib/importer.py +3 -0
- jaclang/runtimelib/machine.py +92 -4
- jaclang/runtimelib/memory.py +1 -1
- jaclang/settings.py +4 -0
- jaclang/tests/fixtures/bar.jac +1 -1
- jaclang/tests/fixtures/builtins_test.jac +16 -0
- jaclang/tests/fixtures/dynamic_architype.jac +34 -0
- jaclang/tests/fixtures/entry_exit.jac +36 -0
- jaclang/tests/fixtures/foo.jac +0 -1
- jaclang/tests/fixtures/match_multi_ex.jac +12 -0
- jaclang/tests/fixtures/trailing_comma.jac +88 -0
- jaclang/tests/fixtures/walker_update.jac +19 -0
- jaclang/tests/test_cli.py +29 -2
- jaclang/tests/test_language.py +131 -2
- jaclang/utils/treeprinter.py +1 -1
- {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/METADATA +4 -2
- {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/RECORD +45 -36
- {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/WHEEL +0 -0
- {jaclang-0.7.18.dist-info → jaclang-0.7.21.dist-info}/entry_points.txt +0 -0
|
@@ -70,19 +70,19 @@ class ImportPassPassTests(TestCase):
|
|
|
70
70
|
)
|
|
71
71
|
assert isinstance(build.ir, ast.Module)
|
|
72
72
|
p = {
|
|
73
|
-
"math": "jaclang/
|
|
74
|
-
"pygame_mock": "pygame_mock/__init__.
|
|
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.
|
|
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"),
|
|
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
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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.
|
|
283
|
-
if
|
|
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
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
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
|
+
}
|
jaclang/compiler/semtable.py
CHANGED
|
@@ -19,13 +19,13 @@ class SemInfo:
|
|
|
19
19
|
self,
|
|
20
20
|
node: ast.AstNode,
|
|
21
21
|
name: str,
|
|
22
|
-
|
|
22
|
+
type_str: Optional[str] = None,
|
|
23
23
|
semstr: str = "",
|
|
24
24
|
) -> None:
|
|
25
25
|
"""Initialize the class."""
|
|
26
|
-
self.
|
|
26
|
+
self.node_type = type(node)
|
|
27
27
|
self.name = name
|
|
28
|
-
self.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
|
|
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
|
|
jaclang/compiler/symtable.py
CHANGED
|
@@ -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)
|
jaclang/langserve/engine.py
CHANGED
|
@@ -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
|
-
|
|
197
|
-
|
|
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 =
|
|
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,
|
|
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__.
|
|
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__.
|
|
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
|
-
|
|
285
|
+
8,
|
|
286
286
|
),
|
|
287
287
|
("<JacSemTokenType.METHOD: 13>, <JacSemTokenModifier.DECLARATION: 1>", 6),
|
|
288
288
|
("<JacSemTokenType.ENUM: 3>, <JacSemTokenModifier.DECLARATION: 1>,", 4),
|
jaclang/langserve/utils.py
CHANGED
|
@@ -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.
|
|
341
|
-
self.
|
|
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.
|
|
439
|
-
self.
|
|
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
|