include.rb 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. ##
  2. # A Module include in a class with \#include
  3. class RDoc::Include < RDoc::CodeObject
  4. ##
  5. # Name of included module
  6. attr_accessor :name
  7. ##
  8. # Creates a new Include for +name+ with +comment+
  9. def initialize(name, comment)
  10. super()
  11. @name = name
  12. self.comment = comment
  13. @module = nil # cache for module if found
  14. end
  15. ##
  16. # Includes are sorted by name
  17. def <=> other
  18. return unless self.class === other
  19. name <=> other.name
  20. end
  21. def == other # :nodoc:
  22. self.class === other and @name == other.name
  23. end
  24. alias eql? ==
  25. ##
  26. # Full name based on #module
  27. def full_name
  28. m = self.module
  29. RDoc::ClassModule === m ? m.full_name : @name
  30. end
  31. def hash # :nodoc:
  32. [@name, self.module].hash
  33. end
  34. def inspect # :nodoc:
  35. "#<%s:0x%x %s.include %s>" % [
  36. self.class,
  37. object_id,
  38. parent_name, @name,
  39. ]
  40. end
  41. ##
  42. # Attempts to locate the included module object. Returns the name if not
  43. # known.
  44. #
  45. # The scoping rules of Ruby to resolve the name of an included module are:
  46. # - first look into the children of the current context;
  47. # - if not found, look into the children of included modules,
  48. # in reverse inclusion order;
  49. # - if still not found, go up the hierarchy of names.
  50. #
  51. # This method has <code>O(n!)</code> behavior when the module calling
  52. # include is referencing nonexistent modules. Avoid calling #module until
  53. # after all the files are parsed. This behavior is due to ruby's constant
  54. # lookup behavior.
  55. #
  56. # As of the beginning of October, 2011, no gem includes nonexistent modules.
  57. def module
  58. return @module if @module
  59. # search the current context
  60. return @name unless parent
  61. full_name = parent.child_name(@name)
  62. @module = RDoc::TopLevel.modules_hash[full_name]
  63. return @module if @module
  64. return @name if @name =~ /^::/
  65. # search the includes before this one, in reverse order
  66. searched = parent.includes.take_while { |i| i != self }.reverse
  67. searched.each do |i|
  68. inc = i.module
  69. next if String === inc
  70. full_name = inc.child_name(@name)
  71. @module = RDoc::TopLevel.modules_hash[full_name]
  72. return @module if @module
  73. end
  74. # go up the hierarchy of names
  75. up = parent.parent
  76. while up
  77. full_name = up.child_name(@name)
  78. @module = RDoc::TopLevel.modules_hash[full_name]
  79. return @module if @module
  80. up = up.parent
  81. end
  82. @name
  83. end
  84. def to_s # :nodoc:
  85. "include #@name in: #{parent}"
  86. end
  87. end