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.

Files changed (103) hide show
  1. jaclang/cli/cli.md +3 -3
  2. jaclang/cli/cli.py +37 -37
  3. jaclang/cli/cmdreg.py +45 -140
  4. jaclang/compiler/constant.py +0 -1
  5. jaclang/compiler/jac.lark +3 -6
  6. jaclang/compiler/larkparse/jac_parser.py +2 -2
  7. jaclang/compiler/parser.py +213 -34
  8. jaclang/compiler/passes/main/__init__.py +2 -4
  9. jaclang/compiler/passes/main/def_use_pass.py +0 -4
  10. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  11. jaclang/compiler/passes/main/pyast_gen_pass.py +83 -55
  12. jaclang/compiler/passes/main/pyast_load_pass.py +66 -40
  13. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  14. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_binary_op.jac +21 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_call_expr_class.jac +12 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
  22. jaclang/compiler/passes/main/tests/fixtures/checker_cyclic_symbol.jac +4 -0
  23. jaclang/compiler/passes/main/tests/fixtures/checker_expr_call.jac +9 -0
  24. jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
  25. jaclang/compiler/passes/main/tests/fixtures/checker_import_missing_module.jac +13 -0
  26. jaclang/compiler/passes/main/tests/fixtures/checker_magic_call.jac +17 -0
  27. jaclang/compiler/passes/main/tests/fixtures/checker_mod_path.jac +8 -0
  28. jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
  29. jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
  30. jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
  31. jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
  32. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
  33. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
  34. jaclang/compiler/passes/main/tests/test_checker_pass.py +265 -0
  35. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
  36. jaclang/compiler/passes/main/type_checker_pass.py +36 -61
  37. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
  38. jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
  39. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  40. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
  41. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +171 -11
  42. jaclang/compiler/passes/transform.py +12 -8
  43. jaclang/compiler/program.py +14 -6
  44. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  45. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  46. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  47. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  48. jaclang/compiler/tests/test_importer.py +39 -0
  49. jaclang/compiler/tests/test_parser.py +49 -0
  50. jaclang/compiler/type_system/operations.py +104 -0
  51. jaclang/compiler/type_system/type_evaluator.py +470 -47
  52. jaclang/compiler/type_system/type_utils.py +246 -0
  53. jaclang/compiler/type_system/types.py +58 -2
  54. jaclang/compiler/unitree.py +79 -94
  55. jaclang/langserve/engine.jac +253 -230
  56. jaclang/langserve/server.jac +46 -15
  57. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  58. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  59. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  60. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  61. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  62. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  63. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -312
  64. jaclang/langserve/tests/server_test/utils.py +153 -116
  65. jaclang/langserve/tests/test_dev_server.py +1 -1
  66. jaclang/langserve/tests/test_server.py +30 -86
  67. jaclang/langserve/utils.jac +56 -63
  68. jaclang/runtimelib/machine.py +7 -0
  69. jaclang/runtimelib/meta_importer.py +27 -1
  70. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  71. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  72. jaclang/settings.py +18 -14
  73. jaclang/tests/fixtures/abc_check.jac +3 -3
  74. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  75. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  76. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  77. jaclang/tests/fixtures/jac_run_py_bugs.py +18 -0
  78. jaclang/tests/fixtures/jac_run_py_import.py +13 -0
  79. jaclang/tests/fixtures/lambda_arg_annotation.jac +15 -0
  80. jaclang/tests/fixtures/lambda_self.jac +18 -0
  81. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  82. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  83. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  84. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  85. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  86. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  87. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  88. jaclang/tests/fixtures/py2jac_params.py +8 -0
  89. jaclang/tests/fixtures/run_test.jac +4 -4
  90. jaclang/tests/test_cli.py +103 -18
  91. jaclang/tests/test_language.py +74 -16
  92. jaclang/utils/helpers.py +47 -2
  93. jaclang/utils/module_resolver.py +11 -1
  94. jaclang/utils/test.py +8 -0
  95. jaclang/utils/treeprinter.py +0 -18
  96. {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/METADATA +3 -3
  97. {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/RECORD +99 -62
  98. {jaclang-0.8.6.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
  99. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  100. jaclang/langserve/dev_engine.jac +0 -645
  101. jaclang/langserve/dev_server.jac +0 -201
  102. jaclang/langserve/tests/server_test/code_test.py +0 -0
  103. {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[VSCE] features"""
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
- create_temp_jac_file,
18
- get_code,
19
- get_jac_file_path,
20
- get_simple_code,
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.vendor.pygls.workspace import Workspace
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 class for Jac language server features."""
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 with a syntax error."""
38
- ls = JacLangServer()
39
-
40
- code = get_code("")
41
- temp_file_path = create_temp_jac_file(code)
42
- uri = from_fs_path(temp_file_path)
43
- ls.lsp._workspace = Workspace(os.path.dirname(temp_file_path), ls)
44
-
45
- params = DidOpenTextDocumentParams(
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
- assert len(diagnostics) == 0
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 a syntax error."""
64
- ls = JacLangServer()
65
-
66
- code = get_code("error")
67
- temp_file_path = create_temp_jac_file(code)
68
- uri = from_fs_path(temp_file_path)
69
- ls.lsp._workspace = Workspace(os.path.dirname(temp_file_path), ls)
70
-
71
- params = DidOpenTextDocumentParams(
72
- text_document=TextDocumentItem(
73
- uri=uri,
74
- language_id="jac",
75
- version=1,
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
- assert len(diagnostics) == 1
84
- assert diagnostics[0].message == "Syntax Error"
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 for a Jac file with a syntax error."""
92
- ls = JacLangServer()
93
-
94
- code = get_code("")
95
- temp_file_path = create_temp_jac_file(code)
96
- uri = from_fs_path(temp_file_path)
97
- ls.lsp._workspace = Workspace(os.path.dirname(temp_file_path), ls)
98
-
99
- params = DidOpenTextDocumentParams(
100
- text_document=TextDocumentItem(
101
- uri=uri,
102
- language_id="jac",
103
- version=1,
104
- text=code,
105
- )
106
- )
107
- await did_open(ls, params)
108
- diagnostics = ls.diagnostics.get(uri, [])
109
- assert isinstance(diagnostics, list)
110
- assert len(diagnostics) == 0
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
- assert hasattr(sem_tokens, "data")
132
- assert isinstance(sem_tokens.data, list)
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
- code = get_code("")
143
- temp_file_path = create_temp_jac_file(code)
144
- uri, ls = create_ls_with_workspace(temp_file_path)
145
-
146
- await did_open(
147
- ls,
148
- DidOpenTextDocumentParams(
149
- text_document=TextDocumentItem(
150
- uri=uri,
151
- language_id="jac",
152
- version=1,
153
- text=code,
154
- )
155
- ),
156
- )
157
-
158
- params = DidSaveTextDocumentParams(
159
- text_document=TextDocumentItem(
160
- uri=uri,
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
- os.remove(temp_file_path)
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
- code = get_code("")
206
- temp_file_path = create_temp_jac_file(code)
207
- uri, ls = create_ls_with_workspace(temp_file_path)
208
-
209
- await did_open(
210
- ls,
211
- DidOpenTextDocumentParams(
212
- text_document=TextDocumentItem(
213
- uri=uri,
214
- language_id="jac",
215
- version=1,
216
- text=code,
217
- )
218
- ),
219
- )
220
-
221
- # No error, should be no diagnostics
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
- os.remove(temp_file_path)
265
-
131
+ test_file.cleanup()
132
+
266
133
  def test_vsce_formatting(self):
267
- """Test formatting a Jac file returns edits."""
268
- code = get_code("")
269
- temp_file_path = create_temp_jac_file(code)
270
- uri, ls = create_ls_with_workspace(temp_file_path)
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={"tabSize": 4, "insertSpaces": True},
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
- len(edits[0].new_text) > 100
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
- os.remove(temp_file_path)
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
- code1 = get_simple_code("")
289
- code2 = get_simple_code("error")
290
- temp_file_path1 = create_temp_jac_file(code1)
291
- temp_file_path2 = create_temp_jac_file(code2)
292
-
293
- uri1, ls = create_ls_with_workspace(temp_file_path1)
294
- uri2 = from_fs_path(temp_file_path2)
295
-
296
- await did_open(
297
- ls,
298
- DidOpenTextDocumentParams(
299
- text_document=TextDocumentItem(
300
- uri=uri1,
301
- language_id="jac",
302
- version=1,
303
- text=code1,
304
- )
305
- ),
306
- )
307
- await did_open(
308
- ls,
309
- DidOpenTextDocumentParams(
310
- text_document=TextDocumentItem(
311
- uri=uri2,
312
- language_id="jac",
313
- version=1,
314
- text=code2,
315
- )
316
- ),
317
- )
318
-
319
- diagnostics1 = ls.diagnostics.get(uri1, [])
320
- diagnostics2 = ls.diagnostics.get(uri2, [])
321
- assert len(diagnostics1) == 0
322
- assert len(diagnostics2) == 1
323
- assert diagnostics2[0].message == "Syntax Error"
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
- os.remove(temp_file_path1)
353
- os.remove(temp_file_path2)
194
+ file1.cleanup()
195
+ file2.cleanup()