[前][次][番号順一覧][スレッド一覧]

ruby-changes:26311

From: drbrain <ko1@a...>
Date: Thu, 13 Dec 2012 16:59:03 +0900 (JST)
Subject: [ruby-changes:26311] drbrain:r38362 (trunk): * lib/rdoc/class_module.rb: Fixed duplicate comments for classes and

drbrain	2012-12-13 16:58:47 +0900 (Thu, 13 Dec 2012)

  New Revision: 38362

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38362

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/lib/rdoc/class_module.rb
    trunk/lib/rdoc/parser/c.rb
    trunk/lib/rdoc/rdoc.rb
    trunk/lib/rdoc/store.rb
    trunk/test/rdoc/test_rdoc_class_module.rb
    trunk/test/rdoc/test_rdoc_parser_c.rb
    trunk/test/rdoc/test_rdoc_store.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38361)
+++ ChangeLog	(revision 38362)
@@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Dec 13 16:53:10 2012  Eric Hodel  <drbrain@s...>
+
+	* 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.
+
 Thu Dec 13 14:20:00 2012  Zachary Scott  <zachary@z...>
 
 	* lib/irb*: merge doc from doc/irb/ird.rd and improve overall
Index: lib/rdoc/rdoc.rb
===================================================================
--- lib/rdoc/rdoc.rb	(revision 38361)
+++ lib/rdoc/rdoc.rb	(revision 38362)
@@ -476,9 +476,12 @@ The internal error was: https://github.com/ruby/ruby/blob/trunk/lib/rdoc/rdoc.rb#L476
     @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"
Index: lib/rdoc/store.rb
===================================================================
--- lib/rdoc/store.rb	(revision 38361)
+++ lib/rdoc/store.rb	(revision 38362)
@@ -69,7 +69,19 @@ class RDoc::Store https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L69
   # 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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L126
     @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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L144
     @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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L342
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L559
 
     @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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L588
     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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L658
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/store.rb#L776
 
     @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
Index: lib/rdoc/class_module.rb
===================================================================
--- lib/rdoc/class_module.rb	(revision 38361)
+++ lib/rdoc/class_module.rb	(revision 38362)
@@ -31,7 +31,7 @@ class RDoc::ClassModule < RDoc::Context https://github.com/ruby/ruby/blob/trunk/lib/rdoc/class_module.rb#L31
   ##
   # 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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/class_module.rb#L134
               else
                 normalize_comment comment
               end
+
+    @comment_location.delete_if { |(_, l)| l == location }
+
     @comment_location << [comment, location]
 
     self.comment = original
Index: lib/rdoc/parser/c.rb
===================================================================
--- lib/rdoc/parser/c.rb	(revision 38361)
+++ lib/rdoc/parser/c.rb	(revision 38362)
@@ -123,6 +123,11 @@ class RDoc::Parser::C < RDoc::Parser https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L123
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L155
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L398
 
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L812
     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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L859
     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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L1016
   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 https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L1171
     do_includes
     do_aliases
     do_attrs
+
+    @store.add_c_variables self
+
     @top_level
   end
 
Index: test/rdoc/test_rdoc_store.rb
===================================================================
--- test/rdoc/test_rdoc_store.rb	(revision 38361)
+++ test/rdoc/test_rdoc_store.rb	(revision 38362)
@@ -18,6 +18,7 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L18
 
     @klass = @top_level.add_class RDoc::NormalClass, 'Object'
     @klass.add_comment 'original', @top_level
+    @klass.record_location @top_level
 
     @cmeth = RDoc::AnyMethod.new nil, 'cmethod'
     @cmeth.singleton = true
@@ -87,15 +88,17 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L88
     @s.clean_cache_collection ancestors
 
     expected = {
-      :ancestors        => ancestors,
-      :attributes       => attrs,
-      :class_methods    => cmethods,
-      :encoding         => nil,
-      :instance_methods => imethods,
-      :modules          => modules,
-      :pages            => pages,
-      :main             => main,
-      :title            => title,
+      :ancestors                   => ancestors,
+      :attributes                  => attrs,
+      :class_methods               => cmethods,
+      :c_class_variables           => {},
+      :c_singleton_class_variables => {},
+      :encoding                    => nil,
+      :instance_methods            => imethods,
+      :modules                     => modules,
+      :pages                       => pages,
+      :main                        => main,
+      :title                       => title,
     }
 
     @s.save_cache
@@ -115,6 +118,38 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L118
     refute File.exist?(path), "#{path} exists"
   end
 
+  def test_add_c_enclosure
+    @s.add_c_enclosure 'cC1', @c1
+
+    expected = { 'cC1' => @c1 }
+
+    assert_equal expected, @s.c_enclosure_classes
+  end
+
+  def test_add_c_variables
+    options = RDoc::Options.new
+
+    c_file = @s.add_file 'ext.c'
+
+    some_ext   = c_file.add_class RDoc::NormalClass, 'SomeExt'
+                 c_file.add_class RDoc::SingleClass, 'SomeExtSingle'
+
+    c_parser = RDoc::Parser::C.new c_file, 'ext.c', '', options, nil
+
+    c_parser.classes['cSomeExt']             = some_ext
+    c_parser.singleton_classes['s_cSomeExt'] = 'SomeExtSingle'
+
+    @s.add_c_variables c_parser
+
+    expected = { 'ext.c' => { 'cSomeExt' => 'SomeExt' } }
+
+    assert_equal expected, @s.c_class_variables
+
+    expected = { 'ext.c' => { 's_cSomeExt' => 'SomeExtSingle' } }
+
+    assert_equal expected, @s.c_singleton_class_variables
+  end
+
   def test_add_file
     top_level = @store.add_file 'file.rb'
 
@@ -214,6 +249,31 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L249
     refute_empty a1.aliases
   end
 
+  def test_find_c_enclosure
+    assert_nil @s.find_c_enclosure 'cC1'
+
+    @s.add_c_enclosure 'cC1', @c1
+
+    assert_equal @c1, @s.find_c_enclosure('cC1')
+  end
+
+  def test_find_c_enclosure_from_cache
+    @s.save_class @klass
+    @s.classes_hash.clear
+
+    assert_nil @s.find_c_enclosure 'cObject'
+
+    @s.c_enclosure_names['cObject'] = 'Object'
+
+    klass = @s.find_c_enclosure('cObject')
+    assert_equal @klass, klass
+
+    assert_empty klass.comment_location
+    assert_equal @top_level, klass.parent
+
+    assert_includes @s.c_enclosure_classes, 'cObject'
+  end
+
   def test_find_class_named
     assert_equal @c1, @store.find_class_named('C1')
 
@@ -329,11 +389,15 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L389
 
   def test_load_cache
     cache = {
-      :encoding => :encoding_value,
-      :methods  => { "Object" => %w[Object#method] },
-      :main     => @page.full_name,
-      :modules  => %w[Object],
-      :pages    => [],
+      :c_class_variables           =>
+        { 'file.c' => { 'cKlass' => 'Klass' } },
+      :c_singleton_class_variables =>
+        { 'file.c' => { 'sKlass' => 'KlassSingle' } },
+      :encoding                    => :encoding_value,
+      :methods                     => { "Object" => %w[Object#method] },
+      :main                        => @page.full_name,
+      :modules                     => %w[Object],
+      :pages                       => [],
     }
 
     Dir.mkdir @tmpdir
@@ -348,17 +412,28 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L412
 
     assert_equal :encoding_value, @s.encoding
     assert_equal 'README.txt',    @s.main
+
+    expected = { 'file.c' => { 'cKlass' => 'Klass' } }
+    assert_equal expected, @s.cache[:c_class_variables]
+
+    expected = { 'file.c' => { 'sKlass' => 'KlassSingle' } }
+    assert_equal expected, @s.cache[:c_singleton_class_variables]
+
+    expected = { 'cKlass' => 'Klass' }
+    assert_equal expected, @s.c_enclosure_names
   end
 
   def test_load_cache_encoding_differs
     skip "Encoding not implemented" unless Object.const_defined? :Encoding
 
     cache = {
-      :encoding => Encoding::ISO_8859_1,
-      :main     => nil,
-      :methods  => { "Object" => %w[Object#method] },
-      :modules  => %w[Object],
-      :pages    => [],
+      :c_class_variables           => {},
+      :c_singleton_class_variables => {},
+      :encoding                    => Encoding::ISO_8859_1,
+      :main                        => nil,
+      :methods                     => { "Object" => %w[Object#method] },
+      :modules                     => %w[Object],
+      :pages                       => [],
     }
 
     Dir.mkdir @tmpdir
@@ -378,15 +453,17 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L453
 
   def test_load_cache_no_cache
     cache = {
-      :ancestors        => {},
-      :attributes       => {},
-      :class_methods    => {},
-      :encoding         => nil,
-      :instance_methods => {},
-      :main             => nil,
-      :modules          => [],
-      :pages            => [],
-      :title            => nil,
+      :ancestors                   => {},
+      :attributes                  => {},
+      :class_methods               => {},
+      :c_class_variables           => {},
+      :c_singleton_class_variables => {},
+      :encoding                    => nil,
+      :instance_methods            => {},
+      :main                        => nil,
+      :modules                     => [],
+      :pages                       => [],
+      :title                       => nil,
     }
 
     @s.load_cache
@@ -404,6 +481,8 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L481
       :modules          => %w[Object],
       # no :pages
       # no :main
+      # no :c_class_variables
+      # no :c_singleton_class_variables
     }
 
     Dir.mkdir @tmpdir
@@ -415,14 +494,16 @@ class TestRDocStore < XrefTestCase https://github.com/ruby/ruby/blob/trunk/test/rdoc/test_rdoc_store.rb#L494
     @s.load_cache
 
     expected = {
-      :ancestors        => {},
-      :attributes       => {},
-      :class_methods    => {},
-      :encoding         => :encoding_value,
-      :instance_methods => { "Object" => %w[Object#method] },
-      :main             => nil,
-      :modules          => %w[Object],
-      :pages            => [],
+      :ancestors                   => {},
+      :attributes                  => {},
+      :class_methods               => {},
+      :c_class_variables           => {},
+      :c_singleton_class_variables => {},
+      :encoding                    => :encoding_value,
+      :instance_methods            => { "Object" => %w[Object#method] }, (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]