mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-21 12:05:10 +00:00
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:
parent
2f125f4019
commit
bcf745c5ba
134 changed files with 5308 additions and 4385 deletions
|
@ -1,22 +1,15 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use ruff_text_size::TextRange;
|
||||
use rustpython_parser::ast::Mod;
|
||||
use ruff_formatter::prelude::*;
|
||||
use ruff_formatter::{format, write};
|
||||
use ruff_formatter::{Formatted, IndentStyle, Printed, SimpleFormatOptions, SourceCode};
|
||||
use ruff_python_ast::node::{AnyNodeRef, AstNode, NodeKind};
|
||||
use ruff_python_ast::source_code::{CommentRanges, CommentRangesBuilder, Locator};
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
use rustpython_parser::ast::{Mod, Ranged};
|
||||
use rustpython_parser::lexer::lex;
|
||||
use rustpython_parser::{parse_tokens, Mode};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use ruff_formatter::format_element::tag::VerbatimKind;
|
||||
use ruff_formatter::formatter::Formatter;
|
||||
use ruff_formatter::prelude::{
|
||||
dynamic_text, source_position, source_text_slice, ContainsNewlines, Tag,
|
||||
};
|
||||
use ruff_formatter::{
|
||||
format, normalize_newlines, write, Buffer, Format, FormatElement, FormatResult, Formatted,
|
||||
IndentStyle, Printed, SimpleFormatOptions, SourceCode,
|
||||
};
|
||||
use ruff_python_ast::node::AstNode;
|
||||
use ruff_python_ast::source_code::{CommentRanges, CommentRangesBuilder, Locator};
|
||||
|
||||
use crate::comments::{
|
||||
dangling_node_comments, leading_node_comments, trailing_node_comments, Comments,
|
||||
};
|
||||
|
@ -142,16 +135,49 @@ pub fn format_node<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) struct NotYetImplemented(NodeKind);
|
||||
|
||||
/// Formats a placeholder for nodes that have not yet been implemented
|
||||
pub(crate) fn not_yet_implemented<'a, T>(node: T) -> NotYetImplemented
|
||||
where
|
||||
T: Into<AnyNodeRef<'a>>,
|
||||
{
|
||||
NotYetImplemented(node.into().kind())
|
||||
}
|
||||
|
||||
impl Format<PyFormatContext<'_>> for NotYetImplemented {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let text = std::format!("NOT_YET_IMPLEMENTED_{:?}", self.0);
|
||||
|
||||
f.write_element(FormatElement::Tag(Tag::StartVerbatim(
|
||||
tag::VerbatimKind::Verbatim {
|
||||
length: text.text_len(),
|
||||
},
|
||||
)))?;
|
||||
|
||||
f.write_element(FormatElement::DynamicText {
|
||||
text: Box::from(text),
|
||||
})?;
|
||||
|
||||
f.write_element(FormatElement::Tag(Tag::EndVerbatim))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct VerbatimText(TextRange);
|
||||
|
||||
pub(crate) const fn verbatim_text(range: TextRange) -> VerbatimText {
|
||||
VerbatimText(range)
|
||||
#[allow(unused)]
|
||||
pub(crate) fn verbatim_text<T>(item: &T) -> VerbatimText
|
||||
where
|
||||
T: Ranged,
|
||||
{
|
||||
VerbatimText(item.range())
|
||||
}
|
||||
|
||||
impl Format<PyFormatContext<'_>> for VerbatimText {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
f.write_element(FormatElement::Tag(Tag::StartVerbatim(
|
||||
VerbatimKind::Verbatim {
|
||||
tag::VerbatimKind::Verbatim {
|
||||
length: self.0.len(),
|
||||
},
|
||||
)))?;
|
||||
|
@ -203,8 +229,7 @@ if True:
|
|||
# trailing
|
||||
"#;
|
||||
let expected = r#"# preceding
|
||||
if True:
|
||||
print( "hi" )
|
||||
NOT_YET_IMPLEMENTED_StmtIf
|
||||
# trailing
|
||||
"#;
|
||||
let actual = format_module(input)?.as_code().to_string();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue