Skip to content

Commit

Permalink
Mention index calls in error messages
Browse files Browse the repository at this point in the history
Part of #1406
  • Loading branch information
lionel- committed Jun 7, 2022
1 parent 11ff506 commit 8c5ddaa
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 3 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# rlang (development version)

* Error messages now mention indexed calls like `foo$bar()`.

* New `env_coalesce()` function to copy bindings from one environment
to another. Unlike approaches based on looping with `[[<-`,
`env_coalesce()` preserves active and lazy bindings.
Expand Down
42 changes: 42 additions & 0 deletions R/call.R
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,48 @@ is_call_simple <- function(x, ns = NULL) {
namespaced || is_symbol(head)
}

is_call_index <- function(x, ns = NULL) {
check_required(x)

if (!is_call(x)) {
return(FALSE)
}

out <- FALSE

while (is_call(fn <- x[[1]])) {
if (!is_call(fn, c("$", "@", "[", "[["))) {
return(FALSE)
}

if (!every(fn[-1], is_arg_index, ns)) {
return(FALSE)
}

out <- TRUE
x <- fn
}

out
}

is_arg_index <- function(arg, ns) {
if (!is_call(arg)) {
return(TRUE)
}

namespaced <- is_call(arg, c("::", ":::"))
if (namespaced) {
if (!is_null(ns) && !identical(namespaced, ns)) {
return(FALSE)
} else {
return(TRUE)
}
}

is_call_simple(arg)
}

#' Extract arguments from a call
#'
#' @inheritParams call_name
Expand Down
6 changes: 5 additions & 1 deletion R/cnd-abort.R
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,11 @@ error_call_as_string <- function(call) {
}

if (!is_call_simple(call)) {
return(NULL)
if (is_expression(call) && is_call_index(call)) {
return(as_label(call[1]))
} else {
return(NULL)
}
}

# Remove namespace for now to simplify conversion
Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/cnd-message.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
Code
writeLines(cnd_message_format_prefixed(err2))
Output
Error:
Error in `foo$bar()`:
! msg
Code
writeLines(cnd_message_format_prefixed(err3))
Expand Down
11 changes: 11 additions & 0 deletions tests/testthat/test-call.R
Original file line number Diff line number Diff line change
Expand Up @@ -592,3 +592,14 @@ test_that("call_name() and call_ns() detect `::` calls (#670)", {
expect_null(call_ns(quote(foo::bar)))
expect_null(call_ns(quote(foo:::bar)))
})

test_that("is_call_index() works", {
expect_true(is_call_index(quote(a$b(...))))
expect_true(is_call_index(quote(a@b$c[[d]](...))))
expect_true(is_call_index(quote(a@b$c[[d]](...))))
expect_true(is_call_index(quote(foo::a$b(...))))

expect_false(is_call_index(quote(a@b$c[[d]])))
expect_false(is_call_index(quote(1 + a@b$c[[d]])))
expect_false(is_call_index(quote((a@b$c[[d]])())))
})
5 changes: 4 additions & 1 deletion tests/testthat/test-cnd-abort.R
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,14 @@ test_that("NSE doesn't interfere with error call contexts", {
})

test_that("error_call() requires a symbol in function position", {
expect_null(format_error_call(quote(foo$bar())))
expect_null(format_error_call(quote((function() NULL)())))
expect_null(format_error_call(call2(function() NULL)))
})

test_that("error_call() preserves index calls", {
expect_equal(format_error_call(quote(foo$bar(...))), "`foo$bar()`")
})

test_that("error_call() preserves `if` (r-lib/testthat#1429)", {
call <- quote(if (foobar) TRUE else FALSE)

Expand Down

0 comments on commit 8c5ddaa

Please sign in to comment.