mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	[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.
0ead78616b
			
			
This commit is contained in:
		
							parent
							
								
									f52a4690f8
								
							
						
					
					
						commit
						7e7981c84f
					
				
					 3 changed files with 76 additions and 65 deletions
				
			
		|  | @ -26,12 +26,6 @@ class RDoc::AnyMethod < RDoc::MethodAttr | ||||||
| 
 | 
 | ||||||
|   attr_accessor :c_function |   attr_accessor :c_function | ||||||
| 
 | 
 | ||||||
|   ## |  | ||||||
|   # Different ways to call this method |  | ||||||
| 
 |  | ||||||
|   attr_reader :call_seq |  | ||||||
| 
 |  | ||||||
|   ## |  | ||||||
|   # Parameters for this method |   # Parameters for this method | ||||||
| 
 | 
 | ||||||
|   attr_accessor :params |   attr_accessor :params | ||||||
|  | @ -93,6 +87,19 @@ class RDoc::AnyMethod < RDoc::MethodAttr | ||||||
|     end |     end | ||||||
|   end |   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+ |   # Sets the different ways you can call this method.  If an empty +call_seq+ | ||||||
|   # is given nil is assumed. |   # is given nil is assumed. | ||||||
|  | @ -312,5 +319,43 @@ class RDoc::AnyMethod < RDoc::MethodAttr | ||||||
|     @superclass_method |     @superclass_method | ||||||
|   end |   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 | ||||||
|  |  | ||||||
|  | @ -98,8 +98,8 @@ | ||||||
| 
 | 
 | ||||||
|     <% methods.each do |method| %> |     <% methods.each do |method| %> | ||||||
|       <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>"> |       <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>"> | ||||||
|         <% if method.call_seq then %> |         <% if (call_seq = method.call_seq) then %> | ||||||
|         <%   method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %> |         <%   call_seq.strip.split("\n").each_with_index do |call_seq, i| %> | ||||||
|         <div class="method-heading"> |         <div class="method-heading"> | ||||||
|           <span class="method-callseq"> |           <span class="method-callseq"> | ||||||
|             <%= h(call_seq.strip. |             <%= h(call_seq.strip. | ||||||
|  |  | ||||||
|  | @ -209,48 +209,6 @@ class RDoc::Parser::C < RDoc::Parser | ||||||
|     end |     end | ||||||
|   end |   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 |   # Scans #content for rb_define_alias | ||||||
| 
 | 
 | ||||||
|  | @ -269,23 +227,29 @@ class RDoc::Parser::C < RDoc::Parser | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       class_obj = find_class var_name, class_name |       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 = find_alias_comment var_name, new_name, old_name | ||||||
| 
 |  | ||||||
|       comment.normalize |       comment.normalize | ||||||
| 
 |       if comment.to_s.empty? and existing_method = class_obj.method_list.find { |m| m.name == old_name} | ||||||
|       al.comment = comment |         comment = existing_method.comment | ||||||
| 
 |       end | ||||||
|       al.record_location @top_level |       add_alias(var_name, class_obj, old_name, new_name, comment) | ||||||
| 
 |  | ||||||
|       class_obj.add_alias al |  | ||||||
|       @stats.add_alias al |  | ||||||
|     end |     end | ||||||
|   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 |   # Scans #content for rb_attr and rb_define_attr | ||||||
| 
 | 
 | ||||||
|  | @ -1021,6 +985,10 @@ class RDoc::Parser::C < RDoc::Parser | ||||||
| 
 | 
 | ||||||
|     class_obj = find_class var_name, class_name |     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 class_obj then | ||||||
|       if meth_name == 'initialize' then |       if meth_name == 'initialize' then | ||||||
|         meth_name = 'new' |         meth_name = 'new' | ||||||
|  | @ -1249,8 +1217,6 @@ class RDoc::Parser::C < RDoc::Parser | ||||||
|     do_aliases |     do_aliases | ||||||
|     do_attrs |     do_attrs | ||||||
| 
 | 
 | ||||||
|     deduplicate_call_seq |  | ||||||
| 
 |  | ||||||
|     @store.add_c_variables self |     @store.add_c_variables self | ||||||
| 
 | 
 | ||||||
|     @top_level |     @top_level | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Evans
						Jeremy Evans