Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose internals used with other style guides #1043

Merged
merged 7 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion API
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,22 @@ cache_activate(cache_name = NULL, verbose = !getOption("styler.quiet", FALSE))
cache_clear(cache_name = NULL, ask = TRUE)
cache_deactivate(verbose = !getOption("styler.quiet", FALSE))
cache_info(cache_name = NULL, format = "both")
compute_parse_data_nested(text, transformers = tidyverse_style(), more_specs = NULL)
create_style_guide(initialize = default_style_guide_attributes, line_break = NULL, space = NULL, token = NULL, indention = NULL, use_raw_indention = FALSE, reindention = tidyverse_reindention(), style_guide_name = NULL, style_guide_version = NULL, more_specs_style_guide = NULL, transformers_drop = specify_transformers_drop(), indent_character = " ")
default_style_guide_attributes(pd_flat)
is_asymmetric_tilde_expr(pd)
is_comment(pd)
is_conditional_expr(pd)
is_curly_expr(pd)
is_for_expr(pd)
is_function_call(pd)
is_function_declaration(pd)
is_symmetric_tilde_expr(pd)
is_tilde_expr(pd, tilde_pos = c(1L, 2L))
is_while_expr(pd)
next_non_comment(pd, pos)
previous_non_comment(pd, pos)
scope_normalize(scope, name = substitute(scope))
specify_math_token_spacing(zero = "'^'", one = c("'+'", "'-'", "'*'", "'/'"))
specify_reindention(regex_pattern = NULL, indention = 0L, comments_only = TRUE)
specify_transformers_drop(spaces = NULL, indention = NULL, line_breaks = NULL, tokens = NULL)
Expand All @@ -17,7 +31,7 @@ style_pkg(pkg = ".", ..., style = tidyverse_style, transformers = style(...), fi
style_text(text, ..., style = tidyverse_style, transformers = style(...), include_roxygen_examples = TRUE, base_indention = 0L)
tidyverse_math_token_spacing()
tidyverse_reindention()
tidyverse_style(scope = "tokens", strict = TRUE, indent_by = 2, start_comments_with_one_space = FALSE, reindention = tidyverse_reindention(), math_token_spacing = tidyverse_math_token_spacing())
tidyverse_style(scope = "tokens", strict = TRUE, indent_by = 2L, start_comments_with_one_space = FALSE, reindention = tidyverse_reindention(), math_token_spacing = tidyverse_math_token_spacing())

## Foreign S3 methods

Expand Down
14 changes: 14 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,22 @@ export(cache_activate)
export(cache_clear)
export(cache_deactivate)
export(cache_info)
export(compute_parse_data_nested)
export(create_style_guide)
export(default_style_guide_attributes)
export(is_asymmetric_tilde_expr)
export(is_comment)
export(is_conditional_expr)
export(is_curly_expr)
export(is_for_expr)
export(is_function_call)
export(is_function_declaration)
export(is_symmetric_tilde_expr)
export(is_tilde_expr)
export(is_while_expr)
export(next_non_comment)
export(previous_non_comment)
export(scope_normalize)
export(specify_math_token_spacing)
export(specify_reindention)
export(specify_transformers_drop)
Expand Down
2 changes: 1 addition & 1 deletion R/detect-alignment.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#' list(styler.cache_name = NULL), # temporarily deactivate cache
#' {
#' transformers <- tidyverse_style()
#' pd_nested <- styler:::compute_parse_data_nested(c(
#' pd_nested <- compute_parse_data_nested(c(
#' "call(",
#' " ab = 1L,",
#' " a = 2",
Expand Down
101 changes: 74 additions & 27 deletions R/expr-is.R
Original file line number Diff line number Diff line change
@@ -1,38 +1,72 @@
#' Check whether a parse table corresponds to a certain expression
#' What is a parse table representing?
#'
#' @param pd A parse table.
#' Check whether a parse table corresponds to a certain expression.
#' @name pd_is
#'
#' @param pd A parse table.
#' @param tilde_pos Integer vector indicating row-indices that should be
#' checked for tilde. See 'Details'.
#'
#' @family third-party style guide helpers
#' @keywords internal
NULL

#' @describeIn pd_is Checks whether `pd` contains an expression wrapped in
#' curly brackets.
#' @keywords internal
#' @describeIn pd_is Checks whether `pd` contains an expression wrapped in curly brackets.
#' @examples
#' code <- "if (TRUE) { 1 }"
#' pd <- compute_parse_data_nested(code)
#' is_curly_expr(pd)
#' child_of_child <- pd$child[[1]]$child[[5]]
#' is_curly_expr(child_of_child)
#'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The blank lines are deliberate.

Without them, all examples are squished together like a centipede, and it's hard to tell where one ends and the other starts.

#' @export
is_curly_expr <- function(pd) {
if (is.null(pd)) {
return(FALSE)
}
pd$token[1L] == "'{'"
}

#' @describeIn pd_is Checks whether `pd` contains a `for` loop.
#' @examples
#' code <- "for (i in 1:5) print(1:i)"
#' pd <- compute_parse_data_nested(code)
#' is_for_expr(pd)
#' is_for_expr(pd$child[[1]])
#'
#' @export
is_for_expr <- function(pd) {
pd$token[1L] == "FOR"
}

#' @describeIn pd_is Checks whether `pd` contains is a conditional expression.
#' @keywords internal
is_cond_expr <- function(pd) {
#' @examples
#' code <- "if (TRUE) x <- 1 else x <- 0"
#' pd <- compute_parse_data_nested(code)
#' is_conditional_expr(pd)
#' is_conditional_expr(pd$child[[1]])
#'
#' @export
is_conditional_expr <- function(pd) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a better name than is_cond_expr().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why do we need to change all the *_expr() functions? Their current names are expressive as they are.

Copy link
Collaborator

@lorenzwalthert lorenzwalthert Oct 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no sorry I read your comment wrongly (which is why I deleted it). I thought you wanted *_expression() everywhere, but that is (obviously) not the case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

Okay, then this should be ready for your review. I don't have any additional changes in mind.

pd$token[1L] == "IF"
}

#' @describeIn pd_is Checks whether `pd` contains is a while loop.
#' @keywords internal
#' @describeIn pd_is Checks whether `pd` contains a `while` loop.
#' @export
is_while_expr <- function(pd) {
pd$token[1L] == "WHILE"
}


#' @describeIn pd_is Checks whether `pd` is a function call.
#' @keywords internal
#' @examples
#' code <- "x <- list(1:3)"
#' pd <- compute_parse_data_nested(code)
#' is_function_call(pd)
#' child_of_child <- pd$child[[1]]$child[[3]]
#' is_function_call(child_of_child)
#'
#' @export
is_function_call <- function(pd) {
if (is.null(pd)) {
return(FALSE)
Expand All @@ -44,56 +78,69 @@ is_function_call <- function(pd) {
}

#' @describeIn pd_is Checks whether `pd` is a function declaration.
#' @keywords internal
is_function_dec <- function(pd) {
#' @examples
#' code <- "foo <- function() NULL"
#' pd <- compute_parse_data_nested(code)
#' is_function_declaration(pd)
#' child_of_child <- pd$child[[1]]$child[[3]]
#' is_function_declaration(child_of_child)
#'
#' @export
is_function_declaration <- function(pd) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a better name than is_function_dec().

if (is.null(pd)) {
return(FALSE)
}
pd$token[1L] == "FUNCTION"
}

#' @describeIn pd_is Checks for every token whether or not it is a comment.
#' @keywords internal
#' @examples
#' code <- "x <- 1 # TODO: check value"
#' pd <- compute_parse_data_nested(code)
#' is_comment(pd)
#'
#' @export
is_comment <- function(pd) {
if (is.null(pd)) {
return(FALSE)
}
pd$token == "COMMENT"
}



#' Check whether a parse table contains a tilde
#'
#'
#' @param pd A parse table.
#' @param tilde_pos Integer vector indicating row-indices that should be
#' checked for tilde. See 'Details'.
#'
#' @describeIn pd_is Checks whether `pd` contains a tilde.
#' @details
#' A tilde is on the top row in the parse table if it is an asymmetric tilde
#' expression (like `~column`), in the second row if it is a symmetric tilde
#' expression (like `a~b`).
#' @keywords internal
#' @examples
#' code <- "lm(wt ~ mpg, mtcars)"
#' pd <- compute_parse_data_nested(code)
#' is_tilde_expr(pd$child[[1]]$child[[3]])
#' is_symmetric_tilde_expr(pd$child[[1]]$child[[3]])
#' is_asymmetric_tilde_expr(pd$child[[1]]$child[[3]])
#'
#' @export
is_tilde_expr <- function(pd, tilde_pos = c(1L, 2L)) {
if (is.null(pd) || nrow(pd) == 1L) {
return(FALSE)
}
any(pd$token[tilde_pos] == "'~'")
}

#' @rdname is_tilde_expr
#' @describeIn pd_is If `pd` contains a tilde, checks whether it is asymmetrical.
#' @export
is_asymmetric_tilde_expr <- function(pd) {
is_tilde_expr(pd, tilde_pos = 1L)
}

#' @rdname is_tilde_expr
#' @describeIn pd_is If `pd` contains a tilde, checks whether it is symmetrical.
#' @export
is_symmetric_tilde_expr <- function(pd) {
is_tilde_expr(pd, tilde_pos = 2L)
}

is_subset_expr <- function(pd) {
if (is.null(pd) || nrow(pd) == 1) {
if (is.null(pd) || nrow(pd) == 1L) {
return(FALSE)
}
pd$token[2L] %in% subset_token_opening
Expand Down Expand Up @@ -152,7 +199,7 @@ contains_else_expr_that_needs_braces <- function(pd) {
non_comment_after_else <- next_non_comment(pd, else_idx)
sub_expr <- pd$child[[non_comment_after_else]]
# needs braces if NOT if_condition, NOT curly expr
!is_cond_expr(sub_expr) && !is_curly_expr(sub_expr)
!is_conditional_expr(sub_expr) && !is_curly_expr(sub_expr)
} else {
FALSE
}
Expand Down
2 changes: 1 addition & 1 deletion R/initialize.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#' list(styler.cache_name = NULL), # temporarily deactivate cache
#' {
#' string_to_format <- "call( 3)"
#' pd <- styler:::compute_parse_data_nested(string_to_format)
#' pd <- compute_parse_data_nested(string_to_format)
#' styler:::pre_visit_one(pd, default_style_guide_attributes)
#' }
#' )
Expand Down
13 changes: 10 additions & 3 deletions R/nest.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@
#' @return A nested parse table. See [tokenize()] for details on the columns
#' of the parse table.
#' @importFrom purrr when
#' @keywords internal
#' @examples
#' code <- "
#' ab <- 1L # some comment
#' abcdef <- 2L
#' "
#' writeLines(code)
#' compute_parse_data_nested(code)
#' @export
compute_parse_data_nested <- function(text,
transformers,
more_specs) {
transformers = tidyverse_style(),
more_specs = NULL) {
parse_data <- text_to_flat_pd(text, transformers, more_specs = more_specs)
env_add_stylerignore(parse_data)
parse_data$child <- rep(list(NULL), length(parse_data$text))
Expand Down
2 changes: 1 addition & 1 deletion R/nested-to-tree.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ create_tree_from_pd_with_default_style_attributes <- function(pd,
#' list(styler.cache_name = NULL), # temporarily deactivate cache
#' {
#' code <- "a <- function(x) { if(x > 1) { 1+1 } else {x} }"
#' nested_pd <- styler:::compute_parse_data_nested(code)
#' nested_pd <- compute_parse_data_nested(code)
#' initialized <- styler:::pre_visit_one(
#' nested_pd, default_style_guide_attributes
#' )
Expand Down
2 changes: 1 addition & 1 deletion R/rules-indention.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ indent_braces <- function(pd, indent_by) {
#' @seealso set_unindention_child update_indention_ref_fun_dec
#' @keywords internal
unindent_fun_dec <- function(pd) {
if (is_function_dec(pd)) {
if (is_function_declaration(pd)) {
idx_closing_brace <- which(pd$token %in% "')'")
fun_dec_head <- seq2(2L, idx_closing_brace)
pd$indent[fun_dec_head] <- 0L
Expand Down
4 changes: 2 additions & 2 deletions R/rules-line-breaks.R
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ set_line_break_before_curly_opening <- function(pd) {
should_not_be_on_same_line_idx <- line_break_to_set_idx[
should_not_be_on_same_line
]
if (is_function_dec(pd)) {
if (is_function_declaration(pd)) {
should_not_be_on_same_line_idx <- setdiff(
1L + should_not_be_on_same_line_idx, nrow(pd)
)
Expand Down Expand Up @@ -228,7 +228,7 @@ remove_line_break_before_round_closing_after_curly <- function(pd) {
}

remove_line_breaks_in_fun_dec <- function(pd) {
if (is_function_dec(pd)) {
if (is_function_declaration(pd)) {
round_after <- (
pd$token == "')'" | pd$token_before == "'('"
) &
Expand Down
27 changes: 12 additions & 15 deletions R/rules-spaces.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ set_space_around_op <- function(pd_flat, strict) {
!getOption("styler.ignore_alignment", FALSE) &&
(
(is_function_call(pd_flat) && sum_lag_newlines > 2L) ||
(is_function_dec(pd_flat) && sum_lag_newlines > 1L)
(is_function_declaration(pd_flat) && sum_lag_newlines > 1L)
) &&
any(pd_flat$token %in% c("EQ_SUB", "','", "EQ_FORMALS"))
) {
Expand Down Expand Up @@ -96,10 +96,8 @@ style_space_around_token <- function(pd_flat,
pd_flat$spaces[idx_before] <- level_before
pd_flat$spaces[idx_after] <- level_after
} else {
pd_flat$spaces[idx_before] <-
pmax(pd_flat$spaces[idx_before], level_before)
pd_flat$spaces[idx_after] <-
pmax(pd_flat$spaces[idx_after], level_after)
pd_flat$spaces[idx_before] <- pmax(pd_flat$spaces[idx_before], level_before)
pd_flat$spaces[idx_after] <- pmax(pd_flat$spaces[idx_after], level_after)
}
pd_flat
}
Expand All @@ -110,12 +108,15 @@ style_space_around_tilde <- function(pd_flat, strict) {
strict, "'~'",
level_before = 1L, level_after = 1L
)
} else if (is_asymmetric_tilde_expr(pd_flat)) {
}

if (is_asymmetric_tilde_expr(pd_flat)) {
pd_flat <- style_space_around_token(pd_flat,
strict = TRUE, "'~'", level_before = 1L,
level_after = as.integer(nrow(pd_flat$child[[2L]]) > 1L)
)
}

pd_flat
}

Expand Down Expand Up @@ -286,7 +287,7 @@ start_comments_with_space <- function(pd, force_one = FALSE) {
comments$text
) %>%
trimws("right")
pd$short[is_comment] <- substr(pd$text[is_comment], 1, 5)
pd$short[is_comment] <- substr(pd$text[is_comment], 1L, 5L)
pd
}

Expand Down Expand Up @@ -345,20 +346,16 @@ remove_space_after_fun_dec <- function(pd_flat) {
}

remove_space_around_colons <- function(pd_flat) {
one_two_or_three_col_after <-
pd_flat$token %in% c("':'", "NS_GET_INT", "NS_GET")

one_two_or_three_col_before <-
lead(one_two_or_three_col_after, default = FALSE)
one_two_or_three_col_after <- pd_flat$token %in% c("':'", "NS_GET_INT", "NS_GET")
one_two_or_three_col_before <- lead(one_two_or_three_col_after, default = FALSE)

col_around <-
one_two_or_three_col_before | one_two_or_three_col_after
col_around <- one_two_or_three_col_before | one_two_or_three_col_after

pd_flat$spaces[col_around & (pd_flat$newlines == 0L)] <- 0L
pd_flat
}

#' Set space between EQ_SUB and "','"
#' Set space between `EQ_SUB` and `"','"`
#' @param pd A parse table.
#' @keywords internal
set_space_between_eq_sub_and_comma <- function(pd) {
Expand Down
Loading