jaclang 0.7.1__py3-none-any.whl → 0.7.7__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 (106) hide show
  1. jaclang/cli/cli.py +2 -2
  2. jaclang/compiler/absyntree.py +539 -297
  3. jaclang/compiler/codeloc.py +2 -2
  4. jaclang/compiler/constant.py +100 -2
  5. jaclang/compiler/jac.lark +27 -19
  6. jaclang/compiler/parser.py +119 -92
  7. jaclang/compiler/passes/main/access_modifier_pass.py +20 -12
  8. jaclang/compiler/passes/main/def_impl_match_pass.py +32 -12
  9. jaclang/compiler/passes/main/def_use_pass.py +59 -40
  10. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +71 -30
  11. jaclang/compiler/passes/main/import_pass.py +12 -7
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +110 -47
  13. jaclang/compiler/passes/main/pyast_load_pass.py +49 -13
  14. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +25 -11
  15. jaclang/compiler/passes/main/pyout_pass.py +3 -1
  16. jaclang/compiler/passes/main/registry_pass.py +6 -6
  17. jaclang/compiler/passes/main/sub_node_tab_pass.py +0 -5
  18. jaclang/compiler/passes/main/sym_tab_build_pass.py +43 -235
  19. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +21 -4
  20. jaclang/compiler/passes/main/tests/test_def_use_pass.py +5 -10
  21. jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
  22. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  23. jaclang/compiler/passes/main/type_check_pass.py +2 -1
  24. jaclang/compiler/passes/tool/jac_formatter_pass.py +44 -11
  25. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +16 -0
  26. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +16 -0
  27. jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
  28. jaclang/compiler/passes/tool/tests/fixtures/genai/essay_review.jac +1 -1
  29. jaclang/compiler/passes/tool/tests/fixtures/genai/expert_answer.jac +1 -1
  30. jaclang/compiler/passes/tool/tests/fixtures/genai/joke_gen.jac +1 -1
  31. jaclang/compiler/passes/tool/tests/fixtures/genai/odd_word_out.jac +1 -1
  32. jaclang/compiler/passes/tool/tests/fixtures/genai/personality_finder.jac +1 -1
  33. jaclang/compiler/passes/tool/tests/fixtures/genai/text_to_type.jac +1 -1
  34. jaclang/compiler/passes/tool/tests/fixtures/genai/translator.jac +1 -1
  35. jaclang/compiler/passes/tool/tests/fixtures/genai/wikipedia.jac +1 -1
  36. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
  37. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
  38. jaclang/compiler/passes/transform.py +2 -4
  39. jaclang/{core/registry.py → compiler/semtable.py} +1 -3
  40. jaclang/compiler/symtable.py +150 -89
  41. jaclang/compiler/tests/test_parser.py +2 -2
  42. jaclang/core/aott.py +118 -18
  43. jaclang/core/{construct.py → architype.py} +44 -93
  44. jaclang/core/constructs.py +44 -0
  45. jaclang/core/context.py +157 -0
  46. jaclang/core/importer.py +18 -9
  47. jaclang/core/memory.py +53 -2
  48. jaclang/core/test.py +90 -0
  49. jaclang/core/utils.py +2 -2
  50. jaclang/langserve/engine.py +199 -138
  51. jaclang/langserve/server.py +48 -53
  52. jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -0
  53. jaclang/langserve/tests/fixtures/circle.jac +16 -12
  54. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  55. jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
  56. jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
  57. jaclang/langserve/tests/fixtures/circle_pure.test.jac +15 -0
  58. jaclang/langserve/tests/fixtures/import_include_statements.jac +6 -0
  59. jaclang/langserve/tests/fixtures/py_import.py +26 -0
  60. jaclang/langserve/tests/test_server.py +200 -2
  61. jaclang/langserve/utils.py +214 -10
  62. jaclang/plugin/builtin.py +1 -1
  63. jaclang/plugin/default.py +48 -92
  64. jaclang/plugin/feature.py +33 -17
  65. jaclang/plugin/spec.py +18 -20
  66. jaclang/plugin/tests/test_features.py +0 -33
  67. jaclang/settings.py +4 -0
  68. jaclang/tests/fixtures/abc.jac +16 -12
  69. jaclang/tests/fixtures/aott_raise.jac +1 -1
  70. jaclang/tests/fixtures/byllmissue.jac +12 -0
  71. jaclang/tests/fixtures/edgetypeissue.jac +10 -0
  72. jaclang/tests/fixtures/hash_init_check.jac +17 -0
  73. jaclang/tests/fixtures/hello.jac +1 -1
  74. jaclang/tests/fixtures/impl_match_confused.impl.jac +1 -0
  75. jaclang/tests/fixtures/impl_match_confused.jac +5 -0
  76. jaclang/tests/fixtures/math_question.jpg +0 -0
  77. jaclang/tests/fixtures/maxfail_run_test.jac +17 -5
  78. jaclang/tests/fixtures/nosigself.jac +19 -0
  79. jaclang/tests/fixtures/run_test.jac +17 -5
  80. jaclang/tests/fixtures/walker_override.jac +21 -0
  81. jaclang/tests/fixtures/with_llm_function.jac +1 -1
  82. jaclang/tests/fixtures/with_llm_lower.jac +1 -1
  83. jaclang/tests/fixtures/with_llm_method.jac +1 -1
  84. jaclang/tests/fixtures/with_llm_type.jac +1 -1
  85. jaclang/tests/fixtures/with_llm_vision.jac +25 -0
  86. jaclang/tests/test_bugs.py +19 -0
  87. jaclang/tests/test_cli.py +1 -1
  88. jaclang/tests/test_language.py +197 -82
  89. jaclang/tests/test_reference.py +1 -1
  90. jaclang/utils/lang_tools.py +5 -4
  91. jaclang/utils/test.py +2 -1
  92. jaclang/utils/treeprinter.py +35 -4
  93. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/METADATA +3 -2
  94. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/RECORD +96 -88
  95. jaclang/core/llms/__init__.py +0 -20
  96. jaclang/core/llms/anthropic.py +0 -61
  97. jaclang/core/llms/base.py +0 -206
  98. jaclang/core/llms/groq.py +0 -67
  99. jaclang/core/llms/huggingface.py +0 -73
  100. jaclang/core/llms/ollama.py +0 -78
  101. jaclang/core/llms/openai.py +0 -61
  102. jaclang/core/llms/togetherai.py +0 -60
  103. jaclang/core/llms/utils.py +0 -9
  104. jaclang/core/shelve_storage.py +0 -55
  105. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/WHEEL +0 -0
  106. {jaclang-0.7.1.dist-info → jaclang-0.7.7.dist-info}/entry_points.txt +0 -0
