Class: RDoc::Generator::Shomen
- Inherits:
-
Object
- Object
- RDoc::Generator::Shomen
- Defined in:
- lib/shomen/rdoc.rb
Overview
Shomen Adaptor for RDoc utilizes the rdoc tool to parse ruby source code to build a Shomen documenation file.
RDoc is almost entirely a free-form documentation system, so it is not possible for Shomen to fully harness all the details it can support from the RDoc documentation, such as method argument descriptions.
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
User options from the command line.
-
#path_base ⇒ Object
readonly
protected
Current pathname.
-
#path_output ⇒ Object
readonly
protected
The output path.
Class Method Summary collapse
-
.for(options) ⇒ Object
Standard generator factory method.
Instance Method Summary collapse
-
#attributes_all ⇒ Object
List of all attributes in all classes and modules.
-
#class_dir ⇒ Object
RDoc needs this to function.
-
#classes ⇒ Object
In the world of the RDoc Generators #classes is the same as #all_classes_and_modules.
-
#classes_toplevel ⇒ Object
Only toplevel classes and modules.
- #collect_attributes(class_module, singleton = false) ⇒ Object protected
- #collect_methods(class_module, singleton = false) ⇒ Object protected
-
#complete_name(name, namespace) ⇒ Object
protected
Returns String of fully qualified name.
- #constants_all ⇒ Object
-
#debug_msg(msg) ⇒ Object
protected
Output progress information if rdoc debugging is enabled.
-
#file_dir ⇒ Object
RDoc needs this to function.
- #files ⇒ Object
- #files_hash ⇒ Object
-
#files_toplevel ⇒ Object
List of toplevel files.
-
#generate(files) ⇒ Object
Build the initial indices and output objects based on an array of top level objects containing the extracted information.
-
#generate_classes ⇒ Object
protected
Add classes (and modules) to table.
-
#generate_constants ⇒ Object
protected
Add constants to table.
-
#generate_documents ⇒ Object
protected
Generate entries for information files, e.g.
- #generate_metadata ⇒ Object protected
-
#generate_methods ⇒ Object
protected
Transform RDoc methods to Shomen model and add to table.
-
#generate_scripts ⇒ Object
protected
Generate script entries.
-
#initialize(options) ⇒ Shomen
constructor
protected
A new instance of Shomen.
- #method_name(method) ⇒ Object protected
-
#methods_all ⇒ Object
List of all methods in all classes and modules.
- #mime_type(path) ⇒ Object protected
-
#parse_interface(interface) ⇒ Object
private
Parse method interface.
- #path_output_relative(path = nil) ⇒ Object protected
-
#shomen ⇒ Object
TODO: Rename ?.
Constructor Details
#initialize(options) ⇒ Shomen (protected)
Returns a new instance of Shomen.
144 145 146 147 148 149 150 151 152 |
# File 'lib/shomen/rdoc.rb', line 144 def initialize() @options = #@options.diagram = false # why? @path_base = Pathname.pwd. # TODO: This is probably not needed any more. @path_output = Pathname.new(@options.op_dir).(@path_base) end |
Instance Attribute Details
#options ⇒ Object (readonly)
User options from the command line.
43 44 45 |
# File 'lib/shomen/rdoc.rb', line 43 def @options end |
#path_base ⇒ Object (readonly, protected)
Current pathname.
155 156 157 |
# File 'lib/shomen/rdoc.rb', line 155 def path_base @path_base end |
#path_output ⇒ Object (readonly, protected)
The output path.
158 159 160 |
# File 'lib/shomen/rdoc.rb', line 158 def path_output @path_output end |
Class Method Details
.for(options) ⇒ Object
Standard generator factory method.
38 39 40 |
# File 'lib/shomen/rdoc.rb', line 38 def self.for() new() end |
Instance Method Details
#attributes_all ⇒ Object
List of all attributes in all classes and modules.
89 90 91 |
# File 'lib/shomen/rdoc.rb', line 89 def attributes_all @attributes_all ||= classes.map{ |m| m.attributes }.flatten.sort end |
#class_dir ⇒ Object
RDoc needs this to function.
104 |
# File 'lib/shomen/rdoc.rb', line 104 def class_dir ; nil ; end |
#classes ⇒ Object
In the world of the RDoc Generators #classes is the same as #all_classes_and_modules. Well, except that its sorted too. For classes sans modules, see #types.
54 55 56 |
# File 'lib/shomen/rdoc.rb', line 54 def classes @classes ||= RDoc::TopLevel.all_classes_and_modules.sort end |
#classes_toplevel ⇒ Object
Only toplevel classes and modules.
59 60 61 |
# File 'lib/shomen/rdoc.rb', line 59 def classes_toplevel @classes_toplevel ||= classes.select {|klass| !(RDoc::ClassModule === klass.parent) } end |
#collect_attributes(class_module, singleton = false) ⇒ Object (protected)
468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/shomen/rdoc.rb', line 468 def collect_attributes(class_module, singleton=false) list = [] class_module.attributes.each do |a| next if singleton ^ a.singleton #p a.rw #case a.rw #when :write, 'W' # list << "#{method_name(a)}=" #else list << method_name(a) #end end list.uniq end |
#collect_methods(class_module, singleton = false) ⇒ Object (protected)
458 459 460 461 462 463 464 465 |
# File 'lib/shomen/rdoc.rb', line 458 def collect_methods(class_module, singleton=false) list = [] class_module.method_list.each do |m| next if singleton ^ m.singleton list << method_name(m) end list.uniq end |
#complete_name(name, namespace) ⇒ Object (protected)
Returns String of fully qualified name.
449 450 451 452 453 454 455 |
# File 'lib/shomen/rdoc.rb', line 449 def complete_name(name, namespace) if name !~ /^#{namespace}/ "#{namespace}::#{name}" else name end end |
#constants_all ⇒ Object
94 95 96 |
# File 'lib/shomen/rdoc.rb', line 94 def constants_all @constants_all ||= classes.map{ |c| c.constants }.flatten end |
#debug_msg(msg) ⇒ Object (protected)
Output progress information if rdoc debugging is enabled
507 508 509 510 511 512 513 514 515 |
# File 'lib/shomen/rdoc.rb', line 507 def debug_msg(msg) return unless $DEBUG_RDOC case msg[-1,1] when '.' then tab = "= " when ':' then tab = "== " else tab = "* " end $stderr.puts(tab + msg) end |
#file_dir ⇒ Object
RDoc needs this to function.
107 |
# File 'lib/shomen/rdoc.rb', line 107 def file_dir ; nil ; end |
#files ⇒ Object
64 65 66 67 68 |
# File 'lib/shomen/rdoc.rb', line 64 def files @files ||= ( @files_rdoc.select{ |f| f.parser != RDoc::Parser::Simple } ) end |
#files_hash ⇒ Object
79 80 81 |
# File 'lib/shomen/rdoc.rb', line 79 def files_hash @files ||= RDoc::TopLevel.files_hash end |
#files_toplevel ⇒ Object
List of toplevel files. RDoc supplies this via the #generate method.
71 72 73 74 75 |
# File 'lib/shomen/rdoc.rb', line 71 def files_toplevel @files_toplevel ||= ( @files_rdoc.select{ |f| f.parser == RDoc::Parser::Simple } ) end |
#generate(files) ⇒ Object
Build the initial indices and output objects based on an array of top level objects containing the extracted information.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/shomen/rdoc.rb', line 117 def generate(files) @files_rdoc = files.sort @table = {} generate_constants generate_classes #generate_attributes generate_methods generate_documents generate_scripts # must be last b/c it depends on the others # TODO: method accessor fields need to be handled # THINK: Internal referencing model, YAML and JSYNC ? #ref_table = reference_table(@table) #rescue StandardError => err # debug_msg "%s: %s\n %s" % [ err.class.name, err.message, err.backtrace.join("\n ") ] # raise err end |
#generate_classes ⇒ Object (protected)
Add classes (and modules) to table.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/shomen/rdoc.rb', line 194 def generate_classes debug_msg "Generating class/module documentation:" classes.each do |rdoc_class| debug_msg "%s (%s)" % [ rdoc_class.full_name, rdoc_class.path ] if rdoc_class.type=='class' model = Shomen::Model::Class.new else model = Shomen::Model::Module.new end model.path = rdoc_class.full_name model.name = rdoc_class.name model.namespace = rdoc_class.full_name.split('::')[0...-1].join('::') model.includes = rdoc_class.includes.map{ |x| x.name } # FIXME: How to "lookup" full name? model.extensions = [] # TODO: How to get extensions? model.comment = rdoc_class.comment model.format = 'rdoc' model.constants = rdoc_class.constants.map{ |x| complete_name(x.name, rdoc_class.full_name) } model.modules = rdoc_class.modules.map{ |x| complete_name(x.name, rdoc_class.full_name) } model.classes = rdoc_class.classes.map{ |x| complete_name(x.name, rdoc_class.full_name) } model.methods = rdoc_class.method_list.map{ |m| method_name(m) }.uniq model.accessors = rdoc_class.attributes.map{ |a| method_name(a) }.uniq #+ ":#{a.rw}" }.uniq model.files = rdoc_class.in_files.map{ |x| "/#{x.full_name}" } if rdoc_class.type == 'class' # HACK: No idea why RDoc is returning some weird superclass: # <RDoc::NormalClass:0xd924d4 class Object < BasicObject includes: [] # attributes: [] methods: [#<RDoc::AnyMethod:0xd92b8c Object#fileutils # (public)>] aliases: []> # Maybe it has something to do with #fileutils? model.superclass = ( case rdoc_class.superclass when nil when String rdoc_class.superclass else rdoc_class.superclass.full_name end ) end @table[model.path] = model.to_h end end |
#generate_constants ⇒ Object (protected)
Add constants to table.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/shomen/rdoc.rb', line 176 def generate_constants debug_msg "Generating constant documentation:" constants_all.each do |rdoc| model = Shomen::Model::Constant.new model.path = rdoc.parent.full_name + '::' + rdoc.name model.name = rdoc.name model.namespace = rdoc.parent.full_name model.comment = rdoc.comment model.format = 'rdoc' model.value = rdoc.value model.files = ["/#{rdoc.file.full_name}"] @table[model.path] = model.to_h end end |
#generate_documents ⇒ Object (protected)
Generate entries for information files, e.g. ‘README.rdoc`.
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/shomen/rdoc.rb', line 380 def generate_documents files_toplevel.each do |rdoc_document| absolute_path = File.join(path_base, rdoc_document.full_name) model = Shomen::Model::Document.new model.path = rdoc_document.full_name model.name = File.basename(absolute_path) model.mtime = File.mtime(absolute_path) model.text = File.read(absolute_path) #file.comment model.format = mime_type(absolute_path) @table['/'+model.path] = model.to_h end end |
#generate_metadata ⇒ Object (protected)
170 171 172 173 |
# File 'lib/shomen/rdoc.rb', line 170 def = Shomen::Metadata.new @table['(metadata)'] = .to_h end |
#generate_methods ⇒ Object (protected)
Transform RDoc methods to Shomen model and add to table.
TODO: How to get literal interface separate from call-sequnces?
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/shomen/rdoc.rb', line 244 def generate_methods debug_msg "Generating method documentation:" list = methods_all + attributes_all list.each do |rdoc_method| #debug_msg "%s" % [rdoc_method.full_name] #full_name = method_name(m) #'prettyname' => m.pretty_name, #'type' => m.type, # class or instance model = Shomen::Model::Method.new model.path = method_name(rdoc_method) model.name = rdoc_method.name model.namespace = rdoc_method.parent_name model.comment = rdoc_method.comment model.format = 'rdoc' model.aliases = rdoc_method.aliases.map{ |a| method_name(a) } model.alias_for = method_name(rdoc_method.is_alias_for) model.singleton = rdoc_method.singleton model.declarations << rdoc_method.type.to_s #singleton ? 'class' : 'instance' model.declarations << rdoc_method.visibility.to_s model.interfaces = [] if rdoc_method.call_seq rdoc_method.call_seq.split("\n").each do |cs| cs = cs.to_s.strip model.interfaces << parse_interface(cs) unless cs == '' end end model.interfaces << parse_interface("#{rdoc_method.name}#{rdoc_method.params}") model.returns = [] # RDoc doesn't support specifying return values model.file = '/'+rdoc_method.source_code_location.first model.line = rdoc_method.source_code_location.last.to_i model.source = rdoc_method.source_code_raw if rdoc_method.respond_to?(:c_function) model.language = rdoc_method.c_function ? 'c' : 'ruby' else model.language = 'ruby' end @table[model.path] = model.to_h end end |
#generate_scripts ⇒ Object (protected)
Generate script entries.
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/shomen/rdoc.rb', line 399 def generate_scripts #debug_msg "Generating file documentation in #{path_output_relative}:" #templatefile = self.path_template + 'file.rhtml' files.each do |rdoc_file| debug_msg "%s" % [rdoc_file.full_name] absolute_path = File.join(path_base, rdoc_file.full_name) #rel_prefix = self.path_output.relative_path_from(outfile.dirname) model = Shomen::Model::Script.new model.path = rdoc_file.full_name model.name = File.basename(rdoc_file.full_name) model.mtime = File.mtime(absolute_path) if Shomen.source? model.source = File.read(absolute_path) #file.comment model.language = mime_type(absolute_path) end #model.header = #model.footer = model.requires = rdoc_file.requires.map{ |r| r.name } model.constants = rdoc_file.constants.map{ |c| c.full_name } # note that this utilizes the table we are building # so it needs to be the last thing done. @table.each do |k, h| case h['!'] when 'module' model.modules ||= [] model.modules << k if h['files'].include?(rdoc_file.full_name) when 'class' model.classes ||= [] model.classes << k if h['files'].include?(rdoc_file.full_name) when 'method' model.methods ||= [] model.methods << k if h['file'] == rdoc_file.full_name when 'class-method' model.class_methods ||= [] model.class_methods << k if h['file'] == rdoc_file.full_name end end @table['/'+model.path] = model.to_h end end |
#method_name(method) ⇒ Object (protected)
484 485 486 487 488 489 490 491 492 |
# File 'lib/shomen/rdoc.rb', line 484 def method_name(method) return nil if method.nil? if method.singleton i = method.full_name.rindex('::') method.full_name[0...i] + '.' + method.full_name[i+2..-1] else method.full_name end end |
#methods_all ⇒ Object
List of all methods in all classes and modules.
84 85 86 |
# File 'lib/shomen/rdoc.rb', line 84 def methods_all @methods_all ||= classes.map{ |m| m.method_list }.flatten.sort end |
#mime_type(path) ⇒ Object (protected)
495 496 497 498 499 500 501 502 503 |
# File 'lib/shomen/rdoc.rb', line 495 def mime_type(path) case File.extname(path) when '.rb', '.rbx' then 'text/ruby' when '.c' then 'text/c-source' when '.rdoc' then 'text/rdoc' when '.md', '.markdown' then 'text/markdown' else 'text/plain' end end |
#parse_interface(interface) ⇒ Object (private)
Parse method interface.
TODO: remove any trailing comment too
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/shomen/rdoc.rb', line 349 def parse_interface(interface) args, block = [], {} interface, returns = interface.split(/[=-]\>/) interface = interface.strip if i = interface.index(/\)\s*\{/) block['signature'] = interface[i+1..-1].strip interface = interface[0..i].strip end arguments = interface.strip.sub(/^.*?\(/,'').chomp(')') arguments = arguments.split(/\s*\,\s*/) arguments.each do |a| if a.start_with?('&') block['name'] = a else n,v = a.split('=') args << (v ? {'name'=>n,'default'=>v} : {'name'=>n}) end end result = {} result['signature'] = interface result['arguments'] = args result['block'] = block unless block.empty? result['returns'] = returns.strip if returns return result end |
#path_output_relative(path = nil) ⇒ Object (protected)
161 162 163 164 165 166 167 |
# File 'lib/shomen/rdoc.rb', line 161 def path_output_relative(path=nil) if path path.to_s.sub(path_base.to_s+'/', '') else @path_output_relative ||= path_output.to_s.sub(path_base.to_s+'/', '') end end |
#shomen ⇒ Object
TODO: Rename ?
110 111 112 |
# File 'lib/shomen/rdoc.rb', line 110 def shomen @table || {} end |