fix: convert Prism::ErrorRecoveryNode, which replaced MissingNode

Merged
MH
14d ago
+35-4

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 to LocalVariableWriteNode(value: Refract::MissingNode) on both prism generations.
  • The converter defines visit_missing_node / visit_error_recovery_node exactly when Prism defines the matching node.

Results, qt -t 1 (passed / failed):

Ruby / prismthis branchmain
3.4.2, prism 1.9.0801 / 1798 / 1
4.0.6, prism 1.8.1801 / 1798 / 1
3.4.2, prism git main (302790a, has ErrorRecoveryNode, no MissingNode)801 / 1NameError: 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 offenses main already has (formatter.rb:16, refract.gemspec:24). The ErrorRecoveryNode block sits in the order the Refract/OrderedVisitMethods cop 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.