feat(r): add R-specific code smell detectors#450
feat(r): add R-specific code smell detectors#450peteromallet merged 3 commits intopeteromallet:mainfrom
Conversation
|
Really like the detector coverage here — the 10 detectors are well-chosen and the test suite is solid for the happy paths. A few things to fix before I can merge:
Happy to help if you want to pair on any of these. The detectors themselves are exactly what R support needs. |
|
I'll take a look tomorrow. |
9ef9846 to
e1ea153
Compare
Add 10 R-specific smell checks: setwd(), <<- global assign, attach(), rm(list=ls()), browser()/debug() leftovers, T/F ambiguity, 1:n() off-by-one, options(stringsAsFactors), and library() inside functions. Also adds custom_phases support to GenericLangOptions so generic plugins can inject language-specific phases without converting to full plugins.
- Fix _strip_r_comments to properly preserve string literals by using placeholder substitution before stripping comments - Fix _detect_library_in_function to only track function-scoped braces by finding function definitions and matching their brace pairs, eliminating false positives from if/for/while blocks at top level - Replace custom _find_r_files with framework's find_source_files to respect project-configured exclusion patterns - Add tests for the fixes: hash in strings, library in non-function blocks, nested functions
Replace manual brace tracking with tree-sitter AST parsing for more accurate detection of library()/require() calls inside function bodies. Includes fallback to regex-based detection when tree-sitter is unavailable. Benefits: - Properly handles nested functions, strings, and edge cases - Uses existing R_SPEC tree-sitter configuration - Deduplicates matches in nested function scenarios
3372d8a to
7062c09
Compare
Summary
Adds 10 R-specific code smell checks to detect common R anti-patterns:
setwd()<<-attach()rm(list=ls())browser()/debug()T/F1:n()options(stringsAsFactors)library()in functionsAlso extends the generic language framework with
custom_phasessupport, allowing any genericplugin to inject language-specific detector phases without converting to a full plugin.
Files changed
desloppify/languages/_framework/generic_support/core.py(+5 lines)desloppify/languages/_framework/generic_support/registration.py(+5 lines)desloppify/languages/r/__init__.py(+7 lines)desloppify/languages/r/detectors/__init__.py(new)desloppify/languages/r/detectors/smells.py(+150 lines)desloppify/languages/r/detectors/smells_catalog.py(+70 lines)desloppify/languages/r/phases_smells.py(+25 lines)desloppify/languages/r/tests/__init__.py(new)desloppify/languages/r/tests/test_r_smells.py(+161 lines)Testing
Includes comprehensive test coverage for all 10 smell detectors.
Dependencies
None - this is a foundational PR that other R enhancements can build on.