relay-knowledge 1.1.17

Graph-database-based knowledge graph project.
Documentation
use tree_sitter::Node;

use crate::code::parser::{
    imports::quoted_specifier,
    nodes::{SyntaxRange, compact_whitespace, node_text, syntax_range},
};

pub(in crate::code::parser) fn dynamic_import(
    language_id: &str,
    content: &str,
    node: Node<'_>,
) -> Option<(String, SyntaxRange)> {
    if !matches!(language_id, "javascript" | "jsx" | "typescript" | "tsx")
        || node.kind() != "call_expression"
    {
        return None;
    }
    let function = node.child_by_field_name("function")?;
    if function.kind() != "import" {
        return None;
    }
    first_direct_string_argument(content, node.child_by_field_name("arguments")?)?;
    let source = dynamic_import_source(content, node);

    Some(source)
}

fn dynamic_import_source(content: &str, node: Node<'_>) -> (String, SyntaxRange) {
    let source_node = node
        .parent()
        .filter(|parent| parent.kind() == "await_expression")
        .unwrap_or(node);

    (
        compact_whitespace(&node_text(content, source_node)),
        syntax_range(source_node),
    )
}

fn first_direct_string_argument(content: &str, arguments: Node<'_>) -> Option<String> {
    for index in 0..arguments.named_child_count() {
        let Ok(index) = u32::try_from(index) else {
            continue;
        };
        let child = arguments.named_child(index)?;
        if matches!(child.kind(), "string" | "string_literal") {
            return Some(node_text(content, child));
        }
        return None;
    }

    None
}

pub(in crate::code::parser) fn re_export(
    language_id: &str,
    content: &str,
    node: Node<'_>,
) -> Option<(String, SyntaxRange)> {
    if !matches!(language_id, "javascript" | "jsx" | "typescript" | "tsx")
        || node.kind() != "export_statement"
    {
        return None;
    }
    let source = node.child_by_field_name("source")?;
    if !matches!(source.kind(), "string" | "string_literal")
        || quoted_specifier(&node_text(content, source)).is_none()
    {
        return None;
    }

    Some((
        compact_whitespace(&node_text(content, node)),
        syntax_range(node),
    ))
}

#[cfg(test)]
#[path = "imports_tests.rs"]
mod tests;