176 |
178 |
177 class Class(ClbrBaseClasses.Class, VisibilityMixin): |
179 class Class(ClbrBaseClasses.Class, VisibilityMixin): |
178 """ |
180 """ |
179 Class to represent a Ruby class. |
181 Class to represent a Ruby class. |
180 """ |
182 """ |
|
183 |
181 def __init__(self, module, name, superClasses, file, lineno): |
184 def __init__(self, module, name, superClasses, file, lineno): |
182 """ |
185 """ |
183 Constructor |
186 Constructor |
184 |
187 |
185 @param module name of the module containing this class |
188 @param module name of the module containing this class |
186 @param name name of this class |
189 @param name name of this class |
187 @param superClasses list of class names this class is inherited from |
190 @param superClasses list of class names this class is inherited from |
188 @param file filename containing this class |
191 @param file filename containing this class |
189 @param lineno linenumber of the class definition |
192 @param lineno linenumber of the class definition |
190 """ |
193 """ |
191 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, |
194 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, lineno) |
192 lineno) |
|
193 VisibilityMixin.__init__(self) |
195 VisibilityMixin.__init__(self) |
194 |
196 |
195 |
197 |
196 class Module(ClbrBaseClasses.Module, VisibilityMixin): |
198 class Module(ClbrBaseClasses.Module, VisibilityMixin): |
197 """ |
199 """ |
198 Class to represent a Ruby module. |
200 Class to represent a Ruby module. |
199 """ |
201 """ |
|
202 |
200 def __init__(self, module, name, file, lineno): |
203 def __init__(self, module, name, file, lineno): |
201 """ |
204 """ |
202 Constructor |
205 Constructor |
203 |
206 |
204 @param module name of the module containing this class |
207 @param module name of the module containing this class |
205 @param name name of this class |
208 @param name name of this class |
206 @param file filename containing this class |
209 @param file filename containing this class |
207 @param lineno linenumber of the class definition |
210 @param lineno linenumber of the class definition |
208 """ |
211 """ |
212 |
215 |
213 class Function(ClbrBaseClasses.Function, VisibilityMixin): |
216 class Function(ClbrBaseClasses.Function, VisibilityMixin): |
214 """ |
217 """ |
215 Class to represent a Ruby function. |
218 Class to represent a Ruby function. |
216 """ |
219 """ |
217 def __init__(self, module, name, file, lineno, signature='', |
220 |
218 separator=','): |
221 def __init__(self, module, name, file, lineno, signature="", separator=","): |
219 """ |
222 """ |
220 Constructor |
223 Constructor |
221 |
224 |
222 @param module name of the module containing this function |
225 @param module name of the module containing this function |
223 @param name name of this function |
226 @param name name of this function |
224 @param file filename containing this class |
227 @param file filename containing this class |
225 @param lineno linenumber of the class definition |
228 @param lineno linenumber of the class definition |
226 @param signature parameterlist of the method |
229 @param signature parameterlist of the method |
227 @param separator string separating the parameters |
230 @param separator string separating the parameters |
228 """ |
231 """ |
229 ClbrBaseClasses.Function.__init__(self, module, name, file, lineno, |
232 ClbrBaseClasses.Function.__init__( |
230 signature, separator) |
233 self, module, name, file, lineno, signature, separator |
|
234 ) |
231 VisibilityMixin.__init__(self) |
235 VisibilityMixin.__init__(self) |
232 |
236 |
233 |
237 |
234 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin): |
238 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin): |
235 """ |
239 """ |
236 Class to represent a class or module attribute. |
240 Class to represent a class or module attribute. |
237 """ |
241 """ |
|
242 |
238 def __init__(self, module, name, file, lineno): |
243 def __init__(self, module, name, file, lineno): |
239 """ |
244 """ |
240 Constructor |
245 Constructor |
241 |
246 |
242 @param module name of the module containing this class |
247 @param module name of the module containing this class |
243 @param name name of this class |
248 @param name name of this class |
244 @param file filename containing this attribute |
249 @param file filename containing this attribute |
245 @param lineno linenumber of the class definition |
250 @param lineno linenumber of the class definition |
246 """ |
251 """ |
278 src = Utilities.readEncodedFile(file)[0] |
283 src = Utilities.readEncodedFile(file)[0] |
279 except (UnicodeError, OSError): |
284 except (UnicodeError, OSError): |
280 # can't do anything with this module |
285 # can't do anything with this module |
281 _modules[module] = {} |
286 _modules[module] = {} |
282 return {} |
287 return {} |
283 |
288 |
284 _modules[module] = scan(src, file, module) |
289 _modules[module] = scan(src, file, module) |
285 return _modules[module] |
290 return _modules[module] |
286 |
291 |
287 |
292 |
288 def scan(src, file, module): |
293 def scan(src, file, module): |
289 """ |
294 """ |
290 Public method to scan the given source text. |
295 Public method to scan the given source text. |
291 |
296 |
292 @param src source text to be scanned |
297 @param src source text to be scanned |
293 @type str |
298 @type str |
294 @param file file name associated with the source text |
299 @param file file name associated with the source text |
295 @type str |
300 @type str |
296 @param module module name associated with the source text |
301 @param module module name associated with the source text |
321 if m.start("Method") >= 0: |
326 if m.start("Method") >= 0: |
322 # found a method definition or function |
327 # found a method definition or function |
323 thisindent = indent |
328 thisindent = indent |
324 indent += 1 |
329 indent += 1 |
325 meth_name = ( |
330 meth_name = ( |
326 m.group("MethodName") or |
331 m.group("MethodName") |
327 m.group("MethodName2") or |
332 or m.group("MethodName2") |
328 m.group("MethodName3") |
333 or m.group("MethodName3") |
329 ) |
334 ) |
330 meth_sig = m.group("MethodSignature") |
335 meth_sig = m.group("MethodSignature") |
331 meth_sig = meth_sig and meth_sig.replace('\\\n', '') or '' |
336 meth_sig = meth_sig and meth_sig.replace("\\\n", "") or "" |
332 meth_sig = _commentsub('', meth_sig) |
337 meth_sig = _commentsub("", meth_sig) |
333 lineno += src.count('\n', last_lineno_pos, start) |
338 lineno += src.count("\n", last_lineno_pos, start) |
334 last_lineno_pos = start |
339 last_lineno_pos = start |
335 if meth_name.startswith('self.'): |
340 if meth_name.startswith("self."): |
336 meth_name = meth_name[5:] |
341 meth_name = meth_name[5:] |
337 elif meth_name.startswith('self::'): |
342 elif meth_name.startswith("self::"): |
338 meth_name = meth_name[6:] |
343 meth_name = meth_name[6:] |
339 # close all classes/modules indented at least as much |
344 # close all classes/modules indented at least as much |
340 while classstack and classstack[-1][1] >= thisindent: |
345 while classstack and classstack[-1][1] >= thisindent: |
341 if classstack[-1][0] is not None: |
346 if classstack[-1][0] is not None: |
342 # record the end line |
347 # record the end line |
364 elif accesscontrol == "public": |
368 elif accesscontrol == "public": |
365 f.setPublic() |
369 f.setPublic() |
366 # else it's a nested def |
370 # else it's a nested def |
367 else: |
371 else: |
368 # it's a function |
372 # it's a function |
369 f = Function(module, meth_name, |
373 f = Function(module, meth_name, file, lineno, meth_sig) |
370 file, lineno, meth_sig) |
|
371 if meth_name in dict_counts: |
374 if meth_name in dict_counts: |
372 dict_counts[meth_name] += 1 |
375 dict_counts[meth_name] += 1 |
373 meth_name = "{0}_{1:d}".format( |
376 meth_name = "{0}_{1:d}".format(meth_name, dict_counts[meth_name]) |
374 meth_name, dict_counts[meth_name]) |
|
375 else: |
377 else: |
376 dict_counts[meth_name] = 0 |
378 dict_counts[meth_name] = 0 |
377 dictionary[meth_name] = f |
379 dictionary[meth_name] = f |
378 if not classstack: |
380 if not classstack: |
379 if lastGlobalEntry: |
381 if lastGlobalEntry: |
383 cur_obj.setEndLine(lineno - 1) |
385 cur_obj.setEndLine(lineno - 1) |
384 cur_obj = f |
386 cur_obj = f |
385 classstack.append((f, thisindent)) # Marker for nested fns |
387 classstack.append((f, thisindent)) # Marker for nested fns |
386 |
388 |
387 elif ( |
389 elif ( |
388 m.start("String") >= 0 or |
390 m.start("String") >= 0 |
389 m.start("Comment") >= 0 or |
391 or m.start("Comment") >= 0 |
390 m.start("ClassIgnored") >= 0 or |
392 or m.start("ClassIgnored") >= 0 |
391 m.start("BeginEnd") >= 0 |
393 or m.start("BeginEnd") >= 0 |
392 ): |
394 ): |
393 pass |
395 pass |
394 |
396 |
395 elif m.start("Class") >= 0: |
397 elif m.start("Class") >= 0: |
396 # we found a class definition |
398 # we found a class definition |
397 thisindent = indent |
399 thisindent = indent |
398 indent += 1 |
400 indent += 1 |
399 lineno += src.count('\n', last_lineno_pos, start) |
401 lineno += src.count("\n", last_lineno_pos, start) |
400 last_lineno_pos = start |
402 last_lineno_pos = start |
401 # close all classes/modules indented at least as much |
403 # close all classes/modules indented at least as much |
402 while classstack and classstack[-1][1] >= thisindent: |
404 while classstack and classstack[-1][1] >= thisindent: |
403 if classstack[-1][0] is not None: |
405 if classstack[-1][0] is not None: |
404 # record the end line |
406 # record the end line |
407 class_name = m.group("ClassName") or m.group("ClassName2") |
409 class_name = m.group("ClassName") or m.group("ClassName2") |
408 inherit = m.group("ClassSupers") |
410 inherit = m.group("ClassSupers") |
409 if inherit: |
411 if inherit: |
410 # the class inherits from other classes |
412 # the class inherits from other classes |
411 inherit = inherit[1:].strip() |
413 inherit = inherit[1:].strip() |
412 inherit = [_commentsub('', inherit)] |
414 inherit = [_commentsub("", inherit)] |
413 # remember this class |
415 # remember this class |
414 cur_class = Class(module, class_name, inherit, |
416 cur_class = Class(module, class_name, inherit, file, lineno) |
415 file, lineno) |
|
416 if not classstack: |
417 if not classstack: |
417 if class_name in dictionary: |
418 if class_name in dictionary: |
418 cur_class = dictionary[class_name] |
419 cur_class = dictionary[class_name] |
419 else: |
420 else: |
420 dictionary[class_name] = cur_class |
421 dictionary[class_name] = cur_class |
439 |
440 |
440 elif m.start("Module") >= 0: |
441 elif m.start("Module") >= 0: |
441 # we found a module definition |
442 # we found a module definition |
442 thisindent = indent |
443 thisindent = indent |
443 indent += 1 |
444 indent += 1 |
444 lineno += src.count('\n', last_lineno_pos, start) |
445 lineno += src.count("\n", last_lineno_pos, start) |
445 last_lineno_pos = start |
446 last_lineno_pos = start |
446 # close all classes/modules indented at least as much |
447 # close all classes/modules indented at least as much |
447 while classstack and classstack[-1][1] >= thisindent: |
448 while classstack and classstack[-1][1] >= thisindent: |
448 if classstack[-1][0] is not None: |
449 if classstack[-1][0] is not None: |
449 # record the end line |
450 # record the end line |
481 if aclist is None: |
482 if aclist is None: |
482 index = -1 |
483 index = -1 |
483 while index >= -len(acstack): |
484 while index >= -len(acstack): |
484 if acstack[index][1] < indent: |
485 if acstack[index][1] < indent: |
485 actype = ( |
486 actype = ( |
486 m.group("AccessControlType") or |
487 m.group("AccessControlType") |
487 m.group("AccessControlType2").split('_')[0] |
488 or m.group("AccessControlType2").split("_")[0] |
488 ) |
489 ) |
489 acstack[index][0] = actype.lower() |
490 acstack[index][0] = actype.lower() |
490 break |
491 break |
491 else: |
492 else: |
492 index -= 1 |
493 index -= 1 |
493 else: |
494 else: |
494 index = -1 |
495 index = -1 |
495 while index >= -len(classstack): |
496 while index >= -len(classstack): |
496 if ( |
497 if ( |
497 classstack[index][0] is not None and |
498 classstack[index][0] is not None |
498 not isinstance(classstack[index][0], Function) and |
499 and not isinstance(classstack[index][0], Function) |
499 classstack[index][1] < indent |
500 and classstack[index][1] < indent |
500 ): |
501 ): |
501 parent = classstack[index][0] |
502 parent = classstack[index][0] |
502 actype = ( |
503 actype = ( |
503 m.group("AccessControlType") or |
504 m.group("AccessControlType") |
504 m.group("AccessControlType2").split('_')[0] |
505 or m.group("AccessControlType2").split("_")[0] |
505 ) |
506 ) |
506 actype = actype.lower() |
507 actype = actype.lower() |
507 for name in aclist.split(","): |
508 for name in aclist.split(","): |
508 name = name.strip()[1:] # get rid of leading ':' |
509 name = name.strip()[1:] # get rid of leading ':' |
509 acmeth = parent._getmethod(name) |
510 acmeth = parent._getmethod(name) |
510 if acmeth is None: |
511 if acmeth is None: |
511 continue |
512 continue |
512 if actype == "private": |
513 if actype == "private": |
513 acmeth.setPrivate() |
514 acmeth.setPrivate() |
518 break |
519 break |
519 else: |
520 else: |
520 index -= 1 |
521 index -= 1 |
521 |
522 |
522 elif m.start("Attribute") >= 0: |
523 elif m.start("Attribute") >= 0: |
523 lineno += src.count('\n', last_lineno_pos, start) |
524 lineno += src.count("\n", last_lineno_pos, start) |
524 last_lineno_pos = start |
525 last_lineno_pos = start |
525 index = -1 |
526 index = -1 |
526 while index >= -len(classstack): |
527 while index >= -len(classstack): |
527 if ( |
528 if ( |
528 classstack[index][0] is not None and |
529 classstack[index][0] is not None |
529 not isinstance(classstack[index][0], Function) and |
530 and not isinstance(classstack[index][0], Function) |
530 classstack[index][1] < indent |
531 and classstack[index][1] < indent |
531 ): |
532 ): |
532 attr = Attribute( |
533 attr = Attribute(module, m.group("AttributeName"), file, lineno) |
533 module, m.group("AttributeName"), file, lineno) |
|
534 classstack[index][0]._addattribute(attr) |
534 classstack[index][0]._addattribute(attr) |
535 break |
535 break |
536 else: |
536 else: |
537 index -= 1 |
537 index -= 1 |
538 if lastGlobalEntry: |
538 if lastGlobalEntry: |
539 lastGlobalEntry.setEndLine(lineno - 1) |
539 lastGlobalEntry.setEndLine(lineno - 1) |
540 lastGlobalEntry = None |
540 lastGlobalEntry = None |
541 |
541 |
542 elif m.start("Attr") >= 0: |
542 elif m.start("Attr") >= 0: |
543 lineno += src.count('\n', last_lineno_pos, start) |
543 lineno += src.count("\n", last_lineno_pos, start) |
544 last_lineno_pos = start |
544 last_lineno_pos = start |
545 index = -1 |
545 index = -1 |
546 while index >= -len(classstack): |
546 while index >= -len(classstack): |
547 if ( |
547 if ( |
548 classstack[index][0] is not None and |
548 classstack[index][0] is not None |
549 not isinstance(classstack[index][0], Function) and |
549 and not isinstance(classstack[index][0], Function) |
550 classstack[index][1] < indent |
550 and classstack[index][1] < indent |
551 ): |
551 ): |
552 parent = classstack[index][0] |
552 parent = classstack[index][0] |
553 if m.group("AttrType") is None: |
553 if m.group("AttrType") is None: |
554 nv = m.group("AttrList").split(",") |
554 nv = m.group("AttrList").split(",") |
555 if not nv: |
555 if not nv: |
556 break |
556 break |
557 name = nv[0].strip()[1:] # get rid of leading ':' |
557 name = nv[0].strip()[1:] # get rid of leading ':' |
558 attr = ( |
558 attr = ( |
559 parent._getattribute("@" + name) or |
559 parent._getattribute("@" + name) |
560 parent._getattribute("@@" + name) or |
560 or parent._getattribute("@@" + name) |
561 Attribute(module, "@" + name, file, lineno) |
561 or Attribute(module, "@" + name, file, lineno) |
562 ) |
562 ) |
563 if len(nv) == 1 or nv[1].strip() == "false": |
563 if len(nv) == 1 or nv[1].strip() == "false": |
564 attr.setProtected() |
564 attr.setProtected() |
565 elif nv[1].strip() == "true": |
565 elif nv[1].strip() == "true": |
566 attr.setPublic() |
566 attr.setPublic() |
567 parent._addattribute(attr) |
567 parent._addattribute(attr) |
568 else: |
568 else: |
569 access = m.group("AttrType") |
569 access = m.group("AttrType") |
570 for name in m.group("AttrList").split(","): |
570 for name in m.group("AttrList").split(","): |
571 name = name.strip()[1:] # get rid of leading ':' |
571 name = name.strip()[1:] # get rid of leading ':' |
572 attr = ( |
572 attr = ( |
573 parent._getattribute("@" + name) or |
573 parent._getattribute("@" + name) |
574 parent._getattribute("@@" + name) or |
574 or parent._getattribute("@@" + name) |
575 Attribute(module, "@" + name, file, lineno) |
575 or Attribute(module, "@" + name, file, lineno) |
576 ) |
576 ) |
577 if access == "_accessor": |
577 if access == "_accessor": |
578 attr.setPublic() |
578 attr.setPublic() |
579 elif access in ("_reader", "_writer"): |
579 elif access in ("_reader", "_writer"): |
580 if attr.isPrivate(): |
580 if attr.isPrivate(): |
598 if classstack: |
598 if classstack: |
599 # it's a class/module method |
599 # it's a class/module method |
600 indent = classstack[-1][1] |
600 indent = classstack[-1][1] |
601 else: |
601 else: |
602 indent = 0 |
602 indent = 0 |
603 |
603 |
604 elif m.start("CodingLine") >= 0: |
604 elif m.start("CodingLine") >= 0: |
605 # a coding statement |
605 # a coding statement |
606 coding = m.group("Coding") |
606 coding = m.group("Coding") |
607 lineno += src.count('\n', last_lineno_pos, start) |
607 lineno += src.count("\n", last_lineno_pos, start) |
608 last_lineno_pos = start |
608 last_lineno_pos = start |
609 if "@@Coding@@" not in dictionary: |
609 if "@@Coding@@" not in dictionary: |
610 dictionary["@@Coding@@"] = ClbrBaseClasses.Coding( |
610 dictionary["@@Coding@@"] = ClbrBaseClasses.Coding( |
611 module, file, lineno, coding) |
611 module, file, lineno, coding |
|
612 ) |
612 |
613 |
613 return dictionary |
614 return dictionary |