Skip to content

Conversation

@tompng
Copy link
Member

@tompng tompng commented Jan 15, 2026

Closes #1024
Fixes #75 and #286

Remove remaining Ripper dependency and completely migrate to Prism.

RubyLex#should_continue?

Instead of checking Ripper's state bits, check for IGNORED_NEWLINE token.
When code is continued to the next line, there's probably a IGNORED_NEWLINE token.

1 + IGNORED_NEWLINE 2
receiver. IGNORED_NEWLINE method
receiver IGNORED_NEWLINE .method
Prism.lex("1 +\n").value
=> [[INTEGER(1,0)-(1,1)("1"), 2], [PLUS(1,2)-(1,3)("+"), 1], [IGNORED_NEWLINE(1,3)-(2,0)("\n"), 1], [EOF(1,3)-(2,0)("\n"), 1]]

Prism.lex("1.+ \n").value
=> [[INTEGER(1,0)-(1,1)("1"), 2], [DOT(1,1)-(1,2)("."), 256], [PLUS(1,2)-(1,3)("+"), 16], [NEWLINE(1,4)-(2,0)("\n"), 1], [EOF(1,4)-(2,0)("\n"), 1]]

RubyLex#check_termination_in_prev_line

When multiline code is pasted (without bracketed-paste mode), IRB checks if the last line is connected to the previous line.

tap do
end # Code looks ended here
.itself # But its' connected

Before: Heuristic, find DOT token
After: Compare two syntax trees: parse(lines.join) and parse(lines[...-1].join)

RubyLex#check_code_syntax

Checks if the code is :valid, :unrecoverable_error or :recoverable_error.
Same as before, use syntax error messages and regexp patterns.

Basic rules

  • meets end of file end-of-input unterminated is likely to be recoverable error
  • is not allowed unexpected or invalid is likely to be unrecoverable error
  • invalid or unexpected error location is near last token position, it may not be unrecoverable error

Checked with many recoverable-error-code collected by

  1. Collect valid short code snippets from ruby/ruby/**/*.rb
  2. Randomly split code snippets into two, check if the first half is invalid code and join with "\n" becomes valid

@tompng tompng changed the title Migrate to prism Completely migrate to prism Jan 17, 2026
@tompng tompng marked this pull request as ready for review January 17, 2026 06:53
@tompng tompng force-pushed the migrate_to_prism branch 4 times, most recently from 6165add to 66e7c60 Compare January 23, 2026 18:24
# foo
# bar
# If it's connected, return the last line string. Otherwise, return false.
def check_termination_in_prev_line(code, local_variables:)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc expresses the behaviour using "connected" or not, but the method name seems to suggest we're checking the opposite: "terminated" or not. Should we rename the method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the method name termination describes what IRB need to do, compared to connected.
Updated the source code comment to be more clear.

Remove remaining ripper dependency in: syntax check, code continue/termination check, show-source, regexp-completion and string-like command arg parse.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replacing Ripper by Prism completion for Symbols

2 participants