-
Notifications
You must be signed in to change notification settings - Fork 0
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
Caller-callee relationship for .R files in a package #2
Comments
Do you have an example package with a structure like you want? |
assuming you have cloned fledge on your machine and are in the root of the package directory
The file directional relationship is indicated in the colours. This info is also in x_rel_df where can you create any output you want. |
Very nice, thanks a lot! I'm looking for evil circles like this. Here I'm interested in the relationship between files: ideally the directed graph should be cycle-free. This means that it must have a topological sort order. To detect the cycles, I'm computing the strongly connected components -- those with size > 1 are clusters of nodes that can be reached mutually in the connected graph, there must be a cycle in such a cluster. (Can't use Maybe a variant of this code could find its place here? library(ggraph)
library(igraph)
library(tidyverse)
setwd("~/git/R/fledge")
x <- foreman::unpack()
#> Warning: No functions found in
#> /home/kirill/git/R/fledge/R/import.R
x_rel <- foreman::relationship(x)
x_rel_df <- as_tibble(as.data.frame(x_rel))
fun_file <-
x %>%
map(names) %>%
enframe("file", "fun") %>%
unnest(fun)
child_file <-
fun_file %>%
rename(child = fun, child_file = file)
x_file_rel_df <-
x_rel_df %>%
left_join(child_file) %>%
count(file, child_file)
#> Joining, by = "child"
graph <- igraph::graph_from_data_frame(x_file_rel_df, directed = TRUE)
scc <- igraph::components(graph, "strong")
circle_comp <- which(scc$csize > 1)[[1]]
circle_files <- names(scc$membership)[scc$membership == circle_comp]
x_file_rel_df %>%
filter(file %in% circle_files & child_file %in% circle_files) %>%
filter(file != child_file)
#> # A tibble: 5 x 3
#> file child_file n
#> <chr> <chr> <int>
#> 1 api-bump-version.R api-update-version.R 1
#> 2 api-bump-version.R bump-version.R 1
#> 3 api-update-version.R update-version.R 1
#> 4 bump-version.R api-update-version.R 1
#> 5 update-version.R api-bump-version.R 1
plot(igraph::induced_subgraph(graph, circle_files)) Created on 2020-10-23 by the reprex package (v0.3.0) |
(FWIW, this is a false positive for fledge -- there's a call of the form library(ggraph)
library(igraph)
library(tidyverse)
setwd("~/git/R/fledge")
x <- foreman::unpack()
#> Warning: No functions found in
#> /home/kirill/git/R/fledge/R/import.R
x_rel <- foreman::relationship(x)
x_rel_df <- as_tibble(as.data.frame(x_rel))
fun_file <-
x %>%
map(names) %>%
enframe("file", "fun") %>%
unnest(fun)
child_file <-
fun_file %>%
rename(child = fun, child_file = file)
x_file_rel_df <-
x_rel_df %>%
left_join(child_file) %>%
select(file, child_file, label = child) %>%
filter(file != child_file)
#> Joining, by = "child"
graph <- igraph::graph_from_data_frame(x_file_rel_df, directed = TRUE)
scc <- igraph::components(graph, "strong")
circle_comp <- which(scc$csize > 1)[[1]]
circle_files <- names(scc$membership)[scc$membership == circle_comp]
x_file_rel_df %>%
filter(file %in% circle_files & child_file %in% circle_files) %>%
filter(file != child_file)
#> # A tibble: 5 x 3
#> file child_file label
#> <chr> <chr> <chr>
#> 1 api-bump-version.R api-update-version.R check_which
#> 2 api-bump-version.R bump-version.R bump_version_impl
#> 3 api-update-version.R update-version.R update_version_impl
#> 4 bump-version.R api-update-version.R update_version
#> 5 update-version.R api-bump-version.R bump_version
plot(igraph::induced_subgraph(graph, circle_files)) Created on 2020-10-23 by the reprex package (v0.3.0) |
In R packages, I try to organize the code in .R files so that if a function in
a.R
calls a function inb.R
, no function fromb.R
calls back toa.R
, also not indirectly. How can foreman help verify or visualize this?Can we do a graphviz visualization with subgraphs -- each file creates a subgraph, each node is a function?
Can we create an igraph object, search for cycles, remove one edge, search again, ... to summarize? (We could label the edges so that they are named by the caller, to identify which function creates the cycle.)
I haven't tried the package yet, appreciate any pointers. Thanks!
The text was updated successfully, but these errors were encountered: