Fix: #2604, Fix: #2240, Fix: #2341, Fix #1355 - Better error handling and and spaces handling in autofmt (#2736)
* add new autofmt sample * Feat: implement rustfmt::skip support for rsx * generally improve error handling with better expect messages * wip: nested rsx formatting and expression formatting * nested rsx formatting works * collapse autofmt crate * cast indent through macros * use proper whitespace * no more eating comments! * Use proper error handling
This commit is contained in:
1 parent
ef0202f999
commit
828cc502f1
47 files changed
+1621
-1055
No files matched your search
+35
-32
@@ -4,14 +4,13 @@
|
||||
|
||||
use crate::writer::*;
|
||||
use dioxus_rsx::{BodyNode, CallBody};
|
||||
use proc_macro2::LineColumn;
|
||||
use syn::{parse::Parser, ExprMacro};
|
||||
use proc_macro2::{LineColumn, Span};
|
||||
use syn::parse::Parser;
|
||||
|
||||
mod buffer;
|
||||
mod collect_macros;
|
||||
mod indent;
|
||||
mod prettier_please;
|
||||
mod rsx_block;
|
||||
mod writer;
|
||||
|
||||
pub use indent::{IndentOptions, IndentType};
|
||||
@@ -37,6 +36,16 @@ pub struct FormattedBlock {
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
/// Format a file into a list of `FormattedBlock`s to be applied by an IDE for autoformatting.
|
||||
///
|
||||
/// It accepts
|
||||
#[deprecated(note = "Use try_fmt_file instead - this function panics on error.")]
|
||||
pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
let parsed =
|
||||
syn::parse_file(contents).expect("fmt_file should only be called on valid syn::File files");
|
||||
try_fmt_file(contents, &parsed, indent).expect("Failed to format file")
|
||||
}
|
||||
|
||||
/// Format a file into a list of `FormattedBlock`s to be applied by an IDE for autoformatting.
|
||||
///
|
||||
/// This function expects a complete file, not just a block of code. To format individual rsx! blocks, use fmt_block instead.
|
||||
@@ -45,19 +54,27 @@ pub struct FormattedBlock {
|
||||
/// back to the file precisely.
|
||||
///
|
||||
/// Nested blocks of RSX will be handled automatically
|
||||
pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
///
|
||||
/// This returns an error if the rsx itself is invalid.
|
||||
///
|
||||
/// Will early return if any of the expressions are not complete. Even though we *could* return the
|
||||
/// expressions, eventually we'll want to pass off expression formatting to rustfmt which will reject
|
||||
/// those.
|
||||
pub fn try_fmt_file(
|
||||
contents: &str,
|
||||
parsed: &syn::File,
|
||||
indent: IndentOptions,
|
||||
) -> syn::Result<Vec<FormattedBlock>> {
|
||||
let mut formatted_blocks = Vec::new();
|
||||
|
||||
let parsed = syn::parse_file(contents).unwrap();
|
||||
let macros = collect_macros::collect_from_file(&parsed);
|
||||
let macros = collect_macros::collect_from_file(parsed);
|
||||
|
||||
// No macros, no work to do
|
||||
if macros.is_empty() {
|
||||
return formatted_blocks;
|
||||
return Ok(formatted_blocks);
|
||||
}
|
||||
|
||||
let mut writer = Writer::new(contents);
|
||||
writer.out.indent = indent;
|
||||
let mut writer = Writer::new(contents, indent);
|
||||
|
||||
// Don't parse nested macros
|
||||
let mut end_span = LineColumn { column: 0, line: 0 };
|
||||
@@ -69,14 +86,7 @@ pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let body = match item.parse_body_with(CallBody::parse_strict) {
|
||||
Ok(v) => v,
|
||||
//there is aparsing error, we give up and don't format the rsx
|
||||
Err(e) => {
|
||||
eprintln!("Error while parsing rsx {:?} ", e);
|
||||
return formatted_blocks;
|
||||
}
|
||||
};
|
||||
let body = item.parse_body_with(CallBody::parse_strict)?;
|
||||
|
||||
let rsx_start = macro_path.span().start();
|
||||
|
||||
@@ -86,15 +96,16 @@ pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
.count_indents(writer.src[rsx_start.line - 1]);
|
||||
|
||||
// TESTME
|
||||
// If we fail to parse this macro then we have no choice to give up and return what we've got
|
||||
// Writing *should* not fail but it's possible that it does
|
||||
if writer.write_rsx_call(&body.body).is_err() {
|
||||
return formatted_blocks;
|
||||
let span = writer.invalid_exprs.pop().unwrap_or_else(Span::call_site);
|
||||
return Err(syn::Error::new(span, "Failed emit valid rsx - likely due to partially complete expressions in the rsx! macro"));
|
||||
}
|
||||
|
||||
// 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();
|
||||
_ = writer.out.new_line();
|
||||
_ = writer.out.tab();
|
||||
}
|
||||
|
||||
let span = item.delimiter.span().join();
|
||||
@@ -124,7 +135,7 @@ pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
});
|
||||
}
|
||||
|
||||
formatted_blocks
|
||||
Ok(formatted_blocks)
|
||||
}
|
||||
|
||||
/// Write a Callbody (the rsx block) to a string
|
||||
@@ -132,14 +143,7 @@ pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||
/// If the tokens can't be formatted, this returns None. This is usually due to an incomplete expression
|
||||
/// that passed partial expansion but failed to parse.
|
||||
pub fn write_block_out(body: &CallBody) -> Option<String> {
|
||||
let mut buf = Writer::new("");
|
||||
buf.write_rsx_call(&body.body).ok()?;
|
||||
buf.consume()
|
||||
}
|
||||
|
||||
pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option<String> {
|
||||
let body = CallBody::parse_strict.parse2(expr.mac.tokens).unwrap();
|
||||
let mut buf = Writer::new(raw);
|
||||
let mut buf = Writer::new("", IndentOptions::default());
|
||||
buf.write_rsx_call(&body.body).ok()?;
|
||||
buf.consume()
|
||||
}
|
||||
@@ -147,8 +151,7 @@ pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option<String> {
|
||||
pub fn fmt_block(block: &str, indent_level: usize, indent: IndentOptions) -> Option<String> {
|
||||
let body = CallBody::parse_strict.parse_str(block).unwrap();
|
||||
|
||||
let mut buf = Writer::new(block);
|
||||
buf.out.indent = indent;
|
||||
let mut buf = Writer::new(block, indent);
|
||||
buf.out.indent_level = indent_level;
|
||||
buf.write_rsx_call(&body.body).ok()?;
|
||||
|
||||
|
||||
Reference in new issue
Block a user