Skip to content

Commit

Permalink
fmt: Fix path formatting issue
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Aug 5, 2024
1 parent 5157d4a commit e48f687
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 82 deletions.
164 changes: 90 additions & 74 deletions crates/rune/src/fmt/format.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::mem::take;

use crate::ast::Kind;
use crate::compile::Result;

Expand Down Expand Up @@ -281,18 +283,21 @@ fn path<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
fn path_generics<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.write(p.expect(K![<])?)?;

let mut last_comma = Remaining::default();
let mut empty = true;
let mut last_comma = Remaining::default();

while let Some(node) = p.try_pump(Path)? {
o.comments(Prefix)?;

if !empty {
last_comma.write(o)?;
o.ws()?;
}

node.parse(|p| path(o, p))?;
last_comma = p.remaining(o, K![,])?;
empty = true;
empty = false;
o.comments(Suffix)?;
}

last_comma.ignore(o)?;
Expand All @@ -311,15 +316,15 @@ fn pat_array<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
let mut empty = true;
let mut last_comma = Remaining::default();

while !matches!(p.peek(), K![']'] | Eof) {
while let Some(node) = p.try_pump(Pat)? {
o.comments(Prefix)?;

if !empty {
last_comma.write(o)?;
o.ws()?;
}

p.expect(Pat)?.parse(|p| pat(o, p))?;
node.parse(|p| pat(o, p))?;
last_comma = p.remaining(o, K![,])?;
empty = false;
o.comments(Suffix)?;
Expand Down Expand Up @@ -347,17 +352,17 @@ fn tuple<'a>(
let mut count = 0usize;
let mut last_comma = Remaining::default();

while p.peek() == kind {
while let Some(node) = p.try_pump(kind)? {
o.comments(Prefix)?;

if count > 0 {
last_comma.write(o)?;
o.ws()?;
}

p.expect(kind)?.parse(|p| parser(o, p))?;
count += 1;
node.parse(|p| parser(o, p))?;
last_comma = p.remaining(o, K![,])?;
count += 1;
o.comments(Suffix)?;
}

Expand Down Expand Up @@ -570,17 +575,10 @@ fn expr_with_kind<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<Kind> {
p.expect(Path)?.parse(|p| path(o, p))?;
}
ExprArray => {
array(o, p)?;
exprs(o, p, K!['['], K![']'])?;
}
ExprTuple => {
let trailing = if let Some(node) = p.try_pump(Path)? {
node.parse(|p| path(o, p))?;
false
} else {
true
};

tuple(o, p, Expr, expr, trailing)?;
tuple(o, p, Expr, expr, true)?;
}
ExprObject => {
expr_object(o, p)?;
Expand All @@ -596,9 +594,9 @@ fn expr_with_kind<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<Kind> {

let mut empty = true;

if !matches!(p.peek(), K![')'] | Eof) {
if let Some(node) = p.try_pump(Expr)? {
o.comments(Prefix)?;
p.pump()?.parse(|p| expr(o, p))?;
node.parse(|p| expr(o, p))?;
o.comments(Suffix)?;
empty = false;
}
Expand Down Expand Up @@ -770,7 +768,7 @@ fn expr_assign<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
Ok(())
}

fn array<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
fn exprs<'a>(o: &mut Output<'a>, p: &mut Stream<'a>, open: Kind, close: Kind) -> Result<()> {
let mut count = 0;
let mut expanded = o.source.is_at_least(p.span(), 80)?;

Expand All @@ -783,49 +781,49 @@ fn array<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
expanded |= matches!(node.kind(), Kind::Comment) || count >= 6;
}

o.write(p.expect(open)?)?;

if expanded {
array_loose(o, p)
exprs_loose(o, p)?;
} else {
array_compact(o, p)
exprs_compact(o, p)?;
}

p.one(close)?.write(o)?;
Ok(())
}

fn array_loose<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.write(p.expect(K!['['])?)?;
fn exprs_loose<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.nl(1)?;
o.indent(1)?;

while !matches!(p.peek(), K![']'] | Eof) {
while let Some(node) = p.try_pump(Expr)? {
o.comments(Line)?;
p.expect(Expr)?.parse(|p| expr(o, p))?;
node.parse(|p| expr(o, p))?;
p.remaining(o, K![,])?.write(o)?;
o.nl(1)?;
}

o.nl(1)?;
o.indent(-1)?;
p.one(K![']'])?.write(o)?;
Ok(())
}

fn array_compact<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.write(p.expect(K!['['])?)?;

fn exprs_compact<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
let mut empty = true;
let mut last_comma = Remaining::default();

while !matches!(p.peek(), K![']'] | Eof) {
while let Some(node) = p.try_pump(Expr)? {
o.comments(Prefix)?;

if !empty {
last_comma.write(o)?;
o.ws()?;
}

o.comments(Line)?;
p.expect(Expr)?.parse(|p| expr(o, p))?;
empty = false;
node.parse(|p| expr(o, p))?;
last_comma = p.remaining(o, K![,])?;
empty = false;
o.comments(Suffix)?;
}

Expand All @@ -835,7 +833,6 @@ fn array_compact<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.comments(Infix)?;
}

p.one(K![']'])?.write(o)?;
Ok(())
}

Expand Down Expand Up @@ -997,7 +994,7 @@ fn expr_select<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
o.indent(1)?;
o.write(open)?;

while !matches!(p.peek(), K!['}'] | Eof) {
while matches!(p.peek(), K![default] | Pat) {
o.nl(1)?;
o.comments(Line)?;

Expand Down Expand Up @@ -1104,8 +1101,8 @@ fn expr_closure<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
}

node.parse(|p| pat(o, p))?;
empty = false;
last_comma = p.remaining(o, K![,])?;
empty = false;
o.comments(Suffix)?;
}

Expand Down Expand Up @@ -1140,33 +1137,73 @@ fn expr_closure<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
}

fn expr_chain<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
let expanded = o.source.is_at_least(p.span(), 60)?;
let expanded = o.source.is_at_least(p.span(), 80)?;

// If the first expression *is* small, and there are no other expressions
// that need indentation in the chain, we can keep it all on one line.
let head = p.pump()?.parse(|p| {
let first = p.span();
expr(o, p)?;
Ok(first)
})?;

p.pump()?.parse(|p| expr(o, p))?;
let tail = 'tail: {
for (n, node) in p.children().enumerate() {
if matches!(node.kind(), ExprCall) {
break 'tail Some((n, node.span()));
}
}

if expanded {
o.indent(1)?;
None
};

let first_is_small = if let Some((_, tail)) = tail {
!o.source.is_at_least(head.join(tail.head()), 80)?
} else {
!o.source.is_at_least(head, 80)?
};

let from;

if expanded && first_is_small {
let mut found = false;
let first = tail.map(|(n, _)| n).unwrap_or_default();

for node in p.children().skip(first.wrapping_add(1)) {
found |= matches!(node.kind(), ExprField | ExprAwait);

if found {
break;
}
}

if found {
from = 0;
} else {
from = first + 1;
}
} else {
from = if expanded { 0 } else { usize::MAX };
}

for node in p.by_ref() {
let mut unindented = true;

for (n, node) in p.by_ref().enumerate() {
if n >= from {
o.indent(isize::from(take(&mut unindented)))?;
o.nl(usize::from(matches!(node.kind(), ExprField | ExprAwait)))?;
}

node.parse(|p| {
match p.kind() {
ExprTry => {
p.one(K![?])?.write(o)?;
}
ExprAwait => {
if expanded {
o.nl(1)?;
}

p.one(K![.])?.write(o)?;
p.one(K![await])?.write(o)?;
}
ExprField => {
if expanded {
o.nl(1)?;
}

p.one(K![.])?.write(o)?;

match p.peek() {
Expand All @@ -1179,28 +1216,7 @@ fn expr_chain<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
}
}
ExprCall => {
o.write(p.expect(K!['('])?)?;

let mut empty = true;

while !matches!(p.peek(), K![')'] | Eof) {
o.comments(Prefix)?;

if !empty {
p.remaining(o, K![,])?.write(o)?;
o.ws()?;
}

p.pump()?.parse(|p| expr(o, p))?;
empty = false;
o.comments(Suffix)?;
}

if empty {
o.comments(Infix)?;
}

p.one(K![')'])?.write(o)?;
exprs(o, p, K!['('], K![')'])?;
}
ExprMacroCall => {
o.write(p.expect(K![!])?)?;
Expand All @@ -1226,7 +1242,7 @@ fn expr_chain<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
})?;
}

if expanded {
if !unindented {
o.indent(-1)?;
}

Expand Down Expand Up @@ -1375,15 +1391,15 @@ fn tuple_body<'a>(o: &mut Output<'a>, p: &mut Stream<'a>) -> Result<()> {
let mut empty = true;
let mut last_comma = Remaining::default();

while let Some(field) = p.try_pump(Field)? {
while let Some(node) = p.try_pump(Field)? {
o.comments(Prefix)?;

if !empty {
last_comma.write(o)?;
o.ws()?;
}

field.parse(|p| o.write(p.pump()?))?;
node.parse(|p| o.write(p.pump()?))?;
last_comma = p.remaining(o, K![,])?;
empty = false;
o.comments(Suffix)?;
Expand Down
9 changes: 8 additions & 1 deletion crates/rune/src/fmt/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ impl<'a> Output<'a> {

/// Indent the output.
pub(super) fn indent(&mut self, indent: isize) -> Result<()> {
self.indent = self.checked_indent(indent)?;
if indent != 0 {
self.indent = self.checked_indent(indent)?;
}

Ok(())
}

Expand All @@ -211,6 +214,10 @@ impl<'a> Output<'a> {
/// This will write any pending line comments which are on the same line as
/// the previously written nodes.
pub(crate) fn nl(&mut self, lines: usize) -> Result<()> {
if lines == 0 {
return Ok(());
}

self.comments_line(true)?;

// If we don't already have line heuristics, adopt the proposed one.
Expand Down
Loading

0 comments on commit e48f687

Please sign in to comment.