Replace verbatim text with NOT_YET_IMPLEMENTED (#4904)

<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR replaces the `verbatim_text` builder with a `not_yet_implemented` builder that emits `NOT_YET_IMPLEMENTED_<NodeKind>` for not yet implemented nodes. 

The motivation for this change is that partially formatting compound statements can result in incorrectly indented code, which is a syntax error:

```python
def func_no_args():
  a; b; c
  if True: raise RuntimeError
  if False: ...
  for i in range(10):
    print(i)
    continue
```

Get's reformatted to

```python
def func_no_args():
    a; b; c
    if True: raise RuntimeError
    if False: ...
    for i in range(10):
    print(i)
    continue
```

because our formatter does not yet support `for` statements and just inserts the text from the source. 

## Downsides

Using an identifier will not work in all situations. For example, an identifier is invalid in an `Arguments ` position. That's why I kept `verbatim_text` around and e.g. use it in the `Arguments` formatting logic where incorrect indentations are impossible (to my knowledge). Meaning, `verbatim_text` we can opt in to `verbatim_text` when we want to iterate quickly on nodes that we don't want to provide a full implementation yet and using an identifier would be invalid. 

## Upsides

Running this on main discovered stability issues with the newline handling that were previously "hidden" because of the verbatim formatting. I guess that's an upside :)

## Test Plan

None?
This commit is contained in:
Micha Reiser 2023-06-07 14:57:25 +02:00 committed by GitHub
parent 2f125f4019
commit bcf745c5ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
134 changed files with 5308 additions and 4385 deletions

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchAs;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchAs;
impl FormatNodeRule<PatternMatchAs> for FormatPatternMatchAs {
fn fmt_fields(&self, item: &PatternMatchAs, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchClass;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchClass;
impl FormatNodeRule<PatternMatchClass> for FormatPatternMatchClass {
fn fmt_fields(&self, item: &PatternMatchClass, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchMapping;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchMapping;
impl FormatNodeRule<PatternMatchMapping> for FormatPatternMatchMapping {
fn fmt_fields(&self, item: &PatternMatchMapping, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchOr;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchOr;
impl FormatNodeRule<PatternMatchOr> for FormatPatternMatchOr {
fn fmt_fields(&self, item: &PatternMatchOr, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchSequence;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchSequence;
impl FormatNodeRule<PatternMatchSequence> for FormatPatternMatchSequence {
fn fmt_fields(&self, item: &PatternMatchSequence, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchSingleton;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchSingleton;
impl FormatNodeRule<PatternMatchSingleton> for FormatPatternMatchSingleton {
fn fmt_fields(&self, item: &PatternMatchSingleton, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchStar;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchStar;
impl FormatNodeRule<PatternMatchStar> for FormatPatternMatchStar {
fn fmt_fields(&self, item: &PatternMatchStar, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}

View file

@ -1,4 +1,4 @@
use crate::{verbatim_text, FormatNodeRule, PyFormatter};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::PatternMatchValue;
@ -7,6 +7,6 @@ pub struct FormatPatternMatchValue;
impl FormatNodeRule<PatternMatchValue> for FormatPatternMatchValue {
fn fmt_fields(&self, item: &PatternMatchValue, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [verbatim_text(item.range)])
write!(f, [not_yet_implemented(item)])
}
}