Skip to main content
Glama

mcp-server-tree-sitter

by wrale
MIT License
175
  • Apple
  • Linux
test_ast_parsing.py7.51 kB
"""Pytest-based diagnostic tests for AST parsing functionality.""" import tempfile from pathlib import Path from typing import Any, Dict, Generator, Tuple import pytest from mcp_server_tree_sitter.api import get_language_registry, get_project_registry, get_tree_cache from mcp_server_tree_sitter.models.ast import node_to_dict from tests.test_helpers import get_ast, register_project_tool @pytest.fixture def test_project() -> Generator[Dict[str, Any], None, None]: """Create a temporary test project with a sample file.""" # Set up a temporary directory with tempfile.TemporaryDirectory() as temp_dir: project_path = Path(temp_dir) # Create a test file test_file = project_path / "test.py" with open(test_file, "w") as f: f.write("def hello():\n print('Hello, world!')\n\nhello()\n") # Register project project_registry = get_project_registry() project_name = "ast_test_project" try: register_project_tool(path=str(project_path), name=project_name) except Exception: # If registration fails, try again with timestamp import time project_name = f"ast_test_project_{int(time.time())}" register_project_tool(path=str(project_path), name=project_name) # Yield the project info yield {"name": project_name, "path": project_path, "file": "test.py"} # Clean up try: project_registry.remove_project(project_name) except Exception: pass def parse_file(file_path: Path, language: str) -> Tuple[Any, bytes]: """Replacement for the relocated parse_file function.""" language_registry = get_language_registry() tree_cache = get_tree_cache() # Get language object # We don't need to store language_obj directly as it's used by ast_parse_file _ = language_registry.get_language(language) # Use the tools.ast_operations.parse_file function from mcp_server_tree_sitter.tools.ast_operations import parse_file as ast_parse_file return ast_parse_file(file_path, language, language_registry, tree_cache) @pytest.mark.diagnostic def test_get_ast_functionality(test_project, diagnostic) -> None: """Test the get_ast MCP tool functionality.""" # Add test details to diagnostic data diagnostic.add_detail("project", test_project["name"]) diagnostic.add_detail("file", test_project["file"]) try: # Try to get the AST using the MCP tool ast_result = get_ast( project=test_project["name"], path=test_project["file"], max_depth=3, include_text=True, ) # Record success details diagnostic.add_detail("ast_result_status", "success") diagnostic.add_detail("ast_result_keys", list(ast_result.keys())) # This assertion would fail if there's an issue with AST parsing assert "tree" in ast_result, "AST result should contain a tree" assert "file" in ast_result, "AST result should contain file info" assert "language" in ast_result, "AST result should contain language info" # Check that the tree doesn't contain an error if isinstance(ast_result["tree"], dict) and "error" in ast_result["tree"]: raise AssertionError(f"AST tree contains an error: {ast_result['tree']['error']}") except Exception as e: # Record the error in diagnostics diagnostic.add_error("AstParsingError", str(e)) # Create an artifact with detailed information artifact = { "error_type": type(e).__name__, "error_message": str(e), "project": test_project["name"], "file": test_project["file"], } diagnostic.add_artifact("ast_failure", artifact) # Re-raise to fail the test raise @pytest.mark.diagnostic def test_direct_parsing(test_project, diagnostic) -> None: """Test lower-level parse_file function to isolate issues.""" file_path = test_project["path"] / test_project["file"] diagnostic.add_detail("file_path", str(file_path)) try: # Get language registry = get_language_registry() language = registry.language_for_file(test_project["file"]) assert language is not None, "Could not detect language for file" language_obj = None try: language_obj = registry.get_language(language) diagnostic.add_detail("language_loaded", True) diagnostic.add_detail("language", language) except Exception as e: diagnostic.add_detail("language_loaded", False) diagnostic.add_error("LanguageLoadError", str(e)) pytest.fail(f"Failed to load language: {e}") # Try direct parsing if language is loaded if language_obj: try: tree, source_bytes = parse_file(file_path, language) if language is not None else (None, None) parsing_info = { "status": "success", "tree_type": type(tree).__name__, "has_root_node": hasattr(tree, "root_node"), } diagnostic.add_detail("parsing", parsing_info) # Try to access the root node if tree is not None and hasattr(tree, "root_node"): root = tree.root_node root_info = { "type": root.type, "start_byte": root.start_byte, "end_byte": root.end_byte, "child_count": (len(root.children) if hasattr(root, "children") else -1), } diagnostic.add_detail("root_node", root_info) # Try to convert to dict try: node_dict = node_to_dict(root, source_bytes, max_depth=2) diagnostic.add_detail( "node_to_dict", { "status": "success", "keys": list(node_dict.keys()), }, ) # Assert dictionary structure assert "type" in node_dict, "node_dict should contain type" assert "children" in node_dict or "truncated" in node_dict, ( "node_dict should contain children or be truncated" ) # Check for error in node dictionary if "error" in node_dict: raise AssertionError(f"node_dict contains an error: {node_dict['error']}") except Exception as e: diagnostic.add_error("NodeToDictError", str(e)) pytest.fail(f"node_to_dict failed: {e}") else: diagnostic.add_error("NoRootNodeError", "Tree has no root_node attribute") pytest.fail("Tree has no root_node attribute") except Exception as e: diagnostic.add_error("ParsingError", str(e)) pytest.fail(f"Direct parsing failed: {e}") except Exception as e: # Catch any unexpected errors diagnostic.add_error("UnexpectedError", str(e)) raise diagnostic.add_detail("test_completed", True)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wrale/mcp-server-tree-sitter'

If you have feedback or need assistance with the MCP directory API, please join our Discord server