From b931e972434a7c50ddf4edf92fee77e5db8d8053 Mon Sep 17 00:00:00 2001 From: Kai Yao Date: Tue, 5 Aug 2025 11:15:35 -0500 Subject: [PATCH] added support for rust 2024 edition (#412) --- .../language_servers/rust_analyzer.py | 10 +- .../repos/rust/test_repo_2024/Cargo.lock | 7 ++ .../repos/rust/test_repo_2024/Cargo.toml | 6 + .../repos/rust/test_repo_2024/src/lib.rs | 21 ++++ .../repos/rust/test_repo_2024/src/main.rs | 19 +++ test/solidlsp/rust/test_rust_2024_edition.py | 112 ++++++++++++++++++ 6 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 test/resources/repos/rust/test_repo_2024/Cargo.lock create mode 100644 test/resources/repos/rust/test_repo_2024/Cargo.toml create mode 100644 test/resources/repos/rust/test_repo_2024/src/lib.rs create mode 100644 test/resources/repos/rust/test_repo_2024/src/main.rs create mode 100644 test/solidlsp/rust/test_rust_2024_edition.py diff --git a/src/solidlsp/language_servers/rust_analyzer.py b/src/solidlsp/language_servers/rust_analyzer.py index de73f045..d9b09090 100644 --- a/src/solidlsp/language_servers/rust_analyzer.py +++ b/src/solidlsp/language_servers/rust_analyzer.py @@ -60,7 +60,7 @@ class RustAnalyzer(SolidLanguageServer): RuntimeDependency( id="RustAnalyzer", description="RustAnalyzer for macOS (x64)", - url="https://github.com/rust-lang/rust-analyzer/releases/download/2023-10-09/rust-analyzer-x86_64-apple-darwin.gz", + url="https://github.com/rust-lang/rust-analyzer/releases/download/2025-08-04/rust-analyzer-x86_64-apple-darwin.gz", platform_id="osx-x64", archive_type="gz", binary_name="rust_analyzer", @@ -68,7 +68,7 @@ class RustAnalyzer(SolidLanguageServer): RuntimeDependency( id="RustAnalyzer", description="RustAnalyzer for macOS (arm64)", - url="https://github.com/rust-lang/rust-analyzer/releases/download/2023-10-09/rust-analyzer-aarch64-apple-darwin.gz", + url="https://github.com/rust-lang/rust-analyzer/releases/download/2025-08-04/rust-analyzer-aarch64-apple-darwin.gz", platform_id="osx-arm64", archive_type="gz", binary_name="rust_analyzer", @@ -76,7 +76,7 @@ class RustAnalyzer(SolidLanguageServer): RuntimeDependency( id="RustAnalyzer", description="RustAnalyzer for Linux (x64)", - url="https://github.com/rust-lang/rust-analyzer/releases/download/2023-10-09/rust-analyzer-x86_64-unknown-linux-gnu.gz", + url="https://github.com/rust-lang/rust-analyzer/releases/download/2025-08-04/rust-analyzer-x86_64-unknown-linux-gnu.gz", platform_id="linux-x64", archive_type="gz", binary_name="rust_analyzer", @@ -84,7 +84,7 @@ class RustAnalyzer(SolidLanguageServer): RuntimeDependency( id="RustAnalyzer", description="RustAnalyzer for Linux (arm64)", - url="https://github.com/rust-lang/rust-analyzer/releases/download/2023-10-09/rust-analyzer-aarch64-unknown-linux-gnu.gz", + url="https://github.com/rust-lang/rust-analyzer/releases/download/2025-08-04/rust-analyzer-aarch64-unknown-linux-gnu.gz", platform_id="linux-arm64", archive_type="gz", binary_name="rust_analyzer", @@ -92,7 +92,7 @@ class RustAnalyzer(SolidLanguageServer): RuntimeDependency( id="RustAnalyzer", description="RustAnalyzer for Windows (x64)", - url="https://github.com/rust-lang/rust-analyzer/releases/download/2023-10-09/rust-analyzer-x86_64-pc-windows-msvc.zip", + url="https://github.com/rust-lang/rust-analyzer/releases/download/2025-08-04/rust-analyzer-x86_64-pc-windows-msvc.zip", platform_id="win-x64", archive_type="zip", binary_name="rust-analyzer.exe", diff --git a/test/resources/repos/rust/test_repo_2024/Cargo.lock b/test/resources/repos/rust/test_repo_2024/Cargo.lock new file mode 100644 index 00000000..88beb720 --- /dev/null +++ b/test/resources/repos/rust/test_repo_2024/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "rsandbox_2024" +version = "0.1.0" diff --git a/test/resources/repos/rust/test_repo_2024/Cargo.toml b/test/resources/repos/rust/test_repo_2024/Cargo.toml new file mode 100644 index 00000000..2f20bf2e --- /dev/null +++ b/test/resources/repos/rust/test_repo_2024/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rsandbox_2024" +version = "0.1.0" +edition = "2024" + +[dependencies] \ No newline at end of file diff --git a/test/resources/repos/rust/test_repo_2024/src/lib.rs b/test/resources/repos/rust/test_repo_2024/src/lib.rs new file mode 100644 index 00000000..28fac4c7 --- /dev/null +++ b/test/resources/repos/rust/test_repo_2024/src/lib.rs @@ -0,0 +1,21 @@ +pub fn multiply(a: i32, b: i32) -> i32 { + a * b +} + +pub struct Calculator { + pub result: i32, +} + +impl Calculator { + pub fn new() -> Self { + Calculator { result: 0 } + } + + pub fn add(&mut self, value: i32) { + self.result += value; + } + + pub fn get_result(&self) -> i32 { + self.result + } +} \ No newline at end of file diff --git a/test/resources/repos/rust/test_repo_2024/src/main.rs b/test/resources/repos/rust/test_repo_2024/src/main.rs new file mode 100644 index 00000000..ec20c47a --- /dev/null +++ b/test/resources/repos/rust/test_repo_2024/src/main.rs @@ -0,0 +1,19 @@ +fn main() { + println!("Hello, Rust 2024 edition!"); + let result = add(2, 3); + println!("2 + 3 = {}", result); +} + +pub fn add(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add() { + assert_eq!(add(2, 3), 5); + } +} \ No newline at end of file diff --git a/test/solidlsp/rust/test_rust_2024_edition.py b/test/solidlsp/rust/test_rust_2024_edition.py new file mode 100644 index 00000000..e73c8d6d --- /dev/null +++ b/test/solidlsp/rust/test_rust_2024_edition.py @@ -0,0 +1,112 @@ +import os +from pathlib import Path + +import pytest + +from solidlsp.ls_config import Language +from solidlsp.ls_utils import SymbolUtils +from test.conftest import create_ls + + +@pytest.mark.rust +class TestRust2024EditionLanguageServer: + @classmethod + def setup_class(cls): + """Set up the test class with the Rust 2024 edition test repository.""" + cls.test_repo_2024_path = Path(__file__).parent.parent.parent / "resources" / "repos" / "rust" / "test_repo_2024" + + if not cls.test_repo_2024_path.exists(): + pytest.skip("Rust 2024 edition test repository not found") + + # Create and start the language server for the 2024 edition repo + cls.language_server = create_ls(Language.RUST, str(cls.test_repo_2024_path)) + cls.language_server.start() + + @classmethod + def teardown_class(cls): + """Clean up the language server.""" + if hasattr(cls, "language_server"): + cls.language_server.stop() + + def test_find_references_raw(self) -> None: + # Test finding references to the 'add' function defined in main.rs + file_path = os.path.join("src", "main.rs") + symbols = self.language_server.request_document_symbols(file_path) + add_symbol = None + for sym in symbols[0]: + if sym.get("name") == "add": + add_symbol = sym + break + assert add_symbol is not None, "Could not find 'add' function symbol in main.rs" + sel_start = add_symbol["selectionRange"]["start"] + refs = self.language_server.request_references(file_path, sel_start["line"], sel_start["character"]) + # The add function should be referenced within main.rs itself (in the main function) + assert any("main.rs" in ref.get("relativePath", "") for ref in refs), "main.rs should reference add function" + + def test_find_symbol(self) -> None: + symbols = self.language_server.request_full_symbol_tree() + assert SymbolUtils.symbol_tree_contains_name(symbols, "main"), "main function not found in symbol tree" + assert SymbolUtils.symbol_tree_contains_name(symbols, "add"), "add function not found in symbol tree" + assert SymbolUtils.symbol_tree_contains_name(symbols, "multiply"), "multiply function not found in symbol tree" + assert SymbolUtils.symbol_tree_contains_name(symbols, "Calculator"), "Calculator struct not found in symbol tree" + + def test_find_referencing_symbols_multiply(self) -> None: + # Find references to 'multiply' function defined in lib.rs + file_path = os.path.join("src", "lib.rs") + symbols = self.language_server.request_document_symbols(file_path) + multiply_symbol = None + for sym in symbols[0]: + if sym.get("name") == "multiply": + multiply_symbol = sym + break + assert multiply_symbol is not None, "Could not find 'multiply' function symbol in lib.rs" + sel_start = multiply_symbol["selectionRange"]["start"] + refs = self.language_server.request_references(file_path, sel_start["line"], sel_start["character"]) + # The multiply function exists but may not be referenced anywhere, which is fine + # This test just verifies we can find the symbol and request references without error + assert isinstance(refs, list), "Should return a list of references (even if empty)" + + def test_find_calculator_struct_and_impl(self) -> None: + # Test finding the Calculator struct and its impl block + file_path = os.path.join("src", "lib.rs") + symbols = self.language_server.request_document_symbols(file_path) + + # Find the Calculator struct + calculator_struct = None + calculator_impl = None + for sym in symbols[0]: + if sym.get("name") == "Calculator" and sym.get("kind") == 23: # Struct kind + calculator_struct = sym + elif sym.get("name") == "Calculator" and sym.get("kind") == 11: # Interface/Impl kind + calculator_impl = sym + + assert calculator_struct is not None, "Could not find 'Calculator' struct symbol in lib.rs" + + # The struct should have the 'result' field + struct_children = calculator_struct.get("children", []) + field_names = [child.get("name") for child in struct_children] + assert "result" in field_names, "Calculator struct should have 'result' field" + + # Find the impl block and check its methods + if calculator_impl is not None: + impl_children = calculator_impl.get("children", []) + method_names = [child.get("name") for child in impl_children] + assert "new" in method_names, "Calculator impl should have 'new' method" + assert "add" in method_names, "Calculator impl should have 'add' method" + assert "get_result" in method_names, "Calculator impl should have 'get_result' method" + + def test_overview_methods(self) -> None: + symbols = self.language_server.request_full_symbol_tree() + assert SymbolUtils.symbol_tree_contains_name(symbols, "main"), "main missing from overview" + assert SymbolUtils.symbol_tree_contains_name(symbols, "add"), "add missing from overview" + assert SymbolUtils.symbol_tree_contains_name(symbols, "multiply"), "multiply missing from overview" + assert SymbolUtils.symbol_tree_contains_name(symbols, "Calculator"), "Calculator missing from overview" + + def test_rust_2024_edition_specific(self) -> None: + # Verify we're actually working with the 2024 edition repository + cargo_toml_path = self.test_repo_2024_path / "Cargo.toml" + assert cargo_toml_path.exists(), "Cargo.toml should exist in test repository" + + with open(cargo_toml_path) as f: + content = f.read() + assert 'edition = "2024"' in content, "Should be using Rust 2024 edition"