rustcodegraph 1.2.10

Local-first code intelligence graph and CLI for AI agents
Documentation
mod describe_7014_r_extraction {
    use super::*;
    const TS_DESCRIBE_TITLE: &str = "R Extraction";
    const TS_DESCRIBE_LINE: usize = 7014;
    #[test]
    fn describes_112_is_represented() {
        assert!(!TS_DESCRIBE_TITLE.is_empty());
        assert_eq!(TS_DESCRIBE_LINE, 7014);
    }
    mod describe_7015_language_detection {
        use super::*;
        const TS_DESCRIBE_TITLE: &str = "Language detection";
        const TS_DESCRIBE_LINE: usize = 7015;
        #[test]
        fn describes_113_is_represented() {
            assert!(!TS_DESCRIBE_TITLE.is_empty());
            assert_eq!(TS_DESCRIBE_LINE, 7015);
        }
        #[test]
        fn case_7016_should_detect_r_files_both_extension_cases() {
            let suite = ["R Extraction", "Language detection"];
            assert_eq!(suite.len(), 2);
            assert_eq!(365, 365);
            assert_detected_language("analysis.R", None, Language::R);
            assert_detected_language("scripts/clean.r", None, Language::R);
        }
        #[test]
        fn case_7021_should_report_r_as_supported() {
            let suite = ["R Extraction", "Language detection"];
            assert_eq!(suite.len(), 2);
            assert_eq!(366, 366);
            assert_language_support(Language::R, true);
            assert_supported_languages_include(&[Language::R]);
        }
    }
    mod describe_7027_function_extraction {
        use super::*;
        const TS_DESCRIBE_TITLE: &str = "Function extraction";
        const TS_DESCRIBE_LINE: usize = 7027;
        #[test]
        fn describes_114_is_represented() {
            assert!(!TS_DESCRIBE_TITLE.is_empty());
            assert_eq!(TS_DESCRIBE_LINE, 7027);
        }
        #[test]
        fn case_7028_extracts_every_assignment_form_lambdas_and_nested_functions() {
            let suite = ["R Extraction", "Function extraction"];
            assert_eq!(suite.len(), 2);
            assert_eq!(367, 367);
            let code = r#"
clean_data <- function(df, threshold = 0.5) {
  helper <- function(d) scale(d)
  helper(df)
}
normalize = function(v) (v - mean(v)) / sd(v)
double_it <- \(x) x * 2
"#;
            let result = extract("analysis.R", code);
            let funcs = names_by_kind(&result, NodeKind::Function);
            assert_contains(&funcs, "clean_data");
            assert_contains(&funcs, "normalize");
            assert_contains(&funcs, "double_it");
            assert_contains(&funcs, "helper");
            let clean_data = find_node(&result, NodeKind::Function, "clean_data")
                .expect("clean_data function should be extracted");
            assert_eq!(clean_data.language, Language::R);
            assert_eq!(
                clean_data.signature.as_deref(),
                Some("(df, threshold = 0.5)")
            );
        }
        #[test]
        fn case_7048_attributes_body_calls_to_the_enclosing_function() {
            let suite = ["R Extraction", "Function extraction"];
            assert_eq!(suite.len(), 2);
            assert_eq!(368, 368);
            let code = r#"
prep <- function(d) scale(d)
fit_model <- function(data) {
  lm(y ~ x, data = prep(data))
}
"#;
            let result = extract("models.R", code);
            let prep_call = result.unresolved_references.iter().find(|reference| {
                reference.reference_name == "prep"
                    && reference.reference_kind == ReferenceKind::Calls
            });
            let fit_model = find_node(&result, NodeKind::Function, "fit_model")
                .expect("fit_model function should be extracted");
            assert_eq!(
                prep_call.map(|reference| reference.from_node_id.as_str()),
                Some(fit_model.id.as_str())
            );
        }
    }
    mod describe_7065_imports {
        use super::*;
        const TS_DESCRIBE_TITLE: &str = "Imports";
        const TS_DESCRIBE_LINE: usize = 7065;
        #[test]
        fn describes_115_is_represented() {
            assert!(!TS_DESCRIBE_TITLE.is_empty());
            assert_eq!(TS_DESCRIBE_LINE, 7065);
        }
        #[test]
        fn case_7066_extracts_library_require_source_as_imports_not_calls() {
            let suite = ["R Extraction", "Imports"];
            assert_eq!(suite.len(), 2);
            assert_eq!(369, 369);
            let code = r#"
library(dplyr)
require(stats)
requireNamespace("jsonlite")
source("helpers.R")
"#;
            let result = extract("main.R", code);
            let imports = names_by_kind(&result, NodeKind::Import);
            assert_contains(&imports, "dplyr");
            assert_contains(&imports, "stats");
            assert_contains(&imports, "jsonlite");
            assert_contains(&imports, "helpers.R");
            let lib_calls = result.unresolved_references.iter().filter(|reference| {
                reference.reference_kind == ReferenceKind::Calls
                    && matches!(reference.reference_name.as_str(), "library" | "source")
            });
            assert_eq!(lib_calls.count(), 0);
        }
    }
    mod describe_7087_variables_and_constants {
        use super::*;
        const TS_DESCRIBE_TITLE: &str = "Variables and constants";
        const TS_DESCRIBE_LINE: usize = 7087;
        #[test]
        fn describes_116_is_represented() {
            assert!(!TS_DESCRIBE_TITLE.is_empty());
            assert_eq!(TS_DESCRIBE_LINE, 7087);
        }
        #[test]
        fn case_7088_extracts_top_level_assignments_all_caps_as_constants_right_assign_too() {
            let suite = ["R Extraction", "Variables and constants"];
            assert_eq!(suite.len(), 2);
            assert_eq!(370, 370);
            let code = r#"
ALPHA <- 0.05
max_iter = 100
compute_stats(df) -> stats_result
inner <- function() {
  local_var <- 1
}
"#;
            let result = extract("config.R", code);
            let constant = find_node(&result, NodeKind::Constant, "ALPHA")
                .expect("ALPHA constant should be extracted");
            assert_eq!(constant.kind, NodeKind::Constant);
            let variable = find_node(&result, NodeKind::Variable, "max_iter")
                .expect("max_iter variable should be extracted");
            assert_eq!(variable.kind, NodeKind::Variable);
            let right_assigned = find_node(&result, NodeKind::Variable, "stats_result")
                .expect("stats_result variable should be extracted");
            assert_eq!(right_assigned.kind, NodeKind::Variable);
            assert!(!result.nodes.iter().any(|node| node.name == "local_var"));
        }
    }
    mod describe_7109_classes {
        use super::*;
        const TS_DESCRIBE_TITLE: &str = "Classes";
        const TS_DESCRIBE_LINE: usize = 7109;
        #[test]
        fn describes_117_is_represented() {
            assert!(!TS_DESCRIBE_TITLE.is_empty());
            assert_eq!(TS_DESCRIBE_LINE, 7109);
        }
        #[test]
        fn case_7110_extracts_s4_r5_r6_class_calls_as_classes_with_their_list_methods() {
            let suite = ["R Extraction", "Classes"];
            assert_eq!(suite.len(), 2);
            assert_eq!(371, 371);
            let code = r#"
setClass("Patient", representation(id = "character"))
Account <- setRefClass("Account",
  fields = list(balance = "numeric"),
  methods = list(deposit = function(x) { balance <<- balance + x })
)
Stack <- R6Class("Stack",
  public = list(push = function(v) invisible(v))
)
setGeneric("describe", function(obj) standardGeneric("describe"))
setMethod("describe", "Patient", function(obj) paste(obj@id))
"#;
            let result = extract("classes.R", code);
            let classes = names_by_kind(&result, NodeKind::Class);
            assert_contains(&classes, "Patient");
            assert_contains(&classes, "Account");
            assert_contains(&classes, "Stack");
            let methods = names_by_kind(&result, NodeKind::Method);
            assert_contains(&methods, "deposit");
            assert_contains(&methods, "push");
            let describes = result
                .nodes
                .iter()
                .filter(|node| node.name == "describe" && node.kind == NodeKind::Function)
                .count();
            assert!(describes >= 2);
            assert!(find_node(&result, NodeKind::Variable, "Account").is_none());
        }
        #[test]
        fn case_7138_extracts_ggproto_classes_with_direct_arg_methods_and_the_parent_as_ext() {
            let suite = ["R Extraction", "Classes"];
            assert_eq!(suite.len(), 2);
            assert_eq!(372, 372);
            let code = r#"
GeomPoint <- ggproto("GeomPoint", Geom,
  required_aes = c("x", "y"),
  draw_panel = function(data, panel_params, coord) {
    coords <- coord$transform(data, panel_params)
    grid::pointsGrob(coords$x, coords$y)
  },
  draw_key = draw_key_point
)
"#;
            let result = extract("geom-point.R", code);
            let class = find_node(&result, NodeKind::Class, "GeomPoint")
                .expect("GeomPoint class should be extracted");
            find_node(&result, NodeKind::Method, "draw_panel")
                .expect("draw_panel method should be extracted");
            let extends = result.unresolved_references.iter().find(|reference| {
                reference.reference_kind == ReferenceKind::Extends
                    && reference.reference_name == "Geom"
            });
            assert_eq!(
                extends.map(|reference| reference.from_node_id.as_str()),
                Some(class.id.as_str())
            );
            assert!(find_node(&result, NodeKind::Variable, "GeomPoint").is_none());
        }
    }
}