summaryrefslogtreecommitdiff
path: root/lib/rdoc
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-13 07:58:47 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-13 07:58:47 +0000
commitd8c7695fbb2944aba9a69dce75f41b6881d1fc12 (patch)
treebe6a5904c879c9fa9a7c2556031064233e70880b /lib/rdoc
parenta0046fe94972ba4873244a1b985cb69f1685b5f3 (diff)
* lib/rdoc/class_module.rb: Fixed duplicate comments for classes and
modules from C. * test/rdoc/test_rdoc_class_module.rb: Test for the above. * lib/rdoc/parser/c.rb: Reload C variable names to allow proper updates of an ri store for C files. * lib/rdoc/rdoc.rb: ditto. * lib/rdoc/store.rb: ditto. * test/rdoc/test_rdoc_parser_c.rb: Test for the above. * test/rdoc/test_rdoc_store.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38362 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc')
-rw-r--r--lib/rdoc/class_module.rb5
-rw-r--r--lib/rdoc/parser/c.rb66
-rw-r--r--lib/rdoc/rdoc.rb3
-rw-r--r--lib/rdoc/store.rb127
4 files changed, 168 insertions, 33 deletions
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb
index a520503598..1dbe57bdf1 100644
--- a/lib/rdoc/class_module.rb
+++ b/lib/rdoc/class_module.rb
@@ -31,7 +31,7 @@ class RDoc::ClassModule < RDoc::Context
##
# Comment and the location it came from. Use #add_comment to add comments
- attr_reader :comment_location
+ attr_accessor :comment_location
attr_accessor :diagram # :nodoc:
@@ -134,6 +134,9 @@ class RDoc::ClassModule < RDoc::Context
else
normalize_comment comment
end
+
+ @comment_location.delete_if { |(_, l)| l == location }
+
@comment_location << [comment, location]
self.comment = original
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index d371ed0e6a..968ca3c789 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -123,6 +123,11 @@ class RDoc::Parser::C < RDoc::Parser
include RDoc::Text
##
+ # Maps C variable names to names of ruby classes or modules
+
+ attr_reader :classes
+
+ ##
# C file the parser is parsing
attr_accessor :content
@@ -150,16 +155,23 @@ class RDoc::Parser::C < RDoc::Parser
attr_reader :singleton_classes
##
- # Prepare to parse a C file
+ # The TopLevel items in the parsed file belong to
+
+ attr_reader :top_level
+
+ ##
+ # Prepares for parsing a C file. See RDoc::Parser#initialize for details on
+ # the arguments.
- def initialize(top_level, file_name, content, options, stats)
+ def initialize top_level, file_name, content, options, stats
super
@known_classes = RDoc::KNOWN_CLASSES.dup
- @content = handle_tab_width handle_ifdefs_in(@content)
- @classes = {}
- @singleton_classes = {}
- @file_dir = File.dirname(@file_name)
+ @content = handle_tab_width handle_ifdefs_in @content
+ @file_dir = File.dirname @file_name
+
+ @classes = load_variable_map :c_class_variables
+ @singleton_classes = load_variable_map :c_singleton_class_variables
# missing variable => [handle_class_module arguments]
@missing_dependencies = {}
@@ -386,13 +398,12 @@ class RDoc::Parser::C < RDoc::Parser
def do_includes
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
- if cls = @classes[c]
- m = @known_classes[m] || m
+ next unless cls = @classes[c]
+ m = @known_classes[m] || m
- comment = RDoc::Comment.new '', @top_level
- incl = cls.add_include RDoc::Include.new(m, comment)
- incl.record_location @top_level
- end
+ comment = RDoc::Comment.new '', @top_level
+ incl = cls.add_include RDoc::Include.new(m, comment)
+ incl.record_location @top_level
end
end
@@ -801,7 +812,7 @@ class RDoc::Parser::C < RDoc::Parser
parent_name = @known_classes[parent] || parent
if in_module then
- enclosure = @classes[in_module] || @store.c_enclosure_classes[in_module]
+ enclosure = @classes[in_module] || @store.find_c_enclosure(in_module)
if enclosure.nil? and enclosure = @known_classes[in_module] then
enc_type = /^rb_m/ =~ in_module ? :module : :class
@@ -848,8 +859,8 @@ class RDoc::Parser::C < RDoc::Parser
end
@classes[var_name] = cm
- @store.c_enclosure_classes[var_name] = cm
@known_classes[var_name] = cm.full_name
+ @store.add_c_enclosure var_name, cm
end
##
@@ -1005,6 +1016,30 @@ class RDoc::Parser::C < RDoc::Parser
end
##
+ # Loads the variable map with the given +name+ from the RDoc::Store, if
+ # present.
+
+ def load_variable_map map_name
+ return {} unless files = @store.cache[map_name]
+ return {} unless name_map = files[@file_name]
+
+ class_map = {}
+
+ name_map.each do |variable, name|
+ next unless mod = @store.find_class_or_module(name)
+
+ class_map[variable] = if map_name == :c_class_variables then
+ mod
+ else
+ name
+ end
+ @known_classes[variable] = name
+ end
+
+ class_map
+ end
+
+ ##
# Look for directives in a normal comment block:
#
# /*
@@ -1136,6 +1171,9 @@ class RDoc::Parser::C < RDoc::Parser
do_includes
do_aliases
do_attrs
+
+ @store.add_c_variables self
+
@top_level
end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index 76da5b4289..cff5e78a20 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -476,9 +476,12 @@ The internal error was:
@store.dry_run = @options.dry_run
@store.main = @options.main_page
@store.title = @options.title
+ @store.path = @options.op_dir
@start_time = Time.now
+ @store.load_cache
+
file_info = parse_files @options.files
@options.default_title = "RDoc Documentation"
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
index cf9ee07625..9beced6423 100644
--- a/lib/rdoc/store.rb
+++ b/lib/rdoc/store.rb
@@ -69,7 +69,19 @@ class RDoc::Store
# Stores the name of the C variable a class belongs to. This helps wire up
# classes defined from C across files.
- attr_reader :c_enclosure_classes
+ attr_reader :c_enclosure_classes # :nodoc:
+
+ attr_reader :c_enclosure_names # :nodoc:
+
+ ##
+ # Maps C variables to class or module names for each parsed C file.
+
+ attr_reader :c_class_variables
+
+ ##
+ # Maps C variables to singleton class names for each parsed C file.
+
+ attr_reader :c_singleton_class_variables
##
# If true this Store will not write any files
@@ -114,15 +126,17 @@ class RDoc::Store
@type = type
@cache = {
- :ancestors => {},
- :attributes => {},
- :class_methods => {},
- :encoding => @encoding,
- :instance_methods => {},
- :main => nil,
- :modules => [],
- :pages => [],
- :title => nil,
+ :ancestors => {},
+ :attributes => {},
+ :class_methods => {},
+ :c_class_variables => {},
+ :c_singleton_class_variables => {},
+ :encoding => @encoding,
+ :instance_methods => {},
+ :main => nil,
+ :modules => [],
+ :pages => [],
+ :title => nil,
}
@classes_hash = {}
@@ -130,12 +144,35 @@ class RDoc::Store
@files_hash = {}
@c_enclosure_classes = {}
+ @c_enclosure_names = {}
+
+ @c_class_variables = {}
+ @c_singleton_class_variables = {}
@unique_classes = nil
@unique_modules = nil
end
##
+ # Adds +module+ as an enclosure (namespace) for the given +variable+ for C
+ # files.
+
+ def add_c_enclosure variable, namespace
+ @c_enclosure_classes[variable] = namespace
+ end
+
+ ##
+ # Adds C variables from an RDoc::Parser::C
+
+ def add_c_variables c_parser
+ filename = c_parser.top_level.relative_name
+
+ @c_class_variables[filename] = make_variable_map c_parser.classes
+
+ @c_singleton_class_variables[filename] = c_parser.singleton_classes
+ end
+
+ ##
# Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
# created RDoc::TopLevel.
@@ -305,6 +342,28 @@ class RDoc::Store
end
##
+ # Finds the enclosure (namespace) for the given C +variable+.
+
+ def find_c_enclosure variable
+ @c_enclosure_classes.fetch variable do
+ break unless name = @c_enclosure_names[variable]
+
+ mod = find_class_or_module name
+
+ unless mod then
+ loaded_mod = load_class_data name
+
+ file = loaded_mod.in_files.first
+ file.store = self
+
+ mod = file.add_module RDoc::NormalModule, name
+ end
+
+ @c_enclosure_classes[variable] = mod
+ end
+ end
+
+ ##
# Finds the class with +name+ in all discovered classes
def find_class_named name
@@ -500,22 +559,26 @@ class RDoc::Store
@encoding = load_enc unless @encoding
- @cache[:pages] ||= []
- @cache[:main] ||= nil
+ @cache[:pages] ||= []
+ @cache[:main] ||= nil
+ @cache[:c_class_variables] ||= {}
+ @cache[:c_singleton_class_variables] ||= {}
+
+ @cache[:c_class_variables].each do |_, map|
+ map.each do |variable, name|
+ @c_enclosure_names[variable] = name
+ end
+ end
@cache
rescue Errno::ENOENT
end
##
- # Loads ri data for +klass_name+
+ # Loads ri data for +klass_name+ and hooks it up to this store.
def load_class klass_name
- file = class_file klass_name
-
- obj = open file, 'rb' do |io|
- Marshal.load io.read
- end
+ obj = load_class_data klass_name
obj.store = self
@@ -525,6 +588,17 @@ class RDoc::Store
when RDoc::NormalModule then
@modules_hash[klass_name] = obj
end
+ end
+
+ ##
+ # Loads ri data for +klass_name+
+
+ def load_class_data klass_name
+ file = class_file klass_name
+
+ obj = open file, 'rb' do |io|
+ Marshal.load io.read
+ end
rescue Errno::ENOENT => e
error = MissingFileError.new(self, file, klass_name)
error.set_backtrace e.backtrace
@@ -584,6 +658,20 @@ class RDoc::Store
end
##
+ # Converts the variable => ClassModule map +variables+ from a C parser into
+ # a variable => class name map.
+
+ def make_variable_map variables
+ map = {}
+
+ variables.each { |variable, class_module|
+ map[variable] = class_module.full_name
+ }
+
+ map
+ end
+
+ ##
# Path to the ri data for +method_name+ in +klass_name+
def method_file klass_name, method_name
@@ -688,6 +776,9 @@ class RDoc::Store
@cache[:encoding] = @encoding # this gets set twice due to assert_cache
+ @cache[:c_class_variables].merge! @c_class_variables
+ @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables
+
return if @dry_run
marshal = Marshal.dump @cache