#![crate_name = "doc"]
use regex::Regex;
use std::fs::{File, OpenOptions};
use std::io::prelude::*;
use std::io::{BufRead, BufReader};
use crate::prelude::*;
pub fn find_class_substring(filename: &str, class_name: &str) -> Result<String> {
let mut owned_string = "".to_owned();
let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
.lines()
.map(|line| line.unwrap())
.collect::<Vec<String>>();
let mut bracket_count = 0;
let mut offset = 0;
let class_string = "class ".to_owned() + class_name;
for i in 0..lines.len() {
if lines[i].contains(&class_string) {
if lines[i].contains("{") {
bracket_count += 1;
}
loop {
offset += 1;
owned_string = owned_string + &lines[i + offset];
if lines[i + offset].contains("{") {
bracket_count += 1
}
if lines[i + offset].contains("}") {
bracket_count -= 1
}
if bracket_count == 0 {
break;
}
}
break;
}
}
Ok(owned_string)
}
pub fn find_class_template(file_name: &str, class_name: &str) -> Option<String> {
let file = File::open(file_name).ok()?;
let reader = BufReader::new(file);
let template_regex = Regex::new(r"^\s*(template\s*<[^>]*>)").ok()?;
let class_regex = Regex::new(&format!(r"^\s*class\s+{}\b", regex::escape(class_name))).ok()?;
let mut template_line: Option<String> = None;
for line in reader.lines() {
let line = line.ok()?;
let line_trimmed = line.trim();
if template_line.is_none() {
if let Some(caps) = template_regex.captures(line_trimmed) {
template_line = Some(caps.get(1)?.as_str().trim().to_string());
continue;
}
}
if class_regex.is_match(line_trimmed) {
return template_line;
}
if template_line.is_some() {
template_line = None;
}
}
None
}
pub fn filter_incorrects(name: &str) -> Result<bool> {
let re = Regex::new(r"\w+\(\s+?\w+?\s+?\)").unwrap();
match re.captures(name) {
Some(x) => Ok(false),
_ => Ok(true),
}
}
pub fn find_function_names(class_string: &str) -> Result<Vec<String>> {
let re = Regex::new(r"(?:static|const|constexpr)?\s*?\w+(?:\s+|\s*\*\*?\s*|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+)(?:const\s*
(?:\s+|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+))?\w+((\n)*)\(([^.{}:=;]*)\)\s?(?:const)?(?:;|\n|\s)").unwrap();
dbg!(&class_string);
let mut result = Vec::new();
for cap in re.captures_iter(&class_string) {
let function_name = cap.get(0).unwrap().as_str().to_string();
if filter_incorrects(&function_name).unwrap() {
let func_n = remove_whitespace(&function_name);
if func_n.contains("static ") {
continue;
}
let func_n_trim = &func_n[0..func_n.find(";").unwrap_or(func_n.len())];
result.push(func_n_trim.to_owned());
}
}
Ok(result)
}
pub fn find_c_function_names(filename: &str) -> Result<Vec<String>> {
let re = Regex::new(r"(?m)^\s*[^#\s]\w+\s+?\s*?\w+((\n)*)\(([^.{}:\-=;]*)\)(?:;|\n)").unwrap();
let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
.lines()
.map(|line| line.unwrap())
.collect::<Vec<String>>();
let mut edited_lines = Vec::new();
for line in lines.iter() {
if line.contains("//") {
let split_line: Vec<&str> = line.split("//").collect();
let edit = split_line[0].trim().to_owned();
edited_lines.push(edit);
} else if line.contains("/*") {
let split_line: Vec<&str> = line.split("/*").collect();
let edit = split_line[0].trim().to_owned();
edited_lines.push(edit);
} else {
let edit = line.to_owned();
edited_lines.push(edit);
}
}
let mut file_string: String = edited_lines.join("\n");
let mut result = Vec::new();
for cap in re.captures_iter(&file_string) {
let function_name = cap.get(0).unwrap().as_str().to_string();
let function_name_trimmed = remove_whitespace(&function_name);
if function_name_trimmed.contains("return")
|| function_name_trimmed.contains("PACKED")
|| function_name_trimmed.contains("#define")
{
continue;
}
result.push(function_name_trimmed);
}
Ok(result)
}
fn remove_whitespace(s: &str) -> String {
let words: Vec<_> = s.split_whitespace().collect();
words.join(" ")
}