jaclang 0.8.6__py3-none-any.whl → 0.8.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.md +3 -3
- jaclang/cli/cli.py +37 -37
- jaclang/cli/cmdreg.py +45 -140
- jaclang/compiler/constant.py +0 -1
- jaclang/compiler/jac.lark +3 -6
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +213 -34
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +0 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +83 -55
- jaclang/compiler/passes/main/pyast_load_pass.py +66 -40
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
- jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_binary_op.jac +21 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_call_expr_class.jac +12 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_cyclic_symbol.jac +4 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_expr_call.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_import_missing_module.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_magic_call.jac +17 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_mod_path.jac +8 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
- jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
- jaclang/compiler/passes/main/tests/test_checker_pass.py +265 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
- jaclang/compiler/passes/main/type_checker_pass.py +36 -61
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
- jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +171 -11
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +14 -6
- jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
- jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
- jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
- jaclang/compiler/tests/fixtures/python_module.py +1 -0
- jaclang/compiler/tests/test_importer.py +39 -0
- jaclang/compiler/tests/test_parser.py +49 -0
- jaclang/compiler/type_system/operations.py +104 -0
- jaclang/compiler/type_system/type_evaluator.py +470 -47
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +79 -94
- jaclang/langserve/engine.jac +253 -230
- jaclang/langserve/server.jac +46 -15
- 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/completion_test_err.jac +10 -0
- jaclang/langserve/tests/server_test/circle_template.jac +80 -0
- jaclang/langserve/tests/server_test/glob_template.jac +4 -0
- jaclang/langserve/tests/server_test/test_lang_serve.py +154 -312
- jaclang/langserve/tests/server_test/utils.py +153 -116
- jaclang/langserve/tests/test_dev_server.py +1 -1
- jaclang/langserve/tests/test_server.py +30 -86
- jaclang/langserve/utils.jac +56 -63
- jaclang/runtimelib/machine.py +7 -0
- jaclang/runtimelib/meta_importer.py +27 -1
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
- jaclang/settings.py +18 -14
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/jac_run_py_bugs.py +18 -0
- jaclang/tests/fixtures/jac_run_py_import.py +13 -0
- jaclang/tests/fixtures/lambda_arg_annotation.jac +15 -0
- jaclang/tests/fixtures/lambda_self.jac +18 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
- jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
- jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
- jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
- jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
- jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
- jaclang/tests/fixtures/py2jac_params.py +8 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/test_cli.py +103 -18
- jaclang/tests/test_language.py +74 -16
- jaclang/utils/helpers.py +47 -2
- jaclang/utils/module_resolver.py +11 -1
- jaclang/utils/test.py +8 -0
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/METADATA +3 -3
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/RECORD +99 -62
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- jaclang/langserve/tests/server_test/code_test.py +0 -0
- {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,353 +1,195 @@
|
|
|
1
|
-
"""Test for Jac language server
|
|
1
|
+
"""Test suite for Jac language server features."""
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import pytest
|
|
5
4
|
|
|
6
5
|
from lsprotocol.types import (
|
|
7
|
-
DidOpenTextDocumentParams,
|
|
8
|
-
TextDocumentItem,
|
|
9
|
-
DidSaveTextDocumentParams,
|
|
10
|
-
DidChangeTextDocumentParams,
|
|
11
6
|
DocumentFormattingParams,
|
|
12
7
|
TextEdit,
|
|
13
|
-
VersionedTextDocumentIdentifier,
|
|
14
8
|
TextDocumentIdentifier,
|
|
15
9
|
)
|
|
16
10
|
from jaclang.langserve.tests.server_test.utils import (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
create_ls_with_workspace, # new helper
|
|
11
|
+
TestFile,
|
|
12
|
+
LanguageServerTestHelper,
|
|
13
|
+
create_ls_with_workspace,
|
|
14
|
+
load_jac_template,
|
|
22
15
|
)
|
|
23
16
|
from jaclang.vendor.pygls.uris import from_fs_path
|
|
24
|
-
from jaclang.
|
|
25
|
-
from jaclang import JacMachineInterface as _
|
|
26
|
-
from jaclang.langserve.engine import JacLangServer
|
|
27
|
-
from jaclang.langserve.server import did_open, did_save, did_change, formatting
|
|
28
|
-
|
|
29
|
-
JAC_FILE = get_jac_file_path()
|
|
17
|
+
from jaclang.langserve.server import formatting
|
|
30
18
|
|
|
31
19
|
|
|
32
20
|
class TestLangServe:
|
|
33
|
-
"""Test
|
|
34
|
-
|
|
21
|
+
"""Test suite for Jac language server features."""
|
|
22
|
+
|
|
23
|
+
CIRCLE_TEMPLATE = "circle_template.jac"
|
|
24
|
+
GLOB_TEMPLATE = "glob_template.jac"
|
|
25
|
+
EXPECTED_CIRCLE_TOKEN_COUNT = 340
|
|
26
|
+
EXPECTED_GLOB_TOKEN_COUNT = 15
|
|
27
|
+
|
|
35
28
|
@pytest.mark.asyncio
|
|
36
29
|
async def test_open_valid_file_no_diagnostics(self):
|
|
37
|
-
"""Test opening a Jac file
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
text_document=TextDocumentItem(
|
|
47
|
-
uri=uri,
|
|
48
|
-
language_id="jac",
|
|
49
|
-
version=1,
|
|
50
|
-
text=code,
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
await did_open(ls, params)
|
|
54
|
-
|
|
55
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
30
|
+
"""Test opening a valid Jac file produces no diagnostics."""
|
|
31
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE)
|
|
32
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
33
|
+
test_file.uri = uri
|
|
34
|
+
helper = LanguageServerTestHelper(ls, test_file)
|
|
35
|
+
|
|
36
|
+
await helper.open_document()
|
|
37
|
+
helper.assert_no_diagnostics()
|
|
38
|
+
|
|
56
39
|
ls.shutdown()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
os.remove(temp_file_path)
|
|
60
|
-
|
|
40
|
+
test_file.cleanup()
|
|
41
|
+
|
|
61
42
|
@pytest.mark.asyncio
|
|
62
43
|
async def test_open_with_syntax_error(self):
|
|
63
|
-
"""Test opening a Jac file with
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
text=code,
|
|
77
|
-
)
|
|
78
|
-
)
|
|
79
|
-
await did_open(ls, params)
|
|
80
|
-
|
|
81
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
44
|
+
"""Test opening a Jac file with syntax error produces diagnostics."""
|
|
45
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE, "error")
|
|
46
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
47
|
+
if uri:
|
|
48
|
+
test_file.uri = uri
|
|
49
|
+
helper = LanguageServerTestHelper(ls, test_file)
|
|
50
|
+
|
|
51
|
+
await helper.open_document()
|
|
52
|
+
helper.assert_has_diagnostics(count=1, message_contains="Unexpected token 'error'")
|
|
53
|
+
|
|
54
|
+
diagnostics = helper.get_diagnostics()
|
|
55
|
+
assert str(diagnostics[0].range) == "65:0-65:5"
|
|
56
|
+
|
|
82
57
|
ls.shutdown()
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
assert str(diagnostics[0].range) == "66:0-66:1"
|
|
86
|
-
|
|
87
|
-
os.remove(temp_file_path)
|
|
88
|
-
|
|
58
|
+
test_file.cleanup()
|
|
59
|
+
|
|
89
60
|
@pytest.mark.asyncio
|
|
90
61
|
async def test_did_open_and_simple_syntax_error(self):
|
|
91
|
-
"""Test diagnostics
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)
|
|
107
|
-
await
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
broken_code = get_code("error")
|
|
113
|
-
with open(temp_file_path, "w") as f:
|
|
114
|
-
f.write(broken_code)
|
|
115
|
-
params = DidOpenTextDocumentParams(
|
|
116
|
-
text_document=TextDocumentItem(
|
|
117
|
-
uri=uri,
|
|
118
|
-
language_id="jac",
|
|
119
|
-
version=1,
|
|
120
|
-
text=broken_code,
|
|
121
|
-
)
|
|
122
|
-
)
|
|
123
|
-
await did_open(ls, params)
|
|
124
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
125
|
-
assert isinstance(diagnostics, list)
|
|
126
|
-
assert len(diagnostics) == 1
|
|
127
|
-
|
|
128
|
-
sem_tokens = ls.get_semantic_tokens(uri)
|
|
129
|
-
print(sem_tokens)
|
|
62
|
+
"""Test diagnostics evolution from valid to invalid code."""
|
|
63
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE)
|
|
64
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
65
|
+
test_file.uri = uri
|
|
66
|
+
helper = LanguageServerTestHelper(ls, test_file)
|
|
67
|
+
|
|
68
|
+
# Open valid file
|
|
69
|
+
print("Opening valid file...")
|
|
70
|
+
await helper.open_document()
|
|
71
|
+
helper.assert_no_diagnostics()
|
|
72
|
+
|
|
73
|
+
# Introduce syntax error
|
|
74
|
+
broken_code = load_jac_template(
|
|
75
|
+
test_file._get_template_path(self.CIRCLE_TEMPLATE),
|
|
76
|
+
"error"
|
|
77
|
+
)
|
|
78
|
+
await helper.change_document(broken_code)
|
|
79
|
+
helper.assert_has_diagnostics(count=1)
|
|
80
|
+
helper.assert_semantic_tokens_count(self.EXPECTED_CIRCLE_TOKEN_COUNT)
|
|
81
|
+
|
|
130
82
|
ls.shutdown()
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
assert (
|
|
134
|
-
len(sem_tokens.data) == 0
|
|
135
|
-
) # TODO: we should retain the sem tokens, will be fixed in next PR
|
|
136
|
-
|
|
137
|
-
os.remove(temp_file_path)
|
|
138
|
-
|
|
83
|
+
test_file.cleanup()
|
|
84
|
+
|
|
139
85
|
@pytest.mark.asyncio
|
|
140
86
|
async def test_did_save(self):
|
|
141
|
-
"""Test saving a Jac file triggers diagnostics."""
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
uri
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
language_id="jac",
|
|
162
|
-
version=2,
|
|
163
|
-
text=code,
|
|
164
|
-
)
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
await did_save(ls, params)
|
|
168
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
169
|
-
assert isinstance(diagnostics, list)
|
|
170
|
-
assert len(diagnostics) == 0
|
|
171
|
-
|
|
172
|
-
# Now simulate a syntax error by updating the workspace and saving
|
|
173
|
-
broken_code = get_code("error")
|
|
174
|
-
ls.workspace.put_text_document(
|
|
175
|
-
TextDocumentItem(
|
|
176
|
-
uri=uri,
|
|
177
|
-
language_id="jac",
|
|
178
|
-
version=3,
|
|
179
|
-
text=broken_code,
|
|
180
|
-
)
|
|
181
|
-
)
|
|
182
|
-
params = DidSaveTextDocumentParams(
|
|
183
|
-
text_document=TextDocumentItem(
|
|
184
|
-
uri=uri,
|
|
185
|
-
language_id="jac",
|
|
186
|
-
version=3,
|
|
187
|
-
text=broken_code,
|
|
188
|
-
)
|
|
189
|
-
)
|
|
190
|
-
await did_save(ls, params)
|
|
191
|
-
sem_tokens = ls.get_semantic_tokens(uri)
|
|
192
|
-
# semantic tokens should still be present even if there is a syntax error
|
|
193
|
-
assert len(sem_tokens.data) == 320
|
|
194
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
195
|
-
assert isinstance(diagnostics, list)
|
|
196
|
-
assert len(diagnostics) == 1
|
|
197
|
-
assert diagnostics[0].message == "Syntax Error"
|
|
198
|
-
|
|
87
|
+
"""Test saving a Jac file triggers appropriate diagnostics."""
|
|
88
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE)
|
|
89
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
90
|
+
if uri:
|
|
91
|
+
test_file.uri = uri
|
|
92
|
+
helper = LanguageServerTestHelper(ls, test_file)
|
|
93
|
+
|
|
94
|
+
await helper.open_document()
|
|
95
|
+
await helper.save_document()
|
|
96
|
+
helper.assert_no_diagnostics()
|
|
97
|
+
|
|
98
|
+
# Save with syntax error
|
|
99
|
+
broken_code = load_jac_template(
|
|
100
|
+
test_file._get_template_path(self.CIRCLE_TEMPLATE),
|
|
101
|
+
"error"
|
|
102
|
+
)
|
|
103
|
+
await helper.save_document(broken_code)
|
|
104
|
+
helper.assert_semantic_tokens_count(self.EXPECTED_CIRCLE_TOKEN_COUNT)
|
|
105
|
+
helper.assert_has_diagnostics(count=1, message_contains="Unexpected token 'error'")
|
|
106
|
+
|
|
199
107
|
ls.shutdown()
|
|
200
|
-
|
|
201
|
-
|
|
108
|
+
test_file.cleanup()
|
|
109
|
+
|
|
202
110
|
@pytest.mark.asyncio
|
|
203
111
|
async def test_did_change(self):
|
|
204
112
|
"""Test changing a Jac file triggers diagnostics."""
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
uri
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
params = DidChangeTextDocumentParams(
|
|
223
|
-
text_document=VersionedTextDocumentIdentifier(uri=uri, version=2),
|
|
224
|
-
content_changes=[{"text": "\n" + code}],
|
|
225
|
-
)
|
|
226
|
-
ls.workspace.put_text_document(
|
|
227
|
-
TextDocumentItem(
|
|
228
|
-
uri=uri,
|
|
229
|
-
language_id="jac",
|
|
230
|
-
version=2,
|
|
231
|
-
text="\n" + code,
|
|
232
|
-
)
|
|
233
|
-
)
|
|
234
|
-
await did_change(ls, params)
|
|
235
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
236
|
-
assert isinstance(diagnostics, list)
|
|
237
|
-
assert len(diagnostics) == 0
|
|
238
|
-
|
|
239
|
-
# Now add a syntax error and update workspace
|
|
240
|
-
# This should trigger diagnostics with a syntax error
|
|
241
|
-
error_code = "\nerror"
|
|
242
|
-
params = DidChangeTextDocumentParams(
|
|
243
|
-
text_document=VersionedTextDocumentIdentifier(uri=uri, version=3),
|
|
244
|
-
content_changes=[{"text": error_code + code}],
|
|
245
|
-
)
|
|
246
|
-
ls.workspace.put_text_document(
|
|
247
|
-
TextDocumentItem(
|
|
248
|
-
uri=uri,
|
|
249
|
-
language_id="jac",
|
|
250
|
-
version=3,
|
|
251
|
-
text=error_code + code,
|
|
252
|
-
)
|
|
253
|
-
)
|
|
254
|
-
await did_change(ls, params)
|
|
255
|
-
sem_tokens = ls.get_semantic_tokens(uri)
|
|
256
|
-
# semantic tokens should still be present even if there is a syntax error
|
|
257
|
-
assert len(sem_tokens.data) == 320
|
|
258
|
-
diagnostics = ls.diagnostics.get(uri, [])
|
|
259
|
-
assert isinstance(diagnostics, list)
|
|
260
|
-
assert len(diagnostics) == 1
|
|
261
|
-
assert diagnostics[0].message == "Syntax Error"
|
|
262
|
-
|
|
113
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE)
|
|
114
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
115
|
+
if uri:
|
|
116
|
+
test_file.uri = uri
|
|
117
|
+
helper = LanguageServerTestHelper(ls, test_file)
|
|
118
|
+
|
|
119
|
+
await helper.open_document()
|
|
120
|
+
|
|
121
|
+
# Change without error
|
|
122
|
+
await helper.change_document("\n" + test_file.code)
|
|
123
|
+
helper.assert_no_diagnostics()
|
|
124
|
+
|
|
125
|
+
# Change with syntax error
|
|
126
|
+
await helper.change_document("\nerror" + test_file.code)
|
|
127
|
+
helper.assert_semantic_tokens_count(self.EXPECTED_CIRCLE_TOKEN_COUNT)
|
|
128
|
+
helper.assert_has_diagnostics(count=1, message_contains="Unexpected token")
|
|
129
|
+
|
|
263
130
|
ls.shutdown()
|
|
264
|
-
|
|
265
|
-
|
|
131
|
+
test_file.cleanup()
|
|
132
|
+
|
|
266
133
|
def test_vsce_formatting(self):
|
|
267
|
-
"""Test formatting a Jac file returns edits."""
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
134
|
+
"""Test formatting a Jac file returns valid edits."""
|
|
135
|
+
test_file = TestFile.from_template(self.CIRCLE_TEMPLATE)
|
|
136
|
+
uri, ls = create_ls_with_workspace(test_file.path)
|
|
137
|
+
|
|
138
|
+
from lsprotocol.types import FormattingOptions
|
|
139
|
+
|
|
271
140
|
params = DocumentFormattingParams(
|
|
272
|
-
text_document=TextDocumentIdentifier(uri=uri),
|
|
273
|
-
options=
|
|
141
|
+
text_document=TextDocumentIdentifier(uri=uri or ""),
|
|
142
|
+
options=FormattingOptions(tab_size=4, insert_spaces=True),
|
|
274
143
|
)
|
|
275
144
|
edits = formatting(ls, params)
|
|
145
|
+
|
|
276
146
|
assert isinstance(edits, list)
|
|
147
|
+
assert len(edits) > 0
|
|
277
148
|
assert isinstance(edits[0], TextEdit)
|
|
278
|
-
assert (
|
|
279
|
-
|
|
280
|
-
) # it is a random number to check if the text is changed
|
|
281
|
-
print(edits[0].new_text)
|
|
149
|
+
assert len(edits[0].new_text) > 100
|
|
150
|
+
|
|
282
151
|
ls.shutdown()
|
|
283
|
-
|
|
284
|
-
|
|
152
|
+
test_file.cleanup()
|
|
153
|
+
|
|
285
154
|
@pytest.mark.asyncio
|
|
286
155
|
async def test_multifile_workspace(self):
|
|
287
156
|
"""Test opening multiple Jac files in a workspace."""
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
before_sem_tokens_1 = ls.get_semantic_tokens(uri1)
|
|
326
|
-
before_sem_tokens_2 = ls.get_semantic_tokens(uri2)
|
|
327
|
-
assert len(before_sem_tokens_1.data) == 15
|
|
328
|
-
assert len(before_sem_tokens_2.data) == 0
|
|
329
|
-
|
|
330
|
-
changed_code = get_simple_code("glob x = 90;")
|
|
331
|
-
ls.workspace.put_text_document(
|
|
332
|
-
TextDocumentItem(
|
|
333
|
-
uri=uri1,
|
|
334
|
-
language_id="jac",
|
|
335
|
-
version=2,
|
|
336
|
-
text=changed_code,
|
|
337
|
-
)
|
|
338
|
-
)
|
|
339
|
-
params = DidChangeTextDocumentParams(
|
|
340
|
-
text_document=VersionedTextDocumentIdentifier(uri=uri1, version=2),
|
|
341
|
-
content_changes=[{"text": changed_code}],
|
|
342
|
-
)
|
|
343
|
-
await did_change(ls, params)
|
|
344
|
-
|
|
345
|
-
after_sem_tokens_1 = ls.get_semantic_tokens(uri1)
|
|
346
|
-
after_sem_tokens_2 = ls.get_semantic_tokens(uri2)
|
|
347
|
-
|
|
348
|
-
assert len(after_sem_tokens_1.data) == 20
|
|
349
|
-
assert len(after_sem_tokens_2.data) == 0
|
|
350
|
-
|
|
157
|
+
file1 = TestFile.from_template(self.GLOB_TEMPLATE)
|
|
158
|
+
file2 = TestFile.from_template(self.GLOB_TEMPLATE, "error")
|
|
159
|
+
|
|
160
|
+
uri1, ls = create_ls_with_workspace(file1.path)
|
|
161
|
+
if uri1:
|
|
162
|
+
file1.uri = uri1
|
|
163
|
+
file2_uri = from_fs_path(file2.path)
|
|
164
|
+
if file2_uri:
|
|
165
|
+
file2.uri = file2_uri
|
|
166
|
+
|
|
167
|
+
helper1 = LanguageServerTestHelper(ls, file1)
|
|
168
|
+
helper2 = LanguageServerTestHelper(ls, file2)
|
|
169
|
+
|
|
170
|
+
# Open both files
|
|
171
|
+
await helper1.open_document()
|
|
172
|
+
await helper2.open_document()
|
|
173
|
+
|
|
174
|
+
# Verify initial state
|
|
175
|
+
helper1.assert_no_diagnostics()
|
|
176
|
+
helper2.assert_has_diagnostics(count=1, message_contains="Unexpected token")
|
|
177
|
+
|
|
178
|
+
# Check semantic tokens before change
|
|
179
|
+
helper1.assert_semantic_tokens_count(self.EXPECTED_GLOB_TOKEN_COUNT)
|
|
180
|
+
helper2.assert_semantic_tokens_count(self.EXPECTED_GLOB_TOKEN_COUNT)
|
|
181
|
+
|
|
182
|
+
# Change first file
|
|
183
|
+
changed_code = load_jac_template(
|
|
184
|
+
file1._get_template_path(self.GLOB_TEMPLATE),
|
|
185
|
+
"glob x = 90;"
|
|
186
|
+
)
|
|
187
|
+
await helper1.change_document(changed_code)
|
|
188
|
+
|
|
189
|
+
# Verify semantic tokens after change
|
|
190
|
+
helper1.assert_semantic_tokens_count(20)
|
|
191
|
+
helper2.assert_semantic_tokens_count(self.EXPECTED_GLOB_TOKEN_COUNT)
|
|
192
|
+
|
|
351
193
|
ls.shutdown()
|
|
352
|
-
|
|
353
|
-
|
|
194
|
+
file1.cleanup()
|
|
195
|
+
file2.cleanup()
|