1 # frozen_string_literal: true
3 # A Mixin adds features from a module into another context. RDoc::Include and
4 # RDoc::Extend are both mixins.
6 class RDoc::Mixin < RDoc::CodeObject
9 # Name of included module
14 # Creates a new Mixin for +name+ with +comment+
16 def initialize(name, comment)
19 self.comment = comment
20 @module = nil # cache for module if found
24 # Mixins are sorted by name
27 return unless self.class === other
32 def == other # :nodoc:
33 self.class === other and @name == other.name
36 alias eql? == # :nodoc:
39 # Full name based on #module
43 RDoc::ClassModule === m ? m.full_name : @name
47 [@name, self.module].hash
51 "#<%s:0x%x %s.%s %s>" % [
54 parent_name, self.class.name.downcase, @name,
59 # Attempts to locate the included module object. Returns the name if not
62 # The scoping rules of Ruby to resolve the name of an included module are:
63 # - first look into the children of the current context;
64 # - if not found, look into the children of included modules,
65 # in reverse inclusion order;
66 # - if still not found, go up the hierarchy of names.
68 # This method has <code>O(n!)</code> behavior when the module calling
69 # include is referencing nonexistent modules. Avoid calling #module until
70 # after all the files are parsed. This behavior is due to ruby's constant
73 # As of the beginning of October, 2011, no gem includes nonexistent modules.
76 return @module if @module
78 # search the current context
79 return @name unless parent
80 full_name = parent.child_name(@name)
81 @module = @store.modules_hash[full_name]
82 return @module if @module
83 return @name if @name =~ /^::/
85 # search the includes before this one, in reverse order
86 searched = parent.includes.take_while { |i| i != self }.reverse
89 next if String === inc
90 full_name = inc.child_name(@name)
91 @module = @store.modules_hash[full_name]
92 return @module if @module
95 # go up the hierarchy of names
98 full_name = up.child_name(@name)
99 @module = @store.modules_hash[full_name]
100 return @module if @module
108 # Sets the store for this class or module and its contained code objects.
113 @file = @store.add_file @file.full_name if @file
117 "#{self.class.name.downcase} #@name in: #{parent}"