fix: convert Prism::ErrorRecoveryNode, which replaced MissingNode
Summary
ruby/ruby@708656c73 ("[PRISM] Replace MissingNode with ErrorRecoveryNode") removed Prism::MissingNode. Refract::Converter references it at class-body time (visit Prism::MissingNode), so on ruby-head, and on prism's main branch, require "refract" raises:
NameError: uninitialized constant Prism::MissingNode (lib/refract/converter.rb:845)
That is what fails Phlex's head CI lanes: about 87 compiler tests in yippee-fun/phlex#1055. Phlex doesn't commit its lockfile, so its CI resolves refract main fresh, and merging this turns those lanes green with no Phlex change.
The converter now visits whichever of Prism::ErrorRecoveryNode / Prism::MissingNode is defined. Both convert to Refract::MissingNode. ErrorRecoveryNode adds only an optional unexpected child, the stray node found where the missing one should be. Prism's own translators (parser, ruby_parser) also map it to a childless "missing" node in that commit, and refract does the same: source with a syntax error can't be emitted either way, and the original node is still kept as prism_node.
No released prism has ErrorRecoveryNode yet (1.9.0 is the latest and still ships MissingNode), so both branches are needed.
Test plan
New tests:
"x = "converts toLocalVariableWriteNode(value: Refract::MissingNode)on both prism generations.- The converter defines
visit_missing_node/visit_error_recovery_nodeexactly when Prism defines the matching node.
Results, qt -t 1 (passed / failed):
| Ruby / prism | this branch | main |
|---|---|---|
| 3.4.2, prism 1.9.0 | 801 / 1 | 798 / 1 |
| 4.0.6, prism 1.8.1 | 801 / 1 | 798 / 1 |
3.4.2, prism git main (302790a, has ErrorRecoveryNode, no MissingNode) | 801 / 1 | NameError: uninitialized constant Prism::MissingNode |
The one failure everywhere is test/refract.test.rb:1445. It compares a subprocess's output, and my machine prints Bundler "missing extensions" warnings into it, so it is local noise and identical on main.
bundle exec rubocop: only the two offensesmainalready has (formatter.rb:16,refract.gemspec:24). TheErrorRecoveryNodeblock sits in the order theRefract/OrderedVisitMethodscop expects.
Note: refract's own CI is red on main independently of this change. It tracks quickdraw unpinned, and quickdraw dropped qt -t and the top-level test DSL on 2026-01-24 (joeldrapper/quickdraw@2e72ea1, @1334398). The results above use quickdraw 06615ef2554d, the last revision before those changes, via a scratch Gemfile that isn't committed here.