1

I'm trying to find a place of the warning in the function:

fun <- function(x, y){
   z = sum(x,y)
   if(z > 15)
     warning("Potential problem")
   
   return(z)
}

x = 10; y = 20
fun(x, y)

The result I'd like to get is the line number of the warning (not only warning msgs created by developer) and the function name where it exists. The name of a function I can get with the withCallingHandlers function, however I don't know how to find the line number of the warning.

|function_name | warning_index | 
--------------------------------
|fun           |4              | 
mario19088
  • 101
  • 6
  • 1
    There is a [question](https://stackoverflow.com/questions/1445964/how-to-get-r-script-line-numbers-at-error) about this asked in 2009. The simplest answer seems to be `options(show.error.locations = TRUE)` though it's from 2016 and some comments say it isn't reliable. Does it work for you? – SamR Feb 15 '23 at 10:27
  • 1
    It doesn't work. There is no change of the result. I'd like to get the line of a code where it spotted a warning, not an error so maybe because of that there is no effect for warnings. – mario19088 Feb 15 '23 at 13:17

1 Answers1

2

EDITED to use base functions:

You can use sys.calls() to see the call stack, and then look through it for lines with debug info. Here's a demonstration that does it.

# First, some code that will generate a warning

fun <- function(x, y){
  z = sum(x,y)
  if(z > 15)
    warning("Potential problem")
  
  return(z)
}

x = 10; y = 20

# Here's a handler that looks through the call stack
# for locations.  Not all calls have recorded locations
# (most packages are installed without debug info) 
# but this will find the debug info if it is there,
# and add it to the warning message.

locatedWarnings <- function(e) {
  calls <- sys.calls()
  locations <- character()
  for (i in rev(seq_along(calls)))
    if (!is.null(srcref <- getSrcref(calls[[i]])))
      locations <- c(locations, sprintf("%s:%d", getSrcFilename(srcref), srcref[1]))
  
  # If we found any locations, redo the warning
  # with those locations prepended to the message
  
  if (length(locations)) {
    call <- if (!is.null(e$call)) paste("In", deparse(e$call)) else ""
    warning(sprintf("%s at %s: %s", call, paste(locations, collapse=","), conditionMessage(e)), call. = FALSE)
    invokeRestart("muffleWarning")
  }
}


withCallingHandlers(fun(x, y), 
                    warning = locatedWarnings)
#> Warning: In fun(x, y) at <text>:5: Potential problem
#> [1] 30

Created on 2023-02-15 with reprex v2.0.2

If you put this example in a file and source it with the default keep.source = TRUE, you'll get the filename and line for the warning line as well as the withCallingHandlers() line. Not sure why reprex didn't give the second one. If you just execute it by cut and paste to the console you won't get very useful line info, because every statement restarts the line count.

user2554330
  • 37,248
  • 4
  • 43
  • 90