From ac6035cb2a04e126275996d4e4dc985fb0cb0afe Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 13 Jan 2023 16:46:34 -0800 Subject: [PATCH 1/3] feat: parse entire file instead of hunting for verbtain --- packages/autofmt/Cargo.toml | 3 +- packages/autofmt/src/collect_macros.rs | 212 +++++++++++++++++ packages/autofmt/src/component.rs | 2 +- packages/autofmt/src/element.rs | 4 +- packages/autofmt/src/expr.rs | 2 +- packages/autofmt/src/lib.rs | 222 ++++++++++++++---- packages/autofmt/src/util.rs | 20 -- packages/autofmt/src/writer.rs | 6 +- packages/autofmt/tests/samples.rs | 3 +- .../autofmt/tests/samples/messy_indent.rsx | 2 +- packages/autofmt/tests/samples/t2.rsx | 7 + packages/autofmt/tests/samples/tiny.rsx | 11 +- packages/autofmt/tests/wrong/multiexpr.rsx | 8 +- .../autofmt/tests/wrong/multiexpr.wrong.rsx | 8 +- 14 files changed, 429 insertions(+), 81 deletions(-) create mode 100644 packages/autofmt/src/collect_macros.rs delete mode 100644 packages/autofmt/src/util.rs create mode 100644 packages/autofmt/tests/samples/t2.rsx diff --git a/packages/autofmt/Cargo.toml b/packages/autofmt/Cargo.toml index e4c9eb1cd..a1a4592d8 100644 --- a/packages/autofmt/Cargo.toml +++ b/packages/autofmt/Cargo.toml @@ -6,11 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -dioxus-rsx = { path = "../rsx", version = "0.0.2"} +dioxus-rsx = { path = "../rsx", version = "0.0.2" } proc-macro2 = { version = "1.0.6", features = ["span-locations"] } quote = "1.0" syn = { version = "1.0.11", features = ["full", "extra-traits"] } -triple_accel = "0.4.0" serde = { version = "1.0.136", features = ["derive"] } prettyplease = { git = "https://github.com/DioxusLabs/prettyplease-macro-fmt.git", features = [ "verbatim", diff --git a/packages/autofmt/src/collect_macros.rs b/packages/autofmt/src/collect_macros.rs new file mode 100644 index 000000000..13a2ea8ee --- /dev/null +++ b/packages/autofmt/src/collect_macros.rs @@ -0,0 +1,212 @@ +//! Collect macros from a file +//! +//! Returns all macros that match a pattern. You can use this information to autoformat them later + +use proc_macro2::LineColumn; +use syn::{Block, Expr, File, Item, Macro, Stmt}; + +type CollectedMacro<'a> = &'a Macro; + +pub fn collect_from_file<'a>(file: &'a File, macros: &mut Vec>) { + for item in file.items.iter() { + collect_from_item(item, macros); + } +} + +pub fn collect_from_item<'a>(item: &'a Item, macros: &mut Vec>) { + match item { + Item::Fn(f) => collect_from_block(&f.block, macros), + + // Ignore macros if they're not rsx or render + Item::Macro(macro_) => { + let to_str = macro_.mac.path.segments[0].ident.to_string(); + // let Some(ident) = ¯o_.ident else { return }; + // let to_str = ident.to_string(); + if to_str == "rsx" || to_str == "render" { + macros.push(¯o_.mac); + } + } + + // Currently disabled since we're not focused on autoformatting these + Item::Impl(_imp) => {} + Item::Trait(_) => {} + + // Global-ish things + Item::Static(f) => collect_from_expr(&f.expr, macros), + Item::Const(f) => collect_from_expr(&f.expr, macros), + Item::Mod(s) => { + if let Some((_, block)) = &s.content { + for item in block { + collect_from_item(item, macros); + } + } + } + + // None of these we can really do anything with at the item level + Item::Macro2(m) => { + panic!("Macro2: {:?}", m); + } + Item::Enum(_) + | Item::ExternCrate(_) + | Item::ForeignMod(_) + | Item::TraitAlias(_) + | Item::Type(_) + | Item::Struct(_) + | Item::Union(_) + | Item::Use(_) + | Item::Verbatim(_) => {} + _ => {} + } +} + +pub fn collect_from_block<'a>(block: &'a Block, macros: &mut Vec>) { + for stmt in &block.stmts { + match stmt { + Stmt::Item(item) => collect_from_item(item, macros), + Stmt::Local(local) => { + if let Some((_eq, init)) = &local.init { + collect_from_expr(init, macros); + } + } + Stmt::Expr(exp) | Stmt::Semi(exp, _) => collect_from_expr(exp, macros), + } + } +} + +pub fn collect_from_expr<'a>(expr: &'a Expr, macros: &mut Vec>) { + // collect an expr from the exprs, descending into blocks + match expr { + Expr::Macro(macro_) => { + let macro_name = macro_.mac.path.segments[0].ident.to_string(); + + if macro_name == "rsx" { + macros.push(¯o_.mac); + } + } + + Expr::MethodCall(e) => { + collect_from_expr(&e.receiver, macros); + for expr in e.args.iter() { + collect_from_expr(expr, macros); + } + } + Expr::Assign(exp) => { + collect_from_expr(&exp.left, macros); + collect_from_expr(&exp.right, macros); + } + + Expr::Async(b) => collect_from_block(&b.block, macros), + Expr::Block(b) => collect_from_block(&b.block, macros), + Expr::Call(c) => { + collect_from_expr(&c.func, macros); + for expr in c.args.iter() { + collect_from_expr(expr, macros); + } + } + Expr::Closure(c) => collect_from_expr(&c.body, macros), + Expr::ForLoop(b) => { + collect_from_expr(&b.expr, macros); + collect_from_block(&b.body, macros); + } + Expr::If(f) => { + collect_from_expr(&f.cond, macros); + collect_from_block(&f.then_branch, macros); + if let Some((_, else_branch)) = &f.else_branch { + collect_from_expr(else_branch, macros); + } + } + Expr::Yield(y) => { + if let Some(expr) = &y.expr { + collect_from_expr(expr, macros); + } + } + + Expr::Let(l) => collect_from_expr(&l.expr, macros), + + Expr::Return(r) => { + if let Some(expr) = &r.expr { + collect_from_expr(expr, macros); + } + } + + Expr::Loop(l) => { + collect_from_block(&l.body, macros); + } + Expr::Match(l) => { + collect_from_expr(&l.expr, macros); + for arm in l.arms.iter() { + if let Some((_, expr)) = &arm.guard { + collect_from_expr(expr, macros); + } + + collect_from_expr(&arm.body, macros); + } + } + + Expr::Unsafe(u) => { + collect_from_block(&u.block, macros); + } + + Expr::While(w) => { + collect_from_expr(&w.cond, macros); + collect_from_block(&w.body, macros); + } + + // don't both formatting these for now + Expr::Array(_) + | Expr::AssignOp(_) + | Expr::Await(_) + | Expr::Binary(_) + | Expr::Box(_) + | Expr::Break(_) + | Expr::Cast(_) + | Expr::Continue(_) + | Expr::Field(_) + | Expr::Group(_) + | Expr::Index(_) + | Expr::Lit(_) + | Expr::Paren(_) + | Expr::Path(_) + | Expr::Range(_) + | Expr::Reference(_) + | Expr::Repeat(_) + | Expr::Struct(_) + | Expr::Try(_) + | Expr::TryBlock(_) + | Expr::Tuple(_) + | Expr::Type(_) + | Expr::Unary(_) + | Expr::Verbatim(_) => {} + + _ => todo!(), + }; +} + +pub fn byte_offset(input: &str, location: LineColumn) -> usize { + let mut offset = 0; + for _ in 1..location.line { + offset += input[offset..].find('\n').unwrap() + 1; + } + offset + + input[offset..] + .chars() + .take(location.column) + .map(char::len_utf8) + .sum::() +} + +#[test] +fn parses_file_and_collects_rsx_macros() { + let contents = include_str!("../tests/samples/long.rsx"); + + let parsed = syn::parse_file(contents).unwrap(); + + let mut macros = vec![]; + collect_from_file(&parsed, &mut macros); + + println!("Collected {} macros", macros.len()); + + for item in macros { + println!("Found macro: {:#?}", item.path.segments[0].ident.span()); + } +} diff --git a/packages/autofmt/src/component.rs b/packages/autofmt/src/component.rs index b3ab7fbbf..38cc7815d 100644 --- a/packages/autofmt/src/component.rs +++ b/packages/autofmt/src/component.rs @@ -19,7 +19,7 @@ enum ShortOptimization { NoOpt, } -impl Writer { +impl Writer<'_> { pub fn write_component( &mut self, Component { diff --git a/packages/autofmt/src/element.rs b/packages/autofmt/src/element.rs index b9903dc47..41a6d1c1c 100644 --- a/packages/autofmt/src/element.rs +++ b/packages/autofmt/src/element.rs @@ -40,7 +40,7 @@ div { } */ -impl Writer { +impl Writer<'_> { pub fn write_element(&mut self, el: &Element) -> Result { let Element { name, @@ -276,7 +276,7 @@ impl Writer { let start = location.start(); let line_start = start.line - 1; - let this_line = self.src[line_start].as_str(); + let this_line = self.src[line_start]; let beginning = if this_line.len() > start.column { this_line[..start.column].trim() diff --git a/packages/autofmt/src/expr.rs b/packages/autofmt/src/expr.rs index 4a916c71a..9e09cdeb5 100644 --- a/packages/autofmt/src/expr.rs +++ b/packages/autofmt/src/expr.rs @@ -5,7 +5,7 @@ use proc_macro2::Span; use crate::Writer; -impl Writer { +impl Writer<'_> { pub fn write_raw_expr(&mut self, placement: Span) -> Result { /* We want to normalize the expr to the appropriate indent level. diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index 184de1003..ae76b67c6 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -1,13 +1,16 @@ +use collect_macros::byte_offset; use dioxus_rsx::CallBody; +use proc_macro2::LineColumn; +use syn::ExprMacro; +use syn::MacroDelimiter; -use crate::util::*; use crate::writer::*; mod buffer; +mod collect_macros; mod component; mod element; mod expr; -mod util; mod writer; /// A modification to the original file to be applied by an IDE @@ -41,65 +44,83 @@ pub struct FormattedBlock { /// Nested blocks of RSX will be handled automatically pub fn fmt_file(contents: &str) -> Vec { let mut formatted_blocks = Vec::new(); - let mut last_bracket_end = 0; - use triple_accel::{levenshtein_search, Match}; + let parsed = syn::parse_file(contents).unwrap(); - for Match { end, start, k } in levenshtein_search(b"rsx! {", contents.as_bytes()) { - let open = end; + let mut macros = vec![]; + collect_macros::collect_from_file(&parsed, &mut macros); - if k > 1 { + // No macros, no work to do + if macros.is_empty() { + return formatted_blocks; + } + + let mut writer = Writer { + src: contents.lines().collect::>(), + ..Writer::default() + }; + + // Dont parse nested macros + let mut end_span = LineColumn { column: 0, line: 0 }; + for item in macros { + let macro_path = &item.path.segments[0].ident; + + // this macro is inside the last macro we parsed, skip it + if macro_path.span().start() < end_span { continue; } - // ensure the marker is not nested - if start < last_bracket_end { - continue; + // item.parse_body::(); + let body = item.parse_body::().unwrap(); + + let rsx_start = macro_path.span().start(); + + writer.out.indent = &writer.src[rsx_start.line - 1] + .chars() + .take_while(|c| *c == ' ') + .count() + / 4; + + // Oneliner optimization + if writer.is_short_children(&body.roots).is_some() { + writer.write_ident(&body.roots[0]).unwrap(); + } else { + writer.write_body_indented(&body.roots).unwrap(); } - let indent_level = { - // walk backwards from start until we find a new line - let mut lines = contents[..start].lines().rev(); - match lines.next() { - Some(line) => { - if line.starts_with("//") || line.starts_with("///") { - continue; - } + // writing idents leaves the final line ended at the end of the last ident + if writer.out.buf.contains('\n') { + writer.out.new_line().unwrap(); + writer.out.tab().unwrap(); + } - line.chars().take_while(|c| *c == ' ').count() / 4 - } - None => 0, - } + let span = match item.delimiter { + MacroDelimiter::Paren(_) => todo!(), + MacroDelimiter::Brace(b) => b.span, + MacroDelimiter::Bracket(_) => todo!(), }; - let remaining = &contents[open - 1..]; - let close = find_bracket_end(remaining).unwrap(); - // Move the last bracket end to the end of this block to avoid nested blocks - last_bracket_end = close + open - 1; + let mut formatted = String::new(); - // Format the substring, doesn't include the outer brackets - let substring = &remaining[1..close - 1]; + std::mem::swap(&mut formatted, &mut writer.out.buf); - // make sure to add back whatever weird whitespace there was at the end - let mut remaining_whitespace = substring.chars().rev().take_while(|c| *c == ' ').count(); + let start = byte_offset(contents, span.start()) + 1; + let end = byte_offset(contents, span.end()) - 1; - let mut new = fmt_block(substring, indent_level).unwrap(); - - // if the new string is not multiline, don't try to adjust the marker ending - // We want to trim off any indentation that there might be - if new.len() <= 80 && !new.contains('\n') { - new = format!(" {new} "); - remaining_whitespace = 0; + if formatted.len() <= 80 && !formatted.contains('\n') { + formatted = format!(" {} ", formatted); } - if new == substring { + end_span = span.end(); + + if contents[start..end] == formatted { continue; } formatted_blocks.push(FormattedBlock { - formatted: new, - start: open, - end: last_bracket_end - remaining_whitespace - 1, + formatted, + start, + end, }); } @@ -108,7 +129,25 @@ pub fn fmt_file(contents: &str) -> Vec { pub fn write_block_out(body: CallBody) -> Option { let mut buf = Writer { - src: vec!["".to_string()], + src: vec![""], + ..Writer::default() + }; + + // Oneliner optimization + if buf.is_short_children(&body.roots).is_some() { + buf.write_ident(&body.roots[0]).unwrap(); + } else { + buf.write_body_indented(&body.roots).unwrap(); + } + + buf.consume() +} + +pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option { + let body = syn::parse2::(expr.mac.tokens).unwrap(); + + let mut buf = Writer { + src: raw.lines().collect(), ..Writer::default() }; @@ -126,7 +165,7 @@ pub fn fmt_block(block: &str, indent_level: usize) -> Option { let body = syn::parse_str::(block).unwrap(); let mut buf = Writer { - src: block.lines().map(|f| f.to_string()).collect(), + src: block.lines().collect(), ..Writer::default() }; @@ -182,3 +221,100 @@ pub fn apply_formats(input: &str, blocks: Vec) -> String { out } + +#[test] +fn get_some_blocks() { + let contents = include_str!("../tests/samples/long.rsx"); + + let out = fmt_file(contents); + + dbg!(out); +} + +// for Match { end, start, k } in levenshtein_search(b"rsx! {", contents.as_bytes()) { +// let open = end; + +// if k > 1 { +// continue; +// } + +// // ensure the marker is not nested +// if start < last_bracket_end { +// continue; +// } + +// let indent_level = { +// // walk backwards from start until we find a new line +// let mut lines = contents[..start].lines().rev(); +// match lines.next() { +// Some(line) => { +// if line.starts_with("//") || line.starts_with("///") { +// continue; +// } + +// line.chars().take_while(|c| *c == ' ').count() / 4 +// } +// None => 0, +// } +// }; + +// let remaining = &contents[open - 1..]; + +// let rest_with_macro = &contents[start..]; + +// dbg!(rest_with_macro); + +// let body = syn::parse_str::(rest_with_macro).unwrap(); + +// let MacroDelimiter::Brace(brace) = body.mac.delimiter else { panic!() }; +// // dbg!(brace.span.end()); +// let lines = &contents[start..] +// .lines() +// .map(|f| f.to_string()) +// .collect::>(); + +// dbg!(lines); + +// let close = lines +// .iter() +// .skip(1) +// .take(brace.span.end().line - 1) +// .map(|f| f.len()) +// .sum::() +// + brace.span.end().column +// + brace.span.end().line +// - 1; + +// // let body = syn::parse::(stream.into()).unwrap(); + +// // let close = find_bracket_end(remaining).unwrap(); + +// dbg!(close); +// // Move the last bracket end to the end of this block to avoid nested blocks +// last_bracket_end = close + open - 1; + +// // Format the substring, doesn't include the outer brackets +// let substring = &remaining[1..close - 1]; + +// // make sure to add back whatever weird whitespace there was at the end +// let mut remaining_whitespace = substring.chars().rev().take_while(|c| *c == ' ').count(); + +// let mut new = fmt_block(substring, indent_level).unwrap(); + +// // if the new string is not multiline, don't try to adjust the marker ending +// // We want to trim off any indentation that there might be +// if new.len() <= 80 && !new.contains('\n') { +// new = format!(" {new} "); +// remaining_whitespace = 0; +// } + +// if new == substring { +// continue; +// } + +// formatted_blocks.push(FormattedBlock { +// formatted: new, +// start: open, +// end: last_bracket_end - remaining_whitespace - 1, +// }); +// } diff --git a/packages/autofmt/src/util.rs b/packages/autofmt/src/util.rs deleted file mode 100644 index 7ffd36a9a..000000000 --- a/packages/autofmt/src/util.rs +++ /dev/null @@ -1,20 +0,0 @@ -pub fn find_bracket_end(contents: &str) -> Option { - let mut depth = 0; - - let mut len = 0; - - for c in contents.chars() { - len += c.len_utf8(); - if c == '{' { - depth += 1; - } else if c == '}' { - depth -= 1; - - if depth == 0 { - return Some(len); - } - } - } - - None -} diff --git a/packages/autofmt/src/writer.rs b/packages/autofmt/src/writer.rs index b60224c88..9e507ed70 100644 --- a/packages/autofmt/src/writer.rs +++ b/packages/autofmt/src/writer.rs @@ -10,8 +10,8 @@ use syn::{spanned::Spanned, Expr, ExprIf}; use crate::buffer::Buffer; #[derive(Debug, Default)] -pub struct Writer { - pub src: Vec, +pub struct Writer<'a> { + pub src: Vec<&'a str>, pub cached_formats: HashMap, pub comments: VecDeque, pub out: Buffer, @@ -31,7 +31,7 @@ impl Location { } } -impl Writer { +impl Writer<'_> { // Expects to be written directly into place pub fn write_ident(&mut self, node: &BodyNode) -> Result { match node { diff --git a/packages/autofmt/tests/samples.rs b/packages/autofmt/tests/samples.rs index 26492e141..c9489d7d0 100644 --- a/packages/autofmt/tests/samples.rs +++ b/packages/autofmt/tests/samples.rs @@ -35,5 +35,6 @@ twoway![ emoji, messy_indent, long_exprs, - ifchain_forloop + ifchain_forloop, + t2 ]; diff --git a/packages/autofmt/tests/samples/messy_indent.rsx b/packages/autofmt/tests/samples/messy_indent.rsx index 260dd08a6..0fba72031 100644 --- a/packages/autofmt/tests/samples/messy_indent.rsx +++ b/packages/autofmt/tests/samples/messy_indent.rsx @@ -9,5 +9,5 @@ fn SaveClipboard(cx: Scope) -> Element { cx.render(rsx! { div { "hello world", "hello world", "hello world" } -}) + }) } diff --git a/packages/autofmt/tests/samples/t2.rsx b/packages/autofmt/tests/samples/t2.rsx new file mode 100644 index 000000000..3dab991b4 --- /dev/null +++ b/packages/autofmt/tests/samples/t2.rsx @@ -0,0 +1,7 @@ +rsx! { + div {} + div { + // div { + } +} + diff --git a/packages/autofmt/tests/samples/tiny.rsx b/packages/autofmt/tests/samples/tiny.rsx index 6bd50b9dd..edbfb762b 100644 --- a/packages/autofmt/tests/samples/tiny.rsx +++ b/packages/autofmt/tests/samples/tiny.rsx @@ -1 +1,10 @@ -rsx! { div {} } +fn ItWorks() { + rsx! { + div { + div { + div {} + div {} + } + } + } +} diff --git a/packages/autofmt/tests/wrong/multiexpr.rsx b/packages/autofmt/tests/wrong/multiexpr.rsx index 1c3f38434..5732f2cdd 100644 --- a/packages/autofmt/tests/wrong/multiexpr.rsx +++ b/packages/autofmt/tests/wrong/multiexpr.rsx @@ -1,3 +1,5 @@ -cx.render(rsx! { - div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right } -}) +fn ItWroks() { + cx.render(rsx! { + div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right } + }) +} diff --git a/packages/autofmt/tests/wrong/multiexpr.wrong.rsx b/packages/autofmt/tests/wrong/multiexpr.wrong.rsx index 1c3f38434..5732f2cdd 100644 --- a/packages/autofmt/tests/wrong/multiexpr.wrong.rsx +++ b/packages/autofmt/tests/wrong/multiexpr.wrong.rsx @@ -1,3 +1,5 @@ -cx.render(rsx! { - div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right } -}) +fn ItWroks() { + cx.render(rsx! { + div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right } + }) +} From ea032eeb8e5a4ecd754221a03765028f1ff33a17 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 13 Jan 2023 16:52:37 -0800 Subject: [PATCH 2/3] clean up macro crate a little bit --- packages/autofmt/src/collect_macros.rs | 25 ++---- packages/autofmt/src/lib.rs | 103 +------------------------ 2 files changed, 9 insertions(+), 119 deletions(-) diff --git a/packages/autofmt/src/collect_macros.rs b/packages/autofmt/src/collect_macros.rs index 13a2ea8ee..b2e99b127 100644 --- a/packages/autofmt/src/collect_macros.rs +++ b/packages/autofmt/src/collect_macros.rs @@ -97,13 +97,18 @@ pub fn collect_from_expr<'a>(expr: &'a Expr, macros: &mut Vec Expr::Async(b) => collect_from_block(&b.block, macros), Expr::Block(b) => collect_from_block(&b.block, macros), + Expr::Closure(c) => collect_from_expr(&c.body, macros), + Expr::Let(l) => collect_from_expr(&l.expr, macros), + Expr::Unsafe(u) => collect_from_block(&u.block, macros), + Expr::Loop(l) => collect_from_block(&l.body, macros), + Expr::Call(c) => { collect_from_expr(&c.func, macros); for expr in c.args.iter() { collect_from_expr(expr, macros); } } - Expr::Closure(c) => collect_from_expr(&c.body, macros), + Expr::ForLoop(b) => { collect_from_expr(&b.expr, macros); collect_from_block(&b.body, macros); @@ -121,17 +126,12 @@ pub fn collect_from_expr<'a>(expr: &'a Expr, macros: &mut Vec } } - Expr::Let(l) => collect_from_expr(&l.expr, macros), - Expr::Return(r) => { if let Some(expr) = &r.expr { collect_from_expr(expr, macros); } } - Expr::Loop(l) => { - collect_from_block(&l.body, macros); - } Expr::Match(l) => { collect_from_expr(&l.expr, macros); for arm in l.arms.iter() { @@ -143,10 +143,6 @@ pub fn collect_from_expr<'a>(expr: &'a Expr, macros: &mut Vec } } - Expr::Unsafe(u) => { - collect_from_block(&u.block, macros); - } - Expr::While(w) => { collect_from_expr(&w.cond, macros); collect_from_block(&w.body, macros); @@ -198,15 +194,8 @@ pub fn byte_offset(input: &str, location: LineColumn) -> usize { #[test] fn parses_file_and_collects_rsx_macros() { let contents = include_str!("../tests/samples/long.rsx"); - let parsed = syn::parse_file(contents).unwrap(); - let mut macros = vec![]; collect_from_file(&parsed, &mut macros); - - println!("Collected {} macros", macros.len()); - - for item in macros { - println!("Found macro: {:#?}", item.path.segments[0].ident.span()); - } + assert_eq!(macros.len(), 3); } diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index ae76b67c6..ba5b4cb20 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -1,10 +1,8 @@ +use crate::writer::*; use collect_macros::byte_offset; use dioxus_rsx::CallBody; use proc_macro2::LineColumn; -use syn::ExprMacro; -use syn::MacroDelimiter; - -use crate::writer::*; +use syn::{ExprMacro, MacroDelimiter}; mod buffer; mod collect_macros; @@ -221,100 +219,3 @@ pub fn apply_formats(input: &str, blocks: Vec) -> String { out } - -#[test] -fn get_some_blocks() { - let contents = include_str!("../tests/samples/long.rsx"); - - let out = fmt_file(contents); - - dbg!(out); -} - -// for Match { end, start, k } in levenshtein_search(b"rsx! {", contents.as_bytes()) { -// let open = end; - -// if k > 1 { -// continue; -// } - -// // ensure the marker is not nested -// if start < last_bracket_end { -// continue; -// } - -// let indent_level = { -// // walk backwards from start until we find a new line -// let mut lines = contents[..start].lines().rev(); -// match lines.next() { -// Some(line) => { -// if line.starts_with("//") || line.starts_with("///") { -// continue; -// } - -// line.chars().take_while(|c| *c == ' ').count() / 4 -// } -// None => 0, -// } -// }; - -// let remaining = &contents[open - 1..]; - -// let rest_with_macro = &contents[start..]; - -// dbg!(rest_with_macro); - -// let body = syn::parse_str::(rest_with_macro).unwrap(); - -// let MacroDelimiter::Brace(brace) = body.mac.delimiter else { panic!() }; -// // dbg!(brace.span.end()); -// let lines = &contents[start..] -// .lines() -// .map(|f| f.to_string()) -// .collect::>(); - -// dbg!(lines); - -// let close = lines -// .iter() -// .skip(1) -// .take(brace.span.end().line - 1) -// .map(|f| f.len()) -// .sum::() -// + brace.span.end().column -// + brace.span.end().line -// - 1; - -// // let body = syn::parse::(stream.into()).unwrap(); - -// // let close = find_bracket_end(remaining).unwrap(); - -// dbg!(close); -// // Move the last bracket end to the end of this block to avoid nested blocks -// last_bracket_end = close + open - 1; - -// // Format the substring, doesn't include the outer brackets -// let substring = &remaining[1..close - 1]; - -// // make sure to add back whatever weird whitespace there was at the end -// let mut remaining_whitespace = substring.chars().rev().take_while(|c| *c == ' ').count(); - -// let mut new = fmt_block(substring, indent_level).unwrap(); - -// // if the new string is not multiline, don't try to adjust the marker ending -// // We want to trim off any indentation that there might be -// if new.len() <= 80 && !new.contains('\n') { -// new = format!(" {new} "); -// remaining_whitespace = 0; -// } - -// if new == substring { -// continue; -// } - -// formatted_blocks.push(FormattedBlock { -// formatted: new, -// start: open, -// end: last_bracket_end - remaining_whitespace - 1, -// }); -// } From 9f9bcd747aede11843dd52bce9686935a6c8ad5e Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 13 Jan 2023 16:58:53 -0800 Subject: [PATCH 3/3] chore: fewer clones in autoformat infrastructure --- packages/autofmt/src/collect_macros.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/autofmt/src/collect_macros.rs b/packages/autofmt/src/collect_macros.rs index b2e99b127..197cafcec 100644 --- a/packages/autofmt/src/collect_macros.rs +++ b/packages/autofmt/src/collect_macros.rs @@ -19,10 +19,9 @@ pub fn collect_from_item<'a>(item: &'a Item, macros: &mut Vec // Ignore macros if they're not rsx or render Item::Macro(macro_) => { - let to_str = macro_.mac.path.segments[0].ident.to_string(); - // let Some(ident) = ¯o_.ident else { return }; - // let to_str = ident.to_string(); - if to_str == "rsx" || to_str == "render" { + if macro_.mac.path.segments[0].ident == "rsx" + || macro_.mac.path.segments[0].ident == "render" + { macros.push(¯o_.mac); } } @@ -43,10 +42,8 @@ pub fn collect_from_item<'a>(item: &'a Item, macros: &mut Vec } // None of these we can really do anything with at the item level - Item::Macro2(m) => { - panic!("Macro2: {:?}", m); - } - Item::Enum(_) + Item::Macro2(_) + | Item::Enum(_) | Item::ExternCrate(_) | Item::ForeignMod(_) | Item::TraitAlias(_) @@ -77,9 +74,9 @@ pub fn collect_from_expr<'a>(expr: &'a Expr, macros: &mut Vec // collect an expr from the exprs, descending into blocks match expr { Expr::Macro(macro_) => { - let macro_name = macro_.mac.path.segments[0].ident.to_string(); - - if macro_name == "rsx" { + if macro_.mac.path.segments[0].ident == "rsx" + || macro_.mac.path.segments[0].ident == "render" + { macros.push(¯o_.mac); } }