Repository: ruby/rdoc (Ruby)

Issue:
Generating RDoc for RDoc fails in Ruby 3.4.x and following
## Observed behaviour

When trying to generate the `RDoc` documentation for `Rdoc` itself, I get the following error message:

```bash
> ruby -v && gem rdoc --rdoc rdoc
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin24]
Parsing documentation for RedCloth-4.3.4
Installing ri documentation for RedCloth-4.3.4
ERROR:  While executing gem ... (TypeError)
    no implicit conversion of nil into String

    @template_dir   = Pathname.new options.template_dir
                                   ^^^^^^^^^^^^^^^^^^^^
```

## Where it still worked

When using Ruby 3.3.8, this worked:
```bash
~/dev > rbenv shell 3.3.8
~/dev > RUBYOPT=""
~/dev > ruby -v && gem rdoc --rdoc rdoc
ruby 3.3.8 (2025-04-09 revision b200bad6cd) [arm64-darwin24]
Parsing documentation for debug-1.9.2
# --- 8< --- several lines cut out --- 8< ---
Parsing documentation for typeprof-0.21.9
```

## Why I assume it's an issue with `RDoc`

Given the error message above and the result of the following command, I presume the issue is within the `rdoc` gem itself since the code cited in the error message only ever appears in the `rdoc` gem:

```bash
 ~/.rbenv > find . -name "*.rb" -type f -exec egrep -Hin "@template_dir\s*=\s*Pathname.new\s*options.template_dir" {} \;
./versions/3.3.8/lib/ruby/3.3.0/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.5.0-preview1/lib/ruby/gems/3.5.0+0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.1/lib/ruby/3.4.0/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.1/lib/ruby/gems/3.4.0/gems/rdoc-6.11.0/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.1/lib/ruby/gems/3.4.0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.1/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:    @template_dir   = Pathname.new options.template_dir
./versions/3.1.6/lib/ruby/3.1.0/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/3.4.0/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.11.0/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.8.1/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.0/lib/rdoc/generator/darkfish.rb:161:    @template_dir   = Pathname.new options.template_dir
./versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.10.0/lib/rdoc/generator/darkfish.rb:167:    @template_dir   = Pathname.new options.template_dir
```

### Hardware & OS used

* OS: macOS Sequoia 15.4.1 arm64
* Host: MacBook Pro (Apple M4 Max (16) @ 4.51 GHz)



Discussion:
Could you share backtrace too?

`gem rdoc --rdoc --backtrace rdoc` may show backtrace.
Sure. 👍 Here you go:

```bash
rdoc ᚠ master > gem rdoc --rdoc --backtrace rdoc
Parsing documentation for RedCloth-4.3.4
ERROR:  While executing gem ... (TypeError)
    no implicit conversion of nil into String

    @template_dir   = Pathname.new options.template_dir
                                   ^^^^^^^^^^^^^^^^^^^^
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:in 'Pathname#initialize'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:in 'Class#new'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/generator/darkfish.rb:161:in 'RDoc::Generator::Darkfish#initialize'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/rubygems_hook.rb:137:in 'Class#new'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/rubygems_hook.rb:137:in 'RDoc::RubyGemsHook#document'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/gems/3.4.0/gems/rdoc-6.13.1/lib/rdoc/rubygems_hook.rb:202:in 'RDoc::RubyGemsHook#generate'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/commands/rdoc_command.rb:87:in 'block in Gem::Commands::RdocCommand#execute'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/commands/rdoc_command.rb:77:in 'Array#each'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/commands/rdoc_command.rb:77:in 'Gem::Commands::RdocCommand#execute'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/command.rb:326:in 'Gem::Command#invoke_with_build_args'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/command_manager.rb:253:in 'Gem::CommandManager#invoke_command'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/command_manager.rb:194:in 'Gem::CommandManager#process_args'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/command_manager.rb:152:in 'Gem::CommandManager#run'
	/Users/stephan/.rbenv/versions/3.4.2/lib/ruby/site_ruby/3.4.0/rubygems/gem_runner.rb:57:in 'Gem::GemRunner#run'
	/Users/stephan/.rbenv/versions/3.4.2/bin/gem:12:in '<main>'
```
I can't reproduce it with `gem rdoc --rdoc rdoc` nor `gem rdoc --rdoc RedCloth`.
But found a similar error for gems that has `spec.rdoc_options << '--ri'` with `gem rdoc --rdoc GEMNAME_HERE`
Example gem names can be found by: https://github.com/search?q=path%3Agemspec+rdoc_options+%22--ri%22&type=code

