You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
-**Generators:** HTML/Aliki (default), HTML/Darkfish (deprecated), RI, POT (gettext), JSON, Markup
241
241
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
+
242
256
### Live Preview Server (`RDoc::Server`)
243
257
244
258
The server (`lib/rdoc/server.rb`) provides `rdoc --server` for live documentation preview.
0 commit comments