feat: ensure parsing works with right indicies

This commit is contained in:
Jonathan Kelley 2022-04-24 19:38:28 -04:00
parent f9d9f85924
commit 4fa909e864
4 changed files with 128 additions and 1 deletions

View file

@ -60,6 +60,7 @@ members = [
"packages/tui",
"packages/liveview",
"packages/rsx",
"packages/autofmt",
]
[dev-dependencies]

View file

@ -10,3 +10,5 @@ proc-macro2 = { version = "1.0.6" }
quote = "1.0"
syn = { version = "1.0.11", features = ["full", "extra-traits"] }
dioxus-rsx = { path = "../rsx" }
triple_accel = "0.4.0"
serde = { version = "1.0.136", features = ["derive"] }

View file

@ -1,9 +1,74 @@
//! pretty printer for rsx!
use dioxus_rsx::*;
use proc_macro2::TokenStream as TokenStream2;
use quote::ToTokens;
use std::fmt::{self, Write};
use std::{
fmt::{self, Write},
ptr::NonNull,
};
use syn::{
buffer::TokenBuffer,
parse::{ParseBuffer, ParseStream},
};
use triple_accel::{levenshtein_search, Match};
mod prettyplease;
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq, Hash)]
pub struct ForamttedBlock {
pub formatted: String,
pub start: usize,
pub end: usize,
}
/*
TODO: nested rsx! calls
*/
pub fn formmat_document(contents: &str) -> Vec<ForamttedBlock> {
let mut matches = levenshtein_search(b"rsx! {", contents.as_bytes()).peekable();
let mut cur_match: Option<Match> = None;
let mut formatted_blocks = Vec::new();
while let Some(item) = matches.next() {
let Match { start, end, k } = item;
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) {
let sub_string = &contents[end..bracket_end + end - 1];
if let Some(new) = fmt_block(sub_string) {
if !new.is_empty() {
formatted_blocks.push(ForamttedBlock {
formatted: new,
start: end,
end: end + bracket_end - 1,
});
}
}
}
}
formatted_blocks
}
pub fn fmt_block(block: &str) -> Option<String> {
let parsed: CallBody = syn::parse_str(block).ok()?;
@ -175,3 +240,24 @@ pub fn write_tabs(f: &mut dyn Write, num: usize) -> std::fmt::Result {
}
Ok(())
}
fn find_bracket_end(contents: &str) -> Option<usize> {
let mut depth = 0;
let mut i = 0;
for c in contents.chars() {
if c == '{' {
depth += 1;
} else if c == '}' {
depth -= 1;
}
if depth == 0 {
return Some(i);
}
i += 1;
}
None
}

View file

@ -93,3 +93,41 @@ fn formats_component_man_props() {
print!("{formatted}");
}
#[test]
fn formats_document() {
let block = r#"
rsx!{
Component {
adsasd: "asd", // this is a comment
onclick: move |_| {
let blah = 120;
},
}
}
"#;
let formatted = formmat_document(block);
print!("{formatted:?}");
}
#[test]
fn formats_valid_rust_src() {
let src = r#"
//
rsx! {
div {}
div {
h3 {"asd"
}
}
}
"#;
let formatted = formmat_document(src);
println!("{formatted:?}");
}