Class Generators::RIGenerator
In: generators/ri_generator.rb
Parent: Object

Methods

Public Class methods

Generators may need to return specific subclasses depending on the options they are passed. Because of this we create them using a factory

[Source]

    # File generators/ri_generator.rb, line 59
59:     def RIGenerator.for(options)
60:       new(options)
61:     end

Set up a new HTML generator. Basically all we do here is load up the correct output temlate

[Source]

    # File generators/ri_generator.rb, line 70
70:     def initialize(options) #:not-new:
71:       @options   = options
72:       @ri_writer = RI::RiWriter.new(options.op_dir)
73:       @markup    = SM::SimpleMarkup.new
74:       @to_flow   = SM::ToFlow.new
75:     end

Public Instance methods

Build the initial indices and output objects based on an array of TopLevel objects containing the extracted information.

[Source]

    # File generators/ri_generator.rb, line 83
83:     def generate(toplevels)
84:       RDoc::TopLevel.all_classes_and_modules.each do |cls|
85:         process_class(cls)
86:       end
87:     end

[Source]

     # File generators/ri_generator.rb, line 98
 98:     def generate_class_info(cls)
 99:       if cls === RDoc::NormalModule
100:         cls_desc = RI::ModuleDescription.new
101:       else
102:         cls_desc = RI::ClassDescription.new
103:         cls_desc.superclass  = cls.superclass
104:       end
105:       cls_desc.name        = cls.name
106:       cls_desc.full_name   = cls.full_name
107:       cls_desc.comment     = markup(cls.comment)
108: 
109:       cls_desc.attributes =cls.attributes.sort.map do |a|
110:         RI::Attribute.new(a.name, a.rw, markup(a.comment))
111:       end
112: 
113:       cls_desc.constants = cls.constants.map do |c|
114:         RI::Constant.new(c.name, c.value, markup(c.comment))
115:       end
116: 
117:       cls_desc.includes = cls.includes.map do |i|
118:         RI::IncludedModule.new(i.name)
119:       end
120: 
121:       class_methods, instance_methods = method_list(cls)
122: 
123:       cls_desc.class_methods = class_methods.map do |m|
124:         RI::MethodSummary.new(m.name)
125:       end
126:       cls_desc.instance_methods = instance_methods.map do |m|
127:         RI::MethodSummary.new(m.name)
128:       end
129: 
130:       update_or_replace(cls_desc)
131: 
132:       class_methods.each do |m|
133:         generate_method_info(cls_desc, m)
134:       end
135: 
136:       instance_methods.each do |m|
137:         generate_method_info(cls_desc, m)
138:       end
139:     end

[Source]

     # File generators/ri_generator.rb, line 142
142:     def generate_method_info(cls_desc, method)
143:       meth_desc = RI::MethodDescription.new
144:       meth_desc.name = method.name
145:       meth_desc.full_name = cls_desc.full_name
146:       if method.singleton
147:         meth_desc.full_name += "::"
148:       else
149:         meth_desc.full_name += "#"
150:       end
151:       meth_desc.full_name << method.name
152: 
153:       meth_desc.comment = markup(method.comment)
154:       meth_desc.params = params_of(method)
155:       meth_desc.visibility = method.visibility.to_s
156:       meth_desc.is_singleton = method.singleton
157:       meth_desc.block_params = method.block_params
158: 
159:       meth_desc.aliases = method.aliases.map do |a|
160:         RI::AliasName.new(a.name)
161:       end
162: 
163:       @ri_writer.add_method(cls_desc, meth_desc)
164:     end

[Source]

     # File generators/ri_generator.rb, line 213
213:     def markup(comment)
214:       return nil if !comment || comment.empty?
215: 
216:       # Convert leading comment markers to spaces, but only
217:       # if all non-blank lines have them
218:       
219:       if comment =~ /^(?>\s*)[^\#]/
220:         content = comment
221:       else
222:         content = comment.gsub(/^\s*(#+)/)  { $1.tr('#',' ') }
223:       end
224:       @markup.convert(content, @to_flow)
225:     end

return a list of class and instance methods that we‘ll be documenting

[Source]

     # File generators/ri_generator.rb, line 171
171:     def method_list(cls)
172:       list = cls.method_list
173:       unless @options.show_all
174:         list = list.find_all do |m|
175:           m.visibility == :public || m.visibility == :protected || m.force_documentation
176:         end
177:       end
178: 
179:       c = []
180:       i = []
181:       list.sort.each do |m|
182:         if m.singleton
183:           c << m
184:         else
185:           i << m
186:         end
187:       end
188:       return c,i
189:     end

[Source]

     # File generators/ri_generator.rb, line 191
191:     def params_of(method)
192:       if method.call_seq
193:         method.call_seq
194:       else
195:         params = method.params || ""
196:         
197:         p = params.gsub(/\s*\#.*/, '')
198:         p = p.tr("\n", " ").squeeze(" ")
199:         p = "(" + p + ")" unless p[0] == ?(
200:         
201:         if (block = method.block_params)
202:           block.gsub!(/\s*\#.*/, '')
203:           block = block.tr("\n", " ").squeeze(" ")
204:           if block[0] == ?(
205:             block.sub!(/^\(/, '').sub!(/\)/, '')
206:           end
207:           p << " {|#{block.strip}| ...}"
208:         end
209:         p
210:       end
211:     end

[Source]

    # File generators/ri_generator.rb, line 89
89:     def process_class(from_class)
90:       generate_class_info(from_class)
91: 
92:       # now recure into this classes constituent classess
93:       from_class.each_classmodule do |mod|
94:         process_class(mod)
95:       end
96:     end

By default we replace existing classes with the same name. If the —merge option was given, we instead merge this definition into an existing class. We add our methods, aliases, etc to that class, but do not change the class‘s description.

[Source]

     # File generators/ri_generator.rb, line 234
234:     def update_or_replace(cls_desc)
235:       old_cls = nil
236: 
237:       if @options.merge
238:         rdr = RI::RiReader.new(RI::RiCache.new(@options.op_dir))
239: 
240:         namespace = rdr.top_level_namespace
241:         namespace = rdr.lookup_namespace_in(cls_desc.name, namespace)
242:         if namespace.empty?
243:           $stderr.puts "You asked me to merge this source into existing "
244:           $stderr.puts "documentation. This file references a class or "
245:           $stderr.puts "module called #{cls_desc.name} which I don't"
246:           $stderr.puts "have existing documentation for."
247:           $stderr.puts 
248:           $stderr.puts "Perhaps you need to generate its documentation first"
249:           exit 1
250:         else
251:           old_cls = namespace[0]
252:         end
253:       end
254: 
255:       if old_cls.nil?
256:         # no merge: simply overwrite
257:         @ri_writer.remove_class(cls_desc)
258:         @ri_writer.add_class(cls_desc)
259:       else
260:         # existing class: merge in
261:         old_desc = rdr.get_class(old_cls)
262: 
263:         old_desc.merge_in(cls_desc)
264:         @ri_writer.add_class(old_desc)
265:       end
266:     end

[Validate]