1 # $Id: module.rb,v 1.20 2012/04/17 02:49:40 machan Exp $
2
3 require 'tmdoc/tmstd'
4 require 'tmdoc/constant'
5 require 'tmdoc/model/object'
6 require 'tmdoc/model/document'
7 require 'tmdoc/transformer/object-into-document/module-infobox'
8 require 'tmdoc/transformer/object-into-document/node'
9 require 'tmdoc/transformer/object-into-document/link'
10 require 'tmdoc/transformer/object-into-document/path'
11
12
13 module TmDoc
14
15 module Transformer::ObjectIntoDocument
16
17 module Module
18
19 module_function
20
21 def transform_modules(
22 mo_root_module,
23 env,
24 mo_toplevel_module,
25 mo_object_class,
26 msg,
27 show_module_siblings,
28 show_class_siblings,
29 sort_by_name,
30 &selector
31 )
32 ASSERT.kind_of mo_root_module, MOLA::RootModule
33 ASSERT.kind_of env, ENV::Environment
34 ASSERT.kind_of mo_toplevel_module, MOLN::ToplevelModule
35 ASSERT.kind_of mo_object_class, MOLN::Object
36 ASSERT.kind_of msg, String
37 ASSERT.boolean show_module_siblings
38 ASSERT.boolean show_class_siblings
39 ASSERT.boolean sort_by_name
40
41 LOG::Progress.log "\t%s", msg
42
43 md_modules = (
44 MOLA::SeqOfGenericModule.new([mo_root_module]) +
45 mo_root_module.descendant_modules(&selector)
46 ).reject { |mo_module|
47 ASSERT.kind_of mo_module, MOLA::GenericModule
48
49 mo_module.suppressable?
50 }.sort { |x, y|
51 if sort_by_name then x.compare_by_name y else x <=> y end
52 }.map { |mo_module|
53 LOG::Progress.log "\t\t%s", mo_module.path.to_s
54
55 transform(
56 mo_module,
57 env,
58 mo_toplevel_module,
59 mo_object_class,
60 show_module_siblings,
61 show_class_siblings
62 )
63 }
64 return nil if md_modules.empty?
65
66 MDM::SeqOfModule.new md_modules
67 end
68
69
70 def transform(
71 mo_module,
72 env,
73 mo_toplevel_module,
74 mo_object_class,
75 show_module_siblings,
76 show_class_siblings
77 )
78 ASSERT.kind_of mo_module, MOLA::GenericModule
79 ASSERT.kind_of env, ENV::Environment
80 ASSERT.kind_of mo_toplevel_module, MOLN::ToplevelModule
81 ASSERT.kind_of mo_object_class, MOLN::Object
82 ASSERT.boolean show_module_siblings
83 ASSERT.boolean show_class_siblings
84
85 md_link_to_above_module =
86 if mo_module.kind_of?(MOLA::ChildModule)
87 mo_above_module = mo_module.an_above_module
88 if mo_above_module
89 Link.transform_link_to_module mo_above_module
90 else
91 nil
92 end
93 else
94 nil
95 end
96
97 mo_related_modules = MOLA::SetOfGenericModule.union(
98 [
99 MOLA::SetOfGenericModule.new([mo_module]),
100
101 mo_module.neighboring_modules(show_module_siblings),
102
103 if mo_module.kind_of?(MOLA::GenericClass)
104 mo_module.neighboring_classes(show_class_siblings)
105 else
106 MOLA::EMPTY_SET_OF_GENERIC_CLASS
107 end
108 ]
109 )
110 md_module_structure = transform_module_structure(
111 mo_module, mo_related_modules, mo_toplevel_module
112 )
113 md_class_hierarchy = transform_class_hierarchy(
114 mo_module, mo_related_modules, mo_object_class
115 )
116
117
118 args = [
119 Path.transform(mo_module.above_path),
120
121 mo_module.name,
122
123 md_link_to_above_module,
124
125 Module::InfoBox.transform(
126 mo_module,
127 env,
128 show_module_siblings,
129 show_class_siblings
130 ),
131
132 if md_module_structure.below_module_nodes.empty?
133 nil
134 else
135 md_module_structure
136 end,
137
138 if md_class_hierarchy.subclass_nodes.empty?
139 nil
140 else
141 md_class_hierarchy
142 end,
143
144 transform_properties(
145 mo_module.properties,
146 mo_module.kind_of?(MOLA::GenericClass)
147 )
148 ]
149
150 md_module =
151 case mo_module
152 when MOLA::GenericClass
153 case mo_module
154 when MOLN::UnknownClass
155 MDM::UnknownClass.new *args
156 else
157 MDM::Class.new *args
158 end
159 when MOLA::RootModule
160 case mo_module
161 when MOLN::ToplevelModule
162 MDM::ToplevelModule.new *args
163 when MOLN::BuiltinModule
164 MDM::BuiltinModule.new *args
165 when MOLN::UnknownModule
166 MDM::UnknownModule.new *args
167 else
168 ASSERT.abort(
169 "Unknown root module: %s", mo_module.class.to_s
170 )
171 end
172 else
173 MDM::Module.new *args
174 end
175
176 ASSERT.kind_of md_module, MDM::Module
177 end
178
179
180 def transform_above_module_name(mo_module)
181 ASSERT.kind_of mo_module, MOLA::GenericModule
182
183 name =
184 if mo_module.kind_of?(MOLA::ChildModule)
185 mo_above_module = mo_module.an_above_module
186 ASSERT.kind_of mo_above_module, MOLA::GenericModule
187
188 mo_above_module.path.elements.join '::'
189 else
190 nil
191 end
192
193 ASSERT.opt_kind_of name, String
194 end
195
196
197 def transform_module_structure(
198 mo_module, mo_related_modules, mo_toplevel_module
199 )
200 ASSERT.kind_of mo_module, MOLA::GenericModule
201 ASSERT.kind_of mo_related_modules, MOLA::SetOfGenericModule
202 ASSERT.kind_of mo_toplevel_module, MOLA::RootModule
203
204 mo_related_module_nodes = MOLA::SetOfGenericModule.union(
205 mo_related_modules.map { |mo_related_module|
206 mo_related_module.ancestor_modules
207 }
208 )
209
210 md_module_structure =
211 Node.transform_module_structure_node(
212 mo_toplevel_module, mo_module
213 ) { |mo_node_module|
214 ASSERT.kind_of mo_node_module, MOLA::GenericModule
215
216 mo_related_module_nodes.include? mo_node_module
217 }
218
219 ASSERT.kind_of md_module_structure, MDN::ModuleStructure
220 end
221
222
223 def transform_class_hierarchy(
224 mo_module, mo_related_modules, mo_object_class
225 )
226 ASSERT.kind_of mo_module, MOLA::GenericModule
227 ASSERT.kind_of mo_related_modules, MOLA::SetOfGenericModule
228 ASSERT.kind_of mo_object_class, MOLN::Object
229
230 mo_related_class_nodes = MOLA::SetOfGenericClass.union(
231 mo_related_modules.select { |mo_related_module|
232 mo_related_module.kind_of?(MOLN::Class)
233 }.map { |mo_related_class|
234 mo_related_class.ancestor_classes
235 }
236 )
237
238 md_class_hierarchy =
239 Node.transform_class_hierarchy_node(
240 mo_object_class, mo_module
241 ) { |mo_node_class|
242 ASSERT.kind_of mo_node_class, MOLN::Class
243
244 mo_related_class_nodes.include? mo_node_class
245 }
246
247 ASSERT.kind_of md_class_hierarchy, MDN::ClassHierarchy
248 end
249
250
251 def transform_properties(mo_properties, is_belongs_to_class)
252 ASSERT.kind_of mo_properties, MOLA::SetOfProperty
253 ASSERT.boolean is_belongs_to_class
254
255 return nil if mo_properties.empty?
256
257 hash_of_md_properties = mo_properties.sort.inject(
258 MDM::TAG_LIST.inject({}) { |result, tag|
259 result.merge(tag => [])
260 }
261 ) { |result, mo_property|
262 ASSERT.kind_of mo_property, MOLA::Property
263
264 mo_location = mo_property.location
265 args = [
266 mo_property.name,
267 Link.transform_link_to_line(mo_location),
268 Link.transform_link_to_file(mo_location.a_file),
269 mo_property.uniq_num,
270 mo_property.max_uniq_num
271 ]
272
273 md_property =
274 case mo_property
275 when MOLL::Constant
276 MDM::Constant.new(*(args << mo_property.value))
277 when MOLL::Alias
278 MDM::Alias.new(*(args << mo_property.orig_name))
279 when MOLL::Attribute
280 accessor = transform_attr_accessor(mo_property.accessor)
281
282 MDM::Attribute.new(*(args << accessor))
283 when MOLL::Method
284 MDM::Method.new(*(args << mo_property.args))
285 else
286 ASSERT.abort(
287 "Unknown mo_property: %s", mo_property.to_s
288 )
289 end
290
291 tag = transform_property_tag(mo_property, is_belongs_to_class)
292 result.merge(tag => result[tag] + [md_property])
293 }
294
295 array_of_md_property_section = MDM::TAG_LIST.reject { |tag|
296 hash_of_md_properties[tag].empty?
297 }.map { |tag|
298 MDM::PropertySection.new(
299 tag,
300 MDA::Module::SeqOfProperty.new(hash_of_md_properties[tag])
301 )
302 }
303
304 MDM::SeqOfPropertySection.new array_of_md_property_section
305 end
306
307
308 def transform_property_tag(mo_property, is_belongs_to_class)
309 ASSERT.kind_of mo_property, MOLA::Property
310 ASSERT.boolean is_belongs_to_class
311
312 tag = case mo_property
313 when MOLL::Constant
314 :constant
315 when MOLL::Alias
316 if mo_property.attach_to_instance?
317 :instance_alias
318 else
319 if is_belongs_to_class
320 :class_alias
321 else
322 :module_alias
323 end
324 end
325 when MOLL::Attribute
326 if mo_property.attach_to_instance?
327 :instance_attribute
328 else
329 if is_belongs_to_class
330 :class_attribute
331 else
332 :module_attribute
333 end
334 end
335 when MOLL::Method
336 if mo_property.module_func?
337 :module_function
338 else
339 if mo_property.attach_to_instance?
340 :instance_method
341 else
342 if is_belongs_to_class
343 :class_method
344 else
345 :module_method
346 end
347 end
348 end
349 else
350 ASSERT.abort(
351 "Unknown mo_property: %s", mo_property.to_s
352 )
353 end
354
355 ASSERT.kind_of tag, Symbol
356 end
357
358
359 def transform_attr_accessor(accessor)
360 ASSERT.kind_of accessor, Symbol
361
362 str = {
363 :reader => 'R',
364 :writer => 'W',
365 :accessor => 'RW',
366 :unknown => '?'
367 }[accessor]
368
369 ASSERT.kind_of(str, String,
370 "Unknown accessor: %s", accessor
371 )
372 end
373 end
374
375 end # TmDoc::Transformer::ObjectIntoDocument
376
377 end # TmDoc