Skip to content

Commit

Permalink
Fix: Printer must print a newline if a line only contains characters …
Browse files Browse the repository at this point in the history
…with a 0 width
  • Loading branch information
MichaReiser committed Jun 5, 2024
1 parent 52af92c commit 674d4df
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 14 deletions.
20 changes: 19 additions & 1 deletion crates/ruff_formatter/src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl<'a> Printer<'a> {
self.flush_line_suffixes(queue, stack, Some(element));
} else {
// Only print a newline if the current line isn't already empty
if self.state.line_width > 0 {
if !self.state.buffer[self.state.line_start..].is_empty() {
self.push_marker();
self.print_char('\n');
}
Expand Down Expand Up @@ -830,6 +830,7 @@ impl<'a> Printer<'a> {
.push_str(self.options.line_ending.as_str());

self.state.line_width = 0;
self.state.line_start = self.state.buffer.len();

// Fit's only tests if groups up to the first line break fit.
// The next group must re-measure if it still fits.
Expand Down Expand Up @@ -872,12 +873,29 @@ enum FillPairLayout {
/// position the printer currently is.
#[derive(Default, Debug)]
struct PrinterState<'a> {
/// The formatted output.
buffer: String,

/// The source markers that map source positions to formatted positions.
source_markers: Vec<SourceMarker>,

/// The next source position that should be flushed when writing the next text.
pending_source_position: Option<TextSize>,

/// The current indentation that should be written before the next text.
pending_indent: Indention,

/// Caches if the code up to the next newline has been measured to fit on a single line.
/// This is used to avoid re-measuring the same content multiple times.
measured_group_fits: bool,

/// The offset at which the current line in `buffer` starts.
line_start: usize,

/// The accumulated unicode-width of all characters on the current line.
line_width: u32,

/// The line suffixes that should be printed at the end of the line.
line_suffixes: LineSuffixes<'a>,
verbatim_markers: Vec<TextRange>,
group_modes: GroupModes,
Expand Down
14 changes: 1 addition & 13 deletions crates/ruff_python_formatter/src/verbatim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use std::borrow::Cow;
use std::iter::FusedIterator;
use std::slice::Iter;

use unicode_width::UnicodeWidthStr;

use ruff_formatter::{write, FormatError};
use ruff_python_ast::AnyNodeRef;
use ruff_python_ast::Stmt;
Expand Down Expand Up @@ -760,17 +758,7 @@ impl Format<PyFormatContext<'_>> for FormatVerbatimStatementRange {

// Write the line separator that terminates the line, except if it is the last line (that isn't separated by a hard line break).
if logical_line.has_trailing_newline {
// Insert an empty line if the text is non-empty but all characters have a width of zero.
// This is necessary to work around the fact that the Printer omits hard line breaks if the line width is 0.
// The alternative is to "fix" the printer and explicitly track the width and whether the line is empty.
// There's currently no use case for zero-width content outside of the verbatim context (and, form feeds are a Python specific speciality).
// It, therefore, feels wrong to add additional complexity to the very hot `Printer::print_char` function,
// to work around this special case. Therefore, work around the Printer behavior here, in the cold verbatim-formatting.
if f.context().source()[trimmed_line_range].width() == 0 {
empty_line().fmt(f)?;
} else {
hard_line_break().fmt(f)?;
}
hard_line_break().fmt(f)?;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring_non_visible_characters.py
---
## Input
```python
# Regresssion test for https://github.com/astral-sh/ruff/issues/11724
'''

'''
```

## Output
```python
# Regresssion test for https://github.com/astral-sh/ruff/issues/11724
"""

"""
```

0 comments on commit 674d4df

Please sign in to comment.