1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
require 'locale/util/memoizable'
module GetText
# For normalize/finding the related classes/modules.
# This is used for realizing the scope of TextDomain.
# (see: http://www.yotabanana.com/hiki/ruby-gettext-scope.html)
module ClassInfo
extend self
include Locale::Util::Memoizable
# normalize the class name
# klass should kind of the class, not object.
def normalize_class(klass)
ret = (klass.kind_of? Module) ? klass : klass.class
if ret.name =~ /^\#<|^$/ or ret == GetText
ret = Object
end
ret
end
def root_ancestors # :nodoc:
Object.ancestors
end
memoize :root_ancestors
# Internal method for related_classes.
def related_classes_internal(klass, all_classes = [], analyzed_classes = [] )
ret = []
klass = normalize_class(klass)
return [Object] if root_ancestors.include? klass
ary = klass.name.split(/::/)
while(v = ary.shift)
ret.unshift(((ret.size == 0) ? Object.const_get(v) : ret[0].const_get(v)))
end
ret -= analyzed_classes
if ret.size > 1
ret += related_classes_internal(ret[1], all_classes, analyzed_classes)
ret.uniq!
end
analyzed_classes << klass unless analyzed_classes.include? klass
klass.ancestors[1..-1].each do |a|
ret += related_classes_internal(a, all_classes, analyzed_classes)
ret.uniq!
end
if all_classes.size > 0
(ret & all_classes).uniq
else
ret.uniq
end
end
# Returns the classes which related to klass
# (klass's ancestors, included modules and nested modules)
def related_classes(klass, all_classes = [])
ret = related_classes_internal(klass, all_classes)
unless ret.include? Object
ret += [Object]
end
ret
end
memoize :related_classes
end
end
|