Skip to content

Commit

Permalink
- fixed issue #17
Browse files Browse the repository at this point in the history
- removed some redundant checks for breaking
  • Loading branch information
its-the-shrimp committed Feb 25, 2024
1 parent 6e049cd commit e4de4e8
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 106 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ anyhow = "1"
regen-tests = [] # solely for testing

[lints.clippy]
unit_arg = "allow"

single_char_lifetime_names = "warn"
deref_by_slicing = "warn"
derive_partial_eq_without_eq = "warn"
Expand Down
138 changes: 60 additions & 78 deletions src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn add_last_line_len(prev: usize, new: &str) -> usize {
enum Comment<'src> {
/// the initial `//` and the newline are not included
Line(&'src str),
/// the `/*` and `*/` are not included
/// the `/*` and `*/` are included
Multi(&'src str),
}

Expand Down Expand Up @@ -116,16 +116,6 @@ pub struct Location {
pub end: LineColumn,
}

impl Location {
pub fn from_slice<T: Located>(src: impl AsRef<[T]>) -> Option<Self> {
match src.as_ref() {
[first, .., last] => Some(Self { start: first.start(), end: last.end() }),
[only] => Some(only.loc()),
[] => None,
}
}
}

/// Represents an object that has an associated location in the source
pub trait Located {
fn start(&self) -> LineColumn;
Expand Down Expand Up @@ -204,16 +194,6 @@ enum FmtToken<'fmt, 'src> {
Block(FmtBlock<'fmt, 'src>),
}

impl FmtToken<'_, '_> {
fn is_broken(&self) -> bool {
match self {
FmtToken::Text(text) => text.bytes().any(|b| b == b'\n'),
FmtToken::LineComment(_) | FmtToken::Sep(_) => false,
FmtToken::Block(block) => block.spacing.is_none(),
}
}
}

#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
pub struct Spacing {
pub before: bool,
Expand Down Expand Up @@ -277,21 +257,40 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
}
}

fn add_raw_text(&mut self, text: &'src str) {
self.tokens.push(FmtToken::Text(text));
self.width += text.len();
}
// Functions for adding all the token kinds directly; not to be exposed

fn add_raw_space(&mut self) {
self.tokens.push(FmtToken::Text(" "));
self.width += 1;
fn add_raw_text(&mut self, text: &'src str) {
match text.bytes().filter(|&b| b == b'\n').count() {
0 => self.width += text.len(),
_ => self.spacing = None,
}
self.tokens.push(FmtToken::Text(text))
}

fn add_line_comment(&mut self, comment: &'src str) {
self.tokens.push(FmtToken::LineComment(comment));
self.width += comment.len() + 4;
self.tokens.push(FmtToken::LineComment(comment))
}

fn add_raw_sep(&mut self, n_newlines: u8) {
self.width += self.spacing.map_or(false, |s| s.between) as usize;
self.tokens.push(FmtToken::Sep(n_newlines))
}

fn add_raw_block(&mut self, mut block: FmtBlock<'fmt, 'src>) {
if matches!(block.tokens.last(), Some(FmtToken::Sep(_))) {
block.tokens.pop();
}
match block.spacing {
Some(_) => self.width += block.width,
None => self.spacing = None,
}
self.cur_offset = block.cur_offset;
self.tokens.push(FmtToken::Block(block))
}

// Utilities

fn add_comments_with_sep(
&mut self,
ctx: &FormatCtx<'_, 'src>,
Expand Down Expand Up @@ -328,7 +327,7 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
}

pub fn add_space(&mut self, ctx: &FormatCtx<'_, 'src>, at: LineColumn) -> Result {
self.add_raw_space();
self.add_raw_text(" ");
self.add_comments(ctx, at)
}

Expand All @@ -344,11 +343,6 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
Ok(())
}

fn add_raw_sep(&mut self, n_newlines: u8) {
self.tokens.push(FmtToken::Sep(n_newlines));
self.width += self.spacing.map_or(false, |s| s.between) as usize;
}

pub fn add_sep(&mut self, ctx: &FormatCtx<'_, 'src>, at: LineColumn) -> Result {
self.add_raw_sep(1);
self.add_comments_with_sep(ctx, at, |b| b.add_raw_sep(1))
Expand Down Expand Up @@ -388,15 +382,7 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
) -> R {
let mut block = Self::new(self.tokens.bump(), spacing, chaining, self.cur_offset);
let res = f(&mut block);
if matches!(block.tokens.last(), Some(FmtToken::Sep(_))) {
block.tokens.pop();
}
match spacing {
Some(_) => self.width += block.width,
None => self.spacing = None,
}
self.cur_offset = block.cur_offset;
self.tokens.push(FmtToken::Block(block));
self.add_raw_block(block);
res
}

Expand Down Expand Up @@ -467,16 +453,19 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
Ok(())
}

pub fn add_source_punctuated(
pub fn add_source_punctuated<T, P>(
&mut self,
ctx: &FormatCtx<'_, 'src>,
iter: &Punctuated<impl Located, impl Located>,
) -> Result {
iter: &Punctuated<T, P>,
) -> Result
where
for<'any> &'any T: Located,
for<'any> &'any P: Located,
{
for pair in iter.pairs() {
self.add_source(ctx, pair.value().loc())?;
if let Some(punct) = pair.punct() {
self.add_source(ctx, punct.loc())?;
}
let (value, punct) = pair.into_tuple();
self.add_source(ctx, value)?;
self.add_source_iter(ctx, punct)?;
}
Ok(())
}
Expand Down Expand Up @@ -561,11 +550,6 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
return true;
}

if self.tokens.iter().any(FmtToken::is_broken) {
self.force_breaking(ctx, indent);
return true;
}

false
}

