[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / rdoc / mixin.rb
blobfa8faefc15c2f0c2066fbba8403064f644943663
1 # frozen_string_literal: true
2 ##
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
8   ##
9   # Name of included module
11   attr_accessor :name
13   ##
14   # Creates a new Mixin for +name+ with +comment+
16   def initialize(name, comment)
17     super()
18     @name = name
19     self.comment = comment
20     @module = nil # cache for module if found
21   end
23   ##
24   # Mixins are sorted by name
26   def <=> other
27     return unless self.class === other
29     name <=> other.name
30   end
32   def == other # :nodoc:
33     self.class === other and @name == other.name
34   end
36   alias eql? == # :nodoc:
38   ##
39   # Full name based on #module
41   def full_name
42     m = self.module
43     RDoc::ClassModule === m ? m.full_name : @name
44   end
46   def hash # :nodoc:
47     [@name, self.module].hash
48   end
50   def inspect # :nodoc:
51     "#<%s:0x%x %s.%s %s>" % [
52       self.class,
53       object_id,
54       parent_name, self.class.name.downcase, @name,
55     ]
56   end
58   ##
59   # Attempts to locate the included module object.  Returns the name if not
60   # known.
61   #
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.
67   #
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
71   # lookup behavior.
72   #
73   # As of the beginning of October, 2011, no gem includes nonexistent modules.
75   def module
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
87     searched.each do |i|
88       inc = i.module
89       next if String === inc
90       full_name = inc.child_name(@name)
91       @module = @store.modules_hash[full_name]
92       return @module if @module
93     end
95     # go up the hierarchy of names
96     up = parent.parent
97     while up
98       full_name = up.child_name(@name)
99       @module = @store.modules_hash[full_name]
100       return @module if @module
101       up = up.parent
102     end
104     @name
105   end
107   ##
108   # Sets the store for this class or module and its contained code objects.
110   def store= store
111     super
113     @file = @store.add_file @file.full_name if @file
114   end
116   def to_s # :nodoc:
117     "#{self.class.name.downcase} #@name in: #{parent}"
118   end