relay-knowledge 1.1.17

Graph-database-based knowledge graph project.
Documentation
pub(super) fn java_code_lines_without_comments(content: &str) -> Vec<String> {
    let mut state = JavaCodeLineState::default();
    content
        .lines()
        .map(|line| java_code_line_without_comments(line, &mut state))
        .collect()
}

pub(super) fn line_declares_java_type(line: &str) -> bool {
    let declaration = line.split('{').next().unwrap_or(line);
    declaration.contains(" class ")
        || declaration.contains(" interface ")
        || declaration.contains(" enum ")
        || declaration.starts_with("class ")
        || declaration.starts_with("interface ")
        || declaration.starts_with("enum ")
}

pub(super) fn line_declares_nested_java_helper_type(line: &str, brace_depth: usize) -> bool {
    if brace_depth == 0 {
        return false;
    }
    let declaration = line.split('{').next().unwrap_or(line).trim();
    line_declares_java_type(declaration)
}

pub(super) fn parse_java_method_def(line: &str) -> Option<String> {
    let trimmed = line.trim();
    let marker = trimmed.find('(')?;
    let before_paren = &trimmed[..marker];
    let name_start = before_paren
        .rfind(|c: char| c.is_whitespace() || c == '<' || c == '>')
        .map_or(0, |pos| pos + 1);
    let name = &before_paren[name_start..];
    if name.is_empty() || name.chars().next().is_some_and(|c| !c.is_alphanumeric()) {
        return None;
    }
    Some(name.to_owned())
}

pub(super) fn update_java_brace_depth(line: &str, brace_depth: &mut usize) {
    let mut quote = None;
    let mut escaped = false;
    for character in line.chars() {
        if let Some(quote_char) = quote {
            if escaped {
                escaped = false;
                continue;
            }
            if character == '\\' {
                escaped = true;
                continue;
            }
            if character == quote_char {
                quote = None;
            }
            continue;
        }
        match character {
            '"' | '\'' => quote = Some(character),
            '{' => *brace_depth += 1,
            '}' => *brace_depth = brace_depth.saturating_sub(1),
            _ => {}
        }
    }
}

#[derive(Default)]
struct JavaCodeLineState {
    in_block_comment: bool,
    in_text_block: bool,
}

fn java_code_line_without_comments(line: &str, state: &mut JavaCodeLineState) -> String {
    let mut result = String::new();
    let mut chars = line.char_indices().peekable();
    let mut quote = None;
    let mut escaped = false;
    while let Some((index, character)) = chars.next() {
        if state.in_block_comment {
            if character == '*' && chars.peek().is_some_and(|(_, next)| *next == '/') {
                chars.next();
                state.in_block_comment = false;
            }
            continue;
        }
        if state.in_text_block {
            if line[index..].starts_with("\"\"\"") {
                chars.next();
                chars.next();
                state.in_text_block = false;
            }
            continue;
        }
        if let Some(quote_char) = quote {
            result.push(character);
            if escaped {
                escaped = false;
                continue;
            }
            if character == '\\' {
                escaped = true;
                continue;
            }
            if character == quote_char {
                quote = None;
            }
            continue;
        }
        if character == '/' && chars.peek().is_some_and(|(_, next)| *next == '*') {
            chars.next();
            state.in_block_comment = true;
            continue;
        }
        if character == '/' && chars.peek().is_some_and(|(_, next)| *next == '/') {
            break;
        }
        if character == '"' && line[index..].starts_with("\"\"\"") {
            chars.next();
            chars.next();
            state.in_text_block = true;
            continue;
        }
        if matches!(character, '"' | '\'') {
            quote = Some(character);
        }
        result.push(character);
    }
    result
}

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