relay-knowledge 1.1.9

Graph-database-based knowledge graph project.
Documentation
use super::super::{
    model::{ConfigFact, ConfigReference},
    source::{push_definition, push_reference, source_lines},
};

pub(in crate::code::config_files) fn facts(
    content: &str,
    definitions: &mut Vec<ConfigFact>,
    references: &mut Vec<ConfigReference>,
) {
    let mut in_require_block = false;
    let mut in_replace_block = false;
    for line in source_lines(content) {
        let trimmed = line.text.trim();
        let code = strip_comment(trimmed).trim();
        if code.starts_with("require (") {
            in_require_block = true;
            continue;
        }
        if code.starts_with("replace (") {
            in_replace_block = true;
            continue;
        }
        if in_require_block && code == ")" {
            in_require_block = false;
            continue;
        }
        if in_replace_block && code == ")" {
            in_replace_block = false;
            continue;
        }
        if let Some(module) = code.strip_prefix("module ").map(str::trim) {
            push_definition(definitions, module, "module", line.range());
        }
        if let Some(module) = code
            .strip_prefix("require ")
            .and_then(|value| value.split_whitespace().next())
        {
            push_reference(references, module, "dependency", line.range());
        }
        if in_require_block
            && !code.is_empty()
            && let Some(module) = code.split_whitespace().next()
        {
            push_reference(references, module, "dependency", line.range());
        }
        if in_replace_block && !code.is_empty() {
            for module in replace_modules(code) {
                push_reference(references, module, "dependency", line.range());
            }
        }
        if let Some(rest) = code.strip_prefix("replace ") {
            for module in replace_modules(rest) {
                push_reference(references, module, "dependency", line.range());
            }
        }
    }
}

fn strip_comment(value: &str) -> &str {
    value
        .split("//")
        .next()
        .unwrap_or(value)
        .split('#')
        .next()
        .unwrap_or(value)
}

fn replace_modules(rest: &str) -> Vec<&str> {
    rest.split("=>")
        .filter_map(|side| {
            side.split_whitespace()
                .next()
                .filter(|module| module_path(module))
        })
        .collect()
}

fn module_path(value: &str) -> bool {
    !value.starts_with('.') && !value.starts_with('/') && !value.contains('\\')
}