Use new formatter infrastructure in CLI and test (#4767)

* Use dummy verbatim formatter for all nodes

* Use new formatter infrastructure in CLI and test

* Expose the new formatter in the CLI

* Merge import blocks
This commit is contained in:
konstin 2023-06-01 11:55:04 +02:00 committed by GitHub
parent 9bf168c0a4
commit d4027d8b65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 41 deletions

1
Cargo.lock generated
View file

@ -1864,6 +1864,7 @@ dependencies = [
"ruff_cache", "ruff_cache",
"ruff_diagnostics", "ruff_diagnostics",
"ruff_python_ast", "ruff_python_ast",
"ruff_python_formatter",
"ruff_python_stdlib", "ruff_python_stdlib",
"ruff_text_size", "ruff_text_size",
"ruff_textwrap", "ruff_textwrap",

View file

@ -26,6 +26,7 @@ ruff = { path = "../ruff", features = ["clap"] }
ruff_cache = { path = "../ruff_cache" } ruff_cache = { path = "../ruff_cache" }
ruff_diagnostics = { path = "../ruff_diagnostics" } ruff_diagnostics = { path = "../ruff_diagnostics" }
ruff_python_ast = { path = "../ruff_python_ast" } ruff_python_ast = { path = "../ruff_python_ast" }
ruff_python_formatter = { path = "../ruff_python_formatter" }
ruff_text_size = { workspace = true } ruff_text_size = { workspace = true }
ruff_textwrap = { path = "../ruff_textwrap" } ruff_textwrap = { path = "../ruff_textwrap" }

View file

@ -12,6 +12,7 @@ use ruff::logging::{set_up_logging, LogLevel};
use ruff::settings::types::SerializationFormat; use ruff::settings::types::SerializationFormat;
use ruff::settings::{flags, CliSettings}; use ruff::settings::{flags, CliSettings};
use ruff::{fs, warn_user_once}; use ruff::{fs, warn_user_once};
use ruff_python_formatter::format_module;
use crate::args::{Args, CheckArgs, Command}; use crate::args::{Args, CheckArgs, Command};
use crate::commands::run_stdin::read_from_stdin; use crate::commands::run_stdin::read_from_stdin;
@ -131,22 +132,26 @@ fn format(files: &[PathBuf]) -> Result<ExitStatus> {
internal use only." internal use only."
); );
// dummy let format_code = |code: &str| {
let format_code = |code: &str| code.replace("# DEL", ""); // dummy, to check that the function was actually called
let contents = code.replace("# DEL", "");
// real formatting that is currently a passthrough
format_module(&contents)
};
match &files { match &files {
// Check if we should read from stdin // Check if we should read from stdin
[path] if path == Path::new("-") => { [path] if path == Path::new("-") => {
let unformatted = read_from_stdin()?; let unformatted = read_from_stdin()?;
let formatted = format_code(&unformatted); let formatted = format_code(&unformatted)?;
stdout().lock().write_all(formatted.as_bytes())?; stdout().lock().write_all(formatted.as_code().as_bytes())?;
} }
_ => { _ => {
for file in files { for file in files {
let unformatted = std::fs::read_to_string(file) let unformatted = std::fs::read_to_string(file)
.with_context(|| format!("Could not read {}: ", file.display()))?; .with_context(|| format!("Could not read {}: ", file.display()))?;
let formatted = format_code(&unformatted); let formatted = format_code(&unformatted)?;
std::fs::write(file, formatted) std::fs::write(file, formatted.as_code().as_bytes())
.with_context(|| format!("Could not write to {}, exiting", file.display()))?; .with_context(|| format!("Could not write to {}, exiting", file.display()))?;
} }
} }

View file

@ -16,7 +16,6 @@ use ruff_python_ast::source_code::{CommentRanges, CommentRangesBuilder, Locator}
use crate::comments::Comments; use crate::comments::Comments;
use crate::context::PyFormatContext; use crate::context::PyFormatContext;
use crate::module::FormatModule;
pub mod cli; pub mod cli;
mod comments; mod comments;
@ -130,9 +129,9 @@ pub fn format_node<'a>(
line_width: 88.try_into().unwrap(), line_width: 88.try_into().unwrap(),
}, },
locator.contents(), locator.contents(),
comments comments,
), ),
[FormatModule::new(root)] [root.format()]
) )
} }
@ -165,13 +164,33 @@ mod tests {
use insta::assert_snapshot; use insta::assert_snapshot;
use rustpython_parser::lexer::lex; use rustpython_parser::lexer::lex;
use rustpython_parser::{parse_tokens, Mode}; use rustpython_parser::{parse_tokens, Mode};
use similar::TextDiff;
use ruff_python_ast::source_code::CommentRangesBuilder; use ruff_python_ast::source_code::CommentRangesBuilder;
use ruff_testing_macros::fixture; use ruff_testing_macros::fixture;
use similar::TextDiff;
use crate::{format_module, format_node}; use crate::{format_module, format_node};
/// Very basic test intentionally kept very similar to the CLI
#[test]
fn basic() -> Result<()> {
let input = r#"
# preceding
if True:
print( "hi" )
# trailing
"#;
let expected = r#"
# preceding
if True:
print( "hi" )
# trailing
"#;
let actual = format_module(input)?.as_code().to_string();
assert_eq!(expected, actual);
Ok(())
}
#[fixture(pattern = "resources/test/fixtures/black/**/*.py")] #[fixture(pattern = "resources/test/fixtures/black/**/*.py")]
#[test] #[test]
fn black_test(input_path: &Path) -> Result<()> { fn black_test(input_path: &Path) -> Result<()> {

View file

@ -6,12 +6,10 @@ use clap::Parser as ClapParser;
use ruff_python_formatter::cli::Cli; use ruff_python_formatter::cli::Cli;
use ruff_python_formatter::format_module; use ruff_python_formatter::format_module;
#[allow(clippy::print_stdout)]
fn main() -> Result<()> { fn main() -> Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
let contents = fs::read_to_string(cli.file)?; let contents = fs::read_to_string(cli.file)?;
#[allow(clippy::print_stdout)] println!("{}", format_module(&contents)?.as_code());
{
println!("{}", format_module(&contents)?.as_code());
}
Ok(()) Ok(())
} }

View file

@ -1,38 +1,37 @@
use crate::context::PyFormatContext;
use crate::{AsFormat, IntoFormat, PyFormatter};
use ruff_formatter::{Format, FormatOwnedWithRule, FormatRefWithRule, FormatResult, FormatRule};
use rustpython_parser::ast::Mod;
pub(crate) mod mod_expression; pub(crate) mod mod_expression;
pub(crate) mod mod_function_type; pub(crate) mod mod_function_type;
pub(crate) mod mod_interactive; pub(crate) mod mod_interactive;
pub(crate) mod mod_module; pub(crate) mod mod_module;
use crate::context::PyFormatContext; #[derive(Default)]
use ruff_formatter::format_element::tag::VerbatimKind; pub struct FormatMod;
use ruff_formatter::prelude::*;
use ruff_formatter::write;
use rustpython_parser::ast::{Mod, Ranged};
pub(crate) struct FormatModule<'a> { impl FormatRule<Mod, PyFormatContext<'_>> for FormatMod {
module: &'a Mod, fn fmt(&self, item: &Mod, f: &mut PyFormatter) -> FormatResult<()> {
} match item {
Mod::Module(x) => x.format().fmt(f),
impl<'a> FormatModule<'a> { Mod::Interactive(x) => x.format().fmt(f),
pub(crate) fn new(module: &'a Mod) -> Self { Mod::Expression(x) => x.format().fmt(f),
Self { module } Mod::FunctionType(x) => x.format().fmt(f),
}
} }
} }
impl Format<PyFormatContext<'_>> for FormatModule<'_> { impl<'ast> AsFormat<PyFormatContext<'ast>> for Mod {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> { type Format<'a> = FormatRefWithRule<'a, Mod, FormatMod, PyFormatContext<'ast>>;
let range = self.module.range(); fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(self, FormatMod::default())
write!(f, [source_position(range.start())])?; }
}
f.write_element(FormatElement::Tag(Tag::StartVerbatim(
VerbatimKind::Verbatim { impl<'ast> IntoFormat<PyFormatContext<'ast>> for Mod {
length: range.len(), type Format = FormatOwnedWithRule<Mod, FormatMod, PyFormatContext<'ast>>;
}, fn into_format(self) -> Self::Format {
)))?; FormatOwnedWithRule::new(self, FormatMod::default())
write!(f, [source_text_slice(range, ContainsNewlines::Detect)])?;
f.write_element(FormatElement::Tag(Tag::EndVerbatim))?;
write!(f, [source_position(range.end())])
} }
} }