Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Switch pretty printer to block-based indentation #93155

Merged
merged 4 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 49 additions & 20 deletions compiler/rustc_ast_pretty/src/pp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ pub enum Breaks {
Inconsistent,
}

#[derive(Clone, Copy)]
enum IndentStyle {
/// Vertically aligned under whatever column this block begins at.
///
/// fn demo(arg1: usize,
/// arg2: usize);
Visual,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason behind retaining both modes? Seems like potentially unnecessary maintenance burden.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used by trailing block comments, which align visually under the /*. I would be very happy to delete that test and revert 269b5a4.

fn f() {} /*
The next line should not be indented.

/// Indented relative to the indentation level of the previous line.
///
/// fn demo(
/// arg1: usize,
/// arg2: usize,
/// );
Block { offset: isize },
}

#[derive(Clone, Copy)]
pub struct BreakToken {
offset: isize,
Expand All @@ -154,7 +170,7 @@ pub struct BreakToken {

#[derive(Clone, Copy)]
pub struct BeginToken {
offset: isize,
indent: IndentStyle,
breaks: Breaks,
}

Expand All @@ -178,7 +194,7 @@ impl Token {
#[derive(Copy, Clone)]
enum PrintFrame {
Fits,
Broken { offset: isize, breaks: Breaks },
Broken { indent: usize, breaks: Breaks },
}

const SIZE_INFINITY: isize = 0xffff;
Expand All @@ -204,6 +220,8 @@ pub struct Printer {
scan_stack: VecDeque<usize>,
/// Stack of blocks-in-progress being flushed by print
print_stack: Vec<PrintFrame>,
/// Level of indentation of current line
indent: usize,
/// Buffered indentation to avoid writing trailing whitespace
pending_indentation: isize,
/// The token most recently popped from the left boundary of the
Expand All @@ -229,6 +247,7 @@ impl Printer {
right_total: 0,
scan_stack: VecDeque::new(),
print_stack: Vec::new(),
indent: 0,
pending_indentation: 0,
last_printed: None,
}
Expand Down Expand Up @@ -368,38 +387,41 @@ impl Printer {
*self
.print_stack
.last()
.unwrap_or(&PrintFrame::Broken { offset: 0, breaks: Breaks::Inconsistent })
.unwrap_or(&PrintFrame::Broken { indent: 0, breaks: Breaks::Inconsistent })
}

fn print_begin(&mut self, token: BeginToken, size: isize) {
if size > self.space {
let col = self.margin - self.space + token.offset;
self.print_stack.push(PrintFrame::Broken { offset: col, breaks: token.breaks });
self.print_stack.push(PrintFrame::Broken { indent: self.indent, breaks: token.breaks });
self.indent = match token.indent {
IndentStyle::Block { offset } => (self.indent as isize + offset) as usize,
IndentStyle::Visual => (self.margin - self.space) as usize,
};
} else {
self.print_stack.push(PrintFrame::Fits);
}
}

fn print_end(&mut self) {
self.print_stack.pop().unwrap();
if let PrintFrame::Broken { indent, .. } = self.print_stack.pop().unwrap() {
self.indent = indent;
}
}

fn print_break(&mut self, token: BreakToken, size: isize) {
let break_offset =
match self.get_top() {
PrintFrame::Fits => None,
PrintFrame::Broken { offset, breaks: Breaks::Consistent } => Some(offset),
PrintFrame::Broken { offset, breaks: Breaks::Inconsistent } => {
if size > self.space { Some(offset) } else { None }
}
};
if let Some(offset) = break_offset {
self.out.push('\n');
self.pending_indentation = offset + token.offset;
self.space = self.margin - (offset + token.offset);
} else {
let fits = match self.get_top() {
PrintFrame::Fits => true,
PrintFrame::Broken { breaks: Breaks::Consistent, .. } => false,
PrintFrame::Broken { breaks: Breaks::Inconsistent, .. } => size <= self.space,
};
if fits {
self.pending_indentation += token.blank_space;
self.space -= token.blank_space;
} else {
self.out.push('\n');
let indent = self.indent as isize + token.offset;
self.pending_indentation = indent;
self.space = self.margin - indent;
}
}

Expand All @@ -422,7 +444,10 @@ impl Printer {

/// "raw box"
pub fn rbox(&mut self, indent: usize, breaks: Breaks) {
self.scan_begin(BeginToken { offset: indent as isize, breaks })
self.scan_begin(BeginToken {
indent: IndentStyle::Block { offset: indent as isize },
breaks,
})
}

/// Inconsistent breaking box
Expand All @@ -435,6 +460,10 @@ impl Printer {
self.rbox(indent, Breaks::Consistent)
}

pub fn visual_align(&mut self) {
self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent });
}

pub fn break_offset(&mut self, n: usize, off: isize) {
self.scan_break(BreakToken { offset: off, blank_space: n as isize })
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.word(cmnt.lines[0].clone());
self.hardbreak()
} else {
self.ibox(0);
self.visual_align();
for line in &cmnt.lines {
if !line.is_empty() {
self.word(line.clone());
Expand Down Expand Up @@ -655,7 +655,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
// Outer-box is consistent.
self.cbox(INDENT_UNIT);
// Head-box is inconsistent.
self.ibox(w.len() + 1);
self.ibox(0);
// Keyword that starts the head.
if !w.is_empty() {
self.word_nbsp(w);
Expand Down
24 changes: 16 additions & 8 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,9 @@ impl<'a> State<'a> {
self.print_ident(label.ident);
self.word_space(":");
}
self.head("while");
self.cbox(0);
self.ibox(0);
self.word_nbsp("while");
self.print_expr_as_cond(test);
self.space();
self.print_block_with_attrs(blk, attrs);
Expand All @@ -330,7 +332,9 @@ impl<'a> State<'a> {
self.print_ident(label.ident);
self.word_space(":");
}
self.head("for");
self.cbox(0);
self.ibox(0);
self.word_nbsp("for");
self.print_pat(pat);
self.space();
self.word_space("in");
Expand All @@ -343,12 +347,14 @@ impl<'a> State<'a> {
self.print_ident(label.ident);
self.word_space(":");
}
self.head("loop");
self.cbox(0);
self.ibox(0);
self.word_nbsp("loop");
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Match(ref expr, ref arms) => {
self.cbox(INDENT_UNIT);
self.ibox(INDENT_UNIT);
self.cbox(0);
self.ibox(0);
self.word_nbsp("match");
self.print_expr_as_cond(expr);
self.space();
Expand Down Expand Up @@ -388,7 +394,7 @@ impl<'a> State<'a> {
self.word_space(":");
}
// containing cbox, will be closed by print-block at }
self.cbox(INDENT_UNIT);
self.cbox(0);
// head-box, will be closed by print-block after {
self.ibox(0);
self.print_block_with_attrs(blk, attrs);
Expand All @@ -397,7 +403,7 @@ impl<'a> State<'a> {
self.word_nbsp("async");
self.print_capture_clause(capture_clause);
// cbox/ibox in analogy to the `ExprKind::Block` arm above
self.cbox(INDENT_UNIT);
self.cbox(0);
self.ibox(0);
self.print_block_with_attrs(blk, attrs);
}
Expand Down Expand Up @@ -500,7 +506,9 @@ impl<'a> State<'a> {
self.word("?")
}
ast::ExprKind::TryBlock(ref blk) => {
self.head("try");
self.cbox(0);
self.ibox(0);
self.word_nbsp("try");
self.print_block_with_attrs(blk, attrs)
}
ast::ExprKind::Err => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::pp::Breaks::Inconsistent;
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
use crate::pprust::state::{AnnNode, PrintState, State};

use rustc_ast as ast;
use rustc_ast::GenericBound;
Expand Down Expand Up @@ -377,7 +377,7 @@ impl<'a> State<'a> {
self.space_if_not_bol();
self.maybe_print_comment(v.span.lo());
self.print_outer_attributes(&v.attrs);
self.ibox(INDENT_UNIT);
self.ibox(0);
self.print_variant(v);
self.word(",");
self.end();
Expand Down
74 changes: 37 additions & 37 deletions src/test/pretty/ast-stmt-expr-attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,67 +28,67 @@ fn syntax() {
let _ = #[attr] (x as Y);
let _ =
#[attr] while true {
#![attr]
};
#![attr]
};
let _ =
#[attr] while let Some(false) = true {
#![attr]
};
#![attr]
};
let _ =
#[attr] for x in y {
#![attr]
};
#![attr]
};
let _ =
#[attr] loop {
#![attr]
};
#![attr]
};
let _ =
#[attr] match true {
#![attr]
#[attr]
_ => false,
};
#![attr]
#[attr]
_ => false,
};
let _ = #[attr] || #[attr] foo;
let _ = #[attr] move || #[attr] foo;
let _ =
#[attr] ||
#[attr] {
#![attr]
foo
};
#[attr] {
#![attr]
foo
};
let _ =
#[attr] move ||
#[attr] {
#![attr]
foo
};
#[attr] {
#![attr]
foo
};
let _ =
#[attr] ||
{
#![attr]
foo
};
{
#![attr]
foo
};
let _ =
#[attr] move ||
{
#![attr]
foo
};
{
#![attr]
foo
};
let _ =
#[attr] {
#![attr]
};
#![attr]
};
let _ =
#[attr] {
#![attr]
let _ = ();
};
#![attr]
let _ = ();
};
let _ =
#[attr] {
#![attr]
let _ = ();
foo
};
#![attr]
let _ = ();
foo
};
let _ = #[attr] x = y;
let _ = #[attr] (x = y);
let _ = #[attr] x += y;
Expand Down
8 changes: 4 additions & 4 deletions src/test/pretty/block-comment-wchar.pp
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@
// Taken from https://www.unicode.org/Public/UNIDATA/PropList.txt
let chars =
['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}',
'\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}',
'\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}',
'\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}',
'\u{205F}', '\u{3000}'];
'\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}',
'\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}',
'\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}',
'\u{205F}', '\u{3000}'];
for c in &chars { let ws = c.is_whitespace(); println!("{} {}", c, ws); }
}
Loading