```
root@e77d76d6c135:/# gem install fastgem
root@e77d76d6c135:/# gem rdoc --rdoc fastgem
Parsing documentation for fastgem-0.1.8
ERROR:  While executing gem ... (TypeError)
    no implicit conversion of nil into String

    @template_dir   = Pathname.new options.template_dir
                                   ^^^^^^^^^^^^^^^^^^^^
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb:167:in 'Pathname#initialize'
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb:167:in 'Class#new'
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb:167:in 'RDoc::Generator::Darkfish#initialize'
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/rubygems_hook.rb:137:in 'Class#new'
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/rubygems_hook.rb:137:in 'RDoc::RubyGemsHook#document'
	/opt/ruby/lib/ruby/gems/3.5.0+0/gems/rdoc-6.12.0/lib/rdoc/rubygems_hook.rb:208:in 'RDoc::RubyGemsHook#generate'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/commands/rdoc_command.rb:87:in 'block in Gem::Commands::RdocCommand#execute'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/commands/rdoc_command.rb:77:in 'Array#each'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/commands/rdoc_command.rb:77:in 'Gem::Commands::RdocCommand#execute'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/command.rb:326:in 'Gem::Command#invoke_with_build_args'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/command_manager.rb:253:in 'Gem::CommandManager#invoke_command'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/command_manager.rb:194:in 'Gem::CommandManager#process_args'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/command_manager.rb:152:in 'Gem::CommandManager#run'
	/opt/ruby/lib/ruby/3.5.0+0/rubygems/gem_runner.rb:57:in 'Gem::GemRunner#run'
	/opt/ruby/bin/gem:12:in '<main>'
```

Cool. Thank you all! 



Patch:
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
index 90cb37f86d..a1216d346d 100644
--- a/lib/rdoc/rubygems_hook.rb
+++ b/lib/rdoc/rubygems_hook.rb
@@ -182,18 +182,21 @@ def generate
       options.default_title = "#{@spec.full_name} Documentation"
       options.parse args
       options.quiet = !Gem.configuration.really_verbose
-      options.finish
     end
 
     @rdoc = new_rdoc
-    @rdoc.options = options
-
-    @rdoc.store = RDoc::Store.new(options)
 
     say "Parsing documentation for #{@spec.full_name}"
 
     Dir.chdir @spec.full_gem_path do
-      @rdoc.parse_files options.files
+      # RDoc::Options#finish must be called before parse_files.
+      # RDoc::Options#finish is also called after ri/darkfish generator setup.
+      # We need to dup the options to avoid modifying it after finish is called.
+      parse_options = options.dup
+      parse_options.finish
+      @rdoc.options = parse_options
+      @rdoc.store = RDoc::Store.new(parse_options)
+      @rdoc.parse_files parse_options.files
     end
 
     document 'ri',       options, @ri_dir if


Test patch:
diff --git a/test/rdoc/test_rdoc_rubygems_hook.rb b/test/rdoc/test_rdoc_rubygems_hook.rb
index ccb86c2a2c..29488e7ac1 100644
--- a/test/rdoc/test_rdoc_rubygems_hook.rb
+++ b/test/rdoc/test_rdoc_rubygems_hook.rb
@@ -241,6 +241,18 @@ def test_generate_no_overwrite
     assert_path_not_exist File.join(@a.doc_dir('ri'),   'cache.ri')
   end
 
+  def test_generate_with_ri_opt
+    @a.rdoc_options << '--ri'
+    FileUtils.mkdir_p @a.doc_dir
+    FileUtils.mkdir_p File.join(@a.gem_dir, 'lib')
+    @hook.generate_rdoc = true
+    @hook.generate_ri   = true
+    @hook.generate
+
+    assert_path_exist File.join(@a.doc_dir('rdoc'), 'index.html')
+    assert_path_exist File.join(@a.doc_dir('ri'),   'cache.ri')
+  end
+
   def test_new_rdoc
     assert_kind_of RDoc::RDoc, @hook.new_rdoc
   end