feat: parse entire file instead of hunting for verbtain
This commit is contained in:
1 parent
bf559a6d06
commit
ac6035cb2a
14 files changed
+429
-81
No files matched your search
@@ -6,11 +6,10 @@ 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]
|
||||||
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"] }
|
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"] }
|
||||||
triple_accel = "0.4.0"
|
|
||||||
serde = { version = "1.0.136", features = ["derive"] }
|
serde = { version = "1.0.136", features = ["derive"] }
|
||||||
prettyplease = { git = "https://github.com/DioxusLabs/prettyplease-macro-fmt.git", features = [
|
prettyplease = { git = "https://github.com/DioxusLabs/prettyplease-macro-fmt.git", features = [
|
||||||
"verbatim",
|
"verbatim",
|
||||||
|
|||||||
@@ -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<CollectedMacro<'a>>) {
|
||||||
|
for item in file.items.iter() {
|
||||||
|
collect_from_item(item, macros);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collect_from_item<'a>(item: &'a Item, macros: &mut Vec<CollectedMacro<'a>>) {
|
||||||
|
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<CollectedMacro<'a>>) {
|
||||||
|
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<CollectedMacro<'a>>) {
|
||||||
|
// 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::<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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ enum ShortOptimization {
|
|||||||
NoOpt,
|
NoOpt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer {
|
impl Writer<'_> {
|
||||||
pub fn write_component(
|
pub fn write_component(
|
||||||
&mut self,
|
&mut self,
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ div {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl Writer {
|
impl Writer<'_> {
|
||||||
pub fn write_element(&mut self, el: &Element) -> Result {
|
pub fn write_element(&mut self, el: &Element) -> Result {
|
||||||
let Element {
|
let Element {
|
||||||
name,
|
name,
|
||||||
@@ -276,7 +276,7 @@ impl Writer {
|
|||||||
let start = location.start();
|
let start = location.start();
|
||||||
let line_start = start.line - 1;
|
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 {
|
let beginning = if this_line.len() > start.column {
|
||||||
this_line[..start.column].trim()
|
this_line[..start.column].trim()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use proc_macro2::Span;
|
|||||||
|
|
||||||
use crate::Writer;
|
use crate::Writer;
|
||||||
|
|
||||||
impl Writer {
|
impl Writer<'_> {
|
||||||
pub fn write_raw_expr(&mut self, placement: Span) -> Result {
|
pub fn write_raw_expr(&mut self, placement: Span) -> Result {
|
||||||
/*
|
/*
|
||||||
We want to normalize the expr to the appropriate indent level.
|
We want to normalize the expr to the appropriate indent level.
|
||||||
|
|||||||
+179
-43
@@ -1,13 +1,16 @@
|
|||||||
|
use collect_macros::byte_offset;
|
||||||
use dioxus_rsx::CallBody;
|
use dioxus_rsx::CallBody;
|
||||||
|
use proc_macro2::LineColumn;
|
||||||
|
use syn::ExprMacro;
|
||||||
|
use syn::MacroDelimiter;
|
||||||
|
|
||||||
use crate::util::*;
|
|
||||||
use crate::writer::*;
|
use crate::writer::*;
|
||||||
|
|
||||||
mod buffer;
|
mod buffer;
|
||||||
|
mod collect_macros;
|
||||||
mod component;
|
mod component;
|
||||||
mod element;
|
mod element;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod util;
|
|
||||||
mod writer;
|
mod writer;
|
||||||
|
|
||||||
/// A modification to the original file to be applied by an IDE
|
/// 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
|
/// Nested blocks of RSX will be handled automatically
|
||||||
pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
||||||
let mut formatted_blocks = Vec::new();
|
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 mut macros = vec![];
|
||||||
let open = end;
|
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::<Vec<_>>(),
|
||||||
|
..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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the marker is not nested
|
// item.parse_body::<CallBody>();
|
||||||
if start < last_bracket_end {
|
let body = item.parse_body::<CallBody>().unwrap();
|
||||||
continue;
|
|
||||||
|
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 = {
|
// writing idents leaves the final line ended at the end of the last ident
|
||||||
// walk backwards from start until we find a new line
|
if writer.out.buf.contains('\n') {
|
||||||
let mut lines = contents[..start].lines().rev();
|
writer.out.new_line().unwrap();
|
||||||
match lines.next() {
|
writer.out.tab().unwrap();
|
||||||
Some(line) => {
|
}
|
||||||
if line.starts_with("//") || line.starts_with("///") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
line.chars().take_while(|c| *c == ' ').count() / 4
|
let span = match item.delimiter {
|
||||||
}
|
MacroDelimiter::Paren(_) => todo!(),
|
||||||
None => 0,
|
MacroDelimiter::Brace(b) => b.span,
|
||||||
}
|
MacroDelimiter::Bracket(_) => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let remaining = &contents[open - 1..];
|
let mut formatted = String::new();
|
||||||
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;
|
|
||||||
|
|
||||||
// Format the substring, doesn't include the outer brackets
|
std::mem::swap(&mut formatted, &mut writer.out.buf);
|
||||||
let substring = &remaining[1..close - 1];
|
|
||||||
|
|
||||||
// make sure to add back whatever weird whitespace there was at the end
|
let start = byte_offset(contents, span.start()) + 1;
|
||||||
let mut remaining_whitespace = substring.chars().rev().take_while(|c| *c == ' ').count();
|
let end = byte_offset(contents, span.end()) - 1;
|
||||||
|
|
||||||
let mut new = fmt_block(substring, indent_level).unwrap();
|
if formatted.len() <= 80 && !formatted.contains('\n') {
|
||||||
|
formatted = format!(" {} ", formatted);
|
||||||
// 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 {
|
end_span = span.end();
|
||||||
|
|
||||||
|
if contents[start..end] == formatted {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted_blocks.push(FormattedBlock {
|
formatted_blocks.push(FormattedBlock {
|
||||||
formatted: new,
|
formatted,
|
||||||
start: open,
|
start,
|
||||||
end: last_bracket_end - remaining_whitespace - 1,
|
end,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +129,25 @@ pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
|||||||
|
|
||||||
pub fn write_block_out(body: CallBody) -> Option<String> {
|
pub fn write_block_out(body: CallBody) -> Option<String> {
|
||||||
let mut buf = Writer {
|
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<String> {
|
||||||
|
let body = syn::parse2::<CallBody>(expr.mac.tokens).unwrap();
|
||||||
|
|
||||||
|
let mut buf = Writer {
|
||||||
|
src: raw.lines().collect(),
|
||||||
..Writer::default()
|
..Writer::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,7 +165,7 @@ pub fn fmt_block(block: &str, indent_level: usize) -> Option<String> {
|
|||||||
let body = syn::parse_str::<dioxus_rsx::CallBody>(block).unwrap();
|
let body = syn::parse_str::<dioxus_rsx::CallBody>(block).unwrap();
|
||||||
|
|
||||||
let mut buf = Writer {
|
let mut buf = Writer {
|
||||||
src: block.lines().map(|f| f.to_string()).collect(),
|
src: block.lines().collect(),
|
||||||
..Writer::default()
|
..Writer::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,3 +221,100 @@ pub fn apply_formats(input: &str, blocks: Vec<FormattedBlock>) -> String {
|
|||||||
|
|
||||||
out
|
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::<ExprMacro>(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::<Vec<_>>();
|
||||||
|
|
||||||
|
// dbg!(lines);
|
||||||
|
|
||||||
|
// let close = lines
|
||||||
|
// .iter()
|
||||||
|
// .skip(1)
|
||||||
|
// .take(brace.span.end().line - 1)
|
||||||
|
// .map(|f| f.len())
|
||||||
|
// .sum::<usize>()
|
||||||
|
// + brace.span.end().column
|
||||||
|
// + brace.span.end().line
|
||||||
|
// - 1;
|
||||||
|
|
||||||
|
// // let body = syn::parse::<CallBody>(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,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
pub fn find_bracket_end(contents: &str) -> Option<usize> {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,8 @@ use syn::{spanned::Spanned, Expr, ExprIf};
|
|||||||
use crate::buffer::Buffer;
|
use crate::buffer::Buffer;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Writer {
|
pub struct Writer<'a> {
|
||||||
pub src: Vec<String>,
|
pub src: Vec<&'a str>,
|
||||||
pub cached_formats: HashMap<Location, String>,
|
pub cached_formats: HashMap<Location, String>,
|
||||||
pub comments: VecDeque<usize>,
|
pub comments: VecDeque<usize>,
|
||||||
pub out: Buffer,
|
pub out: Buffer,
|
||||||
@@ -31,7 +31,7 @@ impl Location {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer {
|
impl Writer<'_> {
|
||||||
// Expects to be written directly into place
|
// Expects to be written directly into place
|
||||||
pub fn write_ident(&mut self, node: &BodyNode) -> Result {
|
pub fn write_ident(&mut self, node: &BodyNode) -> Result {
|
||||||
match node {
|
match node {
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ twoway![
|
|||||||
emoji,
|
emoji,
|
||||||
messy_indent,
|
messy_indent,
|
||||||
long_exprs,
|
long_exprs,
|
||||||
ifchain_forloop
|
ifchain_forloop,
|
||||||
|
t2
|
||||||
];
|
];
|
||||||
@@ -9,5 +9,5 @@ fn SaveClipboard(cx: Scope) -> Element {
|
|||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "hello world", "hello world", "hello world" }
|
div { "hello world", "hello world", "hello world" }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
rsx! {
|
||||||
|
div {}
|
||||||
|
div {
|
||||||
|
// div {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1 +1,10 @@
|
|||||||
rsx! { div {} }
|
fn ItWorks() {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
div {
|
||||||
|
div {}
|
||||||
|
div {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
cx.render(rsx! {
|
fn ItWroks() {
|
||||||
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right }
|
cx.render(rsx! {
|
||||||
})
|
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right }
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
cx.render(rsx! {
|
fn ItWroks() {
|
||||||
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right }
|
cx.render(rsx! {
|
||||||
})
|
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right }
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in new issue
Block a user