Skip to content

Commit b8b239d

Browse files
committed
Document parser duality, alias flow, and ri marshal compat
Refactor the Architecture Notes section so the existing thin "Pluggable System" stub becomes a real "Parsers and Generators" subsection and add two more architecture subsections that capture invariants future work needs to know: * The dual-parser test mixin (RDocParserPrismTestCases) so a single test exercises both PrismRuby and RipperRuby backends. * The two-phase code-object construction (parse-time add_module_alias vs. Store#complete -> update_aliases) and the invariant that safeguards on one path must mirror on the other. * The known lexical-scope limitation in alias resolution. * MARSHAL_VERSION discipline for ri data on disk and the downstream consumers that depend on the format.
1 parent 1f61823 commit b8b239d

1 file changed

Lines changed: 16 additions & 2 deletions

File tree

AGENTS.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,25 @@ exe/
234234

235235
## Architecture Notes
236236

237-
### Pluggable System
237+
### Parsers and Generators
238238

239-
- **Parsers:** Ruby, C, Markdown, RD, Prism-based Ruby (experimental)
239+
- **Parsers:** Prism-based Ruby (default, `RDoc::Parser::PrismRuby`), legacy ripper-based Ruby (`RDoc::Parser::RipperRuby`, opt-in via `RDOC_USE_RIPPER_PARSER=1`), C, Markdown, RD
240240
- **Generators:** HTML/Aliki (default), HTML/Darkfish (deprecated), RI, POT (gettext), JSON, Markup
241241

242+
Both Ruby parsers must produce equivalent code-object trees. Parser tests are written once in the `RDocParserPrismTestCases` module (`test/rdoc/parser/prism_ruby_test.rb`); both `RDocParserPrismRubyTest` and `RDocParserRipperRubyWithPrismRubyTestCasesTest` include it, so each test runs against both backends. Add new parser tests there rather than to a parser-specific class.
243+
244+
### Code Object Model and Constant Aliases
245+
246+
The code-object tree (`lib/rdoc/code_object/`) is built in two phases. Parse-time work happens in the parsers and `RDoc::Context` (`add_constant`, `add_module_alias`). Finalization happens in `Store#complete`, which calls `ClassModule#update_aliases` on each container — this is where forward-reference aliases (`Foo = Bar` parsed before `class Bar` in another file) get resolved via `Constant#resolved_alias_target`.
247+
248+
If you add an invariant to one of these paths — for example the `Context#add_module_alias` collision guard that refuses to clobber an existing class — mirror it on the other. The two paths are not interchangeable: `add_module_alias` runs against partial store state and does extra bookkeeping (`unmatched_constant_alias`); `update_aliases` runs against the finalized store and writes the alias copies into `classes_hash` / `modules_hash`.
249+
250+
**Known limitation: lexical scope.** `Context#find_enclosing_module_named` walks the syntactic parent chain as a stand-in for Ruby's lexical constant lookup. The prism parser doesn't represent module nesting via the parent chain at all (see comment at `lib/rdoc/code_object/context.rb:781-785`), so alias resolution in deeply nested or re-opened classes can pick the wrong target. Don't paper over this in new code without addressing it properly — it's a real feature, not a tweak.
251+
252+
### Marshal / ri Data Compatibility
253+
254+
`RDoc::Constant`, `RDoc::ClassModule`, and other code objects implement `marshal_dump` / `marshal_load` to persist ri data on disk. Downstream consumers (the Ruby core docs build, rubygems-server, IDE integrations) read this format. Each class gates its dump shape with a `MARSHAL_VERSION` constant. Any change that alters the dumped array — adding/removing slots, reinterpreting an existing slot's meaning — needs the version bumped and the loader taught to handle both old and new data, or you break downstream consumers silently.
255+
242256
### Live Preview Server (`RDoc::Server`)
243257

244258
The server (`lib/rdoc/server.rb`) provides `rdoc --server` for live documentation preview.

0 commit comments

Comments
 (0)