Skip to content

Commit 9d8470b

Browse files
Merge pull request #543 from lorenzwalthert/fix-braces-in-function-calls
- Force brace expression in function calls be on their own line (#543).
2 parents 542fce2 + 1c99706 commit 9d8470b

17 files changed

+970
-141
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626
## Minor improvements and fixes
2727

28+
* brace expressions in function calls are formatted in a less compact way. This
29+
improves the formatting of `tryCatch()` in many cases (#543).
30+
2831
* escape characters in roxygen code examples are now correctly escaped (#512).
2932

3033
* style selection Addin now preserves line break when the last line selected is

R/io.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ read_utf8_bare <- function(con, warn = TRUE) {
7474
"The file ", con, " is not encoded in UTF-8. ",
7575
"These lines contain invalid UTF-8 characters: "
7676
),
77-
paste(c(head(i), if (n > 6) "..."), collapse = ", ")
77+
paste(c(utils::head(i), if (n > 6) "..."), collapse = ", ")
7878
)
7979
}
8080
x

R/rules-line-break.R

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,88 @@
1-
# A { should never go on its own line
2-
remove_line_break_before_curly_opening <- function(pd) {
3-
rm_break_idx <- which((pd$token_after == "'{'") & (pd$token != "COMMENT"))
4-
rm_break_idx <- setdiff(rm_break_idx, nrow(pd))
5-
if (length(rm_break_idx) > 0) {
1+
#' Set line break before a curly brace
2+
#'
3+
#' Rule:
4+
#' * Principle: Function arguments that consist of a braced expression always
5+
#' need to start on a new line
6+
#' * Exception: [...] unless it's the last argument and all other
7+
#' arguments fit on the line of the function call
8+
#' * Exception: [...] or they are named.
9+
#' * Extension: Also, expressions following on braced expressions also cause a
10+
#' line trigger.
11+
#' @keywords internal
12+
#' @examples
13+
#' \dontrun{
14+
#' tryCatch(
15+
#' {
16+
#' f(8)
17+
#' },
18+
#' error = function(e) NULL
19+
#' )
20+
#' # last-argument case
21+
#' testthat("braces braces are cool", {
22+
#' code(to = execute)
23+
#' })
24+
#' call2(
25+
#' x = 2,
26+
#' {
27+
#' code(to = execute)
28+
#' },
29+
#' c = { # this is the named case
30+
#' g(x = 7)
31+
#' }
32+
#' )
33+
#' tryGugus(
34+
#' {
35+
#' g5(k = na)
36+
#' },
37+
#' a + b # line break also here because
38+
#' # proceded by brace expression
39+
#' )
40+
#' }
41+
set_line_break_before_curly_opening <- function(pd) {
42+
line_break_to_set_idx <- which(
43+
(pd$token_after == "'{'") & (pd$token != "COMMENT")
44+
)
45+
46+
line_break_to_set_idx <- setdiff(line_break_to_set_idx, nrow(pd))
47+
if (length(line_break_to_set_idx) > 0) {
648
is_not_curly_curly <- map_chr(
7-
rm_break_idx + 1L,
49+
line_break_to_set_idx + 1L,
850
~ next_terminal(pd[.x, ], vars = "token_after")$token_after
951
) != "'{'"
10-
is_not_curly_curly_idx <- rm_break_idx[is_not_curly_curly]
52+
last_expr_idx <- max(which(pd$token == "expr"))
53+
is_last_expr <- ifelse(pd$token[1] == "IF",
54+
# rule not applicable for IF
55+
TRUE, (line_break_to_set_idx + 1L) == last_expr_idx
56+
)
57+
eq_sub_before <- pd$token[line_break_to_set_idx] == "EQ_SUB"
58+
# no line break before last brace expression and named brace expression to
59+
should_be_on_same_line <- is_not_curly_curly & (is_last_expr | eq_sub_before)
60+
is_not_curly_curly_idx <- line_break_to_set_idx[should_be_on_same_line]
1161
pd$lag_newlines[1 + is_not_curly_curly_idx] <- 0L
62+
63+
# other cases: line breaks
64+
should_not_be_on_same_line <- is_not_curly_curly & (!is_last_expr & !eq_sub_before)
65+
should_not_be_on_same_line_idx <- line_break_to_set_idx[should_not_be_on_same_line]
66+
67+
pd$lag_newlines[1 + should_not_be_on_same_line_idx] <- 1L
68+
69+
# non-curly expressions after curly expressions must have line breaks
70+
if (length(should_not_be_on_same_line_idx) > 0) {
71+
comma_exprs_idx <- which(pd$token == "','")
72+
comma_exprs_idx <- setdiff(comma_exprs_idx, 1 + is_not_curly_curly_idx)
73+
non_comment_after_comma <- map_int(comma_exprs_idx,
74+
next_non_comment,
75+
pd = pd
76+
)
77+
non_comment_after_expr <-
78+
non_comment_after_comma[non_comment_after_comma > should_not_be_on_same_line_idx[1]]
79+
pd$lag_newlines[non_comment_after_comma] <- 1L
80+
}
1281
}
1382
pd
1483
}
1584

85+
1686
set_line_break_around_comma <- function(pd) {
1787
comma_with_line_break_that_can_be_removed_before <-
1888
(pd$token == "','") &

R/style-guides.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ tidyverse_style <- function(scope = "tokens",
114114
line_break_manipulators <- if (scope >= "line_breaks") {
115115
lst(
116116
set_line_break_around_comma,
117-
remove_line_break_before_curly_opening,
117+
set_line_break_before_curly_opening,
118118
remove_line_break_before_round_closing_after_curly =
119119
if (strict) remove_line_break_before_round_closing_after_curly,
120120
remove_line_break_before_round_closing_fun_dec =

man/invalid_utf8.Rd

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/set_line_break_before_curly_opening.Rd

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/curly-curly/mixed-in.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ call({
6666

6767
## ............................................................................
6868
## multiple ####
69+
call("test", {
70+
1
71+
})
72+
73+
call(
74+
"test", {
75+
1
76+
})
77+
78+
call("test",
79+
{
80+
1
81+
})
82+
83+
call("test", {
84+
1 }
85+
)
86+
6987
call({
7088
1
7189
}, a + b, { 33 / f(c)})

0 commit comments

Comments
 (0)