[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / rdoc / top_level.rb
blob3864f66431160c0bccff2fb4ae97efb09eb0b042
1 # frozen_string_literal: true
2 ##
3 # A TopLevel context is a representation of the contents of a single file
5 class RDoc::TopLevel < RDoc::Context
7   MARSHAL_VERSION = 0 # :nodoc:
9   ##
10   # This TopLevel's File::Stat struct
12   attr_accessor :file_stat
14   ##
15   # Relative name of this file
17   attr_accessor :relative_name
19   ##
20   # Absolute name of this file
22   attr_accessor :absolute_name
24   ##
25   # All the classes or modules that were declared in
26   # this file. These are assigned to either +#classes_hash+
27   # or +#modules_hash+ once we know what they really are.
29   attr_reader :classes_or_modules
31   attr_accessor :diagram # :nodoc:
33   ##
34   # The parser class that processed this file
36   attr_reader :parser
38   ##
39   # Creates a new TopLevel for the file at +absolute_name+.  If documentation
40   # is being generated outside the source dir +relative_name+ is relative to
41   # the source directory.
43   def initialize absolute_name, relative_name = absolute_name
44     super()
45     @name = nil
46     @absolute_name = absolute_name
47     @relative_name = relative_name
48     @file_stat     = File.stat(absolute_name) rescue nil # HACK for testing
49     @diagram       = nil
50     @parser        = nil
52     @classes_or_modules = []
53   end
55   ##
56   # Sets the parser for this toplevel context, also the store.
58   def parser=(val)
59     @parser = val
60     @store.update_parser_of_file(absolute_name, val) if @store
61     @parser
62   end
64   ##
65   # An RDoc::TopLevel is equal to another with the same relative_name
67   def == other
68     self.class === other and @relative_name == other.relative_name
69   end
71   alias eql? ==
73   ##
74   # Adds +an_alias+ to +Object+ instead of +self+.
76   def add_alias(an_alias)
77     object_class.record_location self
78     return an_alias unless @document_self
79     object_class.add_alias an_alias
80   end
82   ##
83   # Adds +constant+ to +Object+ instead of +self+.
85   def add_constant constant
86     object_class.record_location self
87     return constant unless @document_self
88     object_class.add_constant constant
89   end
91   ##
92   # Adds +include+ to +Object+ instead of +self+.
94   def add_include(include)
95     object_class.record_location self
96     return include unless @document_self
97     object_class.add_include include
98   end
100   ##
101   # Adds +method+ to +Object+ instead of +self+.
103   def add_method(method)
104     object_class.record_location self
105     return method unless @document_self
106     object_class.add_method method
107   end
109   ##
110   # Adds class or module +mod+. Used in the building phase
111   # by the Ruby parser.
113   def add_to_classes_or_modules mod
114     @classes_or_modules << mod
115   end
117   ##
118   # Base name of this file
120   def base_name
121     File.basename @relative_name
122   end
124   alias name base_name
126   ##
127   # Only a TopLevel that contains text file) will be displayed.  See also
128   # RDoc::CodeObject#display?
130   def display?
131     text? and super
132   end
134   ##
135   # See RDoc::TopLevel::find_class_or_module
136   #--
137   # TODO Why do we search through all classes/modules found, not just the
138   #       ones of this instance?
140   def find_class_or_module name
141     @store.find_class_or_module name
142   end
144   ##
145   # Finds a class or module named +symbol+
147   def find_local_symbol(symbol)
148     find_class_or_module(symbol) || super
149   end
151   ##
152   # Finds a module or class with +name+
154   def find_module_named(name)
155     find_class_or_module(name)
156   end
158   ##
159   # Returns the relative name of this file
161   def full_name
162     @relative_name
163   end
165   ##
166   # An RDoc::TopLevel has the same hash as another with the same
167   # relative_name
169   def hash
170     @relative_name.hash
171   end
173   ##
174   # URL for this with a +prefix+
176   def http_url(prefix)
177     path = [prefix, @relative_name.tr('.', '_')]
179     File.join(*path.compact) + '.html'
180   end
182   def inspect # :nodoc:
183     "#<%s:0x%x %p modules: %p classes: %p>" % [
184       self.class, object_id,
185       base_name,
186       @modules.map { |n,m| m },
187       @classes.map { |n,c| c }
188     ]
189   end
191   ##
192   # Time this file was last modified, if known
194   def last_modified
195     @file_stat ? file_stat.mtime : nil
196   end
198   ##
199   # Dumps this TopLevel for use by ri.  See also #marshal_load
201   def marshal_dump
202     [
203       MARSHAL_VERSION,
204       @relative_name,
205       @parser,
206       parse(@comment),
207     ]
208   end
210   ##
211   # Loads this TopLevel from +array+.
213   def marshal_load array # :nodoc:
214     initialize array[1]
216     @parser  = array[2]
217     @comment = array[3]
219     @file_stat          = nil
220   end
222   ##
223   # Returns the NormalClass "Object", creating it if not found.
224   #
225   # Records +self+ as a location in "Object".
227   def object_class
228     @object_class ||= begin
229       oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object')
230       oc.record_location self
231       oc
232     end
233   end
235   ##
236   # Base name of this file without the extension
238   def page_name
239     basename = File.basename @relative_name
240     basename =~ /\.(rb|rdoc|txt|md)$/i
242     $` || basename
243   end
245   ##
246   # Path to this file for use with HTML generator output.
248   def path
249     http_url @store.rdoc.generator.file_dir
250   end
252   def pretty_print q # :nodoc:
253     q.group 2, "[#{self.class}: ", "]" do
254       q.text "base name: #{base_name.inspect}"
255       q.breakable
257       items = @modules.map { |n,m| m }
258       items.concat @modules.map { |n,c| c }
259       q.seplist items do |mod| q.pp mod end
260     end
261   end
263   ##
264   # Search record used by RDoc::Generator::JsonIndex
266   def search_record
267     return unless @parser < RDoc::Parser::Text
269     [
270       page_name,
271       '',
272       page_name,
273       '',
274       path,
275       '',
276       snippet(@comment),
277     ]
278   end
280   ##
281   # Is this TopLevel from a text file instead of a source code file?
283   def text?
284     @parser and @parser.include? RDoc::Parser::Text
285   end
287   def to_s # :nodoc:
288     "file #{full_name}"
289   end