""" Basic integration tests for the MATLAB language server functionality. These tests validate the functionality of the language server APIs like request_document_symbols using the MATLAB test repository. Requirements: - MATLAB R2021b or later must be installed - MATLAB_PATH environment variable should be set to MATLAB installation directory - Node.js and npm must be installed """ import pytest from solidlsp import SolidLanguageServer from solidlsp.ls_config import Language from test.conftest import language_tests_enabled from test.solidlsp.conftest import format_symbol_for_assert, has_malformed_name, request_all_symbols from test.solidlsp.util.diagnostics import assert_file_diagnostics # Skip all tests if MATLAB is not available pytestmark = pytest.mark.matlab @pytest.mark.skipif(not language_tests_enabled(Language.MATLAB), reason="MATLAB tests are disabled (MATLAB installation not found)") class TestMatlabLanguageServerBasics: """Test basic functionality of the MATLAB language server.""" @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_language_server_initialization(self, language_server: SolidLanguageServer) -> None: """Test that MATLAB language server can be initialized successfully.""" assert language_server is not None assert language_server.language == Language.MATLAB @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_request_document_symbols_class(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols for MATLAB class file.""" # Test getting symbols from Calculator.m (class file) all_symbols, _root_symbols = language_server.request_document_symbols("Calculator.m").get_all_symbols_and_roots() # Extract class symbols (LSP Symbol Kind 5 for class) class_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 5] class_names = [symbol["name"] for symbol in class_symbols] # Should find the Calculator class assert "Calculator" in class_names, "Should find Calculator class" # Extract method symbols (LSP Symbol Kind 6 for method or 12 for function) method_symbols = [symbol for symbol in all_symbols if symbol.get("kind") in [6, 12]] method_names = [symbol["name"] for symbol in method_symbols] # Should find key methods expected_methods = ["add", "subtract", "multiply", "divide"] for method in expected_methods: assert method in method_names, f"Should find {method} method in Calculator class" @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_request_document_symbols_function(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols for MATLAB function file.""" # Test getting symbols from lib/mathUtils.m (function file) all_symbols, _root_symbols = language_server.request_document_symbols("lib/mathUtils.m").get_all_symbols_and_roots() # Extract function symbols (LSP Symbol Kind 12 for function) function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12] function_names = [symbol["name"] for symbol in function_symbols] # Should find the main mathUtils function assert "mathUtils" in function_names, "Should find mathUtils function" # Should also find nested/local functions expected_local_functions = ["computeFactorial", "computeFibonacci", "checkPrime", "computeStats"] for func in expected_local_functions: assert func in function_names, f"Should find {func} local function" @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_request_document_symbols_script(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols for MATLAB script file.""" # Test getting symbols from main.m (script file) all_symbols, _root_symbols = language_server.request_document_symbols("main.m").get_all_symbols_and_roots() # Scripts may have variables and sections, but less structured symbols # Just verify we can get symbols without errors assert all_symbols is not None @pytest.mark.skipif(not language_tests_enabled(Language.MATLAB), reason="MATLAB tests are disabled (MATLAB installation not found)") class TestMatlabLanguageServerReferences: """Test find references functionality of the MATLAB language server.""" @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_find_references_within_file(self, language_server: SolidLanguageServer) -> None: """Test finding references within a single MATLAB file.""" # Find references to 'result' variable in Calculator.m # This is a basic test to verify references work references = language_server.request_references("Calculator.m", 25, 12) # 'result' in add method # Should find at least the definition assert references is not None @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_matlab_find_references_cross_file(self, language_server: SolidLanguageServer) -> None: """Test finding references across MATLAB files.""" # Find references to Calculator class used in main.m references = language_server.request_references("main.m", 11, 8) # 'Calculator' reference # Should find references in both main.m and Calculator.m assert references is not None @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_bare_symbol_names(self, language_server) -> None: all_symbols = request_all_symbols(language_server) malformed_symbols = [] for s in all_symbols: if has_malformed_name(s): malformed_symbols.append(s) if malformed_symbols: pytest.fail( f"Found malformed symbols: {[format_symbol_for_assert(sym) for sym in malformed_symbols]}", pytrace=False, ) @pytest.mark.parametrize("language_server", [Language.MATLAB], indirect=True) def test_file_diagnostics(self, language_server: SolidLanguageServer) -> None: assert_file_diagnostics( language_server, "diagnostics_sample.m", (), min_count=1, )