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
Reference in a new issue