PaRe Report: #!P_TITLE"

knitr::opts_chunk$set(echo = TRUE)
library(PaRe)
library(dplyr)
repo <- PaRe::Repository$new("#!P_PATH")

Package overview

repo %>%
  PaRe::pkgDiagram() %>%
  DiagrammeRsvg::export_svg() %>%
  magick::image_read_svg()

Summary of package functions

defFuns <- PaRe::getDefinedFunctions(repo)

defFuns <- defFuns %>%
  dplyr::mutate(size = lineEnd - lineStart + 1)
DT::datatable(data.frame(
  min = c(min(defFuns$nArgs, na.rm = TRUE), 
          min(defFuns$size, na.rm = TRUE), 
          min(defFuns$cycloComp, na.rm = TRUE)),
  median = c(median(defFuns$nArgs, na.rm = TRUE), 
             median(defFuns$size, na.rm = TRUE), 
             median(defFuns$cycloComp, na.rm = TRUE)),
  max = c(max(defFuns$nArgs, na.rm = TRUE), 
          max(defFuns$size, na.rm = TRUE), 
          max(defFuns$cycloComp, na.rm = TRUE)),
  row.names = c("Number of arguments",
                "Lines of code",
                "Cyclomatic complexity")), 
  options = list(dom = 't'))
gg_nArgs <- defFuns %>% 
  ggplot2::ggplot()+
  ggplot2::geom_histogram(ggplot2::aes(nArgs), binwidth = 1,
                 colour = "black",
                 fill = "grey")+
  ggplot2::theme_minimal()+
  ggplot2::xlab("Number of arguments")

gg_size <- defFuns %>% 
  ggplot2::ggplot()+
  ggplot2::geom_histogram(ggplot2::aes(size), binwidth = 1,
                 colour = "black",
                 fill = "grey")+
  ggplot2::theme_minimal()+
  ggplot2::xlab("Lines of code")

gg_cycloComp <- defFuns %>% 
  ggplot2::ggplot()+
  ggplot2::geom_histogram(ggplot2::aes(cycloComp), binwidth = 1,
                 colour = "black",
                 fill = "grey")+
  ggplot2::theme_minimal()+
  ggplot2::xlab("Cyclomatic complexity")

cowplot::plot_grid(gg_nArgs, gg_size, gg_cycloComp, nrow = 3)
p <- defFuns %>% 
  ggplot2::ggplot(ggplot2::aes(group = name))+
  ggplot2::geom_point(ggplot2::aes(size, cycloComp, 
                          colour = nArgs),
                      size = 3)+
  ggplot2::scale_colour_gradient(name = "Number of\nargruments",
                               low = "blue", high = "red")  +
  ggplot2::theme_minimal() +
  ggplot2::xlab("Lines of code") +
  ggplot2::ylab("Cyclomatic complexity") +
  ggplot2::theme(legend.position = "top")

  plotly::ggplotly(p,
                  tooltip = c("group", "colour",
                              "x", "y"))

Function details

colours <- c("", "#81d4fa", "#03a9f4")
argBreaks <- c(5, 7)
complexBreaks <- c(15, 30)
lineBreaks <- c(100, 200)

DT::datatable(
  defFuns %>%
    dplyr::mutate(file_start = paste0(.data$fileName, " (from line: ", lineStart, ")")) %>% 
    dplyr::select("name", "nArgs", "size","cycloComp", "file_start") %>% 
    dplyr::rename(
      "Function" = "name",
      "Number of arguments" = "nArgs",
      "Lines of code" = "size",
      "Cyclomatic complexity" = "cycloComp",
      "Location" = "file_start"),
  rownames = FALSE) %>%
  DT::formatStyle("Number of arguments", backgroundColor = DT::styleInterval(argBreaks, colours)) %>%
  DT::formatStyle("Cyclomatic complexity", backgroundColor = DT::styleInterval(complexBreaks, colours)) %>%
  DT::formatStyle("Lines of code", backgroundColor = DT::styleInterval(lineBreaks, colours))

Use of other programming languages

DT::datatable(
  PaRe::countPackageLines(repo),
  rownames = "# lines of code")

Style adherence, syntax errors and possible semantic issues

Summary

lintMsgs <- PaRe::lintRepo(repo)

DT::datatable(PaRe::lintScore(repo, lintMsgs) %>% 
                dplyr::rename("Percentage of lines assessed" = "pct"),
              rownames = FALSE)

Warnings

DT::datatable(
  lintMsgs %>%
    dplyr::filter(type == "warning") %>% 
  dplyr::group_by(message) %>%
  dplyr::tally(sort = TRUE),
              rownames= FALSE
)

Style

DT::datatable(
  lintMsgs %>%
    dplyr::filter(type == "style") %>% 
  dplyr::group_by(message) %>%
  dplyr::tally(sort = TRUE),
              rownames= FALSE
)

Dependency review

Check dependencies against whitelist

DT::datatable(PaRe::checkDependencies(repo = repo, nThreads = "#!P_THREADS"))

Dependency characteristics

tryCatch({
  graphData <- PaRe::getGraphData(repo = repo, packageTypes = "Imports")

DT::datatable(data.frame(
  countVertices = length(igraph::V(graphData)),
  countEdges = length(igraph::E(graphData)),
  meanDegree = round(mean(igraph::degree(graphData)), 2),
  meanDistance = round(mean(igraph::distances(graphData)), 2)
  ),
              rownames= FALSE)
}, error = function(e) {
  message("Could not get graph data with error:")
  message(sprintf("\t%s", e))
})

Function use per dependency

funsUsed <- PaRe::getFunctionUse(repo = repo)

DT::datatable(
  funsUsed,
  rownames = FALSE)
function_sub <- funsUsed %>% 
  dplyr::filter(!pkg %in% c("base"))

fun_counts <- function_sub %>%
  dplyr::group_by(fun, pkg, name = "n") %>%
  dplyr::tally()

# Filter functions that are defined in the package
nonPkgFuns <- fun_counts[!fun_counts$fun %in% defFuns$fun, ]

ggplot2::ggplot(
  data = nonPkgFuns,
  mapping = ggplot2::aes(x = .data$fun, y = .data$n, fill = .data$pkg)) +
  ggplot2::geom_col() +
  ggplot2::facet_wrap(
    dplyr::vars(.data$pkg),
    scales = "free_x",
    ncol = 2) +
  ggplot2::theme_bw() +
  ggplot2::theme(
    legend.position = "none",
    axis.text.x = (ggplot2::element_text(angle = 45, hjust = 1, vjust = 1)))

Further reading

Style Guide

The styling is based on the following style guide:

Cyclomatic Complexity

Cyclomatic Complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program's source code. It was developed by Thomas J. McCabe, Sr. in 1976.

And is calculated as follows: $M = E - N + 2P$

The complexity score is interpreted as follows:

  • 1-10 Simple procedure, little risk
  • 11-20 More complex, moderate risk
  • 21-50 Complex, high risk
  • >50 Untestable code, very high risk

link, 2023-02-10



Try the PaRe package in your browser

Any scripts or data that you put into this service are public.

PaRe documentation built on April 3, 2025, 6:46 p.m.