use regex::Regex;
use syn;
pub fn split_into_statements(mut code: &str) -> Vec<&str> {
lazy_static! {
static ref SEPARATOR: Regex = Regex::new("(;|};?) *\n?").unwrap();
}
lazy_static! {
static ref ELSE_AT_START: Regex = Regex::new("^[ \n]*else[ \n]").unwrap();
}
let mut output = Vec::new();
loop {
let mut got_statment = false;
for m in SEPARATOR.find_iter(code) {
let offset = m.end();
let candidate = &code[..offset];
let remainder = &code[offset..];
if ELSE_AT_START.is_match(remainder) {
continue;
}
if syn::parse_str::<syn::Stmt>(candidate).is_ok() {
output.push(candidate);
code = remainder;
got_statment = true;
break;
}
}
if !got_statment {
break;
}
}
if !code.trim().is_empty() {
output.push(code);
}
output
}
#[cfg(test)]
mod test {
use super::split_into_statements;
#[test]
fn single_line() {
assert_eq!(
split_into_statements("let mut a = 10i32; a += 32;"),
vec!["let mut a = 10i32; ", "a += 32;"]
);
}
#[test]
fn multiple_lines() {
assert_eq!(
split_into_statements("let mut a = 10i32;\n foo()"),
vec!["let mut a = 10i32;\n", " foo()"]
);
}
#[test]
fn statement_ends_with_brace() {
assert_eq!(
split_into_statements("if a == b {foo(); bar();} baz();"),
vec!["if a == b {foo(); bar();} ", "baz();"]
);
}
#[test]
fn else_statements() {
assert_eq!(
split_into_statements(
"if a == b {foo(); bar();} else if a < b {baz();} else {foo();} b"
),
vec![
"if a == b {foo(); bar();} else if a < b {baz();} else {foo();} ",
"b"
]
);
}
}