Development
How to contribute to Roughly
VS Code Extension Setup
Section titled “VS Code Extension Setup”- Run
cd editors/code && bun install
. This installs all necessary npm modules - Press Ctrl+Shift+B in VS Code to start compiling the client in watch mode.
- Switch to the Run and Debug View in the Sidebar (Ctrl+Shift+D).
- Select
Launch Client
from the drop down (if it is not already). - Press ▷ to run the launch config (F5).
- In the Extension Development Host instance of VSCode, open a document with a
.R
extension.
Words of warning
Section titled “Words of warning”The launch.json
contains a setting:
"autoAttachChildProcesses": true,
For me this led to the issue that the language server wasn’t spawned because I had CodeLLDB
from nixpkgs
installed.
Roadmap
Section titled “Roadmap”- static analysis
- type checking
- name binding
- are all names defined
- unused names (variables & parameters)
- variable renaming
- inlay hints
Formatting
Section titled “Formatting”Comments in expressions
Section titled “Comments in expressions”The main challenge in formatting code is handling comments because they can appear at any location. This is particualar hard to handle these expressions:
- if expression
- for expression
- repeat statment
- while expression
- binary operator
- extract operator
Example of if expressions
Section titled “Example of if expressions”For example, in an if expression comments can appear at any location (numerated):
if# 1( # open # 2 a && b # condition # 3) # close# 4{ y}# 5else# 6{ 4}
With a structured AST, we might typically could write our code in a concise functional style:
let condition = fmt(field("condition")?);let consequence = fmt(field("consequence")?);let alternative = fmt(field("alternative")?);format!("if({condition}) {{ {consequence} }} else {{ {alternative} }}");
However, due to the arbitrary placement of comments, we must adopt a more imperative style. This approach preserves comments but somewhat harder to comprehend:
let mut out = String::new();let mut cursor = node.walk();if cursor.goto_first_child() { loop { match cursor.field_name() { None => match child.kind() { "if" => out.push_str("if"), "else" => ..., "comment" => ..., _ => unreachable!(), }, Some(field_name) => match field_name { "open" => ..., "condition" => ..., "close" => ..., "consequence" | "alternative" => ..., _ => unreachable!(), }, };
if !cursor.goto_next_sibling() { cursor.goto_parent(); break; } }};out
Tree-sitter: How to handle required fields
Section titled “Tree-sitter: How to handle required fields”- For formatting we do an initial check if there are no errors, so we can safely assume that all required fields are present
- For type-checking we should do the same
- For checks/diagnostics that run while typing (syntax & fast), we cannot make any assumption
- Same is true for index. It should still be possible to index a file, while there are parse errors
tree-sitter-r vs R parser
Section titled “tree-sitter-r vs R parser”No default for parameter
Section titled “No default for parameter”Accept by tree-sitter-r
but rejected by R.
function(parameter =) {}
See https://github.com/r-lib/tree-sitter-r/issues/161
line break after else
Section titled “line break after else”This is valid R but cannot be parsed by tree-sitter-r
if (TRUE) { 1} else{ 2}
Two line breaks after extract_operator
Section titled “Two line breaks after extract_operator”This is valid R but cannot be parsed by tree-sitter-r
foo$
bar
See https://github.com/r-lib/tree-sitter-r/issues/166
Linting ideas
Section titled “Linting ideas”- Empty loops: for, while, repeat
- unused variables
References
Section titled “References”- https://github.com/wch/r-source/blob/trunk/src/main/gram.y
- https://cran.r-project.org/doc/manuals/r-release/R-lang.html
- https://www.reddit.com/r/rust/comments/uu47mk/comment/i9dn0yg/
VS Code Extensions
Section titled “VS Code Extensions”- docs:
- examples:
Other Language Servers written in Rust
Section titled “Other Language Servers written in Rust”- https://github.com/gleam-lang/gleam/tree/main/compiler-core/src/language_server
- https://github.com/supabase-community/postgres-language-server
- tower-lsp
- https://github.com/Desdaemon/-lsp/
- https://github.com/FuelLabs/sway
- https://github.com/IWANABETHATGUY/tower-lsp-boilerplate
- https://github.com/TenStrings/glicol-lsp/blob/77e97d9c687dc5d66871ad5ec91b6f049de2b8e8/src/main.rs#L16
- https://github.com/Automattic/harper
- https://github.com/jfecher/ante/blob/5f7446375bc1c6c94b44a44bfb89777c1437aaf5/ante-ls/src/main.rs#L163
- async_lsp
Formatting
Section titled “Formatting”Language Design / Typing
Section titled “Language Design / Typing”- https://github.com/Glyphack/enderpy
- https://github.com/dgkf/R
- https://github.com/fabriceHategekimana/typr
- https://github.com/salsa-rs/salsa/blob/master/examples/calc/type_check.rs