Skip to content

Commit

Permalink
Remove dependency on rowan
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Feb 14, 2023
1 parent 132d710 commit 8223c0e
Show file tree
Hide file tree
Showing 63 changed files with 31 additions and 17,845 deletions.
90 changes: 2 additions & 88 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/ruff_formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cfg-if = { version = "1.0.0" }
countme = { version = "3.0.1" }
drop_bomb = { version = "0.1.5" }
indexmap = { version = "1.9.1" }
ruff_rowan = { path = "../ruff_rowan" }
ruff_text_size = { path = "../ruff_text_size" }
rustc-hash = { workspace = true }
schemars = { version = "0.8.10", optional = true }
serde = { version = "1.0.136", features = ["derive"], optional = true }
Expand All @@ -22,4 +22,4 @@ unicode-width = { version = "0.1.9" }
insta = { version = "1.19.0" }

[features]
serde = ["dep:serde", "schemars", "ruff_rowan/serde"]
serde = ["dep:serde", "schemars"]
189 changes: 4 additions & 185 deletions crates/ruff_formatter/src/builders.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::format_element::tag::{Condition, Tag};
use crate::prelude::tag::{DedentMode, GroupMode, LabelId};
use crate::prelude::*;
use crate::{format_element, write, Argument, Arguments, GroupId, TextRange, TextSize};
use crate::{format_element, write, Argument, Arguments, GroupId, TextSize};
use crate::{Buffer, VecBuffer};
use ruff_rowan::{Language, SyntaxNode, SyntaxToken, SyntaxTokenText, TextLen};
use std::borrow::Cow;

use std::cell::Cell;
use std::marker::PhantomData;
use std::num::NonZeroU8;
Expand Down Expand Up @@ -303,93 +302,6 @@ impl std::fmt::Debug for DynamicText<'_> {
}
}

/// String that is the same as in the input source text if `text` is [`Cow::Borrowed`] or
/// some replaced content if `text` is [`Cow::Owned`].
pub fn syntax_token_cow_slice<'a, L: Language>(
text: Cow<'a, str>,
token: &'a SyntaxToken<L>,
start: TextSize,
) -> SyntaxTokenCowSlice<'a, L> {
debug_assert_no_newlines(&text);

SyntaxTokenCowSlice { text, token, start }
}

pub struct SyntaxTokenCowSlice<'a, L: Language> {
text: Cow<'a, str>,
token: &'a SyntaxToken<L>,
start: TextSize,
}

impl<L: Language, Context> Format<Context> for SyntaxTokenCowSlice<'_, L> {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
match &self.text {
Cow::Borrowed(text) => {
let range = TextRange::at(self.start, text.text_len());
debug_assert_eq!(
*text,
&self.token.text()[range - self.token.text_range().start()],
"The borrowed string doesn't match the specified token substring. Does the borrowed string belong to this token and range?"
);

let relative_range = range - self.token.text_range().start();
let slice = self.token.token_text().slice(relative_range);

f.write_element(FormatElement::SyntaxTokenTextSlice {
slice,
source_position: self.start,
})
}
Cow::Owned(text) => f.write_element(FormatElement::DynamicText {
text: text.to_string().into_boxed_str(),
source_position: self.start,
}),
}
}
}

impl<L: Language> std::fmt::Debug for SyntaxTokenCowSlice<'_, L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::write!(f, "SyntaxTokenCowSlice({})", self.text)
}
}

/// Copies a source text 1:1 into the output text.
pub fn syntax_token_text_slice<L: Language>(
token: &SyntaxToken<L>,
range: TextRange,
) -> SyntaxTokenTextSlice {
let relative_range = range - token.text_range().start();
let slice = token.token_text().slice(relative_range);

debug_assert_no_newlines(&slice);

SyntaxTokenTextSlice {
text: slice,
source_position: range.start(),
}
}

pub struct SyntaxTokenTextSlice {
text: SyntaxTokenText,
source_position: TextSize,
}

impl<Context> Format<Context> for SyntaxTokenTextSlice {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
f.write_element(FormatElement::SyntaxTokenTextSlice {
slice: self.text.clone(),
source_position: self.source_position,
})
}
}

impl std::fmt::Debug for SyntaxTokenTextSlice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::write!(f, "SyntaxTokenTextSlice({})", self.text)
}
}

