diff --git a/jac/jaclang/langserve/engine.py b/jac/jaclang/langserve/engine.py index 5e1aa5037..856685dbb 100644 --- a/jac/jaclang/langserve/engine.py +++ b/jac/jaclang/langserve/engine.py @@ -80,23 +80,28 @@ def update_modules( impl_parent=self.modules[file_path], ) - def quick_check(self, file_path: str) -> bool: + def quick_check(self, file_path: str) -> tuple[bool, list[lspt.Diagnostic]]: """Rebuild a file.""" try: document = self.workspace.get_text_document(file_path) build = jac_str_to_pass( jac_str=document.source, file_path=document.path, schedule=[] ) + diagnostics = gen_diagnostics( + file_path, build.errors_had, build.warnings_had + ) self.publish_diagnostics( file_path, - gen_diagnostics(file_path, build.errors_had, build.warnings_had), + diagnostics, ) - return len(build.errors_had) == 0 + return len(build.errors_had) == 0, diagnostics except Exception as e: self.log_error(f"Error during syntax check: {e}") - return False + return False, [] - def deep_check(self, file_path: str, annex_view: Optional[str] = None) -> bool: + def deep_check( + self, file_path: str, annex_view: Optional[str] = None + ) -> tuple[bool, list[lspt.Diagnostic] | Exception]: """Rebuild a file and its dependencies.""" try: start_time = time.time() @@ -117,29 +122,27 @@ def deep_check(self, file_path: str, annex_view: Optional[str] = None) -> bool: return self.deep_check( uris.from_fs_path(discover), annex_view=file_path ) - + diagnostics = gen_diagnostics( + annex_view if annex_view else file_path, + build.errors_had, + build.warnings_had, + ) self.publish_diagnostics( annex_view if annex_view else file_path, - gen_diagnostics( - annex_view if annex_view else file_path, - build.errors_had, - build.warnings_had, - ), + diagnostics, ) if annex_view: - self.publish_diagnostics( + diagnostics = gen_diagnostics( file_path, - gen_diagnostics( - file_path, - build.errors_had, - build.warnings_had, - ), + build.errors_had, + build.warnings_had, ) + self.publish_diagnostics(file_path, diagnostics) self.log_py(f"PROFILE: Deep check took {time.time() - start_time} seconds.") - return len(build.errors_had) == 0 + return len(build.errors_had) == 0, diagnostics except Exception as e: self.log_error(f"Error during deep check: {e}") - return False + return False, e async def launch_quick_check(self, uri: str) -> None: """Analyze and publish diagnostics.""" @@ -151,7 +154,9 @@ async def launch_deep_check(self, uri: str) -> None: """Analyze and publish diagnostics.""" async def run_in_executor( - func: Callable[[str, Optional[str]], bool], + func: Callable[ + [str, Optional[str]], tuple[bool, list[lspt.Diagnostic] | Exception] + ], file_path: str, annex_view: Optional[str] = None, ) -> None: diff --git a/jac/jaclang/langserve/tests/test_server.py b/jac/jaclang/langserve/tests/test_server.py index 61b5af77b..613232297 100644 --- a/jac/jaclang/langserve/tests/test_server.py +++ b/jac/jaclang/langserve/tests/test_server.py @@ -9,20 +9,6 @@ class TestJacLangServer(TestCase): - def _run_check_and_capture_logs(self, file_path, check_method): - file_uri = uris.from_fs_path(self.fixture_abs_path(file_path)) - import logging - import io - - log_capture = io.StringIO() - handler = logging.StreamHandler(log_capture) - logger = logging.getLogger() - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - status = check_method(file_uri) - log_output = log_capture.getvalue() - return status, log_output - def test_formatting(self) -> None: with LspSession() as s: s.initialize() @@ -590,15 +576,15 @@ def test_syntax_diagnosis(self) -> None: workspace_path = self.fixture_abs_path("") workspace = Workspace(workspace_path, lsp) lsp.lsp._workspace = workspace - status, log_output = self._run_check_and_capture_logs( - "circle_pure_syntax_err.impl.jac", lsp.quick_check - ) + file_path = "circle_pure_syntax_err.impl.jac" + file_uri = uris.from_fs_path(self.fixture_abs_path(file_path)) + status, log_output = lsp.quick_check(file_uri) self.assertEqual(False, status) self.assertIn( "message=\"Syntax Error: Unexpected token Token('KW_RETURN', 'return'", - log_output, + str(log_output), ) - self.assertIn("diagnostics=[Diagnostic(range=10:4-10:5", log_output) + self.assertIn("[Diagnostic(range=10:4-10:5,", str(log_output)) def test_impl_syntax_diagnosis(self) -> None: """Test that the server shows an error if there is a syntax error.""" @@ -606,15 +592,11 @@ def test_impl_syntax_diagnosis(self) -> None: workspace_path = self.fixture_abs_path("") workspace = Workspace(workspace_path, lsp) lsp.lsp._workspace = workspace - status, log_output = self._run_check_and_capture_logs( - "circle_pure_syntax_err.jac", lsp.deep_check - ) + file_path = "circle_pure_syntax_err.jac" + file_uri = uris.from_fs_path(self.fixture_abs_path(file_path)) + status, log_output = lsp.deep_check(file_uri) self.assertEqual(False, status) self.assertIn( - "circle_pure_syntax_err.jac, line 10, col 1: Ability has no body. ", - log_output, - ) - self.assertIn( - "/circle_pure_syntax_err.impl.jac, line 11, col 5: Syntax Error:", - log_output, + "empty body on ClassDef", + str(log_output), )