Skip to content

Commit

Permalink
Format Fixes (#710)
Browse files Browse the repository at this point in the history
  • Loading branch information
SWW13 authored Jun 14, 2024
1 parent e310957 commit 744033b
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 33 deletions.
2 changes: 1 addition & 1 deletion crates/rune/src/fmt/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ fn parse_block_comment(chars: &mut CharIndices<'_>) -> Option<usize> {
while let Some((_, c)) = chars.next() {
if c == '*' {
if let Some((_, '/')) = chars.clone().next() {
return Some(chars.next()?.0);
return Some(chars.next()?.0 + 1);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rune/src/fmt/comments/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn test_parse_block_comment() {
let input = "/* this is a comment */";
let mut chars = input.char_indices();
let end = parse_block_comment(&mut chars).unwrap();
assert_eq!(end, input.len() - 1);
assert_eq!(end, input.len());
}

#[test]
Expand Down
67 changes: 38 additions & 29 deletions crates/rune/src/fmt/indent_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::str;
use crate::alloc::fmt::TryWrite;
use crate::alloc::prelude::*;
use crate::alloc::{self, try_vec, Vec};
use crate::ast::Span;
use crate::ast::{ByteIndex, Span};

use super::comments::Comment;
use super::error::FormattingError;
Expand Down Expand Up @@ -136,19 +136,7 @@ impl<'a> SpanInjectionWriter<'a> {
pub(super) fn into_inner(mut self) -> Result<Vec<Vec<u8>>, FormattingError> {
while !self.queued_spans.is_empty() {
let span = self.queued_spans.remove(0);
match span {
ResolvedSpan::Empty(_) => {
writeln!(self.writer)?;
}
ResolvedSpan::Comment(comment) => {
if comment.on_new_line {
writeln!(self.writer, "{}", self.resolve(comment.span)?)?;
} else {
self.extend_previous_line(b" ")?;
self.extend_previous_line(self.resolve(comment.span)?.as_bytes())?;
}
}
}
self.write_span(span)?;
}

Ok(self.writer.into_inner())
Expand Down Expand Up @@ -195,37 +183,58 @@ impl<'a> SpanInjectionWriter<'a> {
self.write_spanned(Span::new(0, 0), text, false, false)
}

pub(super) fn write_spanned(
&mut self,
span: Span,
text: &str,
newline: bool,
space: bool,
) -> Result<(), FormattingError> {
pub(super) fn write_queued_spans(&mut self, until: ByteIndex) -> Result<(), FormattingError> {
// The queued recovered spans are ordered so we can pop them from the front if they're before the current span.
// If the current span is before the first queued span, we need to inject the queued span.

while let Some(queued_span) = self.queued_spans.first() {
if queued_span.span().start > span.start {
if queued_span.span().start > until {
break;
}

let queued_span = self.queued_spans.remove(0);
match queued_span {
ResolvedSpan::Empty(_) => {
writeln!(self.writer)?;
}
ResolvedSpan::Comment(comment) => {
self.write_span(queued_span)?;
}

Ok(())
}

fn write_span(&mut self, span: ResolvedSpan) -> Result<(), FormattingError> {
match span {
ResolvedSpan::Empty(_) => {
writeln!(self.writer)?;
}
ResolvedSpan::Comment(comment) => {
let mut lines = self.resolve(comment.span)?.lines();

if let Some(first_line) = lines.next() {
if comment.on_new_line {
writeln!(self.writer, "{}", self.resolve(comment.span)?)?;
writeln!(self.writer, "{}", first_line)?;
} else {
self.extend_previous_line(b" ")?;
self.extend_previous_line(self.resolve(comment.span)?.as_bytes())?;
self.extend_previous_line(first_line.as_bytes())?;
}
}

for line in lines {
self.newline()?;
self.extend_previous_line(line.as_bytes())?;
}
}
}

Ok(())
}

pub(super) fn write_spanned(
&mut self,
span: Span,
text: &str,
newline: bool,
space: bool,
) -> Result<(), FormattingError> {
self.write_queued_spans(span.start)?;

write!(self.writer, "{}", text)?;

if space {
Expand Down
4 changes: 2 additions & 2 deletions crates/rune/src/fmt/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ impl<'a> Printer<'a> {
for attribute in attributes {
self.visit_attribute(attribute)?;
}
self.writer.newline()?;

self.emit_visibility(visibility)?;

Expand Down Expand Up @@ -1788,6 +1787,7 @@ impl<'a> Printer<'a> {
self.visit_statement(statement)?;
}

self.writer.write_queued_spans(close.span.start)?;
self.writer.dedent();
self.writer.write_spanned_raw(close.span, false, false)?;

Expand All @@ -1802,7 +1802,7 @@ impl<'a> Printer<'a> {
}
ast::Stmt::Item(item, semi) => {
self.visit_item(item, *semi)?;
if !matches!(item, ast::Item::Fn(_)) {
if !matches!(item, ast::Item::Const(_) | ast::Item::Fn(_)) {
self.writer.newline()?;
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/rune/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ mod external_match;
mod external_ops;
mod float;
mod for_loop;
mod format_source;
mod generics;
mod getter_setter;
mod instance;
Expand Down
195 changes: 195 additions & 0 deletions crates/rune/src/tests/format_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
prelude!();

use crate::fmt::format_source;

#[track_caller]
fn assert_format_source(source: &str, expected: Option<&str>) -> Result<()> {
let formated = format_source(source)?;
let expected = expected.unwrap_or(source);
assert_eq!(formated, expected);

Ok(())
}

/// https://github.com/rune-rs/rune/issues/684
#[test]
fn bug_684() -> Result<()> {
let source = r#"pub fn main() {
/*
test
*/
}
"#;

assert_format_source(source, None)
}

#[test]
fn fmt_block_comment() -> Result<()> {
let source = r#"//test1
/*test2*/"#;
let expected = format!("{source}\n");

assert_format_source(source, Some(&expected))
}

#[test]
fn fmt_block_comment_indent() -> Result<()> {
let source = r#"struct Test {
a, /* test1
test2
test 3*/
}
"#;

assert_format_source(source, None)
}

#[test]
fn fmt_block_comment_indent2() -> Result<()> {
let source = r#"fn test() {
/* test1
test2 */
if true {
/*
if false {
// test3
}
*/
} /* else {
// test 4
} */
}
/* test 5.1
test 5.2
test 5.3
*/
"#;

assert_format_source(source, None)
}

/// https://github.com/rune-rs/rune/issues/693
#[test]
fn bug_693() -> Result<()> {
let source = r#"pub fn main() {
if true {
// test
}
}
"#;

assert_format_source(source, None)
}

#[test]
fn fmt_comment_line() -> Result<()> {
let source = r#"pub fn main() {
// test 1
if true {
// test 2.1
let a = 1;
// test 2.2
}
// test 3
}
"#;

assert_format_source(source, None)
}

/// https://github.com/rune-rs/rune/issues/703
#[test]
fn bug_703() -> Result<()> {
let source = r#"pub fn main() {
const TEST = 1;
}
"#;

assert_format_source(source, None)
}

#[test]
fn fmt_global_const() -> Result<()> {
let source = r#"const TEST1=1;const TEST2=2;
const TEST3=1;"#;
let expected = r#"const TEST1 = 1;
const TEST2 = 2;
const TEST3 = 1;
"#;

assert_format_source(source, Some(expected))
}

#[test]
fn fmt_len() -> Result<()> {
let source = r#"pub fn main() {
let var = 1;
}
"#;

assert_format_source(source, None)
}

#[test]
#[ignore]
fn fmt_println() -> Result<()> {
let source = r#"pub fn main(){println!("The value is {}",42);}"#;
let expected = r#"pub fn main() {
println!("The value is {}", 42);
}
"#;

assert_format_source(source, Some(expected))
}

#[test]
fn fmt_while_loop() -> Result<()> {
let source = r#"pub fn main(){let value=0;while value<100{if value>=50{break;}value=value+1;}println!("The value is {}",value);// => The value is 50
}"#;
let expected = r#"pub fn main() {
let value = 0;
while value < 100 {
if value >= 50 {
break;
}
value = value + 1;
}
println!("The value is {}",value); // => The value is 50
}
"#;

assert_format_source(source, Some(expected))
}

#[test]
fn fmt_async_http_timeout() -> Result<()> {
let source = r#"struct Timeout;
async fn request(timeout) {
let request = http::get(`http://httpstat.us/200?sleep=${timeout}`);
let timeout = time::sleep(time::Duration::from_secs(2));
let result = select {
_ = timeout => Err(Timeout),
res = request => res,
}?;
println!("{}", result.status());
Ok(())
}
pub async fn main() {
if let Err(Timeout) = request(1000).await {
println("Request timed out!");
}
if let Err(Timeout) = request(4000).await {
println("Request timed out!");
}
}
"#;

assert_format_source(source, None)
}

0 comments on commit 744033b

Please sign in to comment.