Skip to content

Commit

Permalink
feat: non-doc comments within rsx (#4)
Browse files Browse the repository at this point in the history
* support non-doc comments

* cleanup

* fix test

* update changelog

* update changelog

* fix comments in nested macros

* cleanup

* formatting

* cleanup
  • Loading branch information
bram209 authored Jun 29, 2023
1 parent d72e177 commit 0b5747f
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 31 deletions.
12 changes: 10 additions & 2 deletions formatter/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,17 @@ impl<'ast> Visit<'ast> for ViewMacroVisitor<'ast> {
.iter()
.filter(|v| v.line == span_line && v.column < span_start)
.map(|v| v.column)
.min();
.min()
.unwrap_or(
self.ident_stack
.iter()
.rev()
.find(|v| v.column < span_start)
.map(|i| i.column)
.unwrap_or(0),
);

if let Some(view_mac) = ViewMacro::try_parse(ident, node) {
if let Some(view_mac) = ViewMacro::try_parse(Some(ident), node) {
self.macros.push(view_mac);
}
}
Expand Down
4 changes: 3 additions & 1 deletion formatter/src/formatter/attribute.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use rstml::node::{KeyedAttribute, NodeAttribute};
use syn::Expr;
use syn::{spanned::Spanned, Expr};

use crate::{formatter::Formatter, AttributeValueBraceStyle as Braces};

impl Formatter<'_> {
pub fn attribute(&mut self, attribute: &NodeAttribute) {
self.write_comments(attribute.span().start().line - 1);

match attribute {
NodeAttribute::Attribute(k) => self.keyed_attribute(k),
NodeAttribute::Block(b) => self.node_block(b),
Expand Down
20 changes: 18 additions & 2 deletions formatter/src/formatter/expr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use syn::{Block, Expr, ExprBlock, ExprLit, LitStr};
use syn::{spanned::Spanned, Block, Expr, ExprBlock, ExprLit, LitStr};

use crate::{formatter::Formatter, view_macro::ViewMacroFormatter};

Expand Down Expand Up @@ -93,10 +93,26 @@ impl Formatter<'_> {
return;
}

let start_line = expr.span().start().line;
let end_line = expr.span().end().line;

let comments = self
.comments
.iter()
.filter_map(|(line, _comment)| {
let line = *line;
if line >= start_line && line <= end_line {
Some((line, *_comment))
} else {
None
}
})
.collect();

leptosfmt_prettyplease::unparse_expr(
expr,
self.printer,
Some(&ViewMacroFormatter::new(self.settings)),
Some(&ViewMacroFormatter::new(self.settings, comments)),
);
}
}
Expand Down
14 changes: 9 additions & 5 deletions formatter/src/formatter/mac.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use leptosfmt_pretty_printer::Printer;
use proc_macro2::{token_stream, Span, TokenStream, TokenTree};
use rstml::node::Node;
Expand Down Expand Up @@ -44,13 +46,12 @@ impl Formatter<'_> {
cx,
global_class,
nodes,
span,
..
} = view_mac;

let indent = parent_ident
.map(|i| i + self.settings.tab_spaces)
.unwrap_or(span.start().column);
.unwrap_or(0);

self.printer.cbox(indent as isize);

Expand Down Expand Up @@ -121,9 +122,12 @@ fn extract_global_class(
Some((tokens, global_class))
}

