jaclang 0.8.7__py3-none-any.whl → 0.8.9__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 +77 -29
- jaclang/cli/cmdreg.py +44 -0
- jaclang/compiler/constant.py +6 -2
- jaclang/compiler/jac.lark +37 -47
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +356 -61
- jaclang/compiler/passes/main/__init__.py +2 -4
- jaclang/compiler/passes/main/def_use_pass.py +1 -4
- jaclang/compiler/passes/main/predynamo_pass.py +221 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
- jaclang/compiler/passes/main/pyast_load_pass.py +54 -20
- 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_cat_is_animal.jac +18 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -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 +190 -0
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
- jaclang/compiler/passes/main/type_checker_pass.py +29 -73
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
- 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/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
- jaclang/compiler/passes/transform.py +12 -8
- jaclang/compiler/program.py +19 -7
- 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/type_evaluator.jac +959 -0
- jaclang/compiler/type_system/type_utils.py +246 -0
- jaclang/compiler/type_system/types.py +58 -2
- jaclang/compiler/unitree.py +102 -107
- jaclang/langserve/engine.jac +138 -159
- jaclang/langserve/server.jac +25 -1
- 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 -309
- jaclang/langserve/tests/server_test/utils.py +153 -116
- jaclang/langserve/tests/test_server.py +21 -84
- jaclang/langserve/utils.jac +12 -15
- jaclang/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/constructs.py +2 -2
- jaclang/runtimelib/machine.py +63 -46
- 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 +19 -16
- jaclang/tests/fixtures/abc_check.jac +3 -3
- jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
- jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -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 +159 -7
- jaclang/tests/test_language.py +213 -38
- jaclang/tests/test_reference.py +3 -1
- jaclang/utils/helpers.py +67 -6
- jaclang/utils/module_resolver.py +10 -0
- jaclang/utils/test.py +8 -0
- jaclang/utils/tests/test_lang_tools.py +4 -15
- jaclang/utils/treeprinter.py +0 -18
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
- jaclang/compiler/passes/main/inheritance_pass.py +0 -131
- jaclang/compiler/type_system/type_evaluator.py +0 -560
- jaclang/langserve/dev_engine.jac +0 -645
- jaclang/langserve/dev_server.jac +0 -201
- /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
- {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
jaclang/langserve/engine.jac
CHANGED
|
@@ -8,9 +8,10 @@ import from typing { Callable, Optional }
|
|
|
8
8
|
|
|
9
9
|
import jaclang.compiler.unitree as uni;
|
|
10
10
|
import from jaclang { JacMachineInterface as Jac }
|
|
11
|
-
import from jaclang.compiler.constant {SymbolType}
|
|
11
|
+
import from jaclang.compiler.constant { SymbolType }
|
|
12
12
|
import from jaclang.compiler.program { JacProgram }
|
|
13
|
-
import from jaclang.compiler.type_system.
|
|
13
|
+
import from jaclang.compiler.type_system.type_utils { get_completion_items }
|
|
14
|
+
import from jaclang.compiler.type_system.types { ClassType, TypeBase }
|
|
14
15
|
import from jaclang.compiler.unitree { UniScopeNode }
|
|
15
16
|
import from sem_manager { SemTokManager }
|
|
16
17
|
import from jaclang.vendor.pygls { uris }
|
|
@@ -201,121 +202,154 @@ class JacLangServer(JacProgram , LanguageServer) {
|
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
def get_token_at_position(self: JacLangServer, file_path: str, position: lspt.Position) -> Optional[uni.AstNode] {
|
|
206
|
+
fs_path = uris.to_fs_path(file_path);
|
|
207
|
+
if fs_path not in self.mod.hub {
|
|
208
|
+
return None;
|
|
209
|
+
}
|
|
210
|
+
sem_mgr = self.sem_managers.get(fs_path);
|
|
211
|
+
if not sem_mgr {
|
|
212
|
+
return None;
|
|
213
|
+
}
|
|
214
|
+
token_index =
|
|
215
|
+
utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
|
|
216
|
+
if token_index is None {
|
|
217
|
+
return None;
|
|
218
|
+
}
|
|
219
|
+
node_selected = sem_mgr.static_sem_tokens[token_index][3];
|
|
220
|
+
return node_selected;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
def debug(self: JacLangServer, msg: str) -> None {
|
|
224
|
+
self.log_py("[DEBUG] " + ("-" * 80));
|
|
225
|
+
self.log_py(f"[DEBUG] {msg}");
|
|
226
|
+
self.log_py("[DEBUG] " + ("-" * 80));
|
|
227
|
+
}
|
|
228
|
+
|
|
204
229
|
"""Return completion for a file."""
|
|
205
230
|
def get_completion(
|
|
206
231
|
self: JacLangServer,
|
|
207
|
-
|
|
232
|
+
file_uri: str,
|
|
208
233
|
position: lspt.Position,
|
|
209
234
|
completion_trigger: Optional[str]
|
|
210
235
|
) -> lspt.CompletionList {
|
|
236
|
+
self.debug("getting completion for " + file_uri + " at " + str(position));
|
|
237
|
+
|
|
211
238
|
try {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
assert isinstance(builtin_tab, UniScopeNode) ;
|
|
226
|
-
completion_items = [];
|
|
227
|
-
node_selected =
|
|
228
|
-
utils.find_deepest_symbol_node_at_pos(
|
|
229
|
-
mod_ir,
|
|
230
|
-
position.line,
|
|
231
|
-
(position.character - 2)
|
|
232
|
-
);
|
|
233
|
-
mod_tab = mod_ir.sym_tab if not node_selected else node_selected.sym_tab;
|
|
234
|
-
current_symbol_table = mod_tab;
|
|
235
|
-
if completion_trigger == '.' {
|
|
236
|
-
if current_symbol_path {
|
|
237
|
-
temp_tab = mod_tab;
|
|
238
|
-
for symbol in current_symbol_path {
|
|
239
|
-
if symbol == 'self' {
|
|
240
|
-
is_ability_def =
|
|
241
|
-
temp_tab
|
|
242
|
-
if isinstance(temp_tab, uni.ImplDef)
|
|
243
|
-
else temp_tab.find_parent_of_type(uni.ImplDef);
|
|
244
|
-
if not is_ability_def {
|
|
245
|
-
archi_owner =
|
|
246
|
-
mod_tab.find_parent_of_type(uni.Archetype);
|
|
247
|
-
temp_tab =
|
|
248
|
-
archi_owner.sym_tab
|
|
249
|
-
if archi_owner and archi_owner.sym_tab
|
|
250
|
-
else mod_tab;
|
|
251
|
-
continue;
|
|
252
|
-
} else {
|
|
253
|
-
archi_owner =
|
|
254
|
-
is_ability_def.decl_link.find_parent_of_type(
|
|
255
|
-
uni.Archetype
|
|
256
|
-
)
|
|
257
|
-
if is_ability_def.decl_link
|
|
258
|
-
else None;
|
|
259
|
-
temp_tab =
|
|
260
|
-
archi_owner.sym_tab
|
|
261
|
-
if archi_owner and archi_owner.sym_tab
|
|
262
|
-
else temp_tab;
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
symb = temp_tab.lookup(symbol);
|
|
267
|
-
if symb {
|
|
268
|
-
fetc_tab = symb.symbol_table;
|
|
269
|
-
if fetc_tab {
|
|
270
|
-
temp_tab = fetc_tab;
|
|
271
|
-
} else {
|
|
272
|
-
temp_tab =
|
|
273
|
-
symb.defn[0].type_sym_tab
|
|
274
|
-
if symb.defn[0].type_sym_tab
|
|
275
|
-
else temp_tab;
|
|
276
|
-
}
|
|
277
|
-
} else {
|
|
278
|
-
break;
|
|
239
|
+
file_path = uris.to_fs_path(file_uri);
|
|
240
|
+
|
|
241
|
+
if (node_at_pos := self.get_node_at_position(file_path, position.line, position.character - 1)) {
|
|
242
|
+
self.debug("found the node at pos " + str(position) + " " + str(node_at_pos));
|
|
243
|
+
|
|
244
|
+
# For each trigger character we need to handle the completion differently
|
|
245
|
+
if isinstance(node_at_pos, uni.Token) {
|
|
246
|
+
if node_at_pos.name == "DOT" {
|
|
247
|
+
member_access = node_at_pos.parent;
|
|
248
|
+
self.debug("found dot " + str(member_access));
|
|
249
|
+
if isinstance(member_access, uni.AtomTrailer) {
|
|
250
|
+
self.debug("before returning the list");
|
|
251
|
+
return self.get_completion_of_node(member_access.target);
|
|
279
252
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if isinstance(base_name, uni.Name) and base_name.sym {
|
|
289
|
-
base.append(base_name.sym);
|
|
290
|
-
}
|
|
253
|
+
|
|
254
|
+
# FIXME: This is wrong but imma do it anyways like this for now.
|
|
255
|
+
} elif node_at_pos.name == "NAME" {
|
|
256
|
+
|
|
257
|
+
# Name of atom trailer.
|
|
258
|
+
if node_at_pos.parent and isinstance(node_at_pos.parent, uni.AtomTrailer) {
|
|
259
|
+
self.debug("found name in atom trailer " + str(node_at_pos.parent));
|
|
260
|
+
return self.get_completion_of_node(node_at_pos.parent.target);
|
|
291
261
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
);
|
|
298
|
-
}
|
|
262
|
+
|
|
263
|
+
# Just a name field.
|
|
264
|
+
if scope_node := node_at_pos.find_parent_of_type(uni.UniScopeNode) {
|
|
265
|
+
self.debug("found name in scope node " + str(scope_node));
|
|
266
|
+
return self.get_completion_of_node(scope_node);
|
|
299
267
|
}
|
|
300
268
|
}
|
|
301
269
|
}
|
|
302
|
-
} elif node_selected and node_selected.find_parent_of_type(uni.Archetype)
|
|
303
|
-
or node_selected.find_parent_of_type(uni.ImplDef)
|
|
304
|
-
{
|
|
305
|
-
self_symbol =
|
|
306
|
-
|
|
307
|
-
[lspt.CompletionItem(
|
|
308
|
-
label='self',
|
|
309
|
-
kind=lspt.CompletionItemKind.Variable
|
|
310
|
-
)];
|
|
311
|
-
} else {
|
|
312
|
-
self_symbol = [];
|
|
313
270
|
}
|
|
314
|
-
|
|
271
|
+
|
|
272
|
+
return lspt.CompletionList(is_incomplete=False, items=[]);
|
|
273
|
+
|
|
315
274
|
} except Exception as e {
|
|
316
275
|
self.log_py(f"'Error during completion: '{e}");
|
|
317
276
|
return lspt.CompletionList(is_incomplete=False, items=[]);
|
|
318
277
|
}
|
|
278
|
+
|
|
279
|
+
self.debug("returning empty list");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
def get_ast_of_file(self: JacLangServer, file_path: str) -> Optional[uni.AstNode] {
|
|
283
|
+
if file_path in self.mod.hub {
|
|
284
|
+
return self.mod.hub[file_path];
|
|
285
|
+
}
|
|
286
|
+
return None;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
def get_node_at_position(self: JacLangServer, file_path: str, line:int, col: int) -> Optional[uni.AstNode] {
|
|
290
|
+
if (ast := self.get_ast_of_file(file_path)) {
|
|
291
|
+
for ast_node in ast._in_mod_nodes {
|
|
292
|
+
if not isinstance(ast_node, uni.Token) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (utils.position_within_node(ast_node, line + 1, col + 1)) {
|
|
296
|
+
return ast_node;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return None;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
def get_completion_of_node(self: JacLangServer, node: uni.AstNode) -> lspt.CompletionList {
|
|
304
|
+
if (node_type := self.get_node_type(node)) {
|
|
305
|
+
self.debug("found type " + str(node_type));
|
|
306
|
+
return self.get_completion_items_of(node_type);
|
|
307
|
+
} elif isinstance(node, UniScopeNode) {
|
|
308
|
+
self.debug("found scope node " + str(node));
|
|
309
|
+
return self.get_completion_items_of(node);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
self.debug("no type found for node " + str(node));
|
|
313
|
+
return lspt.CompletionList(is_incomplete=False, items=[]);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
"""Return the type of an AST node if it has one."""
|
|
317
|
+
def get_node_type(self: JacLangServer, n: uni.AstNode) -> Optional[TypeBase] {
|
|
318
|
+
if isinstance(n, uni.Expr) {
|
|
319
|
+
typ = self.get_type_evaluator().get_type_of_expression(n);
|
|
320
|
+
self.debug("found type " + str(typ) + " for expr " + str(n));
|
|
321
|
+
return typ;
|
|
322
|
+
}
|
|
323
|
+
self.debug("no type found for node " + str(n));
|
|
324
|
+
return None;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
"""Get type members for completion."""
|
|
328
|
+
def get_completion_items_of(self: JacLangServer, ty: TypeBase | uni.UniScopeNode) -> lspt.CompletionList {
|
|
329
|
+
evaluator = self.get_type_evaluator();
|
|
330
|
+
self.debug("getting completion of " + str(ty));
|
|
331
|
+
items = get_completion_items(ty);
|
|
332
|
+
self.debug("completion items are " + str(items));
|
|
333
|
+
|
|
334
|
+
items: list[lspt.CompletionItem] = [];
|
|
335
|
+
for item in get_completion_items(ty) {
|
|
336
|
+
detail: lspt.CompletionItemLabelDetails | None = None;
|
|
337
|
+
if item.detail {
|
|
338
|
+
detail = lspt.CompletionItemLabelDetails(detail=item.detail);
|
|
339
|
+
}
|
|
340
|
+
items.append(
|
|
341
|
+
lspt.CompletionItem(
|
|
342
|
+
label=item.label,
|
|
343
|
+
kind=item.kind,
|
|
344
|
+
label_details=detail,
|
|
345
|
+
)
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return lspt.CompletionList(
|
|
350
|
+
is_incomplete=False,
|
|
351
|
+
items=items,
|
|
352
|
+
);
|
|
319
353
|
}
|
|
320
354
|
|
|
321
355
|
"""Rename module."""
|
|
@@ -370,21 +404,7 @@ class JacLangServer(JacProgram , LanguageServer) {
|
|
|
370
404
|
file_path: str,
|
|
371
405
|
position: lspt.Position
|
|
372
406
|
) -> Optional[lspt.Hover] {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if fs_path not in self.mod.hub {
|
|
376
|
-
return None;
|
|
377
|
-
}
|
|
378
|
-
sem_mgr = self.sem_managers.get(fs_path);
|
|
379
|
-
if not sem_mgr {
|
|
380
|
-
return None;
|
|
381
|
-
}
|
|
382
|
-
token_index =
|
|
383
|
-
utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
|
|
384
|
-
if token_index is None {
|
|
385
|
-
return None;
|
|
386
|
-
}
|
|
387
|
-
node_selected = sem_mgr.static_sem_tokens[token_index][3];
|
|
407
|
+
node_selected = self.get_token_at_position(file_path, position);
|
|
388
408
|
value = self.get_node_info(node_selected) if node_selected else None;
|
|
389
409
|
if value {
|
|
390
410
|
return lspt.Hover(
|
|
@@ -441,21 +461,7 @@ class JacLangServer(JacProgram , LanguageServer) {
|
|
|
441
461
|
file_path: str,
|
|
442
462
|
position: lspt.Position
|
|
443
463
|
) -> Optional[lspt.Location] {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if fs_path not in self.mod.hub {
|
|
447
|
-
return None;
|
|
448
|
-
}
|
|
449
|
-
sem_mgr = self.sem_managers.get(fs_path);
|
|
450
|
-
if not sem_mgr {
|
|
451
|
-
return None;
|
|
452
|
-
}
|
|
453
|
-
token_index =
|
|
454
|
-
utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
|
|
455
|
-
if token_index is None {
|
|
456
|
-
return None;
|
|
457
|
-
}
|
|
458
|
-
node_selected = sem_mgr.static_sem_tokens[token_index][3];
|
|
464
|
+
node_selected = self.get_token_at_position(file_path, position);
|
|
459
465
|
if node_selected {
|
|
460
466
|
if (node_selected.sym.sym_type == SymbolType.MODULE) {
|
|
461
467
|
spec = node_selected.sym.decl.parent.resolve_relative_path();
|
|
@@ -554,21 +560,7 @@ class JacLangServer(JacProgram , LanguageServer) {
|
|
|
554
560
|
file_path: str,
|
|
555
561
|
position: lspt.Position
|
|
556
562
|
) -> list[lspt.Location] {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
if fs_path not in self.mod.hub {
|
|
560
|
-
return [];
|
|
561
|
-
}
|
|
562
|
-
sem_mgr = self.sem_managers.get(fs_path);
|
|
563
|
-
if not sem_mgr {
|
|
564
|
-
return [];
|
|
565
|
-
}
|
|
566
|
-
index1 =
|
|
567
|
-
utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
|
|
568
|
-
if index1 is None {
|
|
569
|
-
return [];
|
|
570
|
-
}
|
|
571
|
-
node_selected = sem_mgr.static_sem_tokens[index1][3];
|
|
563
|
+
node_selected = self.get_token_at_position(file_path, position);
|
|
572
564
|
if node_selected and node_selected.sym {
|
|
573
565
|
list_of_references: list[lspt.Location] =
|
|
574
566
|
[ lspt.Location(
|
|
@@ -587,20 +579,7 @@ class JacLangServer(JacProgram , LanguageServer) {
|
|
|
587
579
|
position: lspt.Position,
|
|
588
580
|
new_name: str
|
|
589
581
|
) -> Optional[lspt.WorkspaceEdit] {
|
|
590
|
-
|
|
591
|
-
if fs_path not in self.mod.hub {
|
|
592
|
-
return None;
|
|
593
|
-
}
|
|
594
|
-
sem_mgr = self.sem_managers.get(fs_path);
|
|
595
|
-
if not sem_mgr {
|
|
596
|
-
return None;
|
|
597
|
-
}
|
|
598
|
-
index1 =
|
|
599
|
-
utils.find_index(sem_mgr.sem_tokens, position.line, position.character);
|
|
600
|
-
if index1 is None {
|
|
601
|
-
return None;
|
|
602
|
-
}
|
|
603
|
-
node_selected = sem_mgr.static_sem_tokens[index1][3];
|
|
582
|
+
node_selected = self.get_token_at_position(file_path, position);
|
|
604
583
|
if node_selected and node_selected.sym {
|
|
605
584
|
changes: dict[(str, list[lspt.TextEdit])] = {};
|
|
606
585
|
for node in [*node_selected.sym.uses, node_selected.sym.defn[0]] {
|
jaclang/langserve/server.jac
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Jaclang Language Server."""
|
|
2
2
|
|
|
3
|
+
import asyncio;
|
|
4
|
+
|
|
3
5
|
import from typing { Optional }
|
|
4
6
|
|
|
5
7
|
import from jaclang.compiler.constant {
|
|
@@ -17,6 +19,11 @@ with entry {
|
|
|
17
19
|
server = JacLangServer();
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
def debug(ls: JacLangServer, msg: str) -> None {
|
|
23
|
+
ls.log_py(f"[DEBUG] " + ("-" * 80));
|
|
24
|
+
ls.log_py(f"[DEBUG]' {msg} ");
|
|
25
|
+
ls.log_py(f"[DEBUG] " + ("-" * 80));
|
|
26
|
+
}
|
|
20
27
|
|
|
21
28
|
"""Check syntax on change."""
|
|
22
29
|
@server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
|
|
@@ -38,6 +45,7 @@ async def did_save(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) ->
|
|
|
38
45
|
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
|
|
39
46
|
}
|
|
40
47
|
|
|
48
|
+
glob still_compiling = False;
|
|
41
49
|
|
|
42
50
|
"""Check syntax on change with debouncing."""
|
|
43
51
|
@ server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
|
|
@@ -45,6 +53,9 @@ async def did_change(
|
|
|
45
53
|
ls: JacLangServer,
|
|
46
54
|
params: lspt.DidChangeTextDocumentParams
|
|
47
55
|
) -> None {
|
|
56
|
+
global still_compiling;
|
|
57
|
+
still_compiling = True;
|
|
58
|
+
|
|
48
59
|
file_path = params.text_document.uri;
|
|
49
60
|
try {
|
|
50
61
|
document = ls.workspace.get_text_document(file_path);
|
|
@@ -58,6 +69,8 @@ async def did_change(
|
|
|
58
69
|
} except Exception as e {
|
|
59
70
|
ls.log_py(f" 'Failed to update semantic tokens: ' {e} ");
|
|
60
71
|
}
|
|
72
|
+
|
|
73
|
+
debug(ls, "Compilation started...");
|
|
61
74
|
ls.log_py(f" 'Launching debounced quick check for ' {file_path} ");
|
|
62
75
|
quick_check_passed = await ls.launch_quick_check(file_path, delay=0.5);
|
|
63
76
|
if quick_check_passed {
|
|
@@ -65,8 +78,11 @@ async def did_change(
|
|
|
65
78
|
f" 'Quick check passed, launching debounced deep check for ' {file_path} "
|
|
66
79
|
);
|
|
67
80
|
await ls.launch_deep_check(file_path, delay=1.0);
|
|
81
|
+
|
|
68
82
|
ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH);
|
|
69
83
|
}
|
|
84
|
+
still_compiling = False;
|
|
85
|
+
debug(ls, "Compilation finished...");
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
"""Format the given document."""
|
|
@@ -124,7 +140,15 @@ def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None
|
|
|
124
140
|
lspt.TEXT_DOCUMENT_COMPLETION,
|
|
125
141
|
lspt.CompletionOptions(trigger_characters=['.', ':', 'a-zA-Z0-9'])
|
|
126
142
|
)
|
|
127
|
-
def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList {
|
|
143
|
+
async def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList {
|
|
144
|
+
|
|
145
|
+
debug(ls, "Waiting for compilation to finish...");
|
|
146
|
+
global still_compiling;
|
|
147
|
+
while still_compiling {
|
|
148
|
+
await asyncio.sleep(0.1);
|
|
149
|
+
}
|
|
150
|
+
debug(ls, "Compilation finished, providing completions...");
|
|
151
|
+
|
|
128
152
|
return ls.get_completion(
|
|
129
153
|
params.text_document.uri,
|
|
130
154
|
params.position,
|
|
@@ -63,15 +63,15 @@ with entry:__main__ {
|
|
|
63
63
|
glob expected_area = 78.53981633974483;
|
|
64
64
|
|
|
65
65
|
test calc_area {
|
|
66
|
-
|
|
66
|
+
assert almostEqual(calculate_area(RAD), expected_area);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
test circle_area {
|
|
70
70
|
c = Circle(RAD);
|
|
71
|
-
|
|
71
|
+
assert almostEqual(c.area(), expected_area);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
test circle_type {
|
|
75
75
|
c = Circle(RAD);
|
|
76
|
-
|
|
76
|
+
assert 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
|
-
|
|
62
|
+
assert almostEqual(calculate_area(RAD), expected_area);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
test circle_area {
|
|
66
66
|
c = Circle(RAD);
|
|
67
|
-
|
|
67
|
+
assert almostEqual(c.area(), expected_area);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
test circle_type {
|
|
71
71
|
c = Circle(RAD);
|
|
72
|
-
|
|
72
|
+
assert 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
|
-
|
|
4
|
+
assert almostEqual(calculate_area(RAD), expected_area);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
test a2 {
|
|
8
8
|
c = Circle(RAD);
|
|
9
|
-
|
|
9
|
+
assert almostEqual(c.area(), expected_area);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
test a3 {
|
|
13
13
|
c = Circle(RAD);
|
|
14
|
-
|
|
14
|
+
assert c.shape_type == ShapeType.CIRCLE;
|
|
15
15
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module demonstrates a simple circle class and a function to calculate
|
|
3
|
+
the area of a circle in all of Jac's glory.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import math;
|
|
7
|
+
|
|
8
|
+
# Module-level global variable
|
|
9
|
+
glob RAD = 5;
|
|
10
|
+
|
|
11
|
+
"""Function to calculate the area of a circle."""
|
|
12
|
+
def calculate_area(radius: float) -> float {
|
|
13
|
+
return math.pi * radius * radius;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#* (This is a multiline comment in Jac)
|
|
17
|
+
Above we have the demonstration of a function to calculate the area of a circle.
|
|
18
|
+
Below we have the demonstration of a class to calculate the area of a circle.
|
|
19
|
+
*#
|
|
20
|
+
|
|
21
|
+
"""Enum for shape types"""
|
|
22
|
+
enum ShapeType {
|
|
23
|
+
CIRCLE = "Circle",
|
|
24
|
+
UNKNOWN = "Unknown"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
"""Base class for a shape."""
|
|
28
|
+
obj Shape {
|
|
29
|
+
has shape_type: ShapeType;
|
|
30
|
+
|
|
31
|
+
"""Abstract method to calculate the area of a shape."""
|
|
32
|
+
def area -> float abs;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
"""Circle class inherits from Shape."""
|
|
36
|
+
obj Circle(Shape) {
|
|
37
|
+
def init(radius: float) {
|
|
38
|
+
super.init(ShapeType.CIRCLE);
|
|
39
|
+
self.radius = radius;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
"""Overridden method to calculate the area of the circle."""
|
|
43
|
+
override def area -> float {
|
|
44
|
+
return math.pi * self.radius * self.radius;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
with entry {
|
|
49
|
+
c = Circle(RAD);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Global also works here
|
|
53
|
+
|
|
54
|
+
with entry:__main__ {
|
|
55
|
+
# To run the program functionality
|
|
56
|
+
print(
|
|
57
|
+
f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
|
|
58
|
+
);
|
|
59
|
+
print(
|
|
60
|
+
f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Unit Tests!
|
|
65
|
+
glob expected_area = 78.53981633974483;
|
|
66
|
+
#{{INJECT_CODE}}
|
|
67
|
+
|
|
68
|
+
test calc_area {
|
|
69
|
+
assert almostEqual(calculate_area(RAD), expected_area);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
test circle_area {
|
|
73
|
+
c = Circle(RAD);
|
|
74
|
+
assert almostEqual(c.area(), expected_area);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
test circle_type {
|
|
78
|
+
c = Circle(RAD);
|
|
79
|
+
assert c.shape_type == ShapeType.CIRCLE;
|
|
80
|
+
}
|