mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* tool/make_hgraph.rb: added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									451fe269e5
								
							
						
					
					
						commit
						7fd053a018
					
				
					 2 changed files with 99 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
Fri May 29 17:39:14 2015  Koichi Sasada  <ko1@atdot.net>
 | 
			
		||||
 | 
			
		||||
	* tool/make_hgraph.rb: added.
 | 
			
		||||
 | 
			
		||||
Fri May 29 14:39:00 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* compile.c (iseq_compile_each): out of range NTH_REF is always
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										95
									
								
								tool/make_hgraph.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								tool/make_hgraph.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,95 @@
 | 
			
		|||
#
 | 
			
		||||
# Make dot file of internal class/module hierarchy graph.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
require 'objspace'
 | 
			
		||||
 | 
			
		||||
module ObjectSpace
 | 
			
		||||
  def self.object_id_of obj
 | 
			
		||||
    if obj.kind_of?(ObjectSpace::InternalObjectWrapper)
 | 
			
		||||
      obj.internal_object_id
 | 
			
		||||
    else
 | 
			
		||||
      obj.object_id
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  T_ICLASS_NAME = {}
 | 
			
		||||
 | 
			
		||||
  def self.class_name_of klass
 | 
			
		||||
    case klass
 | 
			
		||||
    when Class, Module
 | 
			
		||||
      # (singleton class).name returns nil
 | 
			
		||||
      klass.name || klass.inspect
 | 
			
		||||
    when InternalObjectWrapper # T_ICLASS
 | 
			
		||||
      if klass.type == :T_ICLASS
 | 
			
		||||
        "#<I:#{class_name_of(ObjectSpace.internal_class_of(klass))}>"
 | 
			
		||||
      else
 | 
			
		||||
        klass.inspect
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      klass.inspect
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.module_refenreces klass
 | 
			
		||||
    h = {} # object_id -> [klass, class_of, super]
 | 
			
		||||
    stack = [klass]
 | 
			
		||||
    while klass = stack.pop
 | 
			
		||||
      obj_id = ObjectSpace.object_id_of(klass)
 | 
			
		||||
      next if h.has_key?(obj_id)
 | 
			
		||||
      cls = ObjectSpace.internal_class_of(klass)
 | 
			
		||||
      sup = ObjectSpace.internal_super_of(klass)
 | 
			
		||||
      stack << cls if cls
 | 
			
		||||
      stack << sup if sup
 | 
			
		||||
      h[obj_id] = [klass, cls, sup].map{|e| ObjectSpace.class_name_of(e)}
 | 
			
		||||
    end
 | 
			
		||||
    h.values
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.module_refenreces_dot klass
 | 
			
		||||
    result = []
 | 
			
		||||
    rank_set = {}
 | 
			
		||||
 | 
			
		||||
    result << "digraph mod_h {"
 | 
			
		||||
    # result << "  rankdir=LR;"
 | 
			
		||||
    module_refenreces(klass).each{|(m, k, s)|
 | 
			
		||||
      # next if /singleton/ =~ m
 | 
			
		||||
      result << "#{m.dump} -> #{s.dump} [label=\"super\"];"
 | 
			
		||||
      result << "#{m.dump} -> #{k.dump} [label=\"klass\"];"
 | 
			
		||||
 | 
			
		||||
      unless rank = rank_set[m]
 | 
			
		||||
        rank = rank_set[m] = 0
 | 
			
		||||
      end
 | 
			
		||||
      unless rank_set[s]
 | 
			
		||||
        rank_set[s] = rank + 1
 | 
			
		||||
      end
 | 
			
		||||
      unless rank_set[k]
 | 
			
		||||
        rank_set[k] = rank
 | 
			
		||||
      end
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rs = [] # [[mods...], ...]
 | 
			
		||||
    rank_set.each{|m, r|
 | 
			
		||||
      rs[r] = [] unless rs[r]
 | 
			
		||||
      rs[r] << m
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rs.each{|ms|
 | 
			
		||||
      result << "{rank = same; #{ms.map{|m| m.dump}.join(", ")}};"
 | 
			
		||||
    }
 | 
			
		||||
    result << "}"
 | 
			
		||||
    result.join("\n")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.module_refenreces_image klass, file
 | 
			
		||||
    dot = module_refenreces_dot(klass)
 | 
			
		||||
    img = nil
 | 
			
		||||
    IO.popen("dot -Tpng", 'r+'){|io|
 | 
			
		||||
      #
 | 
			
		||||
      io.puts dot
 | 
			
		||||
      io.close_write
 | 
			
		||||
      img = io.read
 | 
			
		||||
    }
 | 
			
		||||
    open(File.expand_path(file), 'w+'){|f| f.puts img}
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue