jaclang 0.7.14__py3-none-any.whl → 0.7.17__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 +147 -77
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +19 -53
- jaclang/compiler/absyntree.py +94 -16
- jaclang/compiler/constant.py +8 -8
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +41 -25
- jaclang/compiler/passes/ir_pass.py +4 -13
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
- jaclang/compiler/passes/main/import_pass.py +99 -75
- jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
- jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
- jaclang/compiler/passes/main/registry_pass.py +37 -3
- jaclang/compiler/passes/main/schedules.py +9 -2
- jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
- jaclang/compiler/passes/main/tests/__init__.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
- jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
- jaclang/compiler/passes/main/type_check_pass.py +22 -5
- jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
- jaclang/compiler/semtable.py +31 -7
- jaclang/compiler/symtable.py +16 -11
- jaclang/compiler/tests/test_importer.py +25 -10
- jaclang/langserve/engine.py +104 -118
- jaclang/langserve/sem_manager.py +379 -0
- jaclang/langserve/server.py +24 -11
- jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/fixtures/rename.jac +30 -0
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +287 -17
- jaclang/langserve/utils.py +184 -98
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +288 -92
- jaclang/plugin/feature.py +65 -27
- jaclang/plugin/spec.py +62 -23
- jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
- jaclang/plugin/tests/test_jaseci.py +414 -42
- jaclang/runtimelib/architype.py +650 -0
- jaclang/{core → runtimelib}/constructs.py +5 -8
- jaclang/{core → runtimelib}/context.py +86 -59
- jaclang/runtimelib/importer.py +361 -0
- jaclang/runtimelib/machine.py +158 -0
- jaclang/runtimelib/memory.py +158 -0
- jaclang/{core → runtimelib}/utils.py +30 -15
- jaclang/settings.py +5 -4
- jaclang/tests/fixtures/abc.jac +3 -3
- jaclang/tests/fixtures/access_checker.jac +12 -17
- jaclang/tests/fixtures/access_modifier.jac +88 -33
- jaclang/tests/fixtures/baddy.jac +3 -0
- jaclang/tests/fixtures/baddy.test.jac +3 -0
- jaclang/tests/fixtures/bar.jac +34 -0
- jaclang/tests/fixtures/byllmissue.jac +1 -5
- jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
- jaclang/tests/fixtures/cls_method.jac +41 -0
- jaclang/tests/fixtures/dblhello.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/fixtures/deep_import_mods.jac +13 -0
- jaclang/tests/fixtures/edge_node_walk.jac +1 -1
- jaclang/tests/fixtures/edge_ops.jac +1 -1
- jaclang/tests/fixtures/edges_walk.jac +1 -1
- jaclang/tests/fixtures/err.impl.jac +3 -0
- jaclang/tests/fixtures/err.jac +4 -2
- jaclang/tests/fixtures/err_runtime.jac +15 -0
- jaclang/tests/fixtures/foo.jac +43 -0
- jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
- jaclang/tests/fixtures/hello.jac +4 -0
- jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
- jaclang/tests/fixtures/impl_grab.jac +4 -1
- jaclang/tests/fixtures/import.jac +9 -0
- jaclang/tests/fixtures/index_slice.jac +30 -0
- jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/needs_import.jac +2 -2
- jaclang/tests/fixtures/pyfunc_1.py +1 -1
- jaclang/tests/fixtures/pyfunc_2.py +5 -2
- jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
- jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
- jaclang/tests/fixtures/registry.jac +9 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/fixtures/semstr.jac +1 -4
- jaclang/tests/fixtures/simple_archs.jac +1 -1
- jaclang/tests/test_cli.py +109 -3
- jaclang/tests/test_language.py +170 -68
- jaclang/tests/test_reference.py +2 -3
- jaclang/utils/helpers.py +45 -21
- jaclang/utils/test.py +9 -0
- jaclang/utils/treeprinter.py +30 -7
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
- jaclang/core/architype.py +0 -502
- jaclang/core/importer.py +0 -344
- jaclang/core/memory.py +0 -99
- jaclang/tests/fixtures/aott_raise.jac +0 -25
- jaclang/tests/fixtures/package_import.jac +0 -6
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
"""Semantic Token Manager module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional, Tuple
|
|
6
|
+
|
|
7
|
+
import jaclang.compiler.absyntree as ast
|
|
8
|
+
from jaclang.langserve.utils import (
|
|
9
|
+
find_surrounding_tokens,
|
|
10
|
+
get_line_of_code,
|
|
11
|
+
get_token_start,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
import lsprotocol.types as lspt
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SemTokManager:
|
|
18
|
+
"""Semantic Token Manager class."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, ir: ast.Module) -> None:
|
|
21
|
+
"""Initialize semantic token manager."""
|
|
22
|
+
self.sem_tokens: List[int] = self.gen_sem_tokens(ir)
|
|
23
|
+
self.static_sem_tokens: List[
|
|
24
|
+
Tuple[lspt.Position, int, int, ast.AstSymbolNode]
|
|
25
|
+
] = self.gen_sem_tok_node(ir)
|
|
26
|
+
|
|
27
|
+
def gen_sem_tokens(self, ir: ast.Module) -> list[int]:
|
|
28
|
+
"""Return semantic tokens."""
|
|
29
|
+
tokens = []
|
|
30
|
+
prev_line, prev_col = 0, 0
|
|
31
|
+
for node in ir._in_mod_nodes:
|
|
32
|
+
if isinstance(node, ast.NameAtom) and node.sem_token:
|
|
33
|
+
line, col_start, col_end = (
|
|
34
|
+
node.loc.first_line - 1,
|
|
35
|
+
node.loc.col_start - 1,
|
|
36
|
+
node.loc.col_end - 1,
|
|
37
|
+
)
|
|
38
|
+
length = col_end - col_start
|
|
39
|
+
tokens += [
|
|
40
|
+
line - prev_line,
|
|
41
|
+
col_start if line != prev_line else col_start - prev_col,
|
|
42
|
+
length,
|
|
43
|
+
*node.sem_token,
|
|
44
|
+
]
|
|
45
|
+
prev_line, prev_col = line, col_start
|
|
46
|
+
return tokens
|
|
47
|
+
|
|
48
|
+
def gen_sem_tok_node(
|
|
49
|
+
self, ir: ast.Module
|
|
50
|
+
) -> List[Tuple[lspt.Position, int, int, ast.AstSymbolNode]]:
|
|
51
|
+
"""Return semantic tokens."""
|
|
52
|
+
tokens: List[Tuple[lspt.Position, int, int, ast.AstSymbolNode]] = []
|
|
53
|
+
for node in ir._in_mod_nodes:
|
|
54
|
+
if isinstance(node, ast.NameAtom) and node.sem_token:
|
|
55
|
+
line, col_start, col_end = (
|
|
56
|
+
node.loc.first_line - 1,
|
|
57
|
+
node.loc.col_start - 1,
|
|
58
|
+
node.loc.col_end - 1,
|
|
59
|
+
)
|
|
60
|
+
length = col_end - col_start
|
|
61
|
+
pos = lspt.Position(line, col_start)
|
|
62
|
+
tokens += [(pos, col_end, length, node)]
|
|
63
|
+
return tokens
|
|
64
|
+
|
|
65
|
+
def update_sem_tokens(
|
|
66
|
+
self,
|
|
67
|
+
content_changes: lspt.DidChangeTextDocumentParams,
|
|
68
|
+
sem_tokens: list[int],
|
|
69
|
+
document_lines: List[str],
|
|
70
|
+
) -> list[int]:
|
|
71
|
+
"""Update semantic tokens on change."""
|
|
72
|
+
for change in [
|
|
73
|
+
x
|
|
74
|
+
for x in content_changes.content_changes
|
|
75
|
+
if isinstance(x, lspt.TextDocumentContentChangeEvent_Type1)
|
|
76
|
+
]:
|
|
77
|
+
change_start_line = change.range.start.line
|
|
78
|
+
change_start_char = change.range.start.character
|
|
79
|
+
change_end_line = change.range.end.line
|
|
80
|
+
change_end_char = change.range.end.character
|
|
81
|
+
|
|
82
|
+
is_delete = change.text == ""
|
|
83
|
+
prev_token_index, next_token_index, insert_inside_token = (
|
|
84
|
+
find_surrounding_tokens(
|
|
85
|
+
change_start_line,
|
|
86
|
+
change_start_char,
|
|
87
|
+
change_end_line,
|
|
88
|
+
change_end_char,
|
|
89
|
+
sem_tokens,
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
prev_tok_pos = get_token_start(prev_token_index, sem_tokens)
|
|
93
|
+
nxt_tok_pos = get_token_start(next_token_index, sem_tokens)
|
|
94
|
+
changing_line_text = get_line_of_code(change_start_line, document_lines)
|
|
95
|
+
if not changing_line_text:
|
|
96
|
+
return sem_tokens
|
|
97
|
+
is_edit_between_tokens = bool(
|
|
98
|
+
(
|
|
99
|
+
change_start_line > prev_tok_pos[0]
|
|
100
|
+
or (
|
|
101
|
+
change_start_line == prev_tok_pos[0]
|
|
102
|
+
and change_start_char
|
|
103
|
+
> prev_tok_pos[1] + sem_tokens[prev_token_index + 2]
|
|
104
|
+
if prev_token_index and prev_token_index + 2 < len(sem_tokens)
|
|
105
|
+
else 0
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
and (
|
|
109
|
+
change_end_line < nxt_tok_pos[0]
|
|
110
|
+
or (
|
|
111
|
+
change_end_line == nxt_tok_pos[0]
|
|
112
|
+
and change_end_char < nxt_tok_pos[1]
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
text = r"%s" % change.text
|
|
117
|
+
line_delta = len(text.split("\n")) - 1
|
|
118
|
+
|
|
119
|
+
is_multiline_insertion = line_delta > 0
|
|
120
|
+
is_next_token_same_line = change_end_line == nxt_tok_pos[0]
|
|
121
|
+
|
|
122
|
+
if is_delete:
|
|
123
|
+
next_token_index = (
|
|
124
|
+
prev_token_index + 5
|
|
125
|
+
if insert_inside_token
|
|
126
|
+
and prev_token_index is not None
|
|
127
|
+
or (
|
|
128
|
+
next_token_index
|
|
129
|
+
and prev_token_index is not None
|
|
130
|
+
and next_token_index >= 10
|
|
131
|
+
and next_token_index - prev_token_index == 10
|
|
132
|
+
)
|
|
133
|
+
else next_token_index
|
|
134
|
+
)
|
|
135
|
+
if next_token_index is None:
|
|
136
|
+
return sem_tokens
|
|
137
|
+
nxt_tok_pos = get_token_start(next_token_index, sem_tokens)
|
|
138
|
+
is_single_line_change = change_end_line == change_start_line
|
|
139
|
+
is_next_token_same_line = change_end_line == nxt_tok_pos[0]
|
|
140
|
+
if (
|
|
141
|
+
is_single_line_change
|
|
142
|
+
and insert_inside_token
|
|
143
|
+
and prev_token_index is not None
|
|
144
|
+
):
|
|
145
|
+
sem_tokens = SemTokManager.handle_single_line_delete(
|
|
146
|
+
sem_tokens,
|
|
147
|
+
next_token_index,
|
|
148
|
+
prev_token_index,
|
|
149
|
+
is_next_token_same_line,
|
|
150
|
+
change,
|
|
151
|
+
)
|
|
152
|
+
elif is_single_line_change and is_edit_between_tokens:
|
|
153
|
+
sem_tokens = SemTokManager.handle_single_line_delete_between_tokens(
|
|
154
|
+
sem_tokens,
|
|
155
|
+
next_token_index,
|
|
156
|
+
is_next_token_same_line,
|
|
157
|
+
change,
|
|
158
|
+
change_start_line,
|
|
159
|
+
change_end_line,
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
sem_tokens = SemTokManager.handle_multi_line_delete(
|
|
163
|
+
sem_tokens,
|
|
164
|
+
next_token_index,
|
|
165
|
+
nxt_tok_pos,
|
|
166
|
+
change_start_line,
|
|
167
|
+
change_end_line,
|
|
168
|
+
change_start_char,
|
|
169
|
+
change_end_char,
|
|
170
|
+
prev_tok_pos,
|
|
171
|
+
is_next_token_same_line,
|
|
172
|
+
)
|
|
173
|
+
return sem_tokens
|
|
174
|
+
|
|
175
|
+
is_token_boundary_edit = False
|
|
176
|
+
if insert_inside_token and prev_token_index is not None:
|
|
177
|
+
sem_tokens, is_token_boundary_edit, nxt_tok_pos, next_token_index = (
|
|
178
|
+
SemTokManager.handle_insert_inside_token(
|
|
179
|
+
change,
|
|
180
|
+
sem_tokens,
|
|
181
|
+
prev_token_index,
|
|
182
|
+
changing_line_text,
|
|
183
|
+
line_delta,
|
|
184
|
+
prev_tok_pos,
|
|
185
|
+
change_start_char,
|
|
186
|
+
change_end_char,
|
|
187
|
+
is_token_boundary_edit,
|
|
188
|
+
nxt_tok_pos,
|
|
189
|
+
)
|
|
190
|
+
)
|
|
191
|
+
tokens_on_same_line = prev_tok_pos[0] == nxt_tok_pos[0]
|
|
192
|
+
if (
|
|
193
|
+
is_edit_between_tokens
|
|
194
|
+
or is_token_boundary_edit
|
|
195
|
+
or is_multiline_insertion
|
|
196
|
+
) and next_token_index is not None:
|
|
197
|
+
if is_multiline_insertion:
|
|
198
|
+
sem_tokens = SemTokManager.handle_multi_line_insertion(
|
|
199
|
+
sem_tokens,
|
|
200
|
+
next_token_index,
|
|
201
|
+
nxt_tok_pos,
|
|
202
|
+
change_start_line,
|
|
203
|
+
change_end_line,
|
|
204
|
+
change_end_char,
|
|
205
|
+
prev_tok_pos,
|
|
206
|
+
tokens_on_same_line,
|
|
207
|
+
changing_line_text,
|
|
208
|
+
line_delta,
|
|
209
|
+
)
|
|
210
|
+
else:
|
|
211
|
+
sem_tokens = SemTokManager.handle_single_line_insertion(
|
|
212
|
+
sem_tokens,
|
|
213
|
+
next_token_index,
|
|
214
|
+
is_next_token_same_line,
|
|
215
|
+
change,
|
|
216
|
+
tokens_on_same_line,
|
|
217
|
+
nxt_tok_pos,
|
|
218
|
+
change_start_line,
|
|
219
|
+
line_delta,
|
|
220
|
+
)
|
|
221
|
+
return sem_tokens
|
|
222
|
+
|
|
223
|
+
@staticmethod
|
|
224
|
+
def handle_multi_line_delete(
|
|
225
|
+
sem_tokens: list[int],
|
|
226
|
+
next_token_index: int,
|
|
227
|
+
nxt_tok_pos: tuple[int, int, int],
|
|
228
|
+
change_start_line: int,
|
|
229
|
+
change_end_line: int,
|
|
230
|
+
change_start_char: int,
|
|
231
|
+
change_end_char: int,
|
|
232
|
+
prev_tok_pos: tuple[int, int, int],
|
|
233
|
+
is_next_token_same_line: bool,
|
|
234
|
+
) -> list[int]:
|
|
235
|
+
"""Handle multi line deletion."""
|
|
236
|
+
if is_next_token_same_line:
|
|
237
|
+
char_del = nxt_tok_pos[1] - change_end_char
|
|
238
|
+
total_char_del = change_start_char + char_del
|
|
239
|
+
sem_tokens[next_token_index + 1] = (
|
|
240
|
+
(total_char_del - prev_tok_pos[1])
|
|
241
|
+
if prev_tok_pos[0] == change_start_line
|
|
242
|
+
else total_char_del
|
|
243
|
+
)
|
|
244
|
+
sem_tokens[next_token_index] -= change_end_line - change_start_line
|
|
245
|
+
return sem_tokens
|
|
246
|
+
|
|
247
|
+
@staticmethod
|
|
248
|
+
def handle_single_line_delete_between_tokens(
|
|
249
|
+
sem_tokens: list[int],
|
|
250
|
+
next_token_index: int,
|
|
251
|
+
is_next_token_same_line: bool,
|
|
252
|
+
change: lspt.TextDocumentContentChangeEvent_Type1,
|
|
253
|
+
change_start_line: int,
|
|
254
|
+
change_end_line: int,
|
|
255
|
+
) -> list[int]:
|
|
256
|
+
"""Handle single line deletion between tokens."""
|
|
257
|
+
if is_next_token_same_line:
|
|
258
|
+
sem_tokens[next_token_index + 1] -= change.range_length
|
|
259
|
+
|
|
260
|
+
else:
|
|
261
|
+
sem_tokens[next_token_index] -= change_end_line - change_start_line
|
|
262
|
+
return sem_tokens
|
|
263
|
+
|
|
264
|
+
@staticmethod
|
|
265
|
+
def handle_single_line_delete(
|
|
266
|
+
sem_tokens: list[int],
|
|
267
|
+
next_token_index: int,
|
|
268
|
+
prev_token_index: int,
|
|
269
|
+
is_next_token_same_line: bool,
|
|
270
|
+
change: lspt.TextDocumentContentChangeEvent_Type1,
|
|
271
|
+
) -> list[int]:
|
|
272
|
+
"""Handle single line deletion."""
|
|
273
|
+
sem_tokens[prev_token_index + 2] -= change.range_length
|
|
274
|
+
if is_next_token_same_line:
|
|
275
|
+
sem_tokens[next_token_index + 1] -= change.range_length
|
|
276
|
+
return sem_tokens
|
|
277
|
+
|
|
278
|
+
@staticmethod
|
|
279
|
+
def handle_single_line_insertion(
|
|
280
|
+
sem_tokens: list[int],
|
|
281
|
+
next_token_index: int,
|
|
282
|
+
is_next_token_same_line: bool,
|
|
283
|
+
change: lspt.TextDocumentContentChangeEvent_Type1,
|
|
284
|
+
tokens_on_same_line: bool,
|
|
285
|
+
nxt_tok_pos: tuple[int, int, int],
|
|
286
|
+
change_start_line: int,
|
|
287
|
+
line_delta: int,
|
|
288
|
+
) -> list[int]:
|
|
289
|
+
"""Handle single line insertion."""
|
|
290
|
+
if tokens_on_same_line:
|
|
291
|
+
sem_tokens[next_token_index + 1] += len(change.text)
|
|
292
|
+
sem_tokens[next_token_index] += line_delta
|
|
293
|
+
else:
|
|
294
|
+
is_next_token_same_line = change_start_line == nxt_tok_pos[0]
|
|
295
|
+
if is_next_token_same_line:
|
|
296
|
+
sem_tokens[next_token_index] += line_delta
|
|
297
|
+
sem_tokens[next_token_index + 1] += len(change.text)
|
|
298
|
+
else:
|
|
299
|
+
sem_tokens[next_token_index] += line_delta
|
|
300
|
+
return sem_tokens
|
|
301
|
+
|
|
302
|
+
@staticmethod
|
|
303
|
+
def handle_multi_line_insertion(
|
|
304
|
+
sem_tokens: list[int],
|
|
305
|
+
next_token_index: int,
|
|
306
|
+
nxt_tok_pos: tuple[int, int, int],
|
|
307
|
+
change_start_line: int,
|
|
308
|
+
change_end_line: int,
|
|
309
|
+
change_end_char: int,
|
|
310
|
+
prev_tok_pos: tuple[int, int, int],
|
|
311
|
+
tokens_on_same_line: bool,
|
|
312
|
+
changing_line_text: tuple[str, int],
|
|
313
|
+
line_delta: int,
|
|
314
|
+
) -> list[int]:
|
|
315
|
+
"""Handle multi line insertion."""
|
|
316
|
+
if tokens_on_same_line:
|
|
317
|
+
char_del = nxt_tok_pos[1] - change_end_char
|
|
318
|
+
total_char_del = changing_line_text[1] + char_del
|
|
319
|
+
|
|
320
|
+
else:
|
|
321
|
+
is_prev_token_same_line = change_end_line == prev_tok_pos[0]
|
|
322
|
+
is_next_token_same_line = change_start_line == nxt_tok_pos[0]
|
|
323
|
+
if is_prev_token_same_line:
|
|
324
|
+
total_char_del = nxt_tok_pos[1]
|
|
325
|
+
elif is_next_token_same_line:
|
|
326
|
+
char_del = nxt_tok_pos[1] - change_end_char
|
|
327
|
+
total_char_del = changing_line_text[1] + char_del
|
|
328
|
+
else:
|
|
329
|
+
total_char_del = sem_tokens[next_token_index + 1]
|
|
330
|
+
line_delta -= change_end_line - change_start_line
|
|
331
|
+
sem_tokens[next_token_index + 1] = total_char_del
|
|
332
|
+
sem_tokens[next_token_index] += line_delta
|
|
333
|
+
return sem_tokens
|
|
334
|
+
|
|
335
|
+
@staticmethod
|
|
336
|
+
def handle_insert_inside_token(
|
|
337
|
+
change: lspt.TextDocumentContentChangeEvent_Type1,
|
|
338
|
+
sem_tokens: list[int],
|
|
339
|
+
prev_token_index: int,
|
|
340
|
+
changing_line_text: tuple[str, int],
|
|
341
|
+
line_delta: int,
|
|
342
|
+
prev_tok_pos: tuple[int, int, int],
|
|
343
|
+
change_start_char: int,
|
|
344
|
+
change_end_char: int,
|
|
345
|
+
is_token_boundary_edit: bool,
|
|
346
|
+
nxt_tok_pos: tuple[int, int, int],
|
|
347
|
+
) -> tuple[list[int], bool, tuple[int, int, int], Optional[int]]:
|
|
348
|
+
"""Handle insert inside token."""
|
|
349
|
+
next_token_index = None
|
|
350
|
+
for i in ["\n", " ", "\t"]:
|
|
351
|
+
if i in change.text:
|
|
352
|
+
if prev_tok_pos[1] == change_start_char:
|
|
353
|
+
if i == "\n":
|
|
354
|
+
sem_tokens[prev_token_index] += line_delta
|
|
355
|
+
sem_tokens[prev_token_index + 1] = changing_line_text[1]
|
|
356
|
+
else:
|
|
357
|
+
sem_tokens[prev_token_index + 1] += len(change.text)
|
|
358
|
+
return (
|
|
359
|
+
sem_tokens,
|
|
360
|
+
is_token_boundary_edit,
|
|
361
|
+
nxt_tok_pos,
|
|
362
|
+
next_token_index,
|
|
363
|
+
)
|
|
364
|
+
else:
|
|
365
|
+
is_token_boundary_edit = True
|
|
366
|
+
next_token_index = prev_token_index + 5
|
|
367
|
+
nxt_tok_pos = get_token_start(next_token_index, sem_tokens)
|
|
368
|
+
break
|
|
369
|
+
if not is_token_boundary_edit:
|
|
370
|
+
selected_region = change_end_char - change_start_char
|
|
371
|
+
index_offset = 2
|
|
372
|
+
sem_tokens[prev_token_index + index_offset] += (
|
|
373
|
+
len(change.text) - selected_region
|
|
374
|
+
)
|
|
375
|
+
if prev_tok_pos[0] == get_token_start(prev_token_index + 5, sem_tokens)[0]:
|
|
376
|
+
sem_tokens[prev_token_index + index_offset + 4] += (
|
|
377
|
+
len(change.text) - selected_region
|
|
378
|
+
)
|
|
379
|
+
return sem_tokens, is_token_boundary_edit, nxt_tok_pos, next_token_index
|
jaclang/langserve/server.py
CHANGED
|
@@ -9,6 +9,7 @@ from jaclang.compiler.constant import (
|
|
|
9
9
|
JacSemTokenType as SemTokType,
|
|
10
10
|
)
|
|
11
11
|
from jaclang.langserve.engine import JacLangServer
|
|
12
|
+
from jaclang.settings import settings
|
|
12
13
|
|
|
13
14
|
import lsprotocol.types as lspt
|
|
14
15
|
|
|
@@ -16,8 +17,14 @@ server = JacLangServer()
|
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
@server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
|
|
19
|
-
@server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
|
|
20
20
|
async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
21
|
+
"""Check syntax on change."""
|
|
22
|
+
ls.deep_check(params.text_document.uri)
|
|
23
|
+
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
|
|
27
|
+
async def did_save(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
|
|
21
28
|
"""Check syntax on change."""
|
|
22
29
|
await ls.launch_deep_check(params.text_document.uri)
|
|
23
30
|
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
|
|
@@ -30,7 +37,11 @@ async def did_change(
|
|
|
30
37
|
"""Check syntax on change."""
|
|
31
38
|
await ls.launch_quick_check(file_path := params.text_document.uri)
|
|
32
39
|
if file_path in ls.modules:
|
|
33
|
-
ls.
|
|
40
|
+
document = ls.workspace.get_text_document(file_path)
|
|
41
|
+
lines = document.source.splitlines()
|
|
42
|
+
ls.modules[file_path].sem_manager.update_sem_tokens(
|
|
43
|
+
params, ls.modules[file_path].sem_manager.sem_tokens, lines
|
|
44
|
+
)
|
|
34
45
|
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
|
|
35
46
|
|
|
36
47
|
|
|
@@ -110,7 +121,7 @@ def document_symbol(
|
|
|
110
121
|
ls: JacLangServer, params: lspt.DocumentSymbolParams
|
|
111
122
|
) -> list[lspt.DocumentSymbol]:
|
|
112
123
|
"""Provide document symbols."""
|
|
113
|
-
return ls.
|
|
124
|
+
return ls.get_outline(params.text_document.uri)
|
|
114
125
|
|
|
115
126
|
|
|
116
127
|
@server.feature(lspt.TEXT_DOCUMENT_DEFINITION)
|
|
@@ -127,6 +138,15 @@ def references(ls: JacLangServer, params: lspt.ReferenceParams) -> list[lspt.Loc
|
|
|
127
138
|
return ls.get_references(params.text_document.uri, params.position)
|
|
128
139
|
|
|
129
140
|
|
|
141
|
+
@server.feature(lspt.TEXT_DOCUMENT_RENAME)
|
|
142
|
+
def rename(
|
|
143
|
+
ls: JacLangServer, params: lspt.RenameParams
|
|
144
|
+
) -> Optional[lspt.WorkspaceEdit]:
|
|
145
|
+
"""Rename symbol."""
|
|
146
|
+
ls.log_warning("Auto Rename is Experimental, Please use with caution.")
|
|
147
|
+
return ls.rename_symbol(params.text_document.uri, params.position, params.new_name)
|
|
148
|
+
|
|
149
|
+
|
|
130
150
|
@server.feature(
|
|
131
151
|
lspt.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
|
|
132
152
|
lspt.SemanticTokensLegend(
|
|
@@ -138,19 +158,12 @@ def semantic_tokens_full(
|
|
|
138
158
|
ls: JacLangServer, params: lspt.SemanticTokensParams
|
|
139
159
|
) -> lspt.SemanticTokens:
|
|
140
160
|
"""Provide semantic tokens."""
|
|
141
|
-
# import logging
|
|
142
|
-
|
|
143
|
-
# logging.info("\nGetting semantic tokens\n")
|
|
144
|
-
# # logging.info(ls.get_semantic_tokens(params.text_document.uri))
|
|
145
|
-
# i = 0
|
|
146
|
-
# while i < len(ls.get_semantic_tokens(params.text_document.uri).data):
|
|
147
|
-
# logging.info(ls.get_semantic_tokens(params.text_document.uri).data[i : i + 5])
|
|
148
|
-
# i += 5
|
|
149
161
|
return ls.get_semantic_tokens(params.text_document.uri)
|
|
150
162
|
|
|
151
163
|
|
|
152
164
|
def run_lang_server() -> None:
|
|
153
165
|
"""Run the language server."""
|
|
166
|
+
settings.pass_timer = True
|
|
154
167
|
server.start_io()
|
|
155
168
|
|
|
156
169
|
|
|
@@ -35,20 +35,41 @@ obj Colour1 {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
:obj:Colour1:can:get_color1 -> Colorenum {
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
return self.color1;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
obj red :Colour1: {
|
|
42
|
-
has base_colorred: Colorenum =
|
|
43
|
+
has base_colorred: Colorenum = Colorenum.RED,
|
|
43
44
|
pointred: int = 10;
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
obj inner_red {
|
|
47
|
+
has color22: enum_red = enum_red.BLUE22,
|
|
48
|
+
doublepoint22:doubleinner.double = 2,
|
|
46
49
|
point22: int = 20;
|
|
50
|
+
|
|
51
|
+
can apply_inner_red -> enum_red {
|
|
52
|
+
return self.color22;
|
|
53
|
+
}
|
|
54
|
+
enum enum_red {
|
|
55
|
+
RED22,
|
|
56
|
+
GREEN22,
|
|
57
|
+
BLUE22
|
|
58
|
+
}
|
|
47
59
|
}
|
|
60
|
+
class doubleinner {
|
|
61
|
+
has double: int = 2;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
can apply_red -> int {
|
|
65
|
+
x =
|
|
66
|
+
self.inner_red.color22.GREEN22;
|
|
67
|
+
return self.point1 + self.pointred;
|
|
68
|
+
}
|
|
48
69
|
}
|
|
49
70
|
|
|
50
71
|
with entry:__main__ {
|
|
51
|
-
r = red(color1=
|
|
72
|
+
r = red(color1=Colorenum.GREEN, point1=20);
|
|
52
73
|
print(r.get_color1());
|
|
53
|
-
print(r.
|
|
74
|
+
print(r.inner_red);
|
|
54
75
|
}
|
|
@@ -63,15 +63,15 @@ with entry:__main__ {
|
|
|
63
63
|
glob expected_area = 78.53981633974483;
|
|
64
64
|
|
|
65
65
|
test calc_area {
|
|
66
|
-
check
|
|
66
|
+
check almostEqual(calculate_area(RAD), expected_area);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
test circle_area {
|
|
70
70
|
c = Circle(RAD);
|
|
71
|
-
check
|
|
71
|
+
check almostEqual(c.area(), expected_area);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
test circle_type {
|
|
75
75
|
c = Circle(RAD);
|
|
76
|
-
check
|
|
76
|
+
check c.shape_type == ShapeType.CIRCLE;
|
|
77
77
|
}
|
|
@@ -59,15 +59,15 @@ print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}
|
|
|
59
59
|
glob expected_area = 78.53981633974483;
|
|
60
60
|
|
|
61
61
|
test calc_area {
|
|
62
|
-
check
|
|
62
|
+
check almostEqual(calculate_area(RAD), expected_area);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
test circle_area {
|
|
66
66
|
c = Circle(RAD);
|
|
67
|
-
check
|
|
67
|
+
check almostEqual(c.area(), expected_area);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
test circle_type {
|
|
71
71
|
c = Circle(RAD);
|
|
72
|
-
check
|
|
72
|
+
check c.shape_type == ShapeType.CIRCLE;
|
|
73
73
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
glob expected_area = 78.53981633974483;
|
|
2
2
|
|
|
3
3
|
test a1 {
|
|
4
|
-
check
|
|
4
|
+
check almostEqual(calculate_area(RAD), expected_area);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
test a2 {
|
|
8
8
|
c = Circle(RAD);
|
|
9
|
-
check
|
|
9
|
+
check almostEqual(c.area(), expected_area);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
test a3 {
|
|
13
13
|
c = Circle(RAD);
|
|
14
|
-
check
|
|
14
|
+
check c.shape_type == ShapeType.CIRCLE;
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import:py os;
|
|
2
2
|
import:py from math, sqrt as square_root;
|
|
3
3
|
import:py datetime as dt;
|
|
4
|
-
import:jac from base_module_structure,
|
|
4
|
+
import:jac from base_module_structure, add as add_numbers , subtract,x,Colorenum as clr;
|
|
5
5
|
import:jac base_module_structure as base_module_structure;
|
|
6
6
|
import:py from py_import,add1 as ss, sub1 as subtract1,apple,Orange1;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
can foo;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
:can:foo{
|
|
6
|
+
print("foo");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
obj out{
|
|
11
|
+
has cnt :int;
|
|
12
|
+
can bar;
|
|
13
|
+
can baz;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
:obj:out:can:bar{
|
|
18
|
+
print("bar");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:obj:out:can:baz{
|
|
22
|
+
print("baz");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
with entry{
|
|
26
|
+
foo();
|
|
27
|
+
new = out();
|
|
28
|
+
new.cnt;
|
|
29
|
+
out(1).bar();
|
|
30
|
+
}
|