Expand All @@ -579,28 +563,26 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {

let space_if = |c| if c { Sep::Space } else { Sep::None };

fn print_token(token: &FmtToken, indent: usize, sep: Sep, cfg: &Config, out: &mut String) {
match token {
FmtToken::Text(text) => out.push_str(text),
FmtToken::LineComment(comment) => {
if let Sep::Newline = sep {
out.push_str("//");
out.push_str(comment);
print_break(out, 1, indent)
} else {
out.push_str("/*");
out.push_str(comment);
out.push_str("*/")
}
let print_token = |token: &FmtToken, out: &mut String, indent, sep| match token {
FmtToken::Text(text) => out.push_str(text),
FmtToken::LineComment(comment) => {
if let Sep::Newline = sep {
out.push_str("//");
out.push_str(comment);
print_break(out, 1, indent)
} else {
out.push_str("/*");
out.push_str(comment);
out.push_str("*/")
}
FmtToken::Sep(n_newlines) => match sep {
Sep::None => (),
Sep::Space => out.push(' '),
Sep::Newline => print_break(out, *n_newlines, indent),
},
FmtToken::Block(block) => block.print(indent, cfg, out),
}
}
FmtToken::Sep(n_newlines) => match sep {
Sep::None => (),
Sep::Space => out.push(' '),
Sep::Newline => print_break(out, *n_newlines, indent),
},
FmtToken::Block(block) => block.print(indent, cfg, out),
};

if self.tokens.is_empty() {
if self.spacing.map_or(false, |s| s.before && s.after) {
Expand All @@ -611,7 +593,7 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
out.push(' ');
}
for token in &self.tokens {
print_token(token, indent, space_if(spacing.between), cfg, out);
print_token(token, out, indent, space_if(spacing.between));
}
if spacing.after {
out.push(' ');
Expand All @@ -620,7 +602,7 @@ impl<'fmt, 'src> FmtBlock<'fmt, 'src> {
let new_indent = indent + cfg.tab_spaces;
print_break(out, 1, new_indent);
for token in &self.tokens {
print_token(token, new_indent, Sep::Newline, cfg, out);
print_token(token, out, new_indent, Sep::Newline);
}
if let Some(FmtToken::LineComment(_)) = self.tokens.last() {
out.truncate(out.len() - 4)
Expand Down
55 changes: 29 additions & 26 deletions src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ pub struct HtmlProp {
pub enum HtmlPropKind {
Shortcut(Brace, Punctuated<AnyIdent, Token![-]>),
Literal(Punctuated<AnyIdent, Token![-]>, Token![=], Lit),
Expr(Punctuated<AnyIdent, Token![-]>, Token![=], Block),
Block(Punctuated<AnyIdent, Token![-]>, Token![=], Block),
}

pub struct HtmlIf {
Expand Down Expand Up @@ -406,7 +406,7 @@ impl Parse for HtmlProp {
let name = Punctuated::parse_separated_nonempty(input)?;
let eq_token = input.parse()?;
if input.peek(Brace) {
HtmlPropKind::Expr(name, eq_token, input.parse()?)
HtmlPropKind::Block(name, eq_token, input.parse()?)
} else {
HtmlPropKind::Literal(name, eq_token, input.parse()?)
}
Expand Down Expand Up @@ -740,11 +740,10 @@ impl<'src> Format<'src> for HtmlLiteralElement {
element_children_spacing(ctx, &self.children),
ChainingRule::End,
|block, ctx| {
for child in &self.children {
Ok(for child in &self.children {
child.format(block, ctx)?;
block.add_sep(ctx, child.end())?;
}
Ok(())
})
},
)?;
block.add_source(ctx, self.div_token)?;
Expand All @@ -759,9 +758,7 @@ impl<'src> Format<'src> for HtmlLiteralElement {

impl<'src> Format<'src> for HtmlProp {
fn format(&self, block: &mut FmtBlock<'_, 'src>, ctx: &mut FormatCtx<'_, 'src>) -> Result {
if let Some(tilde) = &self.access_spec {
block.add_source(ctx, tilde)?;
}
block.add_source_iter(ctx, self.access_spec)?;
match &self.kind {
HtmlPropKind::Shortcut(brace, name) => {
block.add_source(ctx, brace.span.open())?;
Expand All @@ -773,33 +770,39 @@ impl<'src> Format<'src> for HtmlProp {
block.add_source(ctx, eq)?;
block.add_source(ctx, lit)
}
HtmlPropKind::Expr(name, eq, expr) => {
if ctx.config.yew.use_prop_init_shorthand
&& name.len() == 1
&& matches!(&*expr.stmts, [Stmt::Expr(Expr::Path(p), None)]
if p.path.is_ident(&**name.first().context("prop name is empty")?))
HtmlPropKind::Block(name, eq, expr) => match &*expr.stmts {
[Stmt::Expr(Expr::Path(p), None)]
if ctx.config.yew.use_prop_init_shorthand
&& name.len() == 1
&& p.path.is_ident(&**name.first().context("prop name is empty")?) =>
{
return expr.format(block, ctx);
expr.format(block, ctx)
}

block.add_source_punctuated(ctx, name)?;
block.add_source(ctx, eq)?;
if ctx.config.yew.unwrap_literal_prop_values
&& matches!(&*expr.stmts, [Stmt::Expr(Expr::Lit(_), None)])
{
block.add_source_iter(ctx, Location::from_slice(&expr.stmts))
} else {
[Stmt::Expr(Expr::Lit(l), None)] if ctx.config.yew.unwrap_literal_prop_values => {
block.add_source_punctuated(ctx, name)?;
block.add_source(ctx, eq)?;
block.add_source(ctx, l)
}
_ => {
block.add_source_punctuated(ctx, name)?;
block.add_source(ctx, eq)?;
expr.format(block, ctx)
}
}
},
}
}
}

impl<'src> Format<'src> for Block {
fn format(&self, block: &mut FmtBlock<'_, 'src>, ctx: &mut FormatCtx<'_, 'src>) -> Result {
block.add_source(ctx, self.brace_token.span.open())?;
block.add_source_iter(ctx, Location::from_slice(&self.stmts))?;
match &*self.stmts {
[] => (),
[only] => block.add_source(ctx, only)?,
[first, .., last] => {
block.add_source(ctx, Location { start: first.start(), end: last.end() })?
}
}
block.add_source(ctx, self.brace_token.span.close())
}
}
Expand Down Expand Up @@ -1082,7 +1085,7 @@ impl Located for HtmlProp {

match &self.kind {
HtmlPropKind::Shortcut(brace, _) => brace.span.open().start(),
HtmlPropKind::Literal(name, ..) | HtmlPropKind::Expr(name, ..) => unsafe {
HtmlPropKind::Literal(name, ..) | HtmlPropKind::Block(name, ..) => unsafe {
// Safety: the name of the prop is guaranteed to be non-empty by
// `Punctuated::parse_terminated(_nonempty)`
name.first().unwrap_unchecked().span().start()
Expand All @@ -1094,7 +1097,7 @@ impl Located for HtmlProp {
match &self.kind {
HtmlPropKind::Shortcut(brace, _) => brace.span.close().end(),
HtmlPropKind::Literal(_, _, lit) => lit.span().end(),
HtmlPropKind::Expr(_, _, expr) => expr.brace_token.span.close().end(),
HtmlPropKind::Block(_, _, expr) => expr.brace_token.span.close().end(),
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ fn issue_16() {
cmp("tests/samples/issue_16")
}

#[test]
fn issue_17() {
cmp("tests/samples/issue_17")
}

#[test]
fn issue_2() {
cmp("tests/samples/issue_2")
Expand Down
4 changes: 3 additions & 1 deletion tests/samples/block_in_prop/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ fn Comp() -> Html {
html!(<div id={


let id = "idk"; id} />)
let id = "idk"; id} />);
html!(<div id={let id = "one line
another line"; id} />)
}
8 changes: 7 additions & 1 deletion tests/samples/block_in_prop/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@ use yew::prelude::*;

#[function_component]
fn Comp() -> Html {
html!(<div id={let id = "idk"; id} />)
html!(<div id={let id = "idk"; id} />);
html!(
<div
id={let id = "one line
another line"; id}
/>
)
}
Loading

0 comments on commit e4de4e8

Please sign in to comment.