rustcodegraph 1.2.10

Local-first code intelligence graph and CLI for AI agents
Documentation
mod arrow_function_body_traversal {
    use super::*;

    #[test]
    fn should_extract_typescript_function_declaration_with_native_parser() {
        before_all_init_grammars();
        clear_parser_cache();

        let result = extract_from_source(
            "math.ts",
            "export function add(a: number, b: number): number { return a + b; }",
            None,
            None,
        );

        assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
        assert!(
            result
                .nodes
                .iter()
                .any(|node| node.kind == NodeKind::Function && node.name == "add"),
            "nodes: {:?}",
            result
                .nodes
                .iter()
                .map(|node| (&node.kind, node.name.as_str()))
                .collect::<Vec<_>>()
        );
    }

    #[test]
    fn should_extract_unresolved_references_from_arrow_function_bodies() {
        let code = r#"
export const useAuth = () => {
  const user = getUser();
  const token = generateToken(user);
  return { user, token };
};
"#;
        let result = extract_from_source("hooks.ts", code, None, None);

        let func_node = result
            .nodes
            .iter()
            .find(|node| node.kind == NodeKind::Function && node.name == "useAuth");
        assert!(func_node.is_some());

        let call_names = result
            .unresolved_references
            .iter()
            .filter(|reference| reference.reference_kind == ReferenceKind::Calls)
            .map(|reference| reference.reference_name.as_str())
            .collect::<Vec<_>>();
        assert!(call_names.contains(&"getUser"));
        assert!(call_names.contains(&"generateToken"));
    }

    #[test]
    fn should_extract_unresolved_references_from_function_expression_bodies() {
        let code = r#"
export const processData = function(input: string): string {
  const cleaned = sanitize(input);
  return transform(cleaned);
};
"#;
        let result = extract_from_source("utils.ts", code, None, None);

        let func_node = result
            .nodes
            .iter()
            .find(|node| node.kind == NodeKind::Function && node.name == "processData");
        assert!(func_node.is_some());

        let call_names = result
            .unresolved_references
            .iter()
            .filter(|reference| reference.reference_kind == ReferenceKind::Calls)
            .map(|reference| reference.reference_name.as_str())
            .collect::<Vec<_>>();
        assert!(call_names.contains(&"sanitize"));
        assert!(call_names.contains(&"transform"));
    }

    #[test]
    fn should_not_create_duplicate_nodes_for_arrow_functions() {
        let code = r#"
export const handler = () => {
  doSomething();
};
"#;
        let result = extract_from_source("handler.ts", code, None, None);

        let func_nodes = result
            .nodes
            .iter()
            .filter(|node| node.name == "handler" && node.kind == NodeKind::Function)
            .count();
        let var_nodes = result
            .nodes
            .iter()
            .filter(|node| node.name == "handler" && node.kind == NodeKind::Variable)
            .count();
        assert_eq!(func_nodes, 1);
        assert_eq!(var_nodes, 0);
    }

    #[test]
    fn should_extract_nested_calls_in_arrow_functions_in_javascript() {
        let code = r#"
export const fetchData = async () => {
  const response = await fetchAPI('/data');
  return parseResponse(response);
};
"#;
        let result = extract_from_source("api.js", code, None, None);

        let func_node = result.nodes.iter().find(|node| node.name == "fetchData");
        assert!(func_node.is_some());
        assert_eq!(func_node.map(|node| node.kind), Some(NodeKind::Function));

        let call_names = result
            .unresolved_references
            .iter()
            .filter(|reference| reference.reference_kind == ReferenceKind::Calls)
            .map(|reference| reference.reference_name.as_str())
            .collect::<Vec<_>>();
        assert!(call_names.contains(&"fetchAPI"));
        assert!(call_names.contains(&"parseResponse"));
    }
}