A toolchain
for R.

A language server, a type checker, and a formatter, written in Rust.

Language server

Works in any editor that supports LSP.

sales.R report.R ry
# one sale, and what is left of it after fees
sale: list{region: character, amount: double, closed: logical} <- list(region = "north", amount = 1240.5, closed = TRUE)
margin: <T: numeric, U: numeric> fn(gross: T, rate: U) -> double <- function(gross, rate) gross * (1 - rate)
net: double <- margin(sale$amount, 0.18)
label: character <- paste0(sale$region, ": ", round(net, 2))
message(label)
3 references
R/sales.R4:1margin <- function(gross, rate) gross * (1 - rate)
R/sales.R6:8net <- margin(sale$amount, 0.18)
R/report.R2:28paste0(sale$region, " ", margin(sale$amount, rate))
Record fields, with their inferred types. Inferred type and definition site. In this file, another file, or a stub. Every read and write, across the workspace. Every occurrence of the binding. Inferred types. Nothing here is annotated.

Editor features

Checker

Lints out of the box. Type checking with [check] typing = true.

R/sales.R no configuration
read_sales <- function(path) {
read.csv(path, stringsAsFactors = FALSE)
}
top_regions <- function(sales, n) {
ranked = sales[order(-sales$amount), ]
head(unique(ranked$region), n)
}
report <- function(sales, regions) {
message(nrwo(sales), " rows in ", length(regions), " regions")
invisible(regions)
}
sales <- read_sales("sales.csv")
regions <- top_regions(sales, 5)
verbose <- T
if (verbose) report(sales, regions)
$ ry check
assignment-operator
! Use <-, not =, for assignment
--[R/sales.R:6:10]
5 | top_regions <- function(sales, n) {
6 | ranked = sales[order(-sales$amount), ]
| ^
7 | head(unique(ranked$region), n)
unresolved
! I could not resolve `nrwo` in this package, its imports, or builtins. Did you mean `nrow`?
--[R/sales.R:11:11]
10 | report <- function(sales, regions) {
11 | message(nrwo(sales), " rows in ", length(regions), " regions")
| ^^^^
12 | invisible(regions)
boolean-shorthand
! Use TRUE, not T, for Boolean values
--[R/sales.R:18:12]
17 |
18 | verbose <- T
| ^
19 | if (verbose) report(sales, regions)
3 problems in 1 file
Unresolved names and lints, with no setup. exit 1

Tour Diagnostic codes

Formatter

Normalizes spacing, indentation, and braces. Keeps your line breaks.

totals.R operators, commas, quotes
as written
totals<-sapply(sales,function(s)s$amount)
top<-sales[totals>threshold ,]
message(paste0('kept: ',length(top),' of ',length(sales)))
ry fmt
totals <- sapply(sales, function(s) s$amount)
top <- sales[totals > threshold, ]
message(paste0("kept: ", length(top), " of ", length(sales)))
$ ry fmt --diff totals.R Spaces around operators and after commas, double quotes.

Formatter rules

Install

1 · Install

cargo install --git https://github.com/felix-andreas/ry ry-lang

2 · Run it on your project

ry fmt .     # format
ry check .   # lint and type-check

No Rust toolchain? Download a prebuilt release, or install the VS Code extension, which bundles one.