@@ -2,66 +2,37 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import threading
6
5
  from typing import Optional
7
6
 
7
+ from jaclang.compiler.constant import (
8
+ JacSemTokenModifier as SemTokMod,
9
+ JacSemTokenType as SemTokType,
10
+ )
8
11
  from jaclang.langserve.engine import JacLangServer
9
12
  from jaclang.langserve.utils import debounce
10
13
 
11
14
  import lsprotocol.types as lspt
12
15
 
13
16
  server = JacLangServer()
14
- analysis_thread: Optional[threading.Thread] = None
15
- analysis_stop_event = threading.Event()
16
-
17
-
18
- def analyze_and_publish(ls: JacLangServer, uri: str) -> None:
19
- """Analyze and publish diagnostics."""
20
- global analysis_thread, analysis_stop_event
21
-
22
- def run_analysis() -> None:
23
- ls.quick_check(uri)
24
- ls.push_diagnostics(uri)
25
- ls.deep_check(uri)
26
- ls.push_diagnostics(uri)
27
- ls.type_check(uri)
28
- ls.push_diagnostics(uri)
29
-
30
- analysis_thread = threading.Thread(target=run_analysis)
31
- analysis_thread.start()
32
-
33
-
34
- def stop_analysis() -> None:
35
- """Stop analysis."""
36
- global analysis_thread, analysis_stop_event
37
- if analysis_thread is not None:
38
- analysis_stop_event.set()
39
- analysis_thread.join()
40
- analysis_stop_event.clear()
41
17
 
42
18
 
43
19
  @server.feature(lspt.TEXT_DOCUMENT_DID_OPEN)
44
- async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
20
+ @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
21
+ def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
45
22
  """Check syntax on change."""
