duncantl/CodeDepends

how to generate call graph on a function and not a package

Opened this issue · 5 comments

How is one supposed to create a call-graph using makeCallGraph on a function call?

For example, if I wanted to know all the functions that get called by doing:

lm(mpg ~ hp, data = mtcars)

I would have thought I would do something like:

gg = makeCallGraph("lm(mpg ~ hp, data = mtcars)")

But I get the error:

Error in .local(obj, all, ...) : 
Don't know how to make a call graph from this string: lm(mpg ~ hp, data = mtcars)

I was also wondering if this is possible. From the documentation at
https://cran.r-project.org/web/packages/CodeDepends/CodeDepends.pdf
it appears that it currently only accepts packages. However in the vignette it says "We can also create call graphs for functions or entire packages", so I am not sure

Hi, so sorry this apparently slipped by my radar for a full year (mea culpa).

The issue here is that you can't build a callGraph for a specific invocation, only for functions or packages as a whole.

gg <- makeCallGraph("lm", all  = TRUE)
> nodes(gg)
 [1] "-"              "!"              "!="             ".getXlevels"   
 [5] "["              "[[<-"           "{"              "*"             
 [9] "&&"             "<-"             "=="             "$<-"           
[13] "as.vector"      "attr"           "c"              "class<-"       
[17] "eval"           "gettextf"       "if"             "is.empty.model"
[21] "is.matrix"      "is.null"        "is.numeric"     "length"        
[25] "list"           "lm.fit"         "lm.wfit"        "match"         
[29] "match.call"     "matrix"         "model.matrix"   "model.offset"  
[33] "model.response" "model.weights"  "names"          "ncol"          
[37] "nrow"           "NROW"           "numeric"        "parent.frame"  
[41] "quote"          "return"         "stop"           "sum"           
[45] "warning"        "lm"            

does work for me, though from what I'm seeing its not properly (fully) recursive, as .getXlevels contains a call to vapply which doesn't appear here. I will try to find time to investigate that.

The CodeAnalysis package is probably a better place to get this functionality.
You will also need to install rstatic. Both packages should be installed directly from the code on github.

@duncantl does the functionality in https://github.com/duncantl/CodeAnalysis fully subsume makeCallGraph in this package? If so, we should deprecate/remove the functions in this package (instead of me going in to fix them).

A very brief glance at callGraph.R didn't show me the option for being recursive, but then, the recursive argument here isn't connected to anything, so I guess that's a wash?

FYI, I added this top-level functionality in CodeAnalysis, i.e.,

g = callGraph(quote ( lm ( mpg ~ wt + cyl, mtcars) )  ), recursive = 2)
plot(g)

gives the call information and draws the graph. One can use recursive = TRUE or recursive = positive.integer to get the entire call graph (typically way to big and takes a while) or the first "positive.integer" descendants/layers from the current call.

One can use callGraph( "lm ( mpg ~ wt + cyl, mtcars) ", recursive = 3) but working directly with the language objects is better, e.g., quote above or

callGraph(parse(text = codeString) , recursive = 2)