1## 2# Base class for the RDoc code tree. 3# 4# We contain the common stuff for contexts (which are containers) and other 5# elements (methods, attributes and so on) 6# 7# Here's the tree of the CodeObject subclasses: 8# 9# * RDoc::Context 10# * RDoc::TopLevel 11# * RDoc::ClassModule 12# * RDoc::AnonClass (never used so far) 13# * RDoc::NormalClass 14# * RDoc::NormalModule 15# * RDoc::SingleClass 16# * RDoc::MethodAttr 17# * RDoc::Attr 18# * RDoc::AnyMethod 19# * RDoc::GhostMethod 20# * RDoc::MetaMethod 21# * RDoc::Alias 22# * RDoc::Constant 23# * RDoc::Require 24# * RDoc::Include 25 26class RDoc::CodeObject 27 28 include RDoc::Text 29 30 ## 31 # Our comment 32 33 attr_reader :comment 34 35 ## 36 # Do we document our children? 37 38 attr_reader :document_children 39 40 ## 41 # Do we document ourselves? 42 43 attr_reader :document_self 44 45 ## 46 # Are we done documenting (ie, did we come across a :enddoc:)? 47 48 attr_reader :done_documenting 49 50 ## 51 # Which file this code object was defined in 52 53 attr_reader :file 54 55 ## 56 # Force documentation of this CodeObject 57 58 attr_reader :force_documentation 59 60 ## 61 # Line in #file where this CodeObject was defined 62 63 attr_accessor :line 64 65 ## 66 # Hash of arbitrary metadata for this CodeObject 67 68 attr_reader :metadata 69 70 ## 71 # Offset in #file where this CodeObject was defined 72 #-- 73 # TODO character or byte? 74 75 attr_accessor :offset 76 77 ## 78 # Sets the parent CodeObject 79 80 attr_writer :parent 81 82 ## 83 # Did we ever receive a +:nodoc:+ directive? 84 85 attr_reader :received_nodoc 86 87 ## 88 # Set the section this CodeObject is in 89 90 attr_writer :section 91 92 ## 93 # The RDoc::Store for this object. 94 95 attr_accessor :store 96 97 ## 98 # We are the model of the code, but we know that at some point we will be 99 # worked on by viewers. By implementing the Viewable protocol, viewers can 100 # associated themselves with these objects. 101 102 attr_accessor :viewer 103 104 ## 105 # Creates a new CodeObject that will document itself and its children 106 107 def initialize 108 @metadata = {} 109 @comment = '' 110 @parent = nil 111 @parent_name = nil # for loading 112 @parent_class = nil # for loading 113 @section = nil 114 @section_title = nil # for loading 115 @file = nil 116 @full_name = nil 117 @store = nil 118 119 initialize_visibility 120 end 121 122 ## 123 # Initializes state for visibility of this CodeObject and its children. 124 125 def initialize_visibility # :nodoc: 126 @document_children = true 127 @document_self = true 128 @done_documenting = false 129 @force_documentation = false 130 @received_nodoc = false 131 @ignored = false 132 end 133 134 ## 135 # Replaces our comment with +comment+, unless it is empty. 136 137 def comment=(comment) 138 @comment = case comment 139 when NilClass then '' 140 when RDoc::Markup::Document then comment 141 when RDoc::Comment then comment.normalize 142 else 143 if comment and not comment.empty? then 144 normalize_comment comment 145 else 146 # HACK correct fix is to have #initialize create @comment 147 # with the correct encoding 148 if String === @comment and 149 Object.const_defined? :Encoding and @comment.empty? then 150 @comment.force_encoding comment.encoding 151 end 152 @comment 153 end 154 end 155 end 156 157 ## 158 # Should this CodeObject be shown in documentation? 159 160 def display? 161 @document_self and not @ignored 162 end 163 164 ## 165 # Enables or disables documentation of this CodeObject's children unless it 166 # has been turned off by :enddoc: 167 168 def document_children=(document_children) 169 @document_children = document_children unless @done_documenting 170 end 171 172 ## 173 # Enables or disables documentation of this CodeObject unless it has been 174 # turned off by :enddoc:. If the argument is +nil+ it means the 175 # documentation is turned off by +:nodoc:+. 176 177 def document_self=(document_self) 178 return if @done_documenting 179 180 @document_self = document_self 181 @received_nodoc = true if document_self.nil? 182 end 183 184 ## 185 # Does this object have a comment with content or is #received_nodoc true? 186 187 def documented? 188 @received_nodoc or !@comment.empty? 189 end 190 191 ## 192 # Turns documentation on/off, and turns on/off #document_self 193 # and #document_children. 194 # 195 # Once documentation has been turned off (by +:enddoc:+), 196 # the object will refuse to turn #document_self or 197 # #document_children on, so +:doc:+ and +:start_doc:+ directives 198 # will have no effect in the current file. 199 200 def done_documenting=(value) 201 @done_documenting = value 202 @document_self = !value 203 @document_children = @document_self 204 end 205 206 ## 207 # Yields each parent of this CodeObject. See also 208 # RDoc::ClassModule#each_ancestor 209 210 def each_parent 211 code_object = self 212 213 while code_object = code_object.parent do 214 yield code_object 215 end 216 217 self 218 end 219 220 ## 221 # File name where this CodeObject was found. 222 # 223 # See also RDoc::Context#in_files 224 225 def file_name 226 return unless @file 227 228 @file.absolute_name 229 end 230 231 ## 232 # Force the documentation of this object unless documentation 233 # has been turned off by :enddoc: 234 #-- 235 # HACK untested, was assigning to an ivar 236 237 def force_documentation=(value) 238 @force_documentation = value unless @done_documenting 239 end 240 241 ## 242 # Sets the full_name overriding any computed full name. 243 # 244 # Set to +nil+ to clear RDoc's cached value 245 246 def full_name= full_name 247 @full_name = full_name 248 end 249 250 ## 251 # Use this to ignore a CodeObject and all its children until found again 252 # (#record_location is called). An ignored item will not be shown in 253 # documentation. 254 # 255 # See github issue #55 256 # 257 # The ignored status is temporary in order to allow implementation details 258 # to be hidden. At the end of processing a file RDoc allows all classes 259 # and modules to add new documentation to previously created classes. 260 # 261 # If a class was ignored (via stopdoc) then reopened later with additional 262 # documentation it should be shown. If a class was ignored and never 263 # reopened it should not be shown. The ignore flag allows this to occur. 264 265 def ignore 266 @ignored = true 267 268 stop_doc 269 end 270 271 ## 272 # Has this class been ignored? 273 274 def ignored? 275 @ignored 276 end 277 278 ## 279 # Our parent CodeObject. The parent may be missing for classes loaded from 280 # legacy RI data stores. 281 282 def parent 283 return @parent if @parent 284 return nil unless @parent_name 285 286 if @parent_class == RDoc::TopLevel then 287 @parent = @store.add_file @parent_name 288 else 289 @parent = @store.find_class_or_module @parent_name 290 291 return @parent if @parent 292 293 begin 294 @parent = @store.load_class @parent_name 295 rescue RDoc::Store::MissingFileError 296 nil 297 end 298 end 299 end 300 301 ## 302 # File name of our parent 303 304 def parent_file_name 305 @parent ? @parent.base_name : '(unknown)' 306 end 307 308 ## 309 # Name of our parent 310 311 def parent_name 312 @parent ? @parent.full_name : '(unknown)' 313 end 314 315 ## 316 # Records the RDoc::TopLevel (file) where this code object was defined 317 318 def record_location top_level 319 @ignored = false 320 @file = top_level 321 end 322 323 ## 324 # The section this CodeObject is in. Sections allow grouping of constants, 325 # attributes and methods inside a class or module. 326 327 def section 328 return @section if @section 329 330 @section = parent.add_section @section_title if parent 331 end 332 333 ## 334 # Enable capture of documentation unless documentation has been 335 # turned off by :enddoc: 336 337 def start_doc 338 return if @done_documenting 339 340 @document_self = true 341 @document_children = true 342 @ignored = false 343 end 344 345 ## 346 # Disable capture of documentation 347 348 def stop_doc 349 @document_self = false 350 @document_children = false 351 end 352 353end 354 355