debtmap 0.21.0

Code complexity and technical debt analyzer
Documentation
use std::path::Path;

pub fn is_vendor_or_generated_solidity(path: &Path, source: &str) -> bool {
    has_generated_header(source) || is_vendor_path(path) || is_build_output_path(path)
}

fn has_generated_header(source: &str) -> bool {
    source.lines().take(10).any(is_generated_header_line)
}

fn is_generated_header_line(line: &str) -> bool {
    let lower = line.to_ascii_lowercase();
    lower.contains("automatically generated")
        || (lower.contains("generated") && lower.contains("do not edit"))
}

fn is_vendor_path(path: &Path) -> bool {
    let path_text = path.to_string_lossy();
    path_text.contains("node_modules/@openzeppelin/contracts")
        || path_text.contains("lib/openzeppelin-contracts")
        || path_text.contains("lib/openzeppelin-contracts-upgradeable")
}

fn is_build_output_path(path: &Path) -> bool {
    path.components().any(|component| {
        let name = component.as_os_str().to_string_lossy();
        matches!(name.as_ref(), "out" | "cache" | "artifacts")
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generated_header_detection() {
        let source = "// Automatically generated by TypeChain\npragma solidity 0.8.20;";
        assert!(is_vendor_or_generated_solidity(
            Path::new("contracts/Generated.sol"),
            source
        ));
    }

    #[test]
    fn test_openzeppelin_vendor_path_detection() {
        assert!(is_vendor_or_generated_solidity(
            Path::new("node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol"),
            "pragma solidity 0.8.20;"
        ));
        assert!(is_vendor_or_generated_solidity(
            Path::new("lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"),
            "pragma solidity 0.8.20;"
        ));
    }

    #[test]
    fn test_build_output_path_detection() {
        assert!(is_vendor_or_generated_solidity(
            Path::new("out/Token.sol/Token.json"),
            "{}"
        ));
        assert!(is_vendor_or_generated_solidity(
            Path::new("artifacts/contracts/Token.sol"),
            "pragma solidity 0.8.20;"
        ));
    }

    #[test]
    fn test_regular_contract_not_generated() {
        assert!(!is_vendor_or_generated_solidity(
            Path::new("contracts/Token.sol"),
            "import \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";"
        ));
    }
}