feat: more tests and spans
This commit is contained in:
1 parent
804d9af1c7
commit
284860f470
3 files changed
+194
-31
No files matched your search
@@ -6,7 +6,7 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = { version = "1.0.6" }
|
proc-macro2 = { version = "1.0.6", features = ["span-locations"] }
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
syn = { version = "1.0.11", features = ["full", "extra-traits"] }
|
syn = { version = "1.0.11", features = ["full", "extra-traits"] }
|
||||||
dioxus-rsx = { path = "../rsx" }
|
dioxus-rsx = { path = "../rsx" }
|
||||||
|
|||||||
+85
-29
@@ -41,20 +41,6 @@ pub fn get_format_blocks(contents: &str) -> Vec<FormattedBlock> {
|
|||||||
continue;
|
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..];
|
let remaining = &contents[end - 1..];
|
||||||
|
|
||||||
if let Some(bracket_end) = find_bracket_end(remaining) {
|
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 let Some(new) = fmt_block(sub_string) {
|
||||||
if !new.is_empty() {
|
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
|
// 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();
|
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> {
|
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 parsed: CallBody = syn::parse_str(block).ok()?;
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
for node in parsed.roots.iter() {
|
for node in parsed.roots.iter() {
|
||||||
write_ident(&mut buf, node, 0).ok()?;
|
write_ident(&mut buf, &raw_lines, node, 0).ok()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(buf)
|
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 {
|
match node {
|
||||||
BodyNode::Element(el) => {
|
BodyNode::Element(el) => {
|
||||||
let Element {
|
let Element {
|
||||||
@@ -168,7 +169,7 @@ pub fn write_ident(buf: &mut String, node: &BodyNode, indent: usize) -> fmt::Res
|
|||||||
ElementAttr::CustomAttrText { name, value } => {
|
ElementAttr::CustomAttrText { name, value } => {
|
||||||
write!(
|
write!(
|
||||||
buf,
|
buf,
|
||||||
"{name}: \"{value}\"",
|
"\"{name}\": \"{value}\"",
|
||||||
name = name.value(),
|
name = name.value(),
|
||||||
value = value.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 } => {
|
ElementAttr::CustomAttrExpression { name, value } => {
|
||||||
let out = prettyplease::unparse_expr(value);
|
let out = prettyplease::unparse_expr(value);
|
||||||
write!(buf, "{}: {}", name.value(), out)?;
|
write!(buf, "\"{}\": {}", name.value(), out)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementAttr::EventTokens { name, tokens } => {
|
ElementAttr::EventTokens { name, tokens } => {
|
||||||
let out = prettyplease::unparse_expr(tokens);
|
let out = prettyplease::unparse_expr(tokens);
|
||||||
|
|
||||||
|
dbg!(&out);
|
||||||
|
|
||||||
let mut lines = out.split('\n').peekable();
|
let mut lines = out.split('\n').peekable();
|
||||||
let first = lines.next().unwrap();
|
let first = lines.next().unwrap();
|
||||||
write!(buf, "{}: {}", name, first)?;
|
|
||||||
|
|
||||||
while let Some(line) = lines.next() {
|
// a one-liner for whatever reason
|
||||||
write_tabs(buf, indent + 1)?;
|
// Does not need a new line
|
||||||
write!(buf, "{}", line)?;
|
if lines.peek().is_none() {
|
||||||
// write!(buf, "{}", line)?;
|
write!(buf, "{}: {}", name, first)?;
|
||||||
if lines.peek().is_none() {
|
} else {
|
||||||
write!(buf, "")?;
|
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 {
|
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() {
|
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)?;
|
writeln!(buf, "{}: {},", name, out)?;
|
||||||
}
|
}
|
||||||
ContentField::Formatted(s) => {
|
ContentField::Formatted(s) => {
|
||||||
writeln!(buf, "{}: {},", name, s.value())?;
|
writeln!(buf, "{}: \"{}\",", name, s.value())?;
|
||||||
}
|
}
|
||||||
ContentField::OnHandlerRaw(exp) => {
|
ContentField::OnHandlerRaw(exp) => {
|
||||||
let out = prettyplease::unparse_expr(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 {
|
for child in children {
|
||||||
write_ident(buf, child, indent + 1)?;
|
write_ident(buf, lines, child, indent + 1)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !body.is_empty() || !children.is_empty() {
|
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)?;
|
write_tabs(buf, indent)?;
|
||||||
writeln!(buf, "\"{}\"", t.value())?;
|
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))
|
// write!(buf, "{}", " ".repeat(ident))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,6 +203,98 @@ fn formats_component_tiny() {
|
|||||||
print!("{formatted}");
|
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]
|
#[test]
|
||||||
fn formats_document() {
|
fn formats_document() {
|
||||||
let block = r#"
|
let block = r#"
|
||||||
@@ -321,7 +413,6 @@ fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline_props]
|
#[inline_props]
|
||||||
fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
|
fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
|
||||||
const ICON_SIZE: u32 = 36;
|
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),
|
&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);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user