Limitations
July 24, 2026 · View on GitHub
Raven is under active development. The gaps below reflect features that exist in comparable tools but aren't yet in Raven, or where Raven's implementation differs meaningfully from the comparable tool's. Each entry links to the doc where it's discussed in context.
Language server
-
Stan analysis is conservative name resolution, not compilation — Complete
.stanprograms get native syntax and undeclared-variable diagnostics, but Raven does not type-check expressions, validate shapes or overloads, diagnose whether a called function or sampling distribution exists, preprocess#include, or assemble project-specific source fragments. A file with no real top-level Stan block is treated as a fragment and receives no undeclared-variable findings; any include suppresses that semantic pass for the whole file because it may supply declarations. See Diagnostics — Stan Undeclared Variables. -
Full
lintrcoverage — Raven ships a built-in, opt-in style linter that re-implements 18 oflintr's rules natively — most of its default set (see Linting). REditorSupport/languageserver runs the fulllintrpackage, including rules Raven doesn't replicate (object_usage_linter, the full set of style checks, etc.). You can run both language servers at once; see Coexistence: Language servers. -
Session-aware completions — Raven's completions are purely static. REditorSupport can complete symbols from the live R session's
globalenv(), including column names from data frames that only exist at runtime. See Comparison: Language intelligence. -
useDynLibnative routine symbols — When a package registers native routines viauseDynLib(pkg, .registration = TRUE), R creates R-level bindings (e.g. rlang'sffi_enquo,ffi_quos_interp) in the package namespace at load time. These names live in C source (src/init.c) and are not statically derivable from R or NAMESPACE files alone, so Raven flags them as undefined. This affects packages that call their own registered routines directly (most notably rlang). Suppress with# raven: ignore-nextor a directive. -
data()alias expansion not inherited through backward dependencies — When a parent file callsdata(api, package = "survey"), the individual object names it binds (apiclus1,apistrat, …) are not propagated to child files that inherit the parent's scope via a backward dependency (# raven: sourced-byor auto-inferred). The literal stem (api) does flow. Forwardsource()children receive full expansion. See Cross-File & Package Awareness —data()calls for the workarounds. -
Raw path identity for closed symlink spellings — Raven's dependency graph, file caches, workspace indexes, and diagnostic publication keep raw URI spellings rather than globally canonicalizing paths, so closed files reached through different symlink spellings can remain distinct identities. Open buffers are bridged: a case or symlink alias of an on-disk file is authoritative for the corresponding graph URI while it is open, including package-internal scope and workspace
.Rprofileprelude ownership; diagnostics still publish to the URI spelling the editor opened. Raven still avoids full filesystem canonicalization because it follows symlinks and can diverge from the uncanonicalized paths used by the workspace index. The source-path resolver may correct case-only mismatches so graph edges match the on-disk workspace-index spelling. See Cross-File & Package Awareness — Open buffers, disk state, and closing files. -
Member navigation only for static
$/@/literal-[[accessors — go-to-definition, hover, and find-references treat a member access as navigable only when it is statically a name: an identifier RHS of$/@(foo$bar), or a single, positional, literal string subscript of[[(foo[["bar"]], the$-equivalent extractor). A subscript that R only resolves at runtime is intentionally not unified: computed/dynamic indices (x[[i]],x[[paste0("a", "b")]]), numeric indices (x[[1]]), named or multi-argument subscripts (x[[name = "a"]],x[["a", exact = FALSE]]), strings with escapes, and the single-bracket formx["bar"](which returns a sub-container, not the element). See Go-to-Definition and Find References.
box module system (box::use)
Raven models the statically analyzable subset of the box module system across diagnostics, completion, hover, go-to-definition, find-references, dependency revalidation, the language server, and raven check. See Module & import systems — box modules.
Only static box::use() is recognised. The call must be a literal box::use(...) / box:::use(...). Programmatic invocation — do.call(box::use, ...), aliasing box::use to another name, or building the argument list at runtime — is not recognised.
Local modules must be explicit relative paths. A bare name is always treated as an installed package; a local module must begin with ./ or ../. The following non-local module lookups are not supported and fail conservatively (they neither bind names nor emit misleading diagnostics):
- Non-local search-path specs such as
foo/bar(a module found via a search path rather than relative to the importing file). options(box.path = ...)and theR_BOX_PATHenvironment variable.- Remote modules and box's global-module directory.
Local resolution differs from source(). box paths resolve relative to the importing file's own directory and intentionally ignore # raven: cd, the implicit testthat/testit working directory, and the workspace-root fallback. Resolution is case-sensitive: a path that exists only under a different case is reported as a mismatch, not silently corrected. Ambiguous case-insensitive collisions (only possible on a case-sensitive filesystem) fail closed.
import package
Raven models the static first phase of import::from(), import::here(), and
import::into(): literal package or .R/.r script sources, literal
.directory and named destinations, explicit/renamed selections, .all, and
static .except. It does not execute R, model detach/S3 side effects, follow
URL or pins modules, or evaluate dynamic .character_only, .library,
.directory, .into, source, or member expressions. Environment-valued
destinations and import::: internal imports are not modeled. Unsupported calls
are inert rather than partially guessed.
No runtime module execution. Raven does not execute module code, evaluate load/unload hooks or other side effects, or inspect dynamically-created exports. Marker-less legacy export sets are therefore treated as incomplete: known members are available, but absence is not diagnosed unless the module has an authoritative explicit export interface. Installed-package imports use Raven's installed, frozen, or downloaded package export metadata under the same completeness rule.
Static member access only. Namespace-member completion, hover, navigation, and identity-aware references cover $, @, and a single positional literal-string [[...]] subscript. Computed subscripts and nested runtime values are not evaluated. Installed-package members are available for completion and diagnostics but do not navigate to package source files.
targets and tarchetypes
Raven models target declarations and report relationships only when their
source spelling is statically trustworthy. Direct namespace-qualified calls are
recognized; bare calls require a top-level package attachment and no local
shadow. Aliases, do.call(), partial argument names, malformed calls, calls
inside functions/quoted code, and arbitrary metaprogramming are inert.
The supported tar_map() subset requires a literal list() / data.frame() /
tibble() table with named scalar or literal-vector columns, target-definition
objects statically bound to ..., a static unshadowed column-name selection,
compatible lengths, no target-name/value-column collision, and a literal
delimiter. Expansion is all-or-nothing: Raven does not retain partial targets or
report links when one generated name is unsupported. Raven does not predict the
runtime hash fallback, non-ASCII or locale-sensitive make.names() results,
dynamic values/selections/delimiters, replication factories, or other dynamic
branching. Raw/string-expression variants,
tar_eval(), tar_sub(), AST walkers, and internal _run helpers are not
modeled.
Report identity requires a static target name and a literal supported document
path: .Rmd / .Rmarkdown for tar_render() and tar_knit(), or a single
.qmd / .Rmd / .Rmarkdown file for tar_quarto(). Computed paths, Quarto
project directories, and rendering are outside the analysis. Helpers sourced
only by the report do not lend target declarations back into the pipeline.
tar_load() references are enumerated only from a direct name or literal
unshadowed c(name, ...); dynamic tidyselect expressions are not expanded. See
Cross-file awareness — tarchetypes target factories and report documents.
R Markdown / Quarto
R chunk bodies in .Rmd / .Rmarkdown / .qmd documents are fully analyzed as first-class R code. The following gaps are accepted limitations of the current implementation:
- Inline R expressions (
\r expr`` in prose) are not analyzed. Only fenced chunk bodies (```{r} ... ```) are treated as R. - Cross-chunk delimiter leak — chunk bodies are analyzed as a single concatenated R program. An unclosed delimiter (
",(,{) in one chunk body can swallow the opening of the next chunk, causing the next chunk's parse to fail. The unclosed delimiter in the offending chunk is itself flagged as a parse error. This is a consequence of Raven's single-parse analysis model (knitr itself evaluates chunks one at a time and would stop at the offending chunk). - Non-R chunks not analyzed —
{python},{bash},{julia}, and other non-R fenced blocks are never analyzed or linted. - knitr chunk-reuse lines (
<<label>>) are blanked (treated as empty lines) and not resolved. - Quarto preview scope — Raven provides CLI-backed
Raven: Quarto Preview,Raven: Quarto Render, andRaven: Stop Quarto Previewfor.qmdfiles. Preview delegates refresh-on-save to Quarto's watcher, but it is not a Shiny lifecycle: Raven rejects document-levelserver: shinybest-effort and does not detect project-level Shiny configuration before launch. Non-browser-previewable formats such as DOCX and PPTX fail Preview with a 404 message and must use Render. Preview requires a trusted workspace, is owned by the current VS Code window, and is not guaranteed in Codespaces. See Quarto preview and render — Limitations.
R-session features
- Workspace viewer — REditorSupport has a sidebar panel that introspects the live R session, showing objects in
globalenv()with their types and dimensions, plus attached and loaded namespaces; objects can be viewed or removed from the panel. Raven has no equivalent. See Comparison: What REditorSupport's VS Code extension offers that Raven doesn't. - htmlwidget / Shiny viewer — Interactive HTML output (plotly, DT, profvis, etc.) and Shiny apps render in REditorSupport's webview panels. Raven has no equivalent.
- Auto-refresh R Markdown knit preview — Raven's
Raven: Knit Previewfor.Rmd/.Rmarkdownfiles is a static HTML viewer with a manual Knit again button (Shift+Cmd+Enter/Shift+Ctrl+Entersaves and re-knits in one keystroke). REditorSupport's.Rmdpreview adds an opt-in auto-refresh mode. Raven's separate Quarto Preview does refresh.qmdoutput on save through Quarto's built-in watcher; it does not change the deliberately manual Knit Preview pipeline. - List / environment viewer — REditorSupport's
View()on lists and environments opens a collapsible tree view. Raven'sView()only handles data frames and matrices. See Data Viewer.
If you rely on any of the fully-absent features above (workspace viewer, htmlwidget/Shiny viewer, list/environment viewer) and have REditorSupport installed, see Coexistence for how to run both extensions together.