* 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
@ -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>
|
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
|
* 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…
x
Reference in New Issue
Block a user