flowRv2.14.1

Program Analysis for R

flowR is an open source static program analyzer for your R code. It helps you understand existing scripts, find quality issues, improve reproducibility, and check the validity of your analyses.

v2.14.1 · GPL-3.0

Get started Playground ★ Star on GitHub

Available for

VS Code Positron RStudio R package Docker npm

Try It Out

These run on the samples below. For your own code, open the playground, which runs flowR in your browser.

Point at any name below, or at an access like survey$age, and flowR keeps only the lines that matter.

It keeps the lines the value depends on, the called functions included, and drops the rest.

Which way?
origin: what the value is built from.
impact: what it goes on to affect.
survey.R
clean <- function(d) { d$age <- as.numeric(d$age) d } survey <- read.csv("survey.csv") survey <- clean(survey) mean_age <- mean(survey$age) model <- lm(income ~ age, data = survey) plot(survey$age)

On real-world R scripts, flowR (measured for v2.14.1) needs on average:

analyzing a script106 ms linting it84 ms slicing for one name0.6 ms

View the full stats on the benchmark page.

Features

Dependency analysis Which packages a project needs, and every file it reads, writes, sources, or plots to. Program slicing Backward, for the code that can affect one variable, and forward, for the code it goes on to affect. Linting Unused definitions, absolute paths, dead code, unseeded randomness: findings that need the dataflow, not a regex. Value and origin resolution What a name can hold, which definition it reads, and which function a call really reaches. Signature Database Signatures and documentation for every CRAN package, shipped with flowR and resolved without a network. Programming API The FlowrAnalyzer API provides you with a simple interface to use flowR programmatically.

Use Cases

Inherited codecomprehensionmaintenance

Someone left you a script that produces one number you need. Slice to that name and flowR drops every line that cannot affect it, which is usually most of them. The result still runs.

Reproducing a projectreproducibility

Before running anything, ask what it will touch: the packages it loads, the files it reads and writes, the plots it draws, and the scripts it sources. No execution, so nothing is overwritten.

Silent mistakescode qualitycorrectness

The script runs, produces a number, and the number is wrong. flowR reads the code the way it will actually execute, so it can point at the parts that will not do what you meant: a path that only exists on your machine, a sample drawn without a seed so nobody can repeat it, a result computed and then never used, a column read after it was dropped, a credential left in the source.

It reports these before you run anything, and the same analysis answers what a script writes, which packages it needs, and what a variable can hold at any point.

Where a name comes fromcomprehension

A variable is reassigned four times and passed through two functions. flowR answers which definition a use actually reads, and which function a call actually reaches, across files.

Data that changes shapecomprehensioncorrectness

A pipeline filters, joins and selects until a column is gone. The shape inference reports the rows and columns a data frame can have at every step, without the data.

Tooling of your ownextensibility

Every answer on this page is a query. Ask them over the server, the REPL or the FlowrAnalyzer API, and build the editor support your own workflow needs.

Ask for Something

Request a featurea question flowR cannot answer yet, or an R idiom it misreads Report a buga wrong answer, with the smallest script that shows it Ask a questionhow to phrase a query, or whether something is possible at all Suggest a linting rulea mistake you keep seeing in R code Report a vulnerabilityprivately, through the security policy

What flowR Computes

Simplified views of a program: a dataflow graph, a control flow graph, a call graph, a normalized syntax tree, and abstract values over them. Ask with the query API, look around with the search API, and start with the FlowrAnalyzerBuilder.

Contributing

Expand to see the details
  1. Get it running five minutes, and no R needed Clone it, run npm ci, then npm run flowr. That is the whole setup, and you do not need R installed: the tree-sitter parser is the default. See Developing for flowR for more details.
  2. Write a linting rule the friendliest first change This is where most people start, and it is genuinely small: one file with a name, some config, and a function over the graph. The wiki builds a complete rule with you, tests and all.
  3. Add a query ask something flowR cannot answer yet If you keep asking flowR the same thing by hand, turn it into a query. Everything on this page is one, and yours lands in the REPL, the server and the API at the same time.
  4. Propose a plugin teach the analyzer something new Plugins decide how versions, sources and configuration are resolved around an analysis. Tell us what you are missing in an issue first, and we will work out the shape with you.
  5. Open a pull request what we look at, and what we do not mind Conventional commits, npm run checkup passing, and a sentence about what you changed. Small pull requests get read first, and drafts are welcome if you are unsure.

Maintained at Ulm University by Florian Sihler, Oliver Gerstl and everyone else who pitched in, free software under the GPLv3. Funded by the German Research Foundation (DFG), grant 504226141, with a gift from Posit.