Register now and start sharing your code snippets.
-->
How to create a custom RDoc generator
Ruby posted about 1 year ago by christian
This is a work in progress… Heavily influenced by RAnnotate. Copy this to rdoc/generators:
1 module Generators 2 3 class CUSTOMGenerator 4 5 TYPE = {:file => 1, :class => 2, :module => 3 } 6 VISIBILITY = {:public => 1, :private => 2, :protected => 3 } 7 8 def CUSTOMGenerator.for(options) 9 new(options) 10 end 11 12 def initialize(options) #:not-new: 13 @options = options 14 15 # set up a hash to keep track of all the classes/modules we have processed 16 @already_processed = {} 17 18 # set up a hash to keep track of all of the objects to be output 19 @output = { 20 :files => [], 21 :classes => [], 22 :modules => [], 23 :attributes => [], 24 :methods => [], 25 :aliases => [], 26 :constants => [], 27 :requires => [], 28 :includes => [] 29 } 30 end 31 32 # Rdoc passes in TopLevel objects from the code_objects.rb tree (all files) 33 def generate(files) 34 # Each object passed in is a file, process it 35 files.each { |file| process_file(file) } 36 end 37 38 private 39 40 # process a file from the code_object.rb tree 41 def process_file(file) 42 @output[:files].push(file) 43 44 puts "#{file.comment}" 45 46 # Process all of the objects that this file contains 47 file.method_list.each { |child| process_method(child) } 48 file.aliases.each { |child| process_alias(child) } 49 file.constants.each { |child| process_constant(child) } 50 file.requires.each { |child| process_require(child) } 51 file.includes.each { |child| process_include(child) } 52 file.attributes.each { |child| process_attribute(child) } 53 54 # Recursively process contained subclasses and modules 55 file.each_classmodule do |child| 56 process_class_or_module(child) 57 end 58 end 59 60 # Process classes and modiles 61 def process_class_or_module(obj) 62 obj.is_module? ? type = :modules : type = :classes 63 64 # One important note about the code_objects.rb structure. A class or module 65 # definition can be spread a cross many files in Ruby so code_objects.rb handles 66 # this by keeping only *one* reference to each class or module that has a definition 67 # at the root level of a file (ie. not contained in another class or module). 68 # This means that when we are processing files we may run into the same class/module 69 # twice. So we need to keep track of what classes/modules we have 70 # already seen and make sure we don't create two INSERT statements for the same 71 # object. 72 if(!@already_processed.has_key?(obj.full_name)) then 73 @output[type].push(obj) 74 @already_processed[obj.full_name] = true 75 76 # Process all of the objects that this class or module contains 77 obj.method_list.each { |child| process_method(child) } 78 obj.aliases.each { |child| process_alias(child) } 79 obj.constants.each { |child| process_constant(child) } 80 obj.requires.each { |child| process_require(child) } 81 obj.includes.each { |child| process_include(child) } 82 obj.attributes.each { |child| process_attribute(child) } 83 end 84 85 id = @already_processed[obj.full_name] 86 # Recursively process contained subclasses and modules 87 obj.each_classmodule do |child| 88 process_class_or_module(child) 89 end 90 end 91 92 def process_method(obj) 93 obj.source_code = get_source_code(obj) 94 puts "#{obj.name}#{obj.param_seq}" 95 puts "#{obj.source_code}" # Source code, unformatted 96 97 puts "=====================================" 98 99 @output[:methods].push(obj) 100 end 101 102 def process_alias(obj) 103 @output[:aliases].push(obj) 104 end 105 106 def process_constant(obj) 107 @output[:constants].push(obj) 108 end 109 110 def process_attribute(obj) 111 @output[:attributes].push(obj) 112 end 113 114 def process_require(obj) 115 @output[:requires].push(obj) 116 end 117 118 def process_include(obj) 119 @output[:includes].push(obj) 120 end 121 122 123 # get the source code 124 def get_source_code(method) 125 src = "" 126 if(ts = method.token_stream) 127 ts.each do |t| 128 next unless t 129 src << t.text 130 end 131 end 132 return src 133 end 134 135 end 136 137 138 # dynamically add a source code attribute to the base oject of code_objects.rb 139 class RDoc::AnyMethod 140 attr_accessor :source_code 141 end 142 143 end 144 145