46
- stop_analysis()
47
- analyze_and_publish(ls, params.text_document.uri)
23
+ ls.analyze_and_publish(params.text_document.uri)
24
+ # token_params = lspt.SemanticTokensParams(
25
+ # text_document=lspt.TextDocumentIdentifier(uri=params.text_document.uri)
26
+ # )
27
+ # tokens = semantic_tokens_full(ls, token_params)
28
+ # ls.send_notification("textDocument/publishSemanticTokens", tokens)
48
29
 
49
30
 
50
31
  @server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
51
32
  @debounce(0.1)
52
- async def did_change(
53
- ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
54
- ) -> None:
33
+ async def did_change(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
55
34
  """Check syntax on change."""
56
- stop_analysis()
57
- analyze_and_publish(ls, params.text_document.uri)
58
-
59
-
60
- @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
61
- async def did_save(ls: JacLangServer, params: lspt.DidSaveTextDocumentParams) -> None:
62
- """Check syntax on save."""
63
- stop_analysis()
64
- analyze_and_publish(ls, params.text_document.uri)
35
+ ls.analyze_and_publish(params.text_document.uri, level=0)
65
36
 
66
37
 
67
38
  @server.feature(
@@ -72,11 +43,8 @@ async def did_save(ls: JacLangServer, params: lspt.DidSaveTextDocumentParams) ->
72
43
  ]
73
44
  ),
74
45
  )
75
- async def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) -> None:
46
+ def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) -> None:
76
47
  """Check syntax on file creation."""
77
- for file in params.files:
78
- ls.quick_check(file.uri)
79
- ls.push_diagnostics(file.uri)
80
48
 
81
49
 
82
50
  @server.feature(
@@ -87,13 +55,12 @@ async def did_create_files(ls: JacLangServer, params: lspt.CreateFilesParams) ->
87
55
  ]
88
56
  ),
89
57
  )
90
- async def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) -> None:
58
+ def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) -> None:
91
59
  """Check syntax on file rename."""
92
60
  new_uris = [file.new_uri for file in params.files]
93
61
  old_uris = [file.old_uri for file in params.files]
94
62
  for i in range(len(new_uris)):
95
63
  ls.rename_module(old_uris[i], new_uris[i])
96
- ls.quick_check(new_uris[i])
97
64
 
98
65
 
99
66
  @server.feature(
@@ -104,7 +71,7 @@ async def did_rename_files(ls: JacLangServer, params: lspt.RenameFilesParams) ->
104
71
  ]
105
72
  ),
106
73
  )
107
- async def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
74
+ def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
108
75
  """Check syntax on file delete."""
109
76
  for file in params.files:
110
77
  ls.delete_module(file.uri)
@@ -114,9 +81,7 @@ async def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) ->
114
81
  lspt.TEXT_DOCUMENT_COMPLETION,
115
82
  lspt.CompletionOptions(trigger_characters=[".", ":", ""]),
116
83
  )
117
- async def completion(
118
- ls: JacLangServer, params: lspt.CompletionParams
119
- ) -> lspt.CompletionList:
84
+ def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList:
120
85
  """Provide completion."""
121
86
  return ls.get_completion(params.text_document.uri, params.position)
122
87
 
