#![cfg(all(feature = "grammars", feature = "lang-python"))]
#![allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
use panproto_parse::ParserRegistry;
fn registry() -> ParserRegistry {
ParserRegistry::new()
}
fn with_big_stack<F: FnOnce() + Send + 'static>(inner: F) {
std::thread::Builder::new()
.stack_size(32 * 1024 * 1024)
.spawn(inner)
.expect("spawn")
.join()
.expect("worker panicked");
}
#[test]
fn python_function_body_is_fixed_point_and_indented() {
with_big_stack(|| {
let reg = registry();
let src = b"def f():\n x = 1\n return x\n";
let s1 = reg
.parse_with_protocol("python", src, "x.py")
.expect("parse");
let e1 = reg.emit_pretty_with_protocol("python", &s1).expect("emit1");
let s2 = reg
.parse_with_protocol("python", &e1, "x.py")
.expect("reparse");
let e2 = reg.emit_pretty_with_protocol("python", &s2).expect("emit2");
let e1s = String::from_utf8_lossy(&e1).into_owned();
let e2s = String::from_utf8_lossy(&e2).into_owned();
assert_eq!(
e1, e2,
"Python suite emit must be a fixed point.\ne1:\n{e1s}\ne2:\n{e2s}"
);
assert!(
!e1s.contains(';'),
"function body statements must not be joined with ';': {e1s:?}"
);
assert!(
e1s.contains("f()"),
"empty parameter list must stay tight against the name: {e1s:?}"
);
let return_line = e1s
.lines()
.find(|l| l.contains("return"))
.expect("emit must contain the return statement");
assert!(
return_line.starts_with(char::is_whitespace),
"return statement must be indented inside the function body: {e1s:?}"
);
let return_count = s2
.vertices
.values()
.filter(|v| v.kind.as_ref() == "return_statement")
.count();
assert_eq!(
return_count, 1,
"re-parsed schema must keep one return_statement:\n{e1s}"
);
});
}