Skip to content
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
68 changes: 33 additions & 35 deletions librubyfmt/src/line_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,65 +251,64 @@ pub enum AbstractLineToken<'src> {
}

impl<'src> AbstractLineToken<'src> {
pub fn into_single_line(self) -> Vec<ConcreteLineTokenAndTargets<'src>> {
pub fn write_single_line(self, out: &mut Vec<ConcreteLineTokenAndTargets<'src>>) {
match self {
Self::CollapsingNewLine(heredoc_strings) => {
let mut res = Vec::new();
if heredoc_strings.is_some() {
res.push(cltats_hard_newline());
out.push(cltats_hard_newline());
}
res.extend(Self::shimmy_and_shake_heredocs(heredoc_strings));
res
Self::write_heredocs(heredoc_strings, out);
}
Self::SoftNewline(heredoc_strings) => {
let mut res = vec![ConcreteLineTokenAndTargets::ConcreteLineToken(
out.push(ConcreteLineTokenAndTargets::ConcreteLineToken(
ConcreteLineToken::Space,
)];
res.extend(Self::shimmy_and_shake_heredocs(heredoc_strings));
res
));
Self::write_heredocs(heredoc_strings, out);
}
Self::SoftIndent { .. } => Vec::new(),
Self::SoftIndent { .. } => {}
Self::ConcreteLineToken(clt) => {
vec![ConcreteLineTokenAndTargets::ConcreteLineToken(clt)]
out.push(ConcreteLineTokenAndTargets::ConcreteLineToken(clt));
}
Self::BreakableEntry(be) => {
out.push(ConcreteLineTokenAndTargets::BreakableEntry(be));
}
Self::BreakableEntry(be) => vec![ConcreteLineTokenAndTargets::BreakableEntry(be)],
Self::BreakableCallChainEntry(bcce) => {
vec![ConcreteLineTokenAndTargets::BreakableCallChainEntry(bcce)]
out.push(ConcreteLineTokenAndTargets::BreakableCallChainEntry(bcce));
}
}
}

pub fn into_multi_line(self) -> Vec<ConcreteLineTokenAndTargets<'src>> {
pub fn write_multi_line(self, out: &mut Vec<ConcreteLineTokenAndTargets<'src>>) {
match self {
Self::CollapsingNewLine(heredoc_strings) => {
let mut res = vec![cltats_hard_newline()];
res.extend(Self::shimmy_and_shake_heredocs(heredoc_strings));
res
out.push(cltats_hard_newline());
Self::write_heredocs(heredoc_strings, out);
}
Self::SoftNewline(heredoc_strings) => {
let mut res = vec![cltats_hard_newline()];
res.extend(Self::shimmy_and_shake_heredocs(heredoc_strings));
res
out.push(cltats_hard_newline());
Self::write_heredocs(heredoc_strings, out);
}
Self::SoftIndent { depth } => {
vec![ConcreteLineTokenAndTargets::ConcreteLineToken(
out.push(ConcreteLineTokenAndTargets::ConcreteLineToken(
ConcreteLineToken::Indent { depth },
)]
));
}
Self::ConcreteLineToken(clt) => {
vec![ConcreteLineTokenAndTargets::ConcreteLineToken(clt)]
out.push(ConcreteLineTokenAndTargets::ConcreteLineToken(clt));
}
Self::BreakableEntry(be) => {
out.push(ConcreteLineTokenAndTargets::BreakableEntry(be));
}
Self::BreakableEntry(be) => vec![ConcreteLineTokenAndTargets::BreakableEntry(be)],
Self::BreakableCallChainEntry(bcce) => {
vec![ConcreteLineTokenAndTargets::BreakableCallChainEntry(bcce)]
out.push(ConcreteLineTokenAndTargets::BreakableCallChainEntry(bcce));
}
}
}

fn shimmy_and_shake_heredocs(
fn write_heredocs(
heredoc_strings: Option<Vec<HeredocString>>,
) -> Vec<ConcreteLineTokenAndTargets<'src>> {
let mut res = vec![];
out: &mut Vec<ConcreteLineTokenAndTargets<'src>>,
) {
if let Some(values) = heredoc_strings {
for hds in values {
let indent = hds.indent;
Expand All @@ -318,19 +317,18 @@ impl<'src> AbstractLineToken<'src> {

let s = hds.render_as_string();
if !s.is_empty() {
res.push(clats_direct_part(s));
res.push(cltats_hard_newline());
out.push(clats_direct_part(s));
out.push(cltats_hard_newline());
}
if !kind.is_bare() {
res.push(clats_indent(indent));
out.push(clats_indent(indent));
}
res.push(clats_heredoc_close(symbol));
res.push(cltats_hard_newline());
out.push(clats_heredoc_close(symbol));
out.push(cltats_hard_newline());
let indent_depth = if indent != 0 { indent - 2 } else { indent };
res.push(clats_indent(indent_depth));
out.push(clats_indent(indent_depth));
}
}
res
}

pub fn is_comment(&self) -> bool {
Expand Down
13 changes: 9 additions & 4 deletions librubyfmt/src/render_queue_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,15 @@ impl<'src> RenderQueueWriter<'src> {
let force_single_line =
!be.any_collapsing_newline_has_heredoc_content() && be.in_string_embexpr();

let mut tokens = Vec::new();
if !force_single_line
&& (be.is_multiline() || Self::renders_over_max_line_length(accum, &be))
{
Self::render_as(accum, be.into_tokens(ConvertType::MultiLine));
be.write_tokens(ConvertType::MultiLine, &mut tokens);
Self::render_as(accum, tokens);
} else {
Self::render_as(accum, be.into_tokens(ConvertType::SingleLine));
be.write_tokens(ConvertType::SingleLine, &mut tokens);
Self::render_as(accum, tokens);
// after running accum looks like this (or some variant):
// [.., Comma, Space, DirectPart {part: ""}, <close_delimiter>]
// so we remove items at positions length-2 until there is nothing
Expand All @@ -250,15 +253,17 @@ impl<'src> RenderQueueWriter<'src> {
) {
let must_multiline =
bcce.any_collapsing_newline_has_heredoc_content() && bcce.in_string_embexpr();
let mut tokens = Vec::new();
if must_multiline
|| ((bcce.is_multiline() || Self::renders_over_max_line_length(accum, &bcce))
&& !bcce.in_string_embexpr())
{
let tokens = bcce.into_tokens(ConvertType::MultiLine);
bcce.write_tokens(ConvertType::MultiLine, &mut tokens);
Self::render_as(accum, tokens);
} else {
bcce.remove_call_chain_magic_tokens();
Self::render_as(accum, bcce.into_tokens(ConvertType::SingleLine));
bcce.write_tokens(ConvertType::SingleLine, &mut tokens);
Self::render_as(accum, tokens);
}
}

Expand Down
46 changes: 23 additions & 23 deletions librubyfmt/src/render_targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl<'src> BaseQueue<'src> {

pub trait AbstractTokenTarget<'src>: std::fmt::Debug {
fn push(&mut self, lt: AbstractLineToken<'src>);
fn into_tokens(self, ct: ConvertType) -> Vec<ConcreteLineTokenAndTargets<'src>>;
fn write_tokens(self, ct: ConvertType, out: &mut Vec<ConcreteLineTokenAndTargets<'src>>);
fn is_multiline(&self) -> bool;
fn single_line_string_length(&self, current_line_length: usize) -> usize;
fn tokens(&self) -> &Vec<AbstractLineToken<'src>>;
Expand Down Expand Up @@ -96,21 +96,21 @@ impl<'src> AbstractTokenTarget<'src> for BreakableEntry<'src> {
self.tokens.push(lt);
}

fn into_tokens(self, ct: ConvertType) -> Vec<ConcreteLineTokenAndTargets<'src>> {
fn write_tokens(self, ct: ConvertType, out: &mut Vec<ConcreteLineTokenAndTargets<'src>>) {
match ct {
ConvertType::MultiLine => {
let mut new_tokens: Vec<_> = Vec::with_capacity(self.tokens.len() + 2);
new_tokens.push(self.delims.multi_line_open().into());
new_tokens.extend(self.tokens.into_iter().flat_map(|t| t.into_multi_line()));
new_tokens.push(self.delims.multi_line_close().into());
new_tokens
out.push(self.delims.multi_line_open().into());
for t in self.tokens {
t.write_multi_line(out);
}
out.push(self.delims.multi_line_close().into());
}
ConvertType::SingleLine => {
let mut new_tokens: Vec<_> = Vec::with_capacity(self.tokens.len() + 2);
new_tokens.push(self.delims.single_line_open().into());
new_tokens.extend(self.tokens.into_iter().flat_map(|t| t.into_single_line()));
new_tokens.push(self.delims.single_line_close().into());
new_tokens
out.push(self.delims.single_line_open().into());
for t in self.tokens {
t.write_single_line(out);
}
out.push(self.delims.single_line_close().into());
}
}
}
Expand Down Expand Up @@ -228,18 +228,18 @@ impl<'src> AbstractTokenTarget<'src> for BreakableCallChainEntry<'src> {
self.tokens.push(lt);
}

fn into_tokens(self, ct: ConvertType) -> Vec<ConcreteLineTokenAndTargets<'src>> {
fn write_tokens(self, ct: ConvertType, out: &mut Vec<ConcreteLineTokenAndTargets<'src>>) {
match ct {
ConvertType::MultiLine => self
.tokens
.into_iter()
.flat_map(|t| t.into_multi_line())
.collect(),
ConvertType::SingleLine => self
.tokens
.into_iter()
.flat_map(|t| t.into_single_line())
.collect(),
ConvertType::MultiLine => {
for t in self.tokens {
t.write_multi_line(out);
}
}
ConvertType::SingleLine => {
for t in self.tokens {
t.write_single_line(out);
}
}
}
}

Expand Down