#[cfg(test)]
mod tests;
pub fn extract_function(code: &str, function_name: &str) -> Option<String> {
let mut _in_function = false;
let mut brace_count = 0;
let mut _function_start = 0;
let mut function_end = 0;
let mut in_string = false;
let mut in_char = false;
let mut in_line_comment = false;
let mut in_block_comment = false;
let mut prev_char = '\0';
let mut escaped = false;
let function_pattern = format!(
r"(?:\s|^)(?:pub\s+)?(?:\(.*\)\s+)?(?:async\s+)?(?:const\s+)?(?:unsafe\s+)?fn\s+{}\s*(?:<.*?>)?\s*\(",
function_name
);
let re = regex::Regex::new(&function_pattern).ok()?;
if let Some(m) = re.find(code) {
_function_start = m.start();
let function_def_part = &code[_function_start..];
let mut paren_count = 0;
let mut found_opening_brace = false;
for (i, c) in function_def_part.chars().enumerate() {
if in_line_comment {
if c == '\n' {
in_line_comment = false;
}
continue;
} else if in_block_comment {
if prev_char == '*' && c == '/' {
in_block_comment = false;
}
} else if in_string {
if c == '"' && !escaped {
in_string = false;
}
escaped = c == '\\' && !escaped;
} else if in_char {
if c == '\'' && !escaped {
in_char = false;
}
escaped = c == '\\' && !escaped;
} else if c == '/' && prev_char == '/' {
in_line_comment = true;
} else if c == '*' && prev_char == '/' {
in_block_comment = true;
} else if c == '"' {
in_string = true;
escaped = false;
} else if c == '\'' {
in_char = true;
escaped = false;
} else if c == '(' {
paren_count += 1;
} else if c == ')' {
paren_count -= 1;
} else if c == '{' && paren_count == 0 {
brace_count = 1;
_function_start += i;
found_opening_brace = true;
break;
}
prev_char = c;
}
if !found_opening_brace {
return None;
}
let remaining_code = &code[_function_start + 1..];
prev_char = '\0';
in_string = false;
in_char = false;
in_line_comment = false;
in_block_comment = false;
escaped = false;
for (i, c) in remaining_code.chars().enumerate() {
if in_line_comment {
if c == '\n' {
in_line_comment = false;
}
} else if in_block_comment {
if prev_char == '*' && c == '/' {
in_block_comment = false;
}
} else if in_string {
if c == '"' && !escaped {
in_string = false;
}
escaped = c == '\\' && !escaped;
} else if in_char {
if c == '\'' && !escaped {
in_char = false;
}
escaped = c == '\\' && !escaped;
} else if c == '/' && prev_char == '/' {
in_line_comment = true;
} else if c == '*' && prev_char == '/' {
in_block_comment = true;
} else if c == '"' {
in_string = true;
escaped = false;
} else if c == '\'' {
in_char = true;
escaped = false;
} else if c == '{' {
brace_count += 1;
} else if c == '}' {
brace_count -= 1;
if brace_count == 0 {
function_end = _function_start + i + 2; break;
}
}
prev_char = c;
}
if function_end > _function_start {
return Some(
code[_function_start + 1..function_end - 1]
.trim()
.to_string(),
);
}
}
None
}