fn debug_assert_no_newlines(text: &str) {
debug_assert!(!text.contains('\r'), "The content '{}' contains an unsupported '\\r' line terminator character but text must only use line feeds '\\n' as line separator. Use '\\n' instead of '\\r' and '\\r\\n' to insert a line break in strings.", text);
}
Expand Down Expand Up @@ -1824,7 +1736,7 @@ impl<Context, T> std::fmt::Debug for FormatWith<Context, T> {
/// ```
/// use ruff_formatter::prelude::*;
/// use ruff_formatter::{SimpleFormatContext, format, write};
/// use ruff_rowan::TextSize;
/// use ruff_text_size::TextSize;
///
/// struct MyFormat {
/// items: Vec<&'static str>,
Expand Down Expand Up @@ -1919,7 +1831,7 @@ where
/// ```panics
/// use ruff_formatter::prelude::*;
/// use ruff_formatter::{SimpleFormatContext, format, write, Buffer};
/// use ruff_rowan::TextSize;
/// use ruff_text_size::TextSize;
///
/// let mut count = 0;
///
Expand Down Expand Up @@ -2034,99 +1946,6 @@ where
}
}

/// Builder to join together nodes that ensures that nodes separated by empty lines continue
/// to be separated by empty lines in the formatted output.
#[must_use = "must eventually call `finish()` on Format builders"]
pub struct JoinNodesBuilder<'fmt, 'buf, Separator, Context> {
result: FormatResult<()>,
/// The separator to insert between nodes. Either a soft or hard line break
separator: Separator,
fmt: &'fmt mut Formatter<'buf, Context>,
has_elements: bool,
}

impl<'fmt, 'buf, Separator, Context> JoinNodesBuilder<'fmt, 'buf, Separator, Context>
where
Separator: Format<Context>,
{
pub(super) fn new(separator: Separator, fmt: &'fmt mut Formatter<'buf, Context>) -> Self {
Self {
result: Ok(()),
separator,
fmt,
has_elements: false,
}
}

/// Adds a new node with the specified formatted content to the output, respecting any new lines
/// that appear before the node in the input source.
pub fn entry<L: Language>(&mut self, node: &SyntaxNode<L>, content: &dyn Format<Context>) {
self.result = self.result.and_then(|_| {
if self.has_elements {
if get_lines_before(node) > 1 {
write!(self.fmt, [empty_line()])?;
} else {
self.separator.fmt(self.fmt)?;
}
}

self.has_elements = true;

write!(self.fmt, [content])
});
}

/// Writes an entry without adding a separating line break or empty line.
pub fn entry_no_separator(&mut self, content: &dyn Format<Context>) {
self.result = self.result.and_then(|_| {
self.has_elements = true;

write!(self.fmt, [content])
})
}

/// Adds an iterator of entries to the output. Each entry is a `(node, content)` tuple.
pub fn entries<L, F, I>(&mut self, entries: I) -> &mut Self
where
L: Language,
F: Format<Context>,
I: IntoIterator<Item = (SyntaxNode<L>, F)>,
{
for (node, content) in entries {
self.entry(&node, &content)
}

self
}

pub fn finish(&mut self) -> FormatResult<()> {
self.result
}
}

/// Get the number of line breaks between two consecutive SyntaxNodes in the tree
pub fn get_lines_before<L: Language>(next_node: &SyntaxNode<L>) -> usize {
// Count the newlines in the leading trivia of the next node
if let Some(token) = next_node.first_token() {
get_lines_before_token(&token)
} else {
0
}
}

pub fn get_lines_before_token<L: Language>(token: &SyntaxToken<L>) -> usize {
token
.leading_trivia()
.pieces()
.take_while(|piece| {
// Stop at the first comment or skipped piece, the comment printer
// will handle newlines between the comment and the node
!(piece.is_comments() || piece.is_skipped())
})
.filter(|piece| piece.is_newline())
.count()
}

/// Builder to fill as many elements as possible on a single line.
#[must_use = "must eventually call `finish()` on Format builders"]
pub struct FillBuilder<'fmt, 'buf, Context> {
Expand Down
Loading

0 comments on commit 8223c0e

Please sign in to comment.