pub fn format_macro(mac: &ViewMacro, settings: &FormatterSettings) -> String {
pub fn format_macro(mac: &ViewMacro, settings: &FormatterSettings, source: Option<&str>) -> String {
let mut printer = Printer::new(settings.into());
let mut formatter = Formatter::new(*settings, &mut printer);
let mut formatter = match source {
Some(source) => Formatter::with_source(*settings, &mut printer, source),
None => Formatter::new(*settings, &mut printer, HashMap::new()),
};

formatter.view_macro(mac);
printer.eof()
Expand All @@ -139,7 +143,7 @@ mod tests {
macro_rules! view_macro {
($($tt:tt)*) => {{
let mac: Macro = syn::parse2(quote! { $($tt)* }).unwrap();
format_macro(&ViewMacro::try_parse(None, &mac).unwrap(), &Default::default())
format_macro(&ViewMacro::try_parse(None, &mac).unwrap(), &Default::default(), None)
}}
}

Expand Down
50 changes: 48 additions & 2 deletions formatter/src/formatter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use leptosfmt_pretty_printer::{Printer, PrinterSettings};

mod attribute;
Expand Down Expand Up @@ -56,10 +58,54 @@ impl From<&FormatterSettings> for PrinterSettings {
pub struct Formatter<'a> {
pub printer: &'a mut leptosfmt_pretty_printer::Printer,
pub settings: FormatterSettings,
last_line_check: Option<usize>,
comments: HashMap<usize, &'a str>,
}

impl<'a> Formatter<'a> {
pub fn new(settings: FormatterSettings, printer: &'a mut Printer) -> Self {
Self { printer, settings }
pub fn new(
settings: FormatterSettings,
printer: &'a mut Printer,
comments: HashMap<usize, &'a str>,
) -> Self {
Self {
printer,
settings,
comments,
last_line_check: None,
}
}

pub fn with_source(
settings: FormatterSettings,
printer: &'a mut Printer,
source: &'a str,
) -> Self {
Self {
printer,
settings,
comments: source
.lines()
.enumerate()
.filter_map(|(i, l)| l.split("//").nth(1).map(|l| (i, l)))
.collect(),
last_line_check: None,
}
}

pub fn write_comments(&mut self, line_index: usize) {
let last = self.last_line_check.unwrap_or(0);

self.last_line_check = Some(line_index);

let comments = (last..=line_index)
.filter_map(|l| self.comments.remove(&l))
.peekable();

for comment in comments {
self.printer.word("//");
self.printer.word(comment.to_string());
self.printer.hardbreak();
}
}
}
6 changes: 4 additions & 2 deletions formatter/src/formatter/node.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use rstml::node::{Node, NodeBlock, NodeComment, NodeDoctype, NodeName, NodeText, RawText};
use syn::{spanned::Spanned};
use syn::spanned::Spanned;

use crate::formatter::Formatter;

impl Formatter<'_> {
pub fn node(&mut self, node: &Node) {
self.write_comments(node.span().start().line - 1);

match node {
Node::Element(ele) => self.element(ele),
Node::Text(text) => self.node_text(text),
Expand All @@ -13,7 +15,7 @@ impl Formatter<'_> {
Node::Doctype(doctype) => self.doctype(doctype),
Node::Block(block) => self.node_block(block),
Node::Fragment(frag) => self.fragment(frag),
}
};
}

pub fn comment(&mut self, comment: &NodeComment) {
Expand Down
115 changes: 105 additions & 10 deletions formatter/src/source_file.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{io, ops::Range};

use crop::Rope;

use syn::spanned::Spanned;
use thiserror::Error;

Expand Down Expand Up @@ -38,16 +39,16 @@ fn format_source<'a>(
macros: Vec<ViewMacro<'a>>,
settings: FormatterSettings,
) -> Result<String, FormatError> {
let mut source: Rope = source.parse().unwrap();
let mut rope: Rope = source.parse().unwrap();
let mut edits = Vec::new();

for view_mac in macros {
let mac = view_mac.inner();
let start = mac.path.span().start();
let end = mac.delimiter.span().close().end();
let start_byte = line_column_to_byte(&source, start);
let end_byte = line_column_to_byte(&source, end);
let new_text = format_macro(&view_mac, &settings);
let start_byte = line_column_to_byte(&rope, start);
let end_byte = line_column_to_byte(&rope, end);
let new_text = format_macro(&view_mac, &settings, Some(source));

edits.push(TextEdit {
range: start_byte..end_byte,
Expand All @@ -61,14 +62,14 @@ fn format_source<'a>(
let end = edit.range.end;
let new_text = edit.new_text;

source.replace(
rope.replace(
(start as isize + last_offset) as usize..(end as isize + last_offset) as usize,
&new_text,
);
last_offset += new_text.len() as isize - (end as isize - start as isize);
}

Ok(source.to_string())
Ok(rope.to_string())
}

fn line_column_to_byte(source: &Rope, point: proc_macro2::LineColumn) -> usize {
Expand Down Expand Up @@ -101,6 +102,58 @@ mod tests {
</div>
};
}
"###);
}

#[test]
fn with_comments() {
let source = indoc! {r#"
fn main() {
view! { cx ,
// Top level comment
<div>
// This is one beautiful message
<span>"hello"</span> // at the end of the line
<div>// at the end of the line
// double
// comments
<span>"hello"</span> </div>
<For
// a function that returns the items we're iterating over; a signal is fine
each= move || {errors.clone().into_iter().enumerate()}
// a unique key for each item as a reference
key=|(index, _error)| *index // yeah
/>
</div> };
}
"#};

let result = format_file_source(source, Default::default()).unwrap();
insta::assert_snapshot!(result, @r###"
fn main() {
view! { cx,
// Top level comment
<div>
// This is one beautiful message
// at the end of the line
<span>"hello"</span>
// at the end of the line
<div>
// double
// comments
<span>"hello"</span>
</div>
<For
// a function that returns the items we're iterating over; a signal is fine
each=move || { errors.clone().into_iter().enumerate() }
// a unique key for each item as a reference
// yeah
key=|(index, _error)| *index
/>
</div>
};
}
"###);
}

Expand All @@ -115,8 +168,8 @@ mod tests {
<span>{a}</span>
}
}</span></div> };
}
}</span></div> };
}
"#};

let result = format_file_source(source, Default::default()).unwrap();
Expand All @@ -131,8 +184,50 @@ mod tests {
}
</span>
</div>
};
}
};
}
"###);
}

#[test]
fn nested_with_comments() {
let source = indoc! {r#"
fn main() {
view! { cx ,
// parent div
<div>
// parent span
<span>{
let a = 12;
view! { cx,
// wow, a span
<span>{a}</span>
}
}</span></div> };
}
"#};

let result = format_file_source(source, Default::default()).unwrap();
insta::assert_snapshot!(result, @r###"
fn main() {
view! { cx,
// parent div
<div>
// parent span
<span>
{
let a = 12;
view! { cx,
// wow, a span
<span>{a}</span>
}
}
</span>
</div>
};
}
"###);
}

Expand Down
4 changes: 3 additions & 1 deletion formatter/src/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use leptosfmt_pretty_printer::Printer;
use rstml::node::{Node, NodeAttribute, NodeComment, NodeDoctype, NodeElement, NodeFragment};

Expand Down Expand Up @@ -105,7 +107,7 @@ pub fn get_doctype(mut nodes: Vec<Node>, doctype_index: usize) -> NodeDoctype {

pub fn format_with(settings: FormatterSettings, run: impl FnOnce(&mut Formatter)) -> String {
let mut printer = Printer::new((&settings).into());
let mut formatter = Formatter::new(settings, &mut printer);
let mut formatter = Formatter::new(settings, &mut printer, HashMap::new());
run(&mut formatter);
printer.eof()
}
Loading

0 comments on commit 0b5747f

Please sign in to comment.