Overview
sonar_fix() is the complement to
sonar_analyse(). While sonar_analyse()
inspects your code and reports issues, sonar_fix()
automatically corrects many of them — similar to
SonarQube AutoFix, OpenRewrite recipes, or IDE quick-fixes.
⚠️ Unlike sonar_analyse() which is read-only,
sonar_fix() modifies files. Always preview with
dry_run = TRUE (the default) first.
Fix categories
sonar_fix() groups corrections into 18 categories. Use
the fixes parameter to select which ones to apply.
Formatting ("styler" or "air")
Uses styler::style_dir() or Posit’s air
formatter to apply the tidyverse style guide:
# Use styler (default)
fix <- sonar_fix(".", fixes = "styler")
# Use air (faster, needs to be installed first)
install_air()
fix <- sonar_fix(".", fixes = "styler", formatter = "air")Corrections include: indentation, spacing, parentheses alignment, line breaks, pipe formatting, braces, blank lines.
Spacing ("spacing")
Fixes missing spaces around operators and assignments:
x<-1 # Before: no spaces
x <- 1 # After: proper spacing
y = 2 # Before: space only before =
y <- 2 # After: <- with spacesTRUE/FALSE ("true_false")
Replaces T/F with
TRUE/FALSE:
if(T) # Before
if(TRUE) # After
x <- F # Before
x <- FALSE # AfterNULL ("null")
Converts x=NULL to x <- NULL (outside
function arguments):
x = NULL # Before
x <- NULL # AfterCleanup ("cleanup")
Multiple cleanup operations:
# Remove double comment separator lines
########## # (removed if duplicated)
# Remove trailing whitespace
"hello " # trailing space removed
# Remove multiple consecutive blank lines
# line 1
# line 2 (removed, only one blank line)
# Ensure single trailing newline at EOFPipes ("pipes")
Converts %>% (magrittr pipe) to |>
(base R native pipe):
x %>% f() # Before
x |> f() # AfterReturn ("return")
Fixes multi-line return() calls:
Assignment ("assignment")
Converts = to <- for assignment (outside
function calls):
x = 5 # Before
x <- 5 # AfterUnused Variables ("unused_vars")
Detects and removes variable assignments that are never read within the same file:
unused_value <- 42 # Before: variable never used elsewhere
# After: line removedUses conservative heuristics to avoid false positives: - Skips
variables shorter than 3 characters - Skips common names
(i, j, tmp, etc.) - Skips
assignments from function calls (may have side effects) - Skips
<<- super-assignments (visible elsewhere)
⚠️ Enabled in fixes = "all" — use with
dry_run = TRUE first to review what would be removed.
Duplicate Libraries ("duplicate_libs")
Detects and removes duplicate library() calls loading
the same package multiple times:
Report-only categories
These categories detect issues but do not modify files:
-
"library"— Detectslibrary(x)calls that may be unused (also counts duplicates) -
"namespace"— Suggests convertinglibrary(x) + f()tox::f() -
"dead_code"— Detects expressions without effect (e.g.1+1standalone)
Safety features
Dry-run mode (default)
dry_run = TRUE previews changes without modifying
anything. The result shows which files would change and how many fixes
of each type:
Backup
Use backup = TRUE to create .bak copies
before modifying:
fix <- sonar_fix(".", backup = TRUE, dry_run = FALSE)Parallel processing
Files are processed in parallel by default, using all available cores:
# Custom number of cores
fix <- sonar_fix(".", parallel = TRUE, n_cores = 4)JSON report
A JSON report is generated by default:
sonar_fix(".", dry_run = TRUE, report = TRUE, report_file = "sonar-fixes.json")Example output:
Integration with CI/CD
GitLab CI: auto-fix + Merge Request
In your .gitlab-ci.yml, after running
sonar_analyse(), trigger sonar_fix() to
auto-correct issues and open a Merge Request:
rsonar-fix:
stage: fix
when: manual
script:
- |
R -q -e "
library(rsonar)
fix <- sonar_fix('.', dry_run = FALSE)
# If there are changes, create a branch and merge request
if (fix$files_modified > 0) {
system2('git', c('checkout', '-b', 'auto/style'))
system2('git', c('add', '.'))
system2('git', c('commit', '-m', 'style: auto-fix R code'))
system2('git', c('push', '-o', 'merge_request.create',
'origin', 'auto/style'))
}
"Corrections NOT applied
The following are never auto-fixed and remain in
sonar_analyse() for developer review:
- Business logic changes
- Renaming
- Function removal
- API changes
- Type changes
- Algorithm simplification
- Cyclomatic complexity
Comparison: sonar_analyse() vs
sonar_fix()
| Aspect | sonar_analyse() |
sonar_fix() |
|---|---|---|
| Read-only | ✅ Yes | ❌ Modifies files |
| Reported issues | All | Only safe auto-fixes |
| Default mode | Analysis | Dry-run preview |
| Pre-commit usage | Check quality | Auto-format code |
| CI usage | Gate + Reports | Auto-correct + MR/PR |
| Categories | ~20 rule types | 18 fix families |
See also
- Introduction to rsonar for a general overview
- CI/CD Integration for pipeline configuration
- Technical Debt for debt estimation