diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c161d69..08faff05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ - Air no longer emits colored output when stderr is not a terminal, such as when stderr is redirected to a file. +- `#line` directives are no longer indented, since R only reads them as directives at the start of a line (#425). + # 0.12.0 - New `--no-configuration` flag to format with Air's built-in defaults without loading a project or user configuration file (#479, @LeonidasZhak). diff --git a/crates/air_r_formatter/src/comments.rs b/crates/air_r_formatter/src/comments.rs index 60fbd62f..8bdef9a2 100644 --- a/crates/air_r_formatter/src/comments.rs +++ b/crates/air_r_formatter/src/comments.rs @@ -21,6 +21,7 @@ use biome_formatter::comments::CommentTextPosition; use biome_formatter::comments::Comments; use biome_formatter::comments::DecoratedComment; use biome_formatter::comments::SourceComment; +use biome_formatter::format_args; use biome_formatter::write; use biome_rowan::AstNode; use biome_rowan::Direction; @@ -41,12 +42,41 @@ impl FormatRule> for FormatRLeadingComment { comment: &SourceComment, f: &mut Formatter, ) -> FormatResult<()> { + // A `#line` directive is only read as one when it is the first thing on + // its line, so it is written at the start of the line whatever the + // indentation around it. The line break inside the dedent doesn't add a + // line, it only resets the indentation of the line the comment starts. + if is_line_directive(comment) { + return write!( + f, + [dedent_to_root(&format_args![ + hard_line_break(), + comment.piece().as_piece() + ])] + ); + } + // It seems like this is only worth customizing for multi-line comments // that need to be aligned together write!(f, [comment.piece().as_piece()]) } } +/// Whether the comment is a `#line` directive, which maps source references in +/// generated code back to another file. R reads `#line` followed by a line +/// number as one, but only at the start of a line. +fn is_line_directive(comment: &SourceComment) -> bool { + comment.lines_before() > 0 + && comment + .piece() + .text() + .strip_prefix("#line") + .is_some_and(|rest| { + rest.trim_start_matches([' ', '\t']) + .starts_with(|c: char| c.is_ascii_digit()) + }) +} + #[derive(Eq, PartialEq, Copy, Clone, Debug, Default)] pub struct RCommentStyle; diff --git a/crates/air_r_formatter/tests/specs/r/comment_line_directive.R b/crates/air_r_formatter/tests/specs/r/comment_line_directive.R new file mode 100644 index 00000000..413fb815 --- /dev/null +++ b/crates/air_r_formatter/tests/specs/r/comment_line_directive.R @@ -0,0 +1,28 @@ +#line 1 "top.R" +x <- 1 + +{ +#line 1 "file1.R" + withAutoprint({ show.srcref() }) +} + +f <- function() { + x +#line 10 "gen.R" + y +} + +fn( + a, +#line 20 "gen.R" + b +) + +{ + # Comments that only look like one stay indented +#lines of text +#line up the columns + z +} + +x #line 30 "gen.R" diff --git a/crates/air_r_formatter/tests/specs/r/comment_line_directive.R.snap b/crates/air_r_formatter/tests/specs/r/comment_line_directive.R.snap new file mode 100644 index 00000000..4a504543 --- /dev/null +++ b/crates/air_r_formatter/tests/specs/r/comment_line_directive.R.snap @@ -0,0 +1,87 @@ +--- +source: crates/air_formatter_test/src/snapshot_builder.rs +info: r/comment_line_directive.R +--- +# Input + +```R +#line 1 "top.R" +x <- 1 + +{ +#line 1 "file1.R" + withAutoprint({ show.srcref() }) +} + +f <- function() { + x +#line 10 "gen.R" + y +} + +fn( + a, +#line 20 "gen.R" + b +) + +{ + # Comments that only look like one stay indented +#lines of text +#line up the columns + z +} + +x #line 30 "gen.R" + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Space +Indent width: 2 +Line ending: LF +Line width: 80 +Persistent line breaks: Respect +Assignment style: Arrow +Table: fcase, rowwiseDT, tribble +----- + +```R +#line 1 "top.R" +x <- 1 + +{ +#line 1 "file1.R" + withAutoprint({ + show.srcref() + }) +} + +f <- function() { + x +#line 10 "gen.R" + y +} + +fn( + a, +#line 20 "gen.R" + b +) + +{ + # Comments that only look like one stay indented + #lines of text + #line up the columns + z +} + +x #line 30 "gen.R" +```