@@ -137,6 +102,36 @@ def hover(
137
102
  return ls.get_hover_info(params.text_document.uri, params.position)
138
103
 
139
104
 
105
+ @server.feature(lspt.TEXT_DOCUMENT_DOCUMENT_SYMBOL)
106
+ def document_symbol(
107
+ ls: JacLangServer, params: lspt.DocumentSymbolParams
108
+ ) -> list[lspt.DocumentSymbol]:
109
+ """Provide document symbols."""
110
+ return ls.get_document_symbols(params.text_document.uri)
111
+
112
+
113
+ @server.feature(lspt.TEXT_DOCUMENT_DEFINITION)
114
+ def definition(
115
+ ls: JacLangServer, params: lspt.TextDocumentPositionParams
116
+ ) -> Optional[lspt.Location]:
117
+ """Provide definition."""
118
+ return ls.get_definition(params.text_document.uri, params.position)
119
+
120
+
121
+ @server.feature(
122
+ lspt.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
123
+ lspt.SemanticTokensLegend(
124
+ token_types=SemTokType.as_str_list(),
125
+ token_modifiers=SemTokMod.as_str_list(),
126
+ ),
127
+ )
128
+ def semantic_tokens_full(
129
+ ls: JacLangServer, params: lspt.SemanticTokensParams
130
+ ) -> lspt.SemanticTokens:
131
+ """Provide semantic tokens."""
132
+ return ls.get_semantic_tokens(params.text_document.uri)
133
+
134
+
140
135
  def run_lang_server() -> None:
141
136
  """Run the language server."""
142
137
  server.start_io()
@@ -0,0 +1,28 @@
1
+ """A Docstring can be added the head of any module.
2
+
3
+ Any element in the module can also have a docstring.
4
+ If there is only one docstring before the first element,
5
+ it is assumed to be a module docstring.
6
+ """
7
+
8
+ """A docstring for add function"""
9
+ can add(a: int, b: int) -> int {
10
+ return a + b;
11
+ }
12
+ # No docstring for subtract function
13
+
14
+ can subtract(a: int, b: int) -> int {
15
+ return a - b;
16
+ }
17
+
18
+ with entry:__main__ {
19
+ print(add(1, subtract(3, 1)));
20
+ }
21
+
22
+ glob x: int = 10;
23
+
24
+ enum Color {
25
+ RED,
26
+ GREEN,
27
+ BLUE
28
+ }
@@ -18,9 +18,9 @@ Below we have the demonstration of a class to calculate the area of a circle.
18
18
  *#
19
19
 
20
20
  """Enum for shape types"""
21
- enum ShapeType {
22
- CIRCLE="Circle",
23
- UNKNOWN="Unknown"
21
+ enum ShapeType {
22
+ CIRCLE = "Circle",
23
+ UNKNOWN = "Unknown"
24
24
  }
25
25
 
26
26
  """Base class for a shape."""
@@ -50,24 +50,28 @@ with entry {
50
50
  # Global also works here
51
51
 
52
52
  with entry:__main__ {
53
- # To run the program functionality
54
- print(f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}");
55
- print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}");
53
+ # To run the program functionality
54
+ print(
55
+ f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
56
+ );
57
+ print(
58
+ f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
59
+ );
56
60
  }
57
61
  # Unit Tests!
58
62
 
59
63
  glob expected_area = 78.53981633974483;
60
64
 
61
- test calc_area {
62
- check.assertAlmostEqual(calculate_area(RAD), expected_area);
65
+ test calc_area {
66
+ check assertAlmostEqual(calculate_area(RAD), expected_area);
63
67
  }
64
68
 
65
- test circle_area {
69
+ test circle_area {
66
70
  c = Circle(RAD);
67
- check.assertAlmostEqual(c.area(), expected_area);
71
+ check assertAlmostEqual(c.area(), expected_area);
68
72
  }
69
73
 
70
- test circle_type {
74
+ test circle_type {
71
75
  c = Circle(RAD);
72
- check.assertEqual(c.shape_type, ShapeType.CIRCLE);
76
+ check assertEqual(c.shape_type, ShapeType.CIRCLE);
73
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.assertAlmostEqual(calculate_area(RAD), expected_area);
62
+ check assertAlmostEqual(calculate_area(RAD), expected_area);
63
63
  }
64
64
 
65
65
  test circle_area {
66
66
  c = Circle(RAD);
67
- check.assertAlmostEqual(c.area(), expected_area);
67
+ check assertAlmostEqual(c.area(), expected_area);
68
68
  }
69
69
 
70
70
  test circle_type {
71
71
  c = Circle(RAD);
72
- check.assertEqual(c.shape_type, ShapeType.CIRCLE);
72
+ check assertEqual(c.shape_type, ShapeType.CIRCLE);
73
73
  }
@@ -1,8 +1,8 @@
1
1
  """Enum for shape types"""
2
2
 
3
3
  :enum:ShapeType {
4
- CIRCLE="Circle",
5
- UNKNOWN="Unknown"
4
+ CIRCLE = "Circle",
5
+ UNKNOWN = "Unknown"
6
6
  }
7
7
 
8
8
  """Function to calculate the area of a circle."""
@@ -23,6 +23,10 @@
23
23
  }
24
24
 
25
25
  :can:main_run {
26
- print(f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}");
27
- print(f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}");
26
+ print(
27
+ f"Area of a circle with radius {RAD} using function: {calculate_area(RAD)}"
28
+ );
29
+ print(
30
+ f"Area of a {c.shape_type.value} with radius {RAD} using class: {c.area()}"
31
+ );
28
32
  }
@@ -11,7 +11,7 @@ can calculate_area(radius: float) -> float;
11
11
  can main_run;
12
12
 
13
13
  """Base class for a shape."""
14
- obj Shape {
14
+ obj : priv Shape {
15
15
  has shape_type: ShapeType;
16
16
 
17
17
  can area -> float abs;
@@ -22,7 +22,7 @@ obj Circle :Shape: {
22
22
  has radius: float;
23
23
 
24
24
  can init(radius: float);
25
- can area -> float;
25
+ override can area -> float;
26
26
  }
27
27
  # Radius of the demo circle
28
28
 
@@ -0,0 +1,15 @@
1
+ glob expected_area = 78.53981633974483;
2
+
3
+ test a1 {
4
+ check assertAlmostEqual(calculate_area(RAD), expected_area);
5
+ }
6
+
7
+ test a2 {
8
+ c = Circle(RAD);
9
+ check assertAlmostEqual(c.area(), expected_area);
10
+ }
11
+
12
+ test a3 {
13
+ c = Circle(RAD);
14
+ check assertEqual(c.shape_type, ShapeType.CIRCLE);
15
+ }
@@ -0,0 +1,6 @@
1
+ import:py os;
2
+ import:py from math, sqrt as square_root;
3
+ import:py datetime as dt;
4
+ import:jac from base_module_structure, add as adsd, subtract,x,Color as clr;
5
+ import:jac base_module_structure as base_module_structure;
6
+ import:py from py_import,add1 as ss, sub1 as subtract1,apple,Orange1;
@@ -0,0 +1,26 @@
1
+ """This is a helper file."""
2
+
3
+
4
+ def add1():
5
+ return 1 + 1
6
+
7
+
8
+ def sub1():
9
+ return 1 - 1
10
+
11
+
12
+ # classes
13
+ class Orange1:
14
+ def __init__(self):
15
+ self.orange = 1
16
+
17
+ def get_orange(self):
18
+ return self.orange
19
+
20
+ def set_orange(self, orange):
21
+ self.orange = orange
22
+
23
+
24
+ # variables
25
+ orange2 = 1
26
+ apple = 1
@@ -4,6 +4,8 @@ from jaclang.vendor.pygls.workspace import Workspace
4
4
  from jaclang.langserve.engine import JacLangServer
5
5
  from .session import LspSession
6
6
 
7
+ import lsprotocol.types as lspt
8
+
7
9
 
8
10
  class TestJacLangServer(TestCase):
9
11
 
@@ -61,8 +63,204 @@ class TestJacLangServer(TestCase):
61
63
  self.assertEqual(len(lsp.modules), 1)
62
64
  self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
63
65
  lsp.deep_check(circle_file)
64
- self.assertEqual(len(lsp.modules), 1)
66
+ # self.assertEqual(len(lsp.modules), 1)
65
67
  self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
66
68
  lsp.type_check(circle_file)
67
- self.assertEqual(len(lsp.modules), 1)
69
+ # self.assertEqual(len(lsp.modules), 1)
68
70
  self.assertEqual(lsp.modules[circle_file].diagnostics[0].range.start.line, 22)
71
+
72
+ def test_impl_stay_connected(self) -> None:
73
+ """Test that the server doesn't run if there is a syntax error."""
74
+ lsp = JacLangServer()
75
+ # Set up the workspace path to "fixtures/"
76
+ workspace_path = self.fixture_abs_path("")
77
+ workspace = Workspace(workspace_path, lsp)
78
+ lsp.lsp._workspace = workspace
79
+ circle_file = uris.from_fs_path(self.fixture_abs_path("circle_pure.jac"))
80
+ circle_impl_file = uris.from_fs_path(
81
+ self.fixture_abs_path("circle_pure.impl.jac")
82
+ )
83
+ lsp.quick_check(circle_file)
84
+ lsp.deep_check(circle_file)
85
+ lsp.type_check(circle_file)
86
+ pos = lspt.Position(20, 8)
87
+ self.assertIn(
88
+ "Circle class inherits from Shape.",
89
+ lsp.get_hover_info(circle_file, pos).contents.value,
90
+ )
91
+ lsp.type_check(circle_impl_file)
92
+ pos = lspt.Position(8, 11)
93
+ self.assertIn(
94
+ "ability) calculate_area: float",
95
+ lsp.get_hover_info(circle_impl_file, pos).contents.value,
96
+ )
97
+
98
+ def test_impl_auto_discover(self) -> None:
99
+ """Test that the server doesn't run if there is a syntax error."""
100
+ lsp = JacLangServer()
101
+ # Set up the workspace path to "fixtures/"
102
+ workspace_path = self.fixture_abs_path("")
103
+ workspace = Workspace(workspace_path, lsp)
104
+ lsp.lsp._workspace = workspace
105
+ circle_impl_file = uris.from_fs_path(
106
+ self.fixture_abs_path("circle_pure.impl.jac")
107
+ )
108
+ lsp.quick_check(circle_impl_file)
109
+ lsp.deep_check(circle_impl_file)
110
+ lsp.type_check(circle_impl_file)
111
+ pos = lspt.Position(8, 11)
112
+ self.assertIn(
113
+ "ability) calculate_area: float",
114
+ lsp.get_hover_info(circle_impl_file, pos).contents.value,
115
+ )
116
+
117
+ def test_show_type_impl(self) -> None:
118
+ """Test that the server doesn't run if there is a syntax error."""
119
+ lsp = JacLangServer()
120
+ # Set up the workspace path to "fixtures/"
121
+ workspace_path = self.fixture_abs_path("")
122
+ workspace = Workspace(workspace_path, lsp)
123
+ lsp.lsp._workspace = workspace
124
+ target = uris.from_fs_path(
125
+ self.fixture_abs_path("../../../../examples/guess_game/guess_game4.jac")
126
+ )
127
+ lsp.quick_check(target)
128
+ lsp.deep_check(target)
129
+ lsp.type_check(target)
130
+ pos = lspt.Position(43, 18)
131
+ self.assertIn(
132
+ "attempts: int",
133
+ lsp.get_hover_info(target, pos).contents.value,
134
+ )
135
+
136
+ def test_outline_symbols(self) -> None:
137
+ """Test that the outline symbols are correct."""
138
+ lsp = JacLangServer()
139
+ workspace_path = self.fixture_abs_path("")
140
+ workspace = Workspace(workspace_path, lsp)
141
+ lsp.lsp._workspace = workspace
142
+ circle_file = uris.from_fs_path(self.fixture_abs_path("circle_pure.jac"))
143
+ lsp.quick_check(circle_file)
144
+ lsp.deep_check(circle_file)
145
+ lsp.type_check(circle_file)
146
+ self.assertEqual(8, len(lsp.get_document_symbols(circle_file)))
147
+
148
+ def test_go_to_definition(self) -> None:
149
+ """Test that the go to definition is correct."""
150
+ lsp = JacLangServer()
151
+ workspace_path = self.fixture_abs_path("")
152
+ workspace = Workspace(workspace_path, lsp)
153
+ lsp.lsp._workspace = workspace
154
+ circle_file = uris.from_fs_path(self.fixture_abs_path("circle_pure.jac"))
155
+ lsp.quick_check(circle_file)
156
+ lsp.deep_check(circle_file)
157
+ lsp.type_check(circle_file)
158
+ self.assertIn(
159
+ "fixtures/circle_pure.impl.jac:8:0-8:19",
160
+ str(lsp.get_definition(circle_file, lspt.Position(9, 16))),
161
+ )
162
+ self.assertIn(
163
+ "fixtures/circle_pure.jac:13:11-13:16",
164
+ str(lsp.get_definition(circle_file, lspt.Position(20, 17))),
165
+ )
166
+
167
+ def test_go_to_definition_method(self) -> None:
168
+ """Test that the go to definition is correct."""
169
+ lsp = JacLangServer()
170
+ workspace_path = self.fixture_abs_path("")
171
+ workspace = Workspace(workspace_path, lsp)
172
+ lsp.lsp._workspace = workspace
173
+ guess_game_file = uris.from_fs_path(
174
+ self.fixture_abs_path("../../../../examples/guess_game/guess_game4.jac")
175
+ )
176
+ lsp.quick_check(guess_game_file)
177
+ lsp.deep_check(guess_game_file)
178
+ lsp.type_check(guess_game_file)
179
+ self.assertIn(
180
+ "guess_game4.jac:27:8-27:21",
181
+ str(lsp.get_definition(guess_game_file, lspt.Position(46, 45))),
182
+ )
183
+
184
+ def test_test_annex(self) -> None:
185
+ """Test that the server doesn't run if there is a syntax error."""
186
+ lsp = JacLangServer()
187
+ # Set up the workspace path to "fixtures/"
188
+ workspace_path = self.fixture_abs_path("")
189
+ workspace = Workspace(workspace_path, lsp)
190
+ lsp.lsp._workspace = workspace
191
+ circle_file = uris.from_fs_path(self.fixture_abs_path("circle_pure.test.jac"))
192
+ lsp.quick_check(circle_file)
193
+ lsp.deep_check(circle_file)
194
+ lsp.type_check(circle_file)
195
+ pos = lspt.Position(13, 29)
196
+ self.assertIn(
197
+ "shape_type: circle_pure.ShapeType",
198
+ lsp.get_hover_info(circle_file, pos).contents.value,
199
+ )
200
+
201
+ def test_go_to_defintion_import(self) -> None:
202
+ """Test that the go to definition is correct."""
203
+ lsp = JacLangServer()
204
+ workspace_path = self.fixture_abs_path("")
205
+ workspace = Workspace(workspace_path, lsp)
206
+ lsp.lsp._workspace = workspace
207
+ import_file = uris.from_fs_path(
208
+ self.fixture_abs_path("import_include_statements.jac")
209
+ )
210
+ lsp.quick_check(import_file)
211
+ lsp.deep_check(import_file)
212
+ lsp.type_check(import_file)
213
+ positions = [
214
+ (2, 16, "datetime.py:0:0-0:0"),
215
+ (3, 17, "base_module_structure.jac:0:0-0:0"),
216
+ (3, 74, "base_module_structure.jac:23:0-23:5"),
217
+ (5, 65, "py_import.py:12:0-20:5"),
218
+ (5, 35, "py_import.py:3:0-4:5"),
219
+ ]
220
+
221
+ for line, char, expected in positions:
222
+ with self.subTest(line=line, char=char):
223
+ self.assertIn(
224
+ expected,
225
+ str(lsp.get_definition(import_file, lspt.Position(line, char))),
226
+ )
227
+
228
+ def test_sem_tokens(self) -> None:
229
+ """Test that the Semantic Tokens are generated correctly."""
230
+ lsp = JacLangServer()
231
+ workspace_path = self.fixture_abs_path("")
232
+ workspace = Workspace(workspace_path, lsp)
233
+ lsp.lsp._workspace = workspace
234
+ circle_file = uris.from_fs_path(self.fixture_abs_path("circle.jac"))
235
+ lsp.quick_check(circle_file)
236
+ lsp.deep_check(circle_file)
237
+ lsp.type_check(circle_file)
238
+ sem_list = lsp.get_semantic_tokens(circle_file).data
239
+ expected_counts = [
240
+ ("<JacSemTokenType.VARIABLE: 8>, <JacSemTokenModifier.READONLY: 4>", 206),
241
+ (
242
+ "<JacSemTokenType.PROPERTY: 9>, <JacSemTokenModifier.DEFINITION: 2>,",
243
+ 112,
244
+ ),
245
+ (
246
+ "<JacSemTokenType.PARAMETER: 7>, <JacSemTokenModifier.DECLARATION: 1>,",
247
+ 56,
248
+ ),
249
+ (
250
+ "<JacSemTokenType.FUNCTION: 12>, <JacSemTokenModifier.DECLARATION: 1>,",
251
+ 25,
252
+ ),
253
+ ("<JacSemTokenType.METHOD: 13>, <JacSemTokenModifier.DECLARATION: 1>", 12),
254
+ ("<JacSemTokenType.ENUM: 3>, <JacSemTokenModifier.DECLARATION: 1>,", 37),
255
+ ("<JacSemTokenType.CLASS: 2>, <JacSemTokenModifier.DECLARATION: ", 162),
256
+ (
257
+ "<JacSemTokenType.NAMESPACE: 0>, <JacSemTokenModifier.DEFINITION: 2>,",
258
+ 10,
259
+ ),
260
+ ("0, 0, 4,", 22),
261
+ ("0, 0, 3,", 192),
262
+ ("0, 0, 6, ", 65),
263
+ (" 0, 7, 3,", 3),
264
+ ]
265
+ for token_type, expected_count in expected_counts:
266
+ self.assertEqual(str(sem_list).count(token_type), expected_count)