From 7fd053a01832a4899cca28f62af246592f8e3f59 Mon Sep 17 00:00:00 2001 From: ko1 Date: Fri, 29 May 2015 08:39:50 +0000 Subject: * tool/make_hgraph.rb: added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- tool/make_hgraph.rb | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 tool/make_hgraph.rb (limited to 'tool') diff --git a/tool/make_hgraph.rb b/tool/make_hgraph.rb new file mode 100644 index 0000000000..0f388814dd --- /dev/null +++ b/tool/make_hgraph.rb @@ -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 + "#" + 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 -- cgit v1.2.3