diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb index 50bd25021d..563a9c96df 100644 --- a/lib/rdoc/store.rb +++ b/lib/rdoc/store.rb @@ -182,6 +182,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 +205,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 +745,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 +915,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..6caccdc7b5 100644 --- a/test/rdoc/rdoc_store_test.rb +++ b/test/rdoc/rdoc_store_test.rb @@ -650,6 +650,45 @@ def test_page_with_extension assert_equal page, @store.page('PAGE.txt') end + 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 + 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