From 3f8d90ec216d84cc5a817a9960d3b609bafec9c9 Mon Sep 17 00:00:00 2001 From: "Stanislav (Stas) Katkov" Date: Fri, 4 Sep 2026 16:51:12 +0200 Subject: [PATCH 1/2] Introduce page_index to Rdoc::Store --- lib/rdoc/store.rb | 11 ++++++-- test/rdoc/rdoc_store_test.rb | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb index 50bd25021d..be594ef509 100644 --- a/lib/rdoc/store.rb +++ b/lib/rdoc/store.rb @@ -141,6 +141,7 @@ def initialize(options, path: nil, type: nil) @modules_hash = {} @files_hash = {} @text_files_hash = {} + @page_index = nil @c_enclosure_classes = {} @c_enclosure_names = {} @@ -182,6 +183,7 @@ def add_file(absolute_name, relative_name: absolute_name, parser: nil) top_level.store = self @files_hash[relative_name] = top_level @text_files_hash[relative_name] = top_level if top_level.text? + @page_index = nil end top_level @@ -204,6 +206,7 @@ def remove_file(relative_name) @c_singleton_class_variables.delete(relative_name) return unless top_level + @page_index = nil remove_classes_and_modules(top_level.classes_or_modules) end @@ -743,6 +746,7 @@ def load_all end end + @page_index = nil @cache[:pages].each do |page_name| page = load_page page_name @files_hash[page_name] = page @@ -912,9 +916,12 @@ def modules_hash # Returns the RDoc::TopLevel that is a file and has the given +name+ def page(name) - @files_hash.each_value.find do |file| - file.page_name == name or file.base_name == name + @page_index ||= @files_hash.each_value.each_with_object({}) do |file, index| + index[file.page_name] ||= file + index[file.base_name] ||= file end + + @page_index[name] end ## diff --git a/test/rdoc/rdoc_store_test.rb b/test/rdoc/rdoc_store_test.rb index 00fc44ac9f..02d841f78d 100644 --- a/test/rdoc/rdoc_store_test.rb +++ b/test/rdoc/rdoc_store_test.rb @@ -650,6 +650,56 @@ def test_page_with_extension assert_equal page, @store.page('PAGE.txt') end + def test_page_index + page = @store.add_file 'PAGE.txt', parser: RDoc::Parser::Simple + page_name = page.page_name + base_name = page.base_name + name_calls = 0 + page.define_singleton_method(:page_name) do + name_calls += 1 + page_name + end + page.define_singleton_method(:base_name) do + name_calls += 1 + base_name + end + + 2.times do + assert_same page, @store.page('PAGE') + assert_same page, @store.page('PAGE.txt') + assert_nil @store.page('missing') + end + + assert_equal 2, name_calls + end + + def test_page_index_invalidated_when_files_change + assert_nil @store.page('PAGE') + + first_page = @store.add_file 'PAGE.txt', parser: RDoc::Parser::Simple + assert_same first_page, @store.page('PAGE') + + second_page = @store.add_file 'doc/PAGE.md', parser: RDoc::Parser::Simple + assert_same first_page, @store.page('PAGE') + + @store.remove_file 'PAGE.txt' + assert_same second_page, @store.page('PAGE') + end + + def test_page_index_invalidated_by_load_all + FileUtils.mkdir_p @tmpdir + source = RDoc::Store.new RDoc::Options.new, path: @tmpdir + source.add_file 'README.txt', parser: RDoc::Parser::Simple + source.save + + loaded = RDoc::Store.new RDoc::Options.new, path: @tmpdir + assert_nil loaded.page('README') + + loaded.load_all + + assert_equal 'README.txt', loaded.page('README').relative_name + end + def test_save FileUtils.mkdir_p @tmpdir From 54d2b506b2bf2291202ed8f8c2cfbec23605301a Mon Sep 17 00:00:00 2001 From: "Stanislav (Stas) Katkov" Date: Fri, 4 Sep 2026 17:10:47 +0200 Subject: [PATCH 2/2] clean-up --- lib/rdoc/store.rb | 1 - test/rdoc/rdoc_store_test.rb | 29 +++++++++-------------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb index be594ef509..563a9c96df 100644 --- a/lib/rdoc/store.rb +++ b/lib/rdoc/store.rb @@ -141,7 +141,6 @@ def initialize(options, path: nil, type: nil) @modules_hash = {} @files_hash = {} @text_files_hash = {} - @page_index = nil @c_enclosure_classes = {} @c_enclosure_names = {} diff --git a/test/rdoc/rdoc_store_test.rb b/test/rdoc/rdoc_store_test.rb index 02d841f78d..6caccdc7b5 100644 --- a/test/rdoc/rdoc_store_test.rb +++ b/test/rdoc/rdoc_store_test.rb @@ -650,27 +650,16 @@ def test_page_with_extension assert_equal page, @store.page('PAGE.txt') end - def test_page_index - page = @store.add_file 'PAGE.txt', parser: RDoc::Parser::Simple - page_name = page.page_name - base_name = page.base_name - name_calls = 0 - page.define_singleton_method(:page_name) do - name_calls += 1 - page_name - end - page.define_singleton_method(:base_name) do - name_calls += 1 - base_name + def test_page_index_linear_performance + assert_linear_performance((1..4).map { |i| 10**i }) do |count| + store = RDoc::Store.new RDoc::Options.new + count.times { |i| store.add_file "page_#{i}.txt" } + + count.times do + store.page 'page_0' + store.page 'missing' + end end - - 2.times do - assert_same page, @store.page('PAGE') - assert_same page, @store.page('PAGE.txt') - assert_nil @store.page('missing') - end - - assert_equal 2, name_calls end def test_page_index_invalidated_when_files_change