diff --git a/.github/workflows/ruby-core.yml b/.github/workflows/ruby-core.yml
index dbd3597acd..502958a5c8 100644
--- a/.github/workflows/ruby-core.yml
+++ b/.github/workflows/ruby-core.yml
@@ -70,13 +70,13 @@ jobs:
run: make html
working-directory: ruby/ruby
# We need to clear the generated documentation to generate them again
- # with the Prism parser.
+ # with the Ripper parser.
- name: Clear Generated Documentation
run: rm -r .ext/html
working-directory: ruby/ruby
- - name: Generate Documentation with RDoc (Prism parser)
+ - name: Generate Documentation with RDoc (Ripper parser)
run: make html
working-directory: ruby/ruby
env:
- RDOC_USE_PRISM_PARSER: true
+ RDOC_USE_RIPPER_PARSER: true
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a291a7f30e..6c729bc734 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -39,9 +39,6 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- # libyaml-dev is needed for psych, see https://github.com/ruby/setup-ruby/issues/409
- - if: ${{ matrix.os == 'ubuntu-latest' }}
- run: sudo apt install libyaml-dev
- name: Set up Ruby
uses: ruby/setup-ruby@90be1154f987f4dc0fe0dd0feedac9e473aa4ba8 # v1.286.0
with:
@@ -62,3 +59,23 @@ jobs:
run: bundle exec rake rdoc
- if: ${{ matrix.ruby == 'head' && startsWith(matrix.os, 'ubuntu') }}
run: bundle exec rake install
+
+ prism-version-test:
+ needs: ruby-versions
+ strategy:
+ fail-fast: false
+ matrix:
+ prism_version: ['1.0.0', '1.3.0', '1.7.0', 'head']
+ runs-on: ubuntu-latest
+ env:
+ RUBYOPT: --enable-frozen_string_literal
+ PRISM_VERSION: ${{matrix.prism_version}}
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
+ with:
+ ruby-version: ${{ fromJson(needs.ruby-versions.outputs.latest) }}
+ bundler-cache: true
+ - name: Run test
+ run: bundle exec rake
diff --git a/Gemfile b/Gemfile
index 957cbbd227..317623101b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -9,9 +9,14 @@ gem 'test-unit'
gem 'test-unit-ruby-core'
gem 'rubocop', '>= 1.31.0'
gem 'gettext'
-gem 'prism', '>= 0.30.0'
gem 'webrick'
+if ENV['PRISM_VERSION'] == 'head'
+ gem 'prism', github: 'ruby/prism'
+elsif ENV['PRISM_VERSION']
+ gem 'prism', ENV['PRISM_VERSION']
+end
+
platforms :ruby do
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2')
gem 'mini_racer' # For testing the searcher.js file
diff --git a/doc/rdoc/example.rb b/doc/rdoc/example.rb
index 7df8d99b00..20b543cbec 100644
--- a/doc/rdoc/example.rb
+++ b/doc/rdoc/example.rb
@@ -58,7 +58,7 @@ def instance_method_example(foo, bar)
#
# Here is the :call-seq: directive given for this method:
#
- # :call-seq:
+ # \:call-seq:
# call_seq_example(foo, bar)
# Can be anything -> bar
# Also anything more -> baz or bat
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 2ac960e089..33c6788e9f 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -294,4 +294,15 @@ def handle_tab_width(body)
require_relative 'parser/changelog'
require_relative 'parser/markdown'
require_relative 'parser/rd'
-require_relative 'parser/ruby'
+
+if ENV['RDOC_USE_RIPPER_PARSER']
+ puts "========================================================================="
+ puts "RDoc is using the deprecated Ripper parser to generate the documentation."
+ puts "This parser will be removed in a future version of RDoc."
+ puts "========================================================================="
+ require 'rdoc/parser/ripper_ruby'
+ RDoc::Parser::Ruby = RDoc::Parser::RipperRuby
+else
+ require 'rdoc/parser/prism_ruby'
+ RDoc::Parser::Ruby = RDoc::Parser::PrismRuby
+end
diff --git a/lib/rdoc/parser/prism_ruby.rb b/lib/rdoc/parser/prism_ruby.rb
index 56da6ac227..b7a510be5c 100644
--- a/lib/rdoc/parser/prism_ruby.rb
+++ b/lib/rdoc/parser/prism_ruby.rb
@@ -3,17 +3,135 @@
require 'prism'
require_relative 'ripper_state_lex'
-# Unlike lib/rdoc/parser/ruby.rb, this file is not based on rtags and does not contain code from
+# Unlike lib/rdoc/parser/ripper_ruby.rb, this file is not based on rtags and does not contain code from
# rtags.rb -
# ruby-lex.rb - ruby lexcal analyzer
# ruby-token.rb - ruby tokens
# Parse and collect document from Ruby source code.
-# RDoc::Parser::PrismRuby is compatible with RDoc::Parser::Ruby and aims to replace it.
+
+##
+# Extracts code elements from a source file returning a TopLevel object
+# containing the constituent file elements.
+#
+# RubyParser understands how to document:
+# * classes
+# * modules
+# * methods
+# * constants
+# * aliases
+# * private, public, protected
+# * private_class_function, public_class_function
+# * private_constant, public_constant
+# * module_function
+# * attr, attr_reader, attr_writer, attr_accessor
+# * extra accessors given on the command line
+# * metaprogrammed methods
+# * require
+# * include
+#
+# == Method Arguments
+#
+# The parser extracts the arguments from the method definition. You can
+# override this with a custom argument definition using the :args: directive:
+#
+# ##
+# # This method tries over and over until it is tired
+#
+# def go_go_go(thing_to_try, tries = 10) # :args: thing_to_try
+# puts thing_to_try
+# go_go_go thing_to_try, tries - 1
+# end
+#
+# If you have a more-complex set of overrides you can use the :call-seq:
+# directive:
+#
+# ##
+# # This method can be called with a range or an offset and length
+# #
+# # :call-seq:
+# # my_method(Range)
+# # my_method(offset, length)
+#
+# def my_method(*args)
+# end
+#
+# The parser extracts +yield+ expressions from method bodies to gather the
+# yielded argument names. If your method manually calls a block instead of
+# yielding or you want to override the discovered argument names use
+# the :yields: directive:
+#
+# ##
+# # My method is awesome
+#
+# def my_method(&block) # :yields: happy, times
+# block.call 1, 2
+# end
+#
+# == Metaprogrammed Methods
+#
+# To pick up a metaprogrammed method, the parser looks for a comment starting
+# with '##' before a metaprogramming method call:
+#
+# ##
+# # This is a meta-programmed method!
+#
+# add_my_method :meta_method, :arg1, :arg2
+#
+# The parser looks at the first argument to determine the name, in
+# this example, :meta_method. If a name cannot be found, a warning is printed
+# and 'unknown is used.
+#
+# You can force the name of a method using the :method: directive:
+#
+# ##
+# # :method: some_method!
+#
+# By default, meta-methods are instance methods. To indicate that a method is
+# a singleton method instead use the :singleton-method: directive:
+#
+# ##
+# # :singleton-method:
+#
+# You can also use the :singleton-method: directive with a name:
+#
+# ##
+# # :singleton-method: some_method!
+#
+# You can define arguments for metaprogrammed methods via either the
+# \:call-seq:, :arg: or :args: directives.
+#
+# Additionally you can mark a method as an attribute by
+# using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
+# for :method:, the name is optional.
+#
+# ##
+# # :attr_reader: my_attr_name
+#
+# == Hidden methods and attributes
+#
+# You can provide documentation for methods that don't appear using
+# the :method:, :singleton-method: and :attr: directives:
+#
+# ##
+# # :attr_writer: ghost_writer
+# # There is an attribute here, but you can't see it!
+#
+# ##
+# # :method: ghost_method
+# # There is a method here, but you can't see it!
+#
+# ##
+# # this is a comment for a regular method
+#
+# def regular_method() end
+#
+# Note that by default, the :method: directive will be ignored if there is a
+# standard rdocable item following it.
class RDoc::Parser::PrismRuby < RDoc::Parser
- parse_files_matching(/\.rbw?$/) if ENV['RDOC_USE_PRISM_PARSER']
+ parse_files_matching(/\.rbw?$/) unless ENV['RDOC_USE_RIPPER_PARSER']
attr_accessor :visibility
attr_reader :container, :singleton
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ripper_ruby.rb
similarity index 93%
rename from lib/rdoc/parser/ruby.rb
rename to lib/rdoc/parser/ripper_ruby.rb
index c9b662c90a..f72c15bf80 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ripper_ruby.rb
@@ -8,151 +8,14 @@
# by Keiju ISHITSUKA (Nippon Rational Inc.)
#
-if ENV['RDOC_USE_PRISM_PARSER']
- require 'rdoc/parser/prism_ruby'
- RDoc::Parser.const_set(:Ruby, RDoc::Parser::PrismRuby)
- puts "========================================================================="
- puts "RDoc is using the experimental Prism parser to generate the documentation"
- puts "========================================================================="
- return
-end
+# This file is based on rtags
require 'ripper'
require_relative 'ripper_state_lex'
-##
-# Extracts code elements from a source file returning a TopLevel object
-# containing the constituent file elements.
-#
-# This file is based on rtags
-#
-# RubyParser understands how to document:
-# * classes
-# * modules
-# * methods
-# * constants
-# * aliases
-# * private, public, protected
-# * private_class_function, public_class_function
-# * private_constant, public_constant
-# * module_function
-# * attr, attr_reader, attr_writer, attr_accessor
-# * extra accessors given on the command line
-# * metaprogrammed methods
-# * require
-# * include
-#
-# == Method Arguments
-#
-#--
-# NOTE: I don't think this works, needs tests, remove the paragraph following
-# this block when known to work
-#
-# The parser extracts the arguments from the method definition. You can
-# override this with a custom argument definition using the :args: directive:
-#
-# ##
-# # This method tries over and over until it is tired
-#
-# def go_go_go(thing_to_try, tries = 10) # :args: thing_to_try
-# puts thing_to_try
-# go_go_go thing_to_try, tries - 1
-# end
-#
-# If you have a more-complex set of overrides you can use the :call-seq:
-# directive:
-#++
-#
-# The parser extracts the arguments from the method definition. You can
-# override this with a custom argument definition using the :call-seq:
-# directive:
-#
-# ##
-# # This method can be called with a range or an offset and length
-# #
-# # :call-seq:
-# # my_method(Range)
-# # my_method(offset, length)
-#
-# def my_method(*args)
-# end
-#
-# The parser extracts +yield+ expressions from method bodies to gather the
-# yielded argument names. If your method manually calls a block instead of
-# yielding or you want to override the discovered argument names use
-# the :yields: directive:
-#
-# ##
-# # My method is awesome
-#
-# def my_method(&block) # :yields: happy, times
-# block.call 1, 2
-# end
-#
-# == Metaprogrammed Methods
-#
-# To pick up a metaprogrammed method, the parser looks for a comment starting
-# with '##' before an identifier:
-#
-# ##
-# # This is a meta-programmed method!
-#
-# add_my_method :meta_method, :arg1, :arg2
-#
-# The parser looks at the token after the identifier to determine the name, in
-# this example, :meta_method. If a name cannot be found, a warning is printed
-# and 'unknown is used.
-#
-# You can force the name of a method using the :method: directive:
-#
-# ##
-# # :method: some_method!
-#
-# By default, meta-methods are instance methods. To indicate that a method is
-# a singleton method instead use the :singleton-method: directive:
-#
-# ##
-# # :singleton-method:
-#
-# You can also use the :singleton-method: directive with a name:
-#
-# ##
-# # :singleton-method: some_method!
-#
-# You can define arguments for metaprogrammed methods via either the
-# \:call-seq:, :arg: or :args: directives.
-#
-# Additionally you can mark a method as an attribute by
-# using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
-# for :method:, the name is optional.
-#
-# ##
-# # :attr_reader: my_attr_name
-#
-# == Hidden methods and attributes
-#
-# You can provide documentation for methods that don't appear using
-# the :method:, :singleton-method: and :attr: directives:
-#
-# ##
-# # :attr_writer: ghost_writer
-# # There is an attribute here, but you can't see it!
-#
-# ##
-# # :method: ghost_method
-# # There is a method here, but you can't see it!
-#
-# ##
-# # this is a comment for a regular method
-#
-# def regular_method() end
-#
-# Note that by default, the :method: directive will be ignored if there is a
-# standard rdocable item following it.
-
-class RDoc::Parser::Ruby < RDoc::Parser
+class RDoc::Parser::RipperRuby < RDoc::Parser
- parse_files_matching(/\.rbw?$/)
+ parse_files_matching(/\.rbw?$/) if ENV['RDOC_USE_RIPPER_PARSER']
include RDoc::TokenStream
include RDoc::Parser::RubyTools
diff --git a/rdoc.gemspec b/rdoc.gemspec
index 494900b245..caa539b064 100644
--- a/rdoc.gemspec
+++ b/rdoc.gemspec
@@ -69,4 +69,5 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
s.add_dependency 'psych', '>= 4.0.0'
s.add_dependency 'erb'
s.add_dependency 'tsort'
+ s.add_dependency 'prism', '>= 1.0.0'
end
diff --git a/test/rdoc/parser/prism_ruby_test.rb b/test/rdoc/parser/prism_ruby_test.rb
index e393f70e3e..5e50919537 100644
--- a/test/rdoc/parser/prism_ruby_test.rb
+++ b/test/rdoc/parser/prism_ruby_test.rb
@@ -2214,4 +2214,4 @@ def util_parser(content)
@parser = RDoc::Parser::Ruby.new @top_level, content, @options, @stats
@parser.scan
end
-end unless ENV['RDOC_USE_PRISM_PARSER']
+end if ENV['RDOC_USE_RIPPER_PARSER']
diff --git a/test/rdoc/parser/ruby_test.rb b/test/rdoc/parser/ruby_test.rb
index c3dc8a09a1..413de602f8 100644
--- a/test/rdoc/parser/ruby_test.rb
+++ b/test/rdoc/parser/ruby_test.rb
@@ -2,7 +2,7 @@
require_relative '../helper'
-return if ENV['RDOC_USE_PRISM_PARSER']
+return unless ENV['RDOC_USE_RIPPER_PARSER']
class RDocParserRubyTest < RDoc::TestCase
@@ -942,7 +942,7 @@ class Invalid::@@Code
err = stds[1]
expected = <