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

ruby-changes:61364

From: Jeremy <ko1@a...>
Date: Sun, 24 May 2020 23:53:20 +0900 (JST)
Subject: [ruby-changes:61364] 7e7981c84f (master): [ruby/rdoc] Treat multiple Ruby methods calling the same C method as aliases

https://git.ruby-lang.org/ruby.git/commit/?id=7e7981c84f

From 7e7981c84f8cd3225b5e915cba2281869a08b784 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Tue, 10 Sep 2019 16:17:09 -0700
Subject: [ruby/rdoc] Treat multiple Ruby methods calling the same C method as
 aliases

Previously, only calls to rb_define_alias were treated as aliases.
This treats calls to rb_define_method with the same C function as
aliases, with the first function defined being the primary method.

This move the dedup code from the C parser to AnyMethod, and has
AnyMethod look in its aliases to find the call_seq.

Switch the deduplication code to remove lines matching one of the
other aliases, instead of only keeping lines matching the current
alias.  The previous approach could eliminate all call_seq lines
in cases where no line matched.  This was necessary to pass
tests when call_seq does deduplication by default.

The only change to the darkfish template is to not perform
unnecessary work by deduplicating twice.

https://github.com/ruby/rdoc/commit/0ead78616b

diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index 9b0d309..562e684 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -26,12 +26,6 @@ class RDoc::AnyMethod < RDoc::MethodAttr https://github.com/ruby/ruby/blob/trunk/lib/rdoc/any_method.rb#L26
 
   attr_accessor :c_function
 
-  ##
-  # Different ways to call this method
-
-  attr_reader :call_seq
-
-  ##
   # Parameters for this method
 
   attr_accessor :params
@@ -94,6 +88,19 @@ class RDoc::AnyMethod < RDoc::MethodAttr https://github.com/ruby/ruby/blob/trunk/lib/rdoc/any_method.rb#L88
   end
 
   ##
+  # Different ways to call this method
+
+  def call_seq
+    unless call_seq = _call_seq
+      call_seq = is_alias_for._call_seq if is_alias_for
+    end
+
+    return unless call_seq
+
+    deduplicate_call_seq(call_seq)
+  end
+
+  ##
   # Sets the different ways you can call this method.  If an empty +call_seq+
   # is given nil is assumed.
   #
@@ -312,5 +319,43 @@ class RDoc::AnyMethod < RDoc::MethodAttr https://github.com/ruby/ruby/blob/trunk/lib/rdoc/any_method.rb#L319
     @superclass_method
   end
 
-end
+  protected
+
+  ##
+  # call_seq without deduplication and alias lookup.
+
+  def _call_seq
+    @call_seq if defined?(@call_seq) && @call_seq
+  end
+
+  private
+
+  ##
+  # call_seq with alias examples information removed, if this
+  # method is an alias method.
+
+  def deduplicate_call_seq(call_seq)
+    return call_seq unless is_alias_for || !aliases.empty?
+
+    method_name = self.name
+    method_name = method_name[0, 1] if method_name =~ /\A\[/
 
+    entries = call_seq.split "\n"
+
+    ignore = aliases.map(&:name)
+    if is_alias_for
+      ignore << is_alias_for.name
+      ignore.concat is_alias_for.aliases.map(&:name)
+    end
+    ignore.map! { |n| n =~ /\A\[/ ? n[0, 1] : n}
+    ignore.delete(method_name)
+    ignore = Regexp.union(ignore)
+
+    matching = entries.reject do |entry|
+      entry =~ /^\w*\.?#{ignore}/ or
+        entry =~ /\s#{ignore}\s/
+    end
+
+    matching.join "\n"
+  end
+end
diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml
index 7733095..596764d 100644
--- a/lib/rdoc/generator/template/darkfish/class.rhtml
+++ b/lib/rdoc/generator/template/darkfish/class.rhtml
@@ -98,8 +98,8 @@ https://github.com/ruby/ruby/blob/trunk/lib/rdoc/generator/template/darkfish/class.rhtml#L98
 
     <% methods.each do |method| %>
       <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
-        <% if method.call_seq then %>
-        <%   method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
+        <% if (call_seq = method.call_seq) then %>
+        <%   call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
         <div class="method-heading">
           <span class="method-callseq">
             <%= h(call_seq.strip.
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 8265712..707a898 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -210,48 +210,6 @@ class RDoc::Parser::C < RDoc::Parser https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L210
   end
 
   ##
-  # Removes duplicate call-seq entries for methods using the same
-  # implementation.
-
-  def deduplicate_call_seq
-    @methods.each do |var_name, functions|
-      class_name = @known_classes[var_name]
-      next unless class_name
-      class_obj  = find_class var_name, class_name
-
-      functions.each_value do |method_names|
-        next if method_names.length == 1
-
-        method_names.each do |method_name|
-          deduplicate_method_name class_obj, method_name
-        end
-      end
-    end
-  end
-
-  ##
-  # If two ruby methods share a C implementation (and comment) this
-  # deduplicates the examples in the call_seq for the method to reduce
-  # confusion in the output.
-
-  def deduplicate_method_name class_obj, method_name # :nodoc:
-    return unless
-      method = class_obj.method_list.find { |m| m.name == method_name }
-    return unless call_seq = method.call_seq
-
-    method_name = method_name[0, 1] if method_name =~ /\A\[/
-
-    entries = call_seq.split "\n"
-
-    matching = entries.select do |entry|
-      entry =~ /^\w*\.?#{Regexp.escape method_name}/ or
-        entry =~ /\s#{Regexp.escape method_name}\s/
-    end
-
-    method.call_seq = matching.join "\n"
-  end
-
-  ##
   # Scans #content for rb_define_alias
 
   def do_aliases
@@ -269,24 +227,30 @@ class RDoc::Parser::C < RDoc::Parser https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L227
       end
 
       class_obj = find_class var_name, class_name
-
-      al = RDoc::Alias.new '', old_name, new_name, ''
-      al.singleton = @singleton_classes.key? var_name
-
       comment = find_alias_comment var_name, new_name, old_name
-
       comment.normalize
-
-      al.comment = comment
-
-      al.record_location @top_level
-
-      class_obj.add_alias al
-      @stats.add_alias al
+      if comment.to_s.empty? and existing_method = class_obj.method_list.find { |m| m.name == old_name}
+        comment = existing_method.comment
+      end
+      add_alias(var_name, class_obj, old_name, new_name, comment)
     end
   end
 
   ##
+  # Add alias, either from a direct alias definition, or from two
+  # method that reference the same function.
+
+  def add_alias(var_name, class_obj, old_name, new_name, comment)
+    al = RDoc::Alias.new '', old_name, new_name, ''
+    al.singleton = @singleton_classes.key? var_name
+    al.comment = comment
+    al.record_location @top_level
+    class_obj.add_alias al
+    @stats.add_alias al
+    al
+  end
+
+  ##
   # Scans #content for rb_attr and rb_define_attr
 
   def do_attrs
@@ -1021,6 +985,10 @@ class RDoc::Parser::C < RDoc::Parser https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L985
 
     class_obj = find_class var_name, class_name
 
+    if existing_method = class_obj.method_list.find { |m| m.c_function == function }
+      add_alias(var_name, class_obj, existing_method.name, meth_name, existing_method.comment)
+    end
+
     if class_obj then
       if meth_name == 'initialize' then
         meth_name = 'new'
@@ -1249,8 +1217,6 @@ class RDoc::Parser::C < RDoc::Parser https://github.com/ruby/ruby/blob/trunk/lib/rdoc/parser/c.rb#L1217
     do_aliases
     do_attrs
 
-    deduplicate_call_seq
-
     @store.add_c_variables self
 
     @top_level
-- 
cgit v0.10.2


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

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