Skip to main content
roe is a static, name-based analyzer — it never compiles or runs the code it analyzes. That keeps it fast and lets it work on codebases that don’t build, but it comes with known blind spots:
  • Name-based resolution conflates same-named symbols — dead code hiding behind a popular name is missed (by design; the safe direction).
  • String-based reflection is invisibleActivator.CreateInstance("…"), Type.GetType("…"), and config-wired type names can cause false positives; the attribute-root and scan-target heuristics absorb the common cases, and --root covers the rest.
  • MSBuild Condition attributes are not evaluated (all branches included), Directory.Build.props is not read, and InternalsVisibleTo is not modeled.
  • Razor/.cshtml markup is not parsed — build first so the generated sources in obj/ stand in for it.
  • Compiler-synthesized calls are invisible (e.g. range/index polyfills).
  • roe dupes does not de-duplicate overlapping or nested occurrences of the same pattern repeated within a single long method — each is reported as-is.
  • roe health counts overloads as one type member, since name-based resolution merges them, and its coupling graph is built from the same name-based references — so a cycle routed through a conflated name may not be a real one.
  • roe health --hotspots needs git history — it’s the only part of roe that reads a repository, and a shallow clone yields correspondingly shallow churn.
When a limitation produces a false positive, mark it with an inline suppression, an ignore glob, or an extra entry-point root.