feat: more tests and spans

This commit is contained in:
Jonathan Kelley committed 2022-04-28 14:16:21 -04:00
1 parent 804d9af1c7
commit 284860f470
3 files changed
+194 -31

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
proc-macro2 = { version = "1.0.6" }
proc-macro2 = { version = "1.0.6", features = ["span-locations"] }
quote = "1.0"
syn = { version = "1.0.11", features = ["full", "extra-traits"] }
dioxus-rsx = { path = "../rsx" }
+85 -29
View File
@@ -41,20 +41,6 @@ pub fn get_format_blocks(contents: &str) -> Vec<FormattedBlock> {
continue;
}
// match cur_match {
// Some(ref this_match) => {
// // abort nested matches - these get handled automatically
// if start < this_match.end {
// continue;
// } else {
// cur_match = Some(item);
// }
// }
// None => {
// cur_match = Some(item);
// }
// }
let remaining = &contents[end - 1..];
if let Some(bracket_end) = find_bracket_end(remaining) {
@@ -67,6 +53,14 @@ pub fn get_format_blocks(contents: &str) -> Vec<FormattedBlock> {
if let Some(new) = fmt_block(sub_string) {
if !new.is_empty() {
println!("{}", &contents[end + 1..bracket_end + end - 1]);
println!("{}", new);
let stripped = &contents[end + 1..bracket_end + end - 1];
if stripped == new {
println!("no changes necessary");
}
// if we have code to push, we want the code to end up on the right lines with the right indentation
let mut output = String::new();
@@ -94,18 +88,25 @@ pub fn get_format_blocks(contents: &str) -> Vec<FormattedBlock> {
}
pub fn fmt_block(block: &str) -> Option<String> {
let mut raw_lines = block.split('\n').collect::<Vec<_>>();
let parsed: CallBody = syn::parse_str(block).ok()?;
let mut buf = String::new();
for node in parsed.roots.iter() {
write_ident(&mut buf, node, 0).ok()?;
write_ident(&mut buf, &raw_lines, node, 0).ok()?;
}
Some(buf)
}
pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Result {
pub fn write_ident(
buf: &mut String,
lines: &[&str],
node: &BodyNode,
indent: usize,
) -> fmt::Result {
match node {
BodyNode::Element(el) => {
let Element {
@@ -168,7 +169,7 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
ElementAttr::CustomAttrText { name, value } => {
write!(
buf,
"{name}: \"{value}\"",
"\"{name}\": \"{value}\"",
name = name.value(),
value = value.value()
)?;
@@ -176,22 +177,32 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
ElementAttr::CustomAttrExpression { name, value } => {
let out = prettyplease::unparse_expr(value);
write!(buf, "{}: {}", name.value(), out)?;
write!(buf, "\"{}\": {}", name.value(), out)?;
}
ElementAttr::EventTokens { name, tokens } => {
let out = prettyplease::unparse_expr(tokens);
dbg!(&out);
let mut lines = out.split('\n').peekable();
let first = lines.next().unwrap();
write!(buf, "{}: {}", name, first)?;
while let Some(line) = lines.next() {
write_tabs(buf, indent + 1)?;
write!(buf, "{}", line)?;
// write!(buf, "{}", line)?;
if lines.peek().is_none() {
write!(buf, "")?;
// a one-liner for whatever reason
// Does not need a new line
if lines.peek().is_none() {
write!(buf, "{}: {}", name, first)?;
} else {
writeln!(buf, "{}: {}", name, first)?;
while let Some(line) = lines.next() {
write_tabs(buf, indent + 1)?;
write!(buf, "{}", line)?;
if lines.peek().is_none() {
write!(buf, "")?;
} else {
writeln!(buf)?;
}
}
}
}
@@ -221,7 +232,7 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
}
for child in children {
write_ident(buf, child, indent + 1)?;
write_ident(buf, lines, child, indent + 1)?;
}
if is_long_attr_list || !children.is_empty() {
@@ -260,7 +271,7 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
writeln!(buf, "{}: {},", name, out)?;
}
ContentField::Formatted(s) => {
writeln!(buf, "{}: {},", name, s.value())?;
writeln!(buf, "{}: \"{}\",", name, s.value())?;
}
ContentField::OnHandlerRaw(exp) => {
let out = prettyplease::unparse_expr(exp);
@@ -292,7 +303,7 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
}
for child in children {
write_ident(buf, child, indent + 1)?;
write_ident(buf, lines, child, indent + 1)?;
}
if !body.is_empty() || !children.is_empty() {
@@ -310,7 +321,52 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
write_tabs(buf, indent)?;
writeln!(buf, "\"{}\"", t.value())?;
}
BodyNode::RawExpr(_) => {
BodyNode::RawExpr(exp) => {
use syn::spanned::Spanned;
let placement = exp.span();
let start = placement.start();
let end = placement.end();
let num_spaces_desired = (indent * 4) as isize;
let first = lines[start.line - 1];
let num_spaces_real = first.chars().take_while(|c| c.is_whitespace()).count() as isize;
let offset = num_spaces_real - num_spaces_desired;
for line_id in start.line - 1..end.line {
let line = lines[line_id];
// trim the leading whitespace
if offset < 0 {
for _ in 0..-offset {
write!(buf, " ")?;
}
writeln!(buf, "{}", line)?;
} else {
let offset = offset as usize;
let right = &line[offset..];
writeln!(buf, "{}", right)?;
}
}
// let toks = exp.to_token_stream();
// let out = prettyplease::unparse_expr(exp);
// let mut lines = out.split('\n').peekable();
// for line in lines {
// write_tabs(buf, indent)?;
// writeln!(buf, "{}", line)?;
// // writeln!(buf)?;
// }
// write_tabs(buf, indent)?;
// let first = lines.next().unwrap();
// write!(buf, "{}", name, first)?;
// writeln!(buf)?;
//
// write!(buf, "{}", " ".repeat(ident))
}
+108 -1
View File
@@ -203,6 +203,98 @@ fn formats_component_tiny() {
print!("{formatted}");
}
#[test]
fn formats_exprs() {
let block = r#"
ul {
(0..10).map(|f| rsx!{
li {
"hi"
}
})
}
"#;
let formatted = fmt_block(block).unwrap();
print!("{formatted}");
}
#[test]
fn formats_exprs_neg_indent() {
let block = r#"
ul {
(0..10).map(|f| rsx!{
li {
"hi"
}
})
}
"#;
let formatted = fmt_block(block).unwrap();
print!("{formatted}");
}
#[test]
fn formats_exprs_handlers() {
let block = r#"
button {
class: "flex items-center pl-3 py-3 pr-2 text-gray-500 hover:bg-indigo-50 rounded",
onclick: move |evt| {
show_user_menu.set(!show_user_menu.get()); evt.cancel_bubble(); },
onclick: move |evt|
show_user_menu.set(!show_user_menu.get()),
span { class: "inline-block mr-4",
icons::icon_14 {}
}
span { "Settings" }
}
"#;
let formatted = fmt_block(block).unwrap();
print!("{formatted}");
}
#[test]
fn formats_complex() {
let block = r#"
li {
Link {
class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded",
to: "{to}",
span { class: "inline-block mr-3",
icons::icon_0 {}
}
span { "{name}" }
children.is_some().then(|| rsx!{
span {
class: "inline-block ml-auto hover:bg-gray-500",
onclick: move |evt| {
// open.set(!open.get());
evt.cancel_bubble();
},
icons::icon_8 {}
}
})
}
div {
class: "px-4",
is_current.then(|| rsx!{ children })
// open.then(|| rsx!{ children })
}
}
"#;
let formatted = fmt_block(block).unwrap();
print!("{formatted}");
}
#[test]
fn formats_document() {
let block = r#"
@@ -321,7 +413,6 @@ fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape)
}
}
}
#[inline_props]
fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
const ICON_SIZE: u32 = 36;
@@ -362,3 +453,19 @@ fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape)
&format!("{{ {} }}", &block.formatted),
);
}
#[test]
fn empty_blocks() {
let mut src = r###"
pub fn Alert(cx: Scope) -> Element {
cx.render(rsx! {
div { }
})
}
"###
.to_string();
let formatted = get_format_blocks(&src);
dbg!(&formatted);
}