traverse_graph/
parser.rs

1use anyhow::{Context, Result};
2use tree_sitter::{Language, Parser, Tree};
3
4/// Get the Solidity tree-sitter language
5pub fn get_solidity_language() -> Language {
6    tree_sitter_solidity::LANGUAGE.into()
7}
8
9/// Represents a parsed Solidity AST
10#[derive(Debug)] // Add Debug for easier testing/logging if needed
11pub struct SolidityAST {
12    pub tree: Tree,
13    pub source: String,
14}
15
16/// Parse Solidity source code into an AST
17pub fn parse_solidity(source: &str) -> Result<SolidityAST> {
18    let mut parser = Parser::new();
19    parser
20        .set_language(&get_solidity_language())
21        .context("Failed to set language for Solidity parser")?;
22
23    // Parse the source code
24    let tree = parser
25        .parse(source, None)
26        .context("Failed to parse Solidity source")?;
27
28    Ok(SolidityAST {
29        tree,
30        source: source.to_string(),
31    })
32}
33
34pub fn get_node_text<'a>(node: &tree_sitter::Node, source: &'a str) -> &'a str {
35    let start = node.start_byte();
36    let end = node.end_byte();
37    &source[start..end]
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_parse_solidity() {
46        let source = r#"
47        pragma solidity ^0.8.0;
48        
49        contract SimpleStorage {
50            uint256 private value;
51            
52            function setValue(uint256 _value) public {
53                value = _value;
54            }
55            
56            function getValue() public view returns (uint256) {
57                return value;
58            }
59        }
60        "#;
61
62        let ast = parse_solidity(source).unwrap();
63        let root_node = ast.tree.root_node();
64
65        assert_eq!(root_node.kind(), "source_file");
66        assert!(root_node.child_count() > 0);
67    }
68}