Add rome_formatter fork as ruff_formatter (#2872)

The Ruff autoformatter is going to be based on an intermediate representation (IR) formatted via [Wadler's algorithm](https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf). This is architecturally similar to [Rome](https://github.com/rome/tools), Prettier, [Skip](https://github.com/skiplang/skip/blob/master/src/tools/printer/printer.sk), and others.

This PR adds a fork of the `rome_formatter` crate from [Rome](https://github.com/rome/tools), renamed here to `ruff_formatter`, which provides generic definitions for a formatter IR as well as a generic IR printer. (We've also pulled in `rome_rowan`, `rome_text_size`, and `rome_text_edit`, though some of these will be removed in future PRs.)

Why fork? `rome_formatter` contains code that's specific to Rome's AST representation (e.g., it relies on a fork of rust-analyzer's `rowan`), and we'll likely want to support different abstractions and formatting capabilities (there are already a few changes coming in future PRs). Once we've dropped `ruff_rowan` and trimmed down `ruff_formatter` to the code we currently need, it's also not a huge surface area to maintain and update.
This commit is contained in:
Charlie Marsh 2023-02-14 19:22:55 -05:00 committed by GitHub
parent ac028cd9f8
commit 3ef1c2e303
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
83 changed files with 27547 additions and 1 deletions

View file

@ -0,0 +1,235 @@
use crate::format_element::tag::TagKind;
use crate::format_element::PrintMode;
use crate::printer::stack::{Stack, StackedStack};
use crate::printer::Indention;
use crate::{IndentStyle, InvalidDocumentError, PrintError, PrintResult};
use std::fmt::Debug;
use std::num::NonZeroU8;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub(super) enum StackFrameKind {
Root,
Tag(TagKind),
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub(super) struct StackFrame {
kind: StackFrameKind,
args: PrintElementArgs,
}
/// Stores arguments passed to `print_element` call, holding the state specific to printing an element.
/// E.g. the `indent` depends on the token the Printer's currently processing. That's why
/// it must be stored outside of the [PrinterState] that stores the state common to all elements.
///
/// The state is passed by value, which is why it's important that it isn't storing any heavy
/// data structures. Such structures should be stored on the [PrinterState] instead.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub(super) struct PrintElementArgs {
indent: Indention,
mode: PrintMode,
}
impl PrintElementArgs {
pub fn new(indent: Indention) -> Self {
Self {
indent,
..Self::default()
}
}
pub(super) fn mode(&self) -> PrintMode {
self.mode
}
pub(super) fn indention(&self) -> Indention {
self.indent
}
pub fn increment_indent_level(mut self, indent_style: IndentStyle) -> Self {
self.indent = self.indent.increment_level(indent_style);
self
}
pub fn decrement_indent(mut self) -> Self {
self.indent = self.indent.decrement();
self
}
pub fn reset_indent(mut self) -> Self {
self.indent = Indention::default();
self
}
pub fn set_indent_align(mut self, count: NonZeroU8) -> Self {
self.indent = self.indent.set_align(count);
self
}
pub fn with_print_mode(mut self, mode: PrintMode) -> Self {
self.mode = mode;
self
}
}
impl Default for PrintElementArgs {
fn default() -> Self {
Self {
indent: Indention::Level(0),
mode: PrintMode::Expanded,
}
}
}
/// Call stack that stores the [PrintElementCallArgs].
///
/// New [PrintElementCallArgs] are pushed onto the stack for every [`start`](Tag::is_start) [`Tag`](FormatElement::Tag)
/// and popped when reaching the corresponding [`end`](Tag::is_end) [`Tag`](FormatElement::Tag).
pub(super) trait CallStack {
type Stack: Stack<StackFrame> + Debug;
fn stack(&self) -> &Self::Stack;
fn stack_mut(&mut self) -> &mut Self::Stack;
/// Pops the call arguments at the top and asserts that they correspond to a start tag of `kind`.
///
/// Returns `Ok` with the arguments if the kind of the top stack frame matches `kind`, otherwise
/// returns `Err`.
fn pop(&mut self, kind: TagKind) -> PrintResult<PrintElementArgs> {
let last = self.stack_mut().pop();
match last {
Some(StackFrame {
kind: StackFrameKind::Tag(actual_kind),
args,
}) if actual_kind == kind => Ok(args),
// Start / End kind don't match
Some(StackFrame {
kind: StackFrameKind::Tag(expected_kind),
..
}) => Err(PrintError::InvalidDocument(Self::invalid_document_error(
kind,
Some(expected_kind),
))),
// Tried to pop the outer most stack frame, which is not valid
Some(
frame @ StackFrame {
kind: StackFrameKind::Root,
..
},
) => {
// Put it back in to guarantee that the stack is never empty
self.stack_mut().push(frame);
Err(PrintError::InvalidDocument(Self::invalid_document_error(
kind, None,
)))
}
// This should be unreachable but having it for completeness. Happens if the stack is empty.
None => Err(PrintError::InvalidDocument(Self::invalid_document_error(
kind, None,
))),
}
}
#[cold]
fn invalid_document_error(
end_kind: TagKind,
start_kind: Option<TagKind>,
) -> InvalidDocumentError {
match start_kind {
None => InvalidDocumentError::StartTagMissing { kind: end_kind },
Some(start_kind) => InvalidDocumentError::StartEndTagMismatch {
start_kind,
end_kind,
},
}
}
/// Returns the [PrintElementArgs] for the current stack frame.
fn top(&self) -> PrintElementArgs {
self.stack()
.top()
.expect("Expected `stack` to never be empty.")
.args
}
/// Returns the [TagKind] of the current stack frame or [None] if this is the root stack frame.
fn top_kind(&self) -> Option<TagKind> {
match self
.stack()
.top()
.expect("Expected `stack` to never be empty.")
.kind
{
StackFrameKind::Root => None,
StackFrameKind::Tag(kind) => Some(kind),
}
}
/// Creates a new stack frame for a [FormatElement::Tag] of `kind` with `args` as the call arguments.
fn push(&mut self, kind: TagKind, args: PrintElementArgs) {
self.stack_mut().push(StackFrame {
kind: StackFrameKind::Tag(kind),
args,
})
}
}
/// Call stack used for printing the [FormatElement]s
#[derive(Debug, Clone)]
pub(super) struct PrintCallStack(Vec<StackFrame>);
impl PrintCallStack {
pub(super) fn new(args: PrintElementArgs) -> Self {
Self(vec![StackFrame {
kind: StackFrameKind::Root,
args,
}])
}
}
impl CallStack for PrintCallStack {
type Stack = Vec<StackFrame>;
fn stack(&self) -> &Self::Stack {
&self.0
}
fn stack_mut(&mut self) -> &mut Self::Stack {
&mut self.0
}
}
/// Call stack used for measuring if some content fits on the line.
///
/// The stack is a view on top of the [PrintCallStack] because the stack frames are still necessary for printing.
#[must_use]
pub(super) struct FitsCallStack<'print> {
stack: StackedStack<'print, StackFrame>,
}
impl<'print> FitsCallStack<'print> {
pub(super) fn new(print: &'print PrintCallStack, saved: Vec<StackFrame>) -> Self {
let stack = StackedStack::with_vec(&print.0, saved);
Self { stack }
}
pub(super) fn finish(self) -> Vec<StackFrame> {
self.stack.into_vec()
}
}
impl<'a> CallStack for FitsCallStack<'a> {
type Stack = StackedStack<'a, StackFrame>;
fn stack(&self) -> &Self::Stack {
&self.stack
}
fn stack_mut(&mut self) -> &mut Self::Stack {
&mut self.stack
}
}