Skip to content

Commit

Permalink
Better handle LoadErrors from prism
Browse files Browse the repository at this point in the history
There are two different cases that may happen:
1: Prism is compiled in the past, the user updated the ruby version, but it still points to the same library
> linked to incompatible /home/earlopain/.rbenv/versions/3.4.1/lib/libruby.so.3.4 - /home/earlopain/Documents/ruby-prism/lib/prism/prism.so

In that case, bubble up the original error.

On the other hand, since prism is no dependency, users may run older verions that are missing translator classes.
In that case, show a message what they should do.
prism is a default gem since 3.3, so you can even use it without adding it to your gemfile.
  • Loading branch information
Earlopain committed Dec 28, 2024
1 parent 4529384 commit bffc8ed
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/fix_better_handle_prism_loaderror.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#349](https://github.com/rubocop/rubocop-ast/pull/349): Show better error messages when `prism` is too old or linked to the wrong Ruby version. ([@earlopain][])
36 changes: 28 additions & 8 deletions lib/rubocop/ast/processed_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,19 +285,14 @@ def parser_class(ruby_version, parser_engine) # rubocop:disable Metrics/AbcSize,
raise ArgumentError, "RuboCop found unknown Ruby version: #{ruby_version.inspect}"
end
when :parser_prism
begin
require 'prism'
rescue LoadError
warn "Error: Unable to load Prism. Add `gem 'prism'` to your Gemfile."
exit!
end
require_prism

case ruby_version
when 3.3
require 'prism/translation/parser33'
require_prism_parser(3.3)
Prism::Translation::Parser33
when 3.4
require 'prism/translation/parser34'
require_prism_parser(3.4)
Prism::Translation::Parser34
else
raise ArgumentError, 'RuboCop supports target Ruby versions 3.3 and above with Prism. ' \
Expand All @@ -306,6 +301,31 @@ def parser_class(ruby_version, parser_engine) # rubocop:disable Metrics/AbcSize,
end
end

# Prism is a native extension, a LoadError will be raised if linked to an incompatible
# Ruby version. Only raise if this NameError really was caused by prism not being present.
def require_prism
require 'prism'
rescue LoadError => e
raise unless e.path == 'prism'

warn "Error: Unable to load Prism. Add `gem 'prism'` to your Gemfile."
exit!
end

# While prism is not yet a dependency, users may run with outdated versions that
# don't have all the parsers.
def require_prism_parser(version)
require "prism/translation/parser#{version.to_s.delete('.')}"
rescue LoadError
warn <<~WARN
Error: Unable to load Prism Parser for Ruby #{version}.
* If you're using bundler and don't yet have prism as a dependency, add it now.
* If you're using bundler and already have prism as a dependency, update it to the most recent version.
* If you don't use bundler, run `gem update prism`.
WARN
exit!
end

def create_parser(ruby_version, parser_engine)
builder = RuboCop::AST::Builder.new

Expand Down

0 comments on commit bffc8ed

Please sign in to comment.