diff options
author | Hiroshi SHIBATA <[email protected]> | 2025-01-15 11:52:40 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2025-01-15 16:52:56 +0900 |
commit | 86d871d29cda15810d9d60dc1b94a07e9530e0cb (patch) | |
tree | ae0fd977690197a4c82eed861527c109caade4f1 /lib/rdoc/code_object | |
parent | e0be1b902549f80fcdc95e801d4d533b0fdec43b (diff) |
Migrate rdoc as bundled gems
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12577
Diffstat (limited to 'lib/rdoc/code_object')
-rw-r--r-- | lib/rdoc/code_object/alias.rb | 111 | ||||
-rw-r--r-- | lib/rdoc/code_object/anon_class.rb | 10 | ||||
-rw-r--r-- | lib/rdoc/code_object/any_method.rb | 379 | ||||
-rw-r--r-- | lib/rdoc/code_object/attr.rb | 175 | ||||
-rw-r--r-- | lib/rdoc/code_object/class_module.rb | 868 | ||||
-rw-r--r-- | lib/rdoc/code_object/constant.rb | 186 | ||||
-rw-r--r-- | lib/rdoc/code_object/context.rb | 1264 | ||||
-rw-r--r-- | lib/rdoc/code_object/context/section.rb | 233 | ||||
-rw-r--r-- | lib/rdoc/code_object/extend.rb | 9 | ||||
-rw-r--r-- | lib/rdoc/code_object/ghost_method.rb | 6 | ||||
-rw-r--r-- | lib/rdoc/code_object/include.rb | 9 | ||||
-rw-r--r-- | lib/rdoc/code_object/meta_method.rb | 6 | ||||
-rw-r--r-- | lib/rdoc/code_object/method_attr.rb | 430 | ||||
-rw-r--r-- | lib/rdoc/code_object/mixin.rb | 120 | ||||
-rw-r--r-- | lib/rdoc/code_object/normal_class.rb | 92 | ||||
-rw-r--r-- | lib/rdoc/code_object/normal_module.rb | 73 | ||||
-rw-r--r-- | lib/rdoc/code_object/require.rb | 51 | ||||
-rw-r--r-- | lib/rdoc/code_object/single_class.rb | 30 | ||||
-rw-r--r-- | lib/rdoc/code_object/top_level.rb | 291 |
19 files changed, 0 insertions, 4343 deletions
diff --git a/lib/rdoc/code_object/alias.rb b/lib/rdoc/code_object/alias.rb deleted file mode 100644 index 92df7e448f..0000000000 --- a/lib/rdoc/code_object/alias.rb +++ /dev/null @@ -1,111 +0,0 @@ -# frozen_string_literal: true -## -# Represent an alias, which is an old_name/new_name pair associated with a -# particular context -#-- -# TODO implement Alias as a proxy to a method/attribute, inheriting from -# MethodAttr - -class RDoc::Alias < RDoc::CodeObject - - ## - # Aliased method's name - - attr_reader :new_name - - alias name new_name - - ## - # Aliasee method's name - - attr_reader :old_name - - ## - # Is this an alias declared in a singleton context? - - attr_accessor :singleton - - ## - # Source file token stream - - attr_reader :text - - ## - # Creates a new Alias with a token stream of +text+ that aliases +old_name+ - # to +new_name+, has +comment+ and is a +singleton+ context. - - def initialize(text, old_name, new_name, comment, singleton = false) - super() - - @text = text - @singleton = singleton - @old_name = old_name - @new_name = new_name - self.comment = comment - end - - ## - # Order by #singleton then #new_name - - def <=>(other) - [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name] - end - - ## - # HTML fragment reference for this alias - - def aref - type = singleton ? 'c' : 'i' - "#alias-#{type}-#{html_name}" - end - - ## - # Full old name including namespace - - def full_old_name - @full_name || "#{parent.name}#{pretty_old_name}" - end - - ## - # HTML id-friendly version of +#new_name+. - - def html_name - CGI.escape(@new_name.gsub('-', '-2D')).gsub('%', '-').sub(/^-/, '') - end - - def inspect # :nodoc: - parent_name = parent ? parent.name : '(unknown)' - "#<%s:0x%x %s.alias_method %s, %s>" % [ - self.class, object_id, - parent_name, @old_name, @new_name, - ] - end - - ## - # '::' for the alias of a singleton method/attribute, '#' for instance-level. - - def name_prefix - singleton ? '::' : '#' - end - - ## - # Old name with prefix '::' or '#'. - - def pretty_old_name - "#{singleton ? '::' : '#'}#{@old_name}" - end - - ## - # New name with prefix '::' or '#'. - - def pretty_new_name - "#{singleton ? '::' : '#'}#{@new_name}" - end - - alias pretty_name pretty_new_name - - def to_s # :nodoc: - "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}" - end - -end diff --git a/lib/rdoc/code_object/anon_class.rb b/lib/rdoc/code_object/anon_class.rb deleted file mode 100644 index 3c2f0e1877..0000000000 --- a/lib/rdoc/code_object/anon_class.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true -## -# An anonymous class like: -# -# c = Class.new do end -# -# AnonClass is currently not used. - -class RDoc::AnonClass < RDoc::ClassModule -end diff --git a/lib/rdoc/code_object/any_method.rb b/lib/rdoc/code_object/any_method.rb deleted file mode 100644 index 465c4a4fb2..0000000000 --- a/lib/rdoc/code_object/any_method.rb +++ /dev/null @@ -1,379 +0,0 @@ -# frozen_string_literal: true -## -# AnyMethod is the base class for objects representing methods - -class RDoc::AnyMethod < RDoc::MethodAttr - - ## - # 2:: - # RDoc 4 - # Added calls_super - # Added parent name and class - # Added section title - # 3:: - # RDoc 4.1 - # Added is_alias_for - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Don't rename \#initialize to \::new - - attr_accessor :dont_rename_initialize - - ## - # The C function that implements this method (if it was defined in a C file) - - attr_accessor :c_function - - # The section title of the method (if defined in a C file via +:category:+) - attr_accessor :section_title - - # Parameters for this method - - attr_accessor :params - - ## - # If true this method uses +super+ to call a superclass version - - attr_accessor :calls_super - - include RDoc::TokenStream - - ## - # Creates a new AnyMethod with a token stream +text+ and +name+ - - def initialize text, name - super - - @c_function = nil - @dont_rename_initialize = false - @token_stream = nil - @calls_super = false - @superclass_method = nil - end - - ## - # Adds +an_alias+ as an alias for this method in +context+. - - def add_alias an_alias, context = nil - method = self.class.new an_alias.text, an_alias.new_name - - method.record_location an_alias.file - method.singleton = self.singleton - method.params = self.params - method.visibility = self.visibility - method.comment = an_alias.comment - method.is_alias_for = self - @aliases << method - context.add_method method if context - method - end - - ## - # Prefix for +aref+ is 'method'. - - def aref_prefix - 'method' - end - - ## - # The call_seq or the param_seq with method name, if there is no call_seq. - # - # Use this for displaying a method's argument lists. - - def arglists - if @call_seq then - @call_seq - elsif @params then - "#{name}#{param_seq}" - end - end - - ## - # Different ways to call this method - - def call_seq - unless call_seq = _call_seq - call_seq = is_alias_for._call_seq if is_alias_for - end - - return unless call_seq - - deduplicate_call_seq(call_seq) - end - - ## - # Sets the different ways you can call this method. If an empty +call_seq+ - # is given nil is assumed. - # - # See also #param_seq - - def call_seq= call_seq - return if call_seq.empty? - - @call_seq = call_seq - end - - ## - # Whether the method has a call-seq. - - def has_call_seq? - !!(@call_seq || is_alias_for&._call_seq) - end - - ## - # Loads is_alias_for from the internal name. Returns nil if the alias - # cannot be found. - - def is_alias_for # :nodoc: - case @is_alias_for - when RDoc::MethodAttr then - @is_alias_for - when Array then - return nil unless @store - - klass_name, singleton, method_name = @is_alias_for - - return nil unless klass = @store.find_class_or_module(klass_name) - - @is_alias_for = klass.find_method method_name, singleton - end - end - - ## - # Dumps this AnyMethod for use by ri. See also #marshal_load - - def marshal_dump - aliases = @aliases.map do |a| - [a.name, parse(a.comment)] - end - - is_alias_for = [ - @is_alias_for.parent.full_name, - @is_alias_for.singleton, - @is_alias_for.name - ] if @is_alias_for - - [ MARSHAL_VERSION, - @name, - full_name, - @singleton, - @visibility, - parse(@comment), - @call_seq, - @block_params, - aliases, - @params, - @file.relative_name, - @calls_super, - @parent.name, - @parent.class, - @section.title, - is_alias_for, - ] - end - - ## - # Loads this AnyMethod from +array+. For a loaded AnyMethod the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize_visibility - - @dont_rename_initialize = nil - @token_stream = nil - @aliases = [] - @parent = nil - @parent_name = nil - @parent_class = nil - @section = nil - @file = nil - - version = array[0] - @name = array[1] - @full_name = array[2] - @singleton = array[3] - @visibility = array[4] - @comment = array[5] - @call_seq = array[6] - @block_params = array[7] - # 8 handled below - @params = array[9] - # 10 handled below - @calls_super = array[11] - @parent_name = array[12] - @parent_title = array[13] - @section_title = array[14] - @is_alias_for = array[15] - - array[8].each do |new_name, comment| - add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton) - end - - @parent_name ||= if @full_name =~ /#/ then - $` - else - name = @full_name.split('::') - name.pop - name.join '::' - end - - @file = RDoc::TopLevel.new array[10] if version > 0 - end - - ## - # Method name - # - # If the method has no assigned name, it extracts it from #call_seq. - - def name - return @name if @name - - @name = - @call_seq[/^.*?\.(\w+)/, 1] || - @call_seq[/^.*?(\w+)/, 1] || - @call_seq if @call_seq - end - - ## - # A list of this method's method and yield parameters. +call-seq+ params - # are preferred over parsed method and block params. - - def param_list - if @call_seq then - params = @call_seq.split("\n").last - params = params.sub(/.*?\((.*)\)/, '\1') - params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2') - elsif @params then - params = @params.sub(/\((.*)\)/, '\1') - - params << ",#{@block_params}" if @block_params - elsif @block_params then - params = @block_params - else - return [] - end - - if @block_params then - # If this method has explicit block parameters, remove any explicit - # &block - params = params.sub(/,?\s*&\w+/, '') - else - params = params.sub(/\&(\w+)/, '\1') - end - - params = params.gsub(/\s+/, '').split(',').reject(&:empty?) - - params.map { |param| param.sub(/=.*/, '') } - end - - ## - # Pretty parameter list for this method. If the method's parameters were - # given by +call-seq+ it is preferred over the parsed values. - - def param_seq - if @call_seq then - params = @call_seq.split("\n").last - params = params.sub(/[^( ]+/, '') - params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2') - elsif @params then - params = @params.gsub(/\s*\#.*/, '') - params = params.tr_s("\n ", " ") - params = "(#{params})" unless params[0] == ?( - else - params = '' - end - - if @block_params then - # If this method has explicit block parameters, remove any explicit - # &block - params = params.sub(/,?\s*&\w+/, '') - - block = @block_params.tr_s("\n ", " ") - if block[0] == ?( - block = block.sub(/^\(/, '').sub(/\)/, '') - end - params << " { |#{block}| ... }" - end - - params - end - - ## - # Whether to skip the method description, true for methods that have - # aliases with a call-seq that doesn't include the method name. - - def skip_description? - has_call_seq? && call_seq.nil? && !!(is_alias_for || !aliases.empty?) - end - - ## - # Sets the store for this method and its referenced code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - ## - # For methods that +super+, find the superclass method that would be called. - - def superclass_method - return unless @calls_super - return @superclass_method if @superclass_method - - parent.each_ancestor do |ancestor| - if method = ancestor.method_list.find { |m| m.name == @name } then - @superclass_method = method - break - end - end - - @superclass_method - end - - protected - - ## - # call_seq without deduplication and alias lookup. - - def _call_seq - @call_seq if defined?(@call_seq) && @call_seq - end - - private - - ## - # call_seq with alias examples information removed, if this - # method is an alias method. - - def deduplicate_call_seq(call_seq) - return call_seq unless is_alias_for || !aliases.empty? - - method_name = self.name - method_name = method_name[0, 1] if method_name =~ /\A\[/ - - entries = call_seq.split "\n" - - ignore = aliases.map(&:name) - if is_alias_for - ignore << is_alias_for.name - ignore.concat is_alias_for.aliases.map(&:name) - end - ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n} - ignore.delete(method_name) - ignore = Regexp.union(ignore) - - matching = entries.reject do |entry| - entry =~ /^\w*\.?#{ignore}[$\(\s]/ or - entry =~ /\s#{ignore}\s/ - end - - matching.empty? ? nil : matching.join("\n") - end -end diff --git a/lib/rdoc/code_object/attr.rb b/lib/rdoc/code_object/attr.rb deleted file mode 100644 index a403235933..0000000000 --- a/lib/rdoc/code_object/attr.rb +++ /dev/null @@ -1,175 +0,0 @@ -# frozen_string_literal: true -## -# An attribute created by \#attr, \#attr_reader, \#attr_writer or -# \#attr_accessor - -class RDoc::Attr < RDoc::MethodAttr - - ## - # 3:: - # RDoc 4 - # Added parent name and class - # Added section title - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Is the attribute readable ('R'), writable ('W') or both ('RW')? - - attr_accessor :rw - - ## - # Creates a new Attr with body +text+, +name+, read/write status +rw+ and - # +comment+. +singleton+ marks this as a class attribute. - - def initialize(text, name, rw, comment, singleton = false) - super text, name - - @rw = rw - @singleton = singleton - self.comment = comment - end - - ## - # Attributes are equal when their names, singleton and rw are identical - - def == other - self.class == other.class and - self.name == other.name and - self.rw == other.rw and - self.singleton == other.singleton - end - - ## - # Add +an_alias+ as an attribute in +context+. - - def add_alias(an_alias, context) - new_attr = self.class.new(self.text, an_alias.new_name, self.rw, - self.comment, self.singleton) - - new_attr.record_location an_alias.file - new_attr.visibility = self.visibility - new_attr.is_alias_for = self - @aliases << new_attr - context.add_attribute new_attr - new_attr - end - - ## - # The #aref prefix for attributes - - def aref_prefix - 'attribute' - end - - ## - # Attributes never call super. See RDoc::AnyMethod#calls_super - # - # An RDoc::Attr can show up in the method list in some situations (see - # Gem::ConfigFile) - - def calls_super # :nodoc: - false - end - - ## - # Returns attr_reader, attr_writer or attr_accessor as appropriate. - - def definition - case @rw - when 'RW' then 'attr_accessor' - when 'R' then 'attr_reader' - when 'W' then 'attr_writer' - end - end - - def inspect # :nodoc: - alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil - visibility = self.visibility - visibility = "forced #{visibility}" if force_documentation - "#<%s:0x%x %s %s (%s)%s>" % [ - self.class, object_id, - full_name, - rw, - visibility, - alias_for, - ] - end - - ## - # Dumps this Attr for use by ri. See also #marshal_load - - def marshal_dump - [ MARSHAL_VERSION, - @name, - full_name, - @rw, - @visibility, - parse(@comment), - singleton, - @file.relative_name, - @parent.full_name, - @parent.class, - @section.title - ] - end - - ## - # Loads this Attr from +array+. For a loaded Attr the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize_visibility - - @aliases = [] - @parent = nil - @parent_name = nil - @parent_class = nil - @section = nil - @file = nil - - version = array[0] - @name = array[1] - @full_name = array[2] - @rw = array[3] - @visibility = array[4] - @comment = array[5] - @singleton = array[6] || false # MARSHAL_VERSION == 0 - # 7 handled below - @parent_name = array[8] - @parent_class = array[9] - @section_title = array[10] - - @file = RDoc::TopLevel.new array[7] if version > 1 - - @parent_name ||= @full_name.split('#', 2).first - end - - def pretty_print q # :nodoc: - q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do - unless comment.empty? then - q.breakable - q.text "comment:" - q.breakable - q.pp @comment - end - end - end - - def to_s # :nodoc: - "#{definition} #{name} in: #{parent}" - end - - ## - # Attributes do not have token streams. - # - # An RDoc::Attr can show up in the method list in some situations (see - # Gem::ConfigFile) - - def token_stream # :nodoc: - end - -end diff --git a/lib/rdoc/code_object/class_module.rb b/lib/rdoc/code_object/class_module.rb deleted file mode 100644 index 33e71ab3f3..0000000000 --- a/lib/rdoc/code_object/class_module.rb +++ /dev/null @@ -1,868 +0,0 @@ -# frozen_string_literal: true -## -# ClassModule is the base class for objects representing either a class or a -# module. - -class RDoc::ClassModule < RDoc::Context - - ## - # 1:: - # RDoc 3.7 - # * Added visibility, singleton and file to attributes - # * Added file to constants - # * Added file to includes - # * Added file to methods - # 2:: - # RDoc 3.13 - # * Added extends - # 3:: - # RDoc 4.0 - # * Added sections - # * Added in_files - # * Added parent name - # * Complete Constant dump - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Constants that are aliases for this class or module - - attr_accessor :constant_aliases - - ## - # Comment and the location it came from. Use #add_comment to add comments - - attr_accessor :comment_location - - attr_accessor :diagram # :nodoc: - - ## - # Class or module this constant is an alias for - - attr_accessor :is_alias_for - - ## - # Return a RDoc::ClassModule of class +class_type+ that is a copy - # of module +module+. Used to promote modules to classes. - #-- - # TODO move to RDoc::NormalClass (I think) - - def self.from_module class_type, mod - klass = class_type.new mod.name - - mod.comment_location.each do |comment, location| - klass.add_comment comment, location - end - - klass.parent = mod.parent - klass.section = mod.section - klass.viewer = mod.viewer - - klass.attributes.concat mod.attributes - klass.method_list.concat mod.method_list - klass.aliases.concat mod.aliases - klass.external_aliases.concat mod.external_aliases - klass.constants.concat mod.constants - klass.includes.concat mod.includes - klass.extends.concat mod.extends - - klass.methods_hash.update mod.methods_hash - klass.constants_hash.update mod.constants_hash - - klass.current_section = mod.current_section - klass.in_files.concat mod.in_files - klass.sections.concat mod.sections - klass.unmatched_alias_lists = mod.unmatched_alias_lists - klass.current_section = mod.current_section - klass.visibility = mod.visibility - - klass.classes_hash.update mod.classes_hash - klass.modules_hash.update mod.modules_hash - klass.metadata.update mod.metadata - - klass.document_self = mod.received_nodoc ? nil : mod.document_self - klass.document_children = mod.document_children - klass.force_documentation = mod.force_documentation - klass.done_documenting = mod.done_documenting - - # update the parent of all children - - (klass.attributes + - klass.method_list + - klass.aliases + - klass.external_aliases + - klass.constants + - klass.includes + - klass.extends + - klass.classes + - klass.modules).each do |obj| - obj.parent = klass - obj.full_name = nil - end - - klass - end - - ## - # Creates a new ClassModule with +name+ with optional +superclass+ - # - # This is a constructor for subclasses, and must never be called directly. - - def initialize(name, superclass = nil) - @constant_aliases = [] - @diagram = nil - @is_alias_for = nil - @name = name - @superclass = superclass - @comment_location = [] # [[comment, location]] - - super() - end - - ## - # Adds +comment+ to this ClassModule's list of comments at +location+. This - # method is preferred over #comment= since it allows ri data to be updated - # across multiple runs. - - def add_comment comment, location - return unless document_self - - original = comment - - comment = case comment - when RDoc::Comment then - comment.normalize - else - normalize_comment comment - end - - if location.parser == RDoc::Parser::C - @comment_location.delete_if { |(_, l)| l == location } - end - - @comment_location << [comment, location] - - self.comment = original - end - - def add_things my_things, other_things # :nodoc: - other_things.each do |group, things| - my_things[group].each { |thing| yield false, thing } if - my_things.include? group - - things.each do |thing| - yield true, thing - end - end - end - - ## - # Ancestors list for this ClassModule: the list of included modules - # (classes will add their superclass if any). - # - # Returns the included classes or modules, not the includes - # themselves. The returned values are either String or - # RDoc::NormalModule instances (see RDoc::Include#module). - # - # The values are returned in reverse order of their inclusion, - # which is the order suitable for searching methods/attributes - # in the ancestors. The superclass, if any, comes last. - - def ancestors - includes.map { |i| i.module }.reverse - end - - def aref_prefix # :nodoc: - raise NotImplementedError, "missing aref_prefix for #{self.class}" - end - - ## - # HTML fragment reference for this module or class. See - # RDoc::NormalClass#aref and RDoc::NormalModule#aref - - def aref - "#{aref_prefix}-#{full_name}" - end - - ## - # Ancestors of this class or module only - - alias direct_ancestors ancestors - - ## - # Clears the comment. Used by the Ruby parser. - - def clear_comment - @comment = '' - end - - ## - # This method is deprecated, use #add_comment instead. - # - # Appends +comment+ to the current comment, but separated by a rule. Works - # more like <tt>+=</tt>. - - def comment= comment # :nodoc: - comment = case comment - when RDoc::Comment then - comment.normalize - else - normalize_comment comment - end - - comment = "#{@comment.to_s}\n---\n#{comment.to_s}" unless @comment.empty? - - super comment - end - - ## - # Prepares this ClassModule for use by a generator. - # - # See RDoc::Store#complete - - def complete min_visibility - update_aliases - remove_nodoc_children - embed_mixins - update_includes - remove_invisible min_visibility - end - - ## - # Does this ClassModule or any of its methods have document_self set? - - def document_self_or_methods - document_self || method_list.any?{ |m| m.document_self } - end - - ## - # Does this class or module have a comment with content or is - # #received_nodoc true? - - def documented? - return true if @received_nodoc - return false if @comment_location.empty? - @comment_location.any? { |comment, _| not comment.empty? } - end - - ## - # Iterates the ancestors of this class or module for which an - # RDoc::ClassModule exists. - - def each_ancestor # :yields: module - return enum_for __method__ unless block_given? - - ancestors.each do |mod| - next if String === mod - next if self == mod - yield mod - end - end - - ## - # Looks for a symbol in the #ancestors. See Context#find_local_symbol. - - def find_ancestor_local_symbol symbol - each_ancestor do |m| - res = m.find_local_symbol(symbol) - return res if res - end - - nil - end - - ## - # Finds a class or module with +name+ in this namespace or its descendants - - def find_class_named name - return self if full_name == name - return self if @name == name - - @classes.values.find do |klass| - next if klass == self - klass.find_class_named name - end - end - - ## - # Return the fully qualified name of this class or module - - def full_name - @full_name ||= if RDoc::ClassModule === parent then - "#{parent.full_name}::#{@name}" - else - @name - end - end - - ## - # TODO: filter included items by #display? - - def marshal_dump # :nodoc: - attrs = attributes.sort.map do |attr| - next unless attr.display? - [ attr.name, attr.rw, - attr.visibility, attr.singleton, attr.file_name, - ] - end.compact - - method_types = methods_by_type.map do |type, visibilities| - visibilities = visibilities.map do |visibility, methods| - method_names = methods.map do |method| - next unless method.display? - [method.name, method.file_name] - end.compact - - [visibility, method_names.uniq] - end - - [type, visibilities] - end - - [ MARSHAL_VERSION, - @name, - full_name, - @superclass, - parse(@comment_location), - attrs, - constants.select { |constant| constant.display? }, - includes.map do |incl| - next unless incl.display? - [incl.name, parse(incl.comment), incl.file_name] - end.compact, - method_types, - extends.map do |ext| - next unless ext.display? - [ext.name, parse(ext.comment), ext.file_name] - end.compact, - @sections.values, - @in_files.map do |tl| - tl.relative_name - end, - parent.full_name, - parent.class, - ] - end - - def marshal_load array # :nodoc: - initialize_visibility - initialize_methods_etc - @current_section = nil - @document_self = true - @done_documenting = false - @parent = nil - @temporary_section = nil - @visibility = nil - @classes = {} - @modules = {} - - @name = array[1] - @full_name = array[2] - @superclass = array[3] - @comment = array[4] - - @comment_location = if RDoc::Markup::Document === @comment.parts.first then - @comment - else - RDoc::Markup::Document.new @comment - end - - array[5].each do |name, rw, visibility, singleton, file| - singleton ||= false - visibility ||= :public - - attr = RDoc::Attr.new nil, name, rw, nil, singleton - - add_attribute attr - attr.visibility = visibility - attr.record_location RDoc::TopLevel.new file - end - - array[6].each do |constant, comment, file| - case constant - when RDoc::Constant then - add_constant constant - else - constant = add_constant RDoc::Constant.new(constant, nil, comment) - constant.record_location RDoc::TopLevel.new file - end - end - - array[7].each do |name, comment, file| - incl = add_include RDoc::Include.new(name, comment) - incl.record_location RDoc::TopLevel.new file - end - - array[8].each do |type, visibilities| - visibilities.each do |visibility, methods| - @visibility = visibility - - methods.each do |name, file| - method = RDoc::AnyMethod.new nil, name - method.singleton = true if type == 'class' - method.record_location RDoc::TopLevel.new file - add_method method - end - end - end - - array[9].each do |name, comment, file| - ext = add_extend RDoc::Extend.new(name, comment) - ext.record_location RDoc::TopLevel.new file - end if array[9] # Support Marshal version 1 - - sections = (array[10] || []).map do |section| - [section.title, section] - end - - @sections = Hash[*sections.flatten] - @current_section = add_section nil - - @in_files = [] - - (array[11] || []).each do |filename| - record_location RDoc::TopLevel.new filename - end - - @parent_name = array[12] - @parent_class = array[13] - end - - ## - # Merges +class_module+ into this ClassModule. - # - # The data in +class_module+ is preferred over the receiver. - - def merge class_module - @parent = class_module.parent - @parent_name = class_module.parent_name - - other_document = parse class_module.comment_location - - if other_document then - document = parse @comment_location - - document = document.merge other_document - - @comment = @comment_location = document - end - - cm = class_module - other_files = cm.in_files - - merge_collections attributes, cm.attributes, other_files do |add, attr| - if add then - add_attribute attr - else - @attributes.delete attr - @methods_hash.delete attr.pretty_name - end - end - - merge_collections constants, cm.constants, other_files do |add, const| - if add then - add_constant const - else - @constants.delete const - @constants_hash.delete const.name - end - end - - merge_collections includes, cm.includes, other_files do |add, incl| - if add then - add_include incl - else - @includes.delete incl - end - end - - @includes.uniq! # clean up - - merge_collections extends, cm.extends, other_files do |add, ext| - if add then - add_extend ext - else - @extends.delete ext - end - end - - @extends.uniq! # clean up - - merge_collections method_list, cm.method_list, other_files do |add, meth| - if add then - add_method meth - else - @method_list.delete meth - @methods_hash.delete meth.pretty_name - end - end - - merge_sections cm - - self - end - - ## - # Merges collection +mine+ with +other+ preferring other. +other_files+ is - # used to help determine which items should be deleted. - # - # Yields whether the item should be added or removed (true or false) and the - # item to be added or removed. - # - # merge_collections things, other.things, other.in_files do |add, thing| - # if add then - # # add the thing - # else - # # remove the thing - # end - # end - - def merge_collections mine, other, other_files, &block # :nodoc: - my_things = mine. group_by { |thing| thing.file } - other_things = other.group_by { |thing| thing.file } - - remove_things my_things, other_files, &block - add_things my_things, other_things, &block - end - - ## - # Merges the comments in this ClassModule with the comments in the other - # ClassModule +cm+. - - def merge_sections cm # :nodoc: - my_sections = sections.group_by { |section| section.title } - other_sections = cm.sections.group_by { |section| section.title } - - other_files = cm.in_files - - remove_things my_sections, other_files do |_, section| - @sections.delete section.title - end - - other_sections.each do |group, sections| - if my_sections.include? group - my_sections[group].each do |my_section| - other_section = cm.sections_hash[group] - - my_comments = my_section.comments - other_comments = other_section.comments - - other_files = other_section.in_files - - merge_collections my_comments, other_comments, other_files do |add, comment| - if add then - my_section.add_comment comment - else - my_section.remove_comment comment - end - end - end - else - sections.each do |section| - add_section group, section.comments - end - end - end - end - - ## - # Does this object represent a module? - - def module? - false - end - - ## - # Allows overriding the initial name. - # - # Used for modules and classes that are constant aliases. - - def name= new_name - @name = new_name - end - - ## - # Parses +comment_location+ into an RDoc::Markup::Document composed of - # multiple RDoc::Markup::Documents with their file set. - - def parse comment_location - case comment_location - when String then - super - when Array then - docs = comment_location.map do |comment, location| - doc = super comment - doc.file = location - doc - end - - RDoc::Markup::Document.new(*docs) - when RDoc::Comment then - doc = super comment_location.text, comment_location.format - doc.file = comment_location.location - doc - when RDoc::Markup::Document then - return comment_location - else - raise ArgumentError, "unknown comment class #{comment_location.class}" - end - end - - ## - # Path to this class or module for use with HTML generator output. - - def path - http_url @store.rdoc.generator.class_dir - end - - ## - # Name to use to generate the url: - # modules and classes that are aliases for another - # module or class return the name of the latter. - - def name_for_path - is_alias_for ? is_alias_for.full_name : full_name - end - - ## - # Returns the classes and modules that are not constants - # aliasing another class or module. For use by formatters - # only (caches its result). - - def non_aliases - @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } - end - - ## - # Updates the child modules or classes of class/module +parent+ by - # deleting the ones that have been removed from the documentation. - # - # +parent_hash+ is either <tt>parent.modules_hash</tt> or - # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or - # ::all_classes_hash. - - def remove_nodoc_children - prefix = self.full_name + '::' - - modules_hash.each_key do |name| - full_name = prefix + name - modules_hash.delete name unless @store.modules_hash[full_name] - end - - classes_hash.each_key do |name| - full_name = prefix + name - classes_hash.delete name unless @store.classes_hash[full_name] - end - end - - def remove_things my_things, other_files # :nodoc: - my_things.delete_if do |file, things| - next false unless other_files.include? file - - things.each do |thing| - yield false, thing - end - - true - end - end - - ## - # Search record used by RDoc::Generator::JsonIndex - - def search_record - [ - name, - full_name, - full_name, - '', - path, - '', - snippet(@comment_location), - ] - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @attributes .each do |attr| attr.store = store end - @constants .each do |const| const.store = store end - @includes .each do |incl| incl.store = store end - @extends .each do |ext| ext.store = store end - @method_list.each do |meth| meth.store = store end - end - - ## - # Get the superclass of this class. Attempts to retrieve the superclass - # object, returns the name if it is not known. - - def superclass - @store.find_class_named(@superclass) || @superclass - end - - ## - # Set the superclass of this class to +superclass+ - # - # where +superclass+ is one of: - # - # - +nil+ - # - a String containing the full name of the superclass - # - the RDoc::ClassModule representing the superclass - - def superclass=(superclass) - raise NoMethodError, "#{full_name} is a module" if module? - case superclass - when RDoc::ClassModule - @superclass = superclass.full_name - when nil, String - @superclass = superclass - else - raise TypeError, "superclass must be a String or RDoc::ClassModule, not #{superclass.class}" - end - end - - ## - # Get all super classes of this class in an array. The last element might be - # a string if the name is unknown. - - def super_classes - result = [] - parent = self - while parent = parent.superclass - result << parent - return result if parent.is_a?(String) - end - result - end - - def to_s # :nodoc: - if is_alias_for then - "#{self.class.name} #{self.full_name} -> #{is_alias_for}" - else - super - end - end - - ## - # 'module' or 'class' - - def type - module? ? 'module' : 'class' - end - - ## - # Updates the child modules & classes by replacing the ones that are - # aliases through a constant. - # - # The aliased module/class is replaced in the children and in - # RDoc::Store#modules_hash or RDoc::Store#classes_hash - # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to - # the aliased module/class, and this copy is added to <tt>#aliases</tt> - # of the aliased module/class. - # - # Formatters can use the #non_aliases method to retrieve children that - # are not aliases, for instance to list the namespace content, since - # the aliased modules are included in the constants of the class/module, - # that are listed separately. - - def update_aliases - constants.each do |const| - next unless cm = const.is_alias_for - cm_alias = cm.dup - cm_alias.name = const.name - - # Don't move top-level aliases under Object, they look ugly there - unless RDoc::TopLevel === cm_alias.parent then - cm_alias.parent = self - cm_alias.full_name = nil # force update for new parent - end - - cm_alias.aliases.clear - cm_alias.is_alias_for = cm - - if cm.module? then - @store.modules_hash[cm_alias.full_name] = cm_alias - modules_hash[const.name] = cm_alias - else - @store.classes_hash[cm_alias.full_name] = cm_alias - classes_hash[const.name] = cm_alias - end - - cm.aliases << cm_alias - end - end - - ## - # Deletes from #includes those whose module has been removed from the - # documentation. - #-- - # FIXME: includes are not reliably removed, see _possible_bug test case - - def update_includes - includes.reject! do |include| - mod = include.module - !(String === mod) && @store.modules_hash[mod.full_name].nil? - end - - includes.uniq! - end - - ## - # Deletes from #extends those whose module has been removed from the - # documentation. - #-- - # FIXME: like update_includes, extends are not reliably removed - - def update_extends - extends.reject! do |ext| - mod = ext.module - - !(String === mod) && @store.modules_hash[mod.full_name].nil? - end - - extends.uniq! - end - - def embed_mixins - return unless options.embed_mixins - - includes.each do |include| - next if String === include.module - include.module.method_list.each do |code_object| - add_method(prepare_to_embed(code_object)) - end - include.module.constants.each do |code_object| - add_constant(prepare_to_embed(code_object)) - end - include.module.attributes.each do |code_object| - add_attribute(prepare_to_embed(code_object)) - end - end - - extends.each do |ext| - next if String === ext.module - ext.module.method_list.each do |code_object| - add_method(prepare_to_embed(code_object, true)) - end - ext.module.attributes.each do |code_object| - add_attribute(prepare_to_embed(code_object, true)) - end - end - end - - private - - def prepare_to_embed(code_object, singleton=false) - code_object = code_object.dup - code_object.mixin_from = code_object.parent - code_object.singleton = true if singleton - set_current_section(code_object.section.title, code_object.section.comment) - # add_method and add_attribute will reassign self's visibility back to the method/attribute - # so we need to sync self's visibility with the object's to properly retain that information - self.visibility = code_object.visibility - code_object - end -end diff --git a/lib/rdoc/code_object/constant.rb b/lib/rdoc/code_object/constant.rb deleted file mode 100644 index 12b8be775c..0000000000 --- a/lib/rdoc/code_object/constant.rb +++ /dev/null @@ -1,186 +0,0 @@ -# frozen_string_literal: true -## -# A constant - -class RDoc::Constant < RDoc::CodeObject - - MARSHAL_VERSION = 0 # :nodoc: - - ## - # Sets the module or class this is constant is an alias for. - - attr_writer :is_alias_for - - ## - # The constant's name - - attr_accessor :name - - ## - # The constant's value - - attr_accessor :value - - ## - # The constant's visibility - - attr_accessor :visibility - - ## - # Creates a new constant with +name+, +value+ and +comment+ - - def initialize(name, value, comment) - super() - - @name = name - @value = value - - @is_alias_for = nil - @visibility = :public - - self.comment = comment - end - - ## - # Constants are ordered by name - - def <=> other - return unless self.class === other - - [parent_name, name] <=> [other.parent_name, other.name] - end - - ## - # Constants are equal when their #parent and #name is the same - - def == other - self.class == other.class and - @parent == other.parent and - @name == other.name - end - - ## - # A constant is documented if it has a comment, or is an alias - # for a documented class or module. - - def documented? - return true if super - return false unless @is_alias_for - case @is_alias_for - when String then - found = @store.find_class_or_module @is_alias_for - return false unless found - @is_alias_for = found - end - @is_alias_for.documented? - end - - ## - # Full constant name including namespace - - def full_name - @full_name ||= "#{parent_name}::#{@name}" - end - - ## - # The module or class this constant is an alias for - - def is_alias_for - case @is_alias_for - when String then - found = @store.find_class_or_module @is_alias_for - @is_alias_for = found if found - @is_alias_for - else - @is_alias_for - end - end - - def inspect # :nodoc: - "#<%s:0x%x %s::%s>" % [ - self.class, object_id, - parent_name, @name, - ] - end - - ## - # Dumps this Constant for use by ri. See also #marshal_load - - def marshal_dump - alias_name = case found = is_alias_for - when RDoc::CodeObject then found.full_name - else found - end - - [ MARSHAL_VERSION, - @name, - full_name, - @visibility, - alias_name, - parse(@comment), - @file.relative_name, - parent.name, - parent.class, - section.title, - ] - end - - ## - # Loads this Constant from +array+. For a loaded Constant the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize array[1], nil, array[5] - - @full_name = array[2] - @visibility = array[3] || :public - @is_alias_for = array[4] - # 5 handled above - # 6 handled below - @parent_name = array[7] - @parent_class = array[8] - @section_title = array[9] - - @file = RDoc::TopLevel.new array[6] - end - - ## - # Path to this constant for use with HTML generator output. - - def path - "#{@parent.path}##{@name}" - end - - def pretty_print q # :nodoc: - q.group 2, "[#{self.class.name} #{full_name}", "]" do - unless comment.empty? then - q.breakable - q.text "comment:" - q.breakable - q.pp @comment - end - end - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - def to_s # :nodoc: - parent_name = parent ? parent.full_name : '(unknown)' - if is_alias_for - "constant #{parent_name}::#@name -> #{is_alias_for}" - else - "constant #{parent_name}::#@name" - end - end - -end diff --git a/lib/rdoc/code_object/context.rb b/lib/rdoc/code_object/context.rb deleted file mode 100644 index c688d562c3..0000000000 --- a/lib/rdoc/code_object/context.rb +++ /dev/null @@ -1,1264 +0,0 @@ -# frozen_string_literal: true -## -# A Context is something that can hold modules, classes, methods, attributes, -# aliases, requires, and includes. Classes, modules, and files are all -# Contexts. - -class RDoc::Context < RDoc::CodeObject - - include Comparable - - ## - # Types of methods - - TYPES = %w[class instance] - - ## - # If a context has these titles it will be sorted in this order. - - TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: - TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: - - ## - # Class/module aliases - - attr_reader :aliases - - ## - # All attr* methods - - attr_reader :attributes - - ## - # Block params to be used in the next MethodAttr parsed under this context - - attr_accessor :block_params - - ## - # Constants defined - - attr_reader :constants - - ## - # Sets the current documentation section of documentation - - attr_writer :current_section - - ## - # Files this context is found in - - attr_reader :in_files - - ## - # Modules this context includes - - attr_reader :includes - - ## - # Modules this context is extended with - - attr_reader :extends - - ## - # Methods defined in this context - - attr_reader :method_list - - ## - # Name of this class excluding namespace. See also full_name - - attr_reader :name - - ## - # Files this context requires - - attr_reader :requires - - ## - # Use this section for the next method, attribute or constant added. - - attr_accessor :temporary_section - - ## - # Hash <tt>old_name => [aliases]</tt>, for aliases - # that haven't (yet) been resolved to a method/attribute. - # (Not to be confused with the aliases of the context.) - - attr_accessor :unmatched_alias_lists - - ## - # Aliases that could not be resolved. - - attr_reader :external_aliases - - ## - # Current visibility of this context - - attr_accessor :visibility - - ## - # Current visibility of this line - - attr_writer :current_line_visibility - - ## - # Hash of registered methods. Attributes are also registered here, - # twice if they are RW. - - attr_reader :methods_hash - - ## - # Params to be used in the next MethodAttr parsed under this context - - attr_accessor :params - - ## - # Hash of registered constants. - - attr_reader :constants_hash - - ## - # Creates an unnamed empty context with public current visibility - - def initialize - super - - @in_files = [] - - @name ||= "unknown" - @parent = nil - @visibility = :public - - @current_section = Section.new self, nil, nil - @sections = { nil => @current_section } - @temporary_section = nil - - @classes = {} - @modules = {} - - initialize_methods_etc - end - - ## - # Sets the defaults for methods and so-forth - - def initialize_methods_etc - @method_list = [] - @attributes = [] - @aliases = [] - @requires = [] - @includes = [] - @extends = [] - @constants = [] - @external_aliases = [] - @current_line_visibility = nil - - # This Hash maps a method name to a list of unmatched aliases (aliases of - # a method not yet encountered). - @unmatched_alias_lists = {} - - @methods_hash = {} - @constants_hash = {} - - @params = nil - - @store ||= nil - end - - ## - # Contexts are sorted by full_name - - def <=>(other) - return nil unless RDoc::CodeObject === other - - full_name <=> other.full_name - end - - ## - # Adds an item of type +klass+ with the given +name+ and +comment+ to the - # context. - # - # Currently only RDoc::Extend and RDoc::Include are supported. - - def add klass, name, comment - if RDoc::Extend == klass then - ext = RDoc::Extend.new name, comment - add_extend ext - elsif RDoc::Include == klass then - incl = RDoc::Include.new name, comment - add_include incl - else - raise NotImplementedError, "adding a #{klass} is not implemented" - end - end - - ## - # Adds +an_alias+ that is automatically resolved - - def add_alias an_alias - return an_alias unless @document_self - - method_attr = find_method(an_alias.old_name, an_alias.singleton) || - find_attribute(an_alias.old_name, an_alias.singleton) - - if method_attr then - method_attr.add_alias an_alias, self - else - add_to @external_aliases, an_alias - unmatched_alias_list = - @unmatched_alias_lists[an_alias.pretty_old_name] ||= [] - unmatched_alias_list.push an_alias - end - - an_alias - end - - ## - # Adds +attribute+ if not already there. If it is (as method(s) or attribute), - # updates the comment if it was empty. - # - # The attribute is registered only if it defines a new method. - # For instance, <tt>attr_reader :foo</tt> will not be registered - # if method +foo+ exists, but <tt>attr_accessor :foo</tt> will be registered - # if method +foo+ exists, but <tt>foo=</tt> does not. - - def add_attribute attribute - return attribute unless @document_self - - # mainly to check for redefinition of an attribute as a method - # TODO find a policy for 'attr_reader :foo' + 'def foo=()' - register = false - - key = nil - - if attribute.rw.index 'R' then - key = attribute.pretty_name - known = @methods_hash[key] - - if known then - known.comment = attribute.comment if known.comment.empty? - elsif registered = @methods_hash[attribute.pretty_name + '='] and - RDoc::Attr === registered then - registered.rw = 'RW' - else - @methods_hash[key] = attribute - register = true - end - end - - if attribute.rw.index 'W' then - key = attribute.pretty_name + '=' - known = @methods_hash[key] - - if known then - known.comment = attribute.comment if known.comment.empty? - elsif registered = @methods_hash[attribute.pretty_name] and - RDoc::Attr === registered then - registered.rw = 'RW' - else - @methods_hash[key] = attribute - register = true - end - end - - if register then - attribute.visibility = @visibility - add_to @attributes, attribute - resolve_aliases attribute - end - - attribute - end - - ## - # Adds a class named +given_name+ with +superclass+. - # - # Both +given_name+ and +superclass+ may contain '::', and are - # interpreted relative to the +self+ context. This allows handling correctly - # examples like these: - # class RDoc::Gauntlet < Gauntlet - # module Mod - # class Object # implies < ::Object - # class SubObject < Object # this is _not_ ::Object - # - # Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module - # unless it later sees <tt>class Container</tt>. +add_class+ automatically - # upgrades +given_name+ to a class in this case. - - def add_class class_type, given_name, superclass = '::Object' - # superclass +nil+ is passed by the C parser in the following cases: - # - registering Object in 1.8 (correct) - # - registering BasicObject in 1.9 (correct) - # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c) - # - # If we later find a superclass for a registered class with a nil - # superclass, we must honor it. - - # find the name & enclosing context - if given_name =~ /^:+(\w+)$/ then - full_name = $1 - enclosing = top_level - name = full_name.split(/:+/).last - else - full_name = child_name given_name - - if full_name =~ /^(.+)::(\w+)$/ then - name = $2 - ename = $1 - enclosing = @store.classes_hash[ename] || @store.modules_hash[ename] - # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming) - unless enclosing then - # try the given name at top level (will work for the above example) - enclosing = @store.classes_hash[given_name] || - @store.modules_hash[given_name] - return enclosing if enclosing - # not found: create the parent(s) - names = ename.split('::') - enclosing = self - names.each do |n| - enclosing = enclosing.classes_hash[n] || - enclosing.modules_hash[n] || - enclosing.add_module(RDoc::NormalModule, n) - end - end - else - name = full_name - enclosing = self - end - end - - # fix up superclass - if full_name == 'BasicObject' then - superclass = nil - elsif full_name == 'Object' then - superclass = '::BasicObject' - end - - # find the superclass full name - if superclass then - if superclass =~ /^:+/ then - superclass = $' #' - else - if superclass =~ /^(\w+):+(.+)$/ then - suffix = $2 - mod = find_module_named($1) - superclass = mod.full_name + '::' + suffix if mod - else - mod = find_module_named(superclass) - superclass = mod.full_name if mod - end - end - - # did we believe it was a module? - mod = @store.modules_hash.delete superclass - - upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod - - # e.g., Object < Object - superclass = nil if superclass == full_name - end - - klass = @store.classes_hash[full_name] - - if klass then - # if TopLevel, it may not be registered in the classes: - enclosing.classes_hash[name] = klass - - # update the superclass if needed - if superclass then - existing = klass.superclass - existing = existing.full_name unless existing.is_a?(String) if existing - if existing.nil? || - (existing == 'Object' && superclass != 'Object') then - klass.superclass = superclass - end - end - else - # this is a new class - mod = @store.modules_hash.delete full_name - - if mod then - klass = upgrade_to_class mod, RDoc::NormalClass, enclosing - - klass.superclass = superclass unless superclass.nil? - else - klass = class_type.new name, superclass - - enclosing.add_class_or_module(klass, enclosing.classes_hash, - @store.classes_hash) - end - end - - klass.parent = self - - klass - end - - ## - # Adds the class or module +mod+ to the modules or - # classes Hash +self_hash+, and to +all_hash+ (either - # <tt>TopLevel::modules_hash</tt> or <tt>TopLevel::classes_hash</tt>), - # unless #done_documenting is +true+. Sets the #parent of +mod+ - # to +self+, and its #section to #current_section. Returns +mod+. - - def add_class_or_module mod, self_hash, all_hash - mod.section = current_section # TODO declaring context? something is - # wrong here... - mod.parent = self - mod.full_name = nil - mod.store = @store - - unless @done_documenting then - self_hash[mod.name] = mod - # this must be done AFTER adding mod to its parent, so that the full - # name is correct: - all_hash[mod.full_name] = mod - if @store.unmatched_constant_alias[mod.full_name] then - to, file = @store.unmatched_constant_alias[mod.full_name] - add_module_alias mod, mod.name, to, file - end - end - - mod - end - - ## - # Adds +constant+ if not already there. If it is, updates the comment, - # value and/or is_alias_for of the known constant if they were empty/nil. - - def add_constant constant - return constant unless @document_self - - # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code) - # (this is a #ifdef: should be handled by the C parser) - known = @constants_hash[constant.name] - - if known then - known.comment = constant.comment if known.comment.empty? - - known.value = constant.value if - known.value.nil? or known.value.strip.empty? - - known.is_alias_for ||= constant.is_alias_for - else - @constants_hash[constant.name] = constant - add_to @constants, constant - end - - constant - end - - ## - # Adds included module +include+ which should be an RDoc::Include - - def add_include include - add_to @includes, include - - include - end - - ## - # Adds extension module +ext+ which should be an RDoc::Extend - - def add_extend ext - add_to @extends, ext - - ext - end - - ## - # Adds +method+ if not already there. If it is (as method or attribute), - # updates the comment if it was empty. - - def add_method method - return method unless @document_self - - # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code) - key = method.pretty_name - known = @methods_hash[key] - - if known then - if @store then # otherwise we are loading - known.comment = method.comment if known.comment.empty? - previously = ", previously in #{known.file}" unless - method.file == known.file - @store.rdoc.options.warn \ - "Duplicate method #{known.full_name} in #{method.file}#{previously}" - end - else - @methods_hash[key] = method - if @current_line_visibility - method.visibility, @current_line_visibility = @current_line_visibility, nil - else - method.visibility = @visibility - end - add_to @method_list, method - resolve_aliases method - end - - method - end - - ## - # Adds a module named +name+. If RDoc already knows +name+ is a class then - # that class is returned instead. See also #add_class. - - def add_module(class_type, name) - mod = @classes[name] || @modules[name] - return mod if mod - - full_name = child_name name - mod = @store.modules_hash[full_name] || class_type.new(name) - - add_class_or_module mod, @modules, @store.modules_hash - end - - ## - # Adds a module by +RDoc::NormalModule+ instance. See also #add_module. - - def add_module_by_normal_module(mod) - add_class_or_module mod, @modules, @store.modules_hash - end - - ## - # Adds an alias from +from+ (a class or module) to +name+ which was defined - # in +file+. - - def add_module_alias from, from_name, to, file - return from if @done_documenting - - to_full_name = child_name to.name - - # if we already know this name, don't register an alias: - # see the metaprogramming in lib/active_support/basic_object.rb, - # where we already know BasicObject is a class when we find - # BasicObject = BlankSlate - return from if @store.find_class_or_module to_full_name - - unless from - @store.unmatched_constant_alias[child_name(from_name)] = [to, file] - return to - end - - new_to = from.dup - new_to.name = to.name - new_to.full_name = nil - - if new_to.module? then - @store.modules_hash[to_full_name] = new_to - @modules[to.name] = new_to - else - @store.classes_hash[to_full_name] = new_to - @classes[to.name] = new_to - end - - # Registers a constant for this alias. The constant value and comment - # will be updated later, when the Ruby parser adds the constant - const = RDoc::Constant.new to.name, nil, new_to.comment - const.record_location file - const.is_alias_for = from - add_constant const - - new_to - end - - ## - # Adds +require+ to this context's top level - - def add_require(require) - return require unless @document_self - - if RDoc::TopLevel === self then - add_to @requires, require - else - parent.add_require require - end - end - - ## - # Returns a section with +title+, creating it if it doesn't already exist. - # +comment+ will be appended to the section's comment. - # - # A section with a +title+ of +nil+ will return the default section. - # - # See also RDoc::Context::Section - - def add_section title, comment = nil - if section = @sections[title] then - section.add_comment comment if comment - else - section = Section.new self, title, comment - @sections[title] = section - end - - section - end - - ## - # Adds +thing+ to the collection +array+ - - def add_to array, thing - array << thing if @document_self - - thing.parent = self - thing.store = @store if @store - thing.section = current_section - end - - ## - # Is there any content? - # - # This means any of: comment, aliases, methods, attributes, external - # aliases, require, constant. - # - # Includes and extends are also checked unless <tt>includes == false</tt>. - - def any_content(includes = true) - @any_content ||= !( - @comment.empty? && - @method_list.empty? && - @attributes.empty? && - @aliases.empty? && - @external_aliases.empty? && - @requires.empty? && - @constants.empty? - ) - @any_content || (includes && !(@includes + @extends).empty? ) - end - - ## - # Creates the full name for a child with +name+ - - def child_name name - if name =~ /^:+/ - $' #' - elsif RDoc::TopLevel === self then - name - else - "#{self.full_name}::#{name}" - end - end - - ## - # Class attributes - - def class_attributes - @class_attributes ||= attributes.select { |a| a.singleton } - end - - ## - # Class methods - - def class_method_list - @class_method_list ||= method_list.select { |a| a.singleton } - end - - ## - # Array of classes in this context - - def classes - @classes.values - end - - ## - # All classes and modules in this namespace - - def classes_and_modules - classes + modules - end - - ## - # Hash of classes keyed by class name - - def classes_hash - @classes - end - - ## - # The current documentation section that new items will be added to. If - # temporary_section is available it will be used. - - def current_section - if section = @temporary_section then - @temporary_section = nil - else - section = @current_section - end - - section - end - - ## - # Is part of this thing was defined in +file+? - - def defined_in?(file) - @in_files.include?(file) - end - - def display(method_attr) # :nodoc: - if method_attr.is_a? RDoc::Attr - "#{method_attr.definition} #{method_attr.pretty_name}" - else - "method #{method_attr.pretty_name}" - end - end - - ## - # Iterator for ancestors for duck-typing. Does nothing. See - # RDoc::ClassModule#each_ancestor. - # - # This method exists to make it easy to work with Context subclasses that - # aren't part of RDoc. - - def each_ancestor(&_) # :nodoc: - end - - ## - # Iterator for attributes - - def each_attribute # :yields: attribute - @attributes.each { |a| yield a } - end - - ## - # Iterator for classes and modules - - def each_classmodule(&block) # :yields: module - classes_and_modules.sort.each(&block) - end - - ## - # Iterator for constants - - def each_constant # :yields: constant - @constants.each {|c| yield c} - end - - ## - # Iterator for included modules - - def each_include # :yields: include - @includes.each do |i| yield i end - end - - ## - # Iterator for extension modules - - def each_extend # :yields: extend - @extends.each do |e| yield e end - end - - ## - # Iterator for methods - - def each_method # :yields: method - return enum_for __method__ unless block_given? - - @method_list.sort.each { |m| yield m } - end - - ## - # Iterator for each section's contents sorted by title. The +section+, the - # section's +constants+ and the sections +attributes+ are yielded. The - # +constants+ and +attributes+ collections are sorted. - # - # To retrieve methods in a section use #methods_by_type with the optional - # +section+ parameter. - # - # NOTE: Do not edit collections yielded by this method - - def each_section # :yields: section, constants, attributes - return enum_for __method__ unless block_given? - - constants = @constants.group_by do |constant| constant.section end - attributes = @attributes.group_by do |attribute| attribute.section end - - constants.default = [] - attributes.default = [] - - sort_sections.each do |section| - yield section, constants[section].select(&:display?).sort, attributes[section].select(&:display?).sort - end - end - - ## - # Finds an attribute +name+ with singleton value +singleton+. - - def find_attribute(name, singleton) - name = $1 if name =~ /^(.*)=$/ - @attributes.find { |a| a.name == name && a.singleton == singleton } - end - - ## - # Finds an attribute with +name+ in this context - - def find_attribute_named(name) - case name - when /\A#/ then - find_attribute name[1..-1], false - when /\A::/ then - find_attribute name[2..-1], true - else - @attributes.find { |a| a.name == name } - end - end - - ## - # Finds a class method with +name+ in this context - - def find_class_method_named(name) - @method_list.find { |meth| meth.singleton && meth.name == name } - end - - ## - # Finds a constant with +name+ in this context - - def find_constant_named(name) - @constants.find do |m| - m.name == name || m.full_name == name - end - end - - ## - # Find a module at a higher scope - - def find_enclosing_module_named(name) - parent && parent.find_module_named(name) - end - - ## - # Finds an external alias +name+ with singleton value +singleton+. - - def find_external_alias(name, singleton) - @external_aliases.find { |m| m.name == name && m.singleton == singleton } - end - - ## - # Finds an external alias with +name+ in this context - - def find_external_alias_named(name) - case name - when /\A#/ then - find_external_alias name[1..-1], false - when /\A::/ then - find_external_alias name[2..-1], true - else - @external_aliases.find { |a| a.name == name } - end - end - - ## - # Finds a file with +name+ in this context - - def find_file_named name - @store.find_file_named name - end - - ## - # Finds an instance method with +name+ in this context - - def find_instance_method_named(name) - @method_list.find { |meth| !meth.singleton && meth.name == name } - end - - ## - # Finds a method, constant, attribute, external alias, module or file - # named +symbol+ in this context. - - def find_local_symbol(symbol) - find_method_named(symbol) or - find_constant_named(symbol) or - find_attribute_named(symbol) or - find_external_alias_named(symbol) or - find_module_named(symbol) or - find_file_named(symbol) - end - - ## - # Finds a method named +name+ with singleton value +singleton+. - - def find_method(name, singleton) - @method_list.find { |m| - if m.singleton - m.name == name && m.singleton == singleton - else - m.name == name && !m.singleton && !singleton - end - } - end - - ## - # Finds a instance or module method with +name+ in this context - - def find_method_named(name) - case name - when /\A#/ then - find_method name[1..-1], false - when /\A::/ then - find_method name[2..-1], true - else - @method_list.find { |meth| meth.name == name } - end - end - - ## - # Find a module with +name+ using ruby's scoping rules - - def find_module_named(name) - res = @modules[name] || @classes[name] - return res if res - return self if self.name == name - find_enclosing_module_named name - end - - ## - # Look up +symbol+, first as a module, then as a local symbol. - - def find_symbol(symbol) - find_symbol_module(symbol) || find_local_symbol(symbol) - end - - ## - # Look up a module named +symbol+. - - def find_symbol_module(symbol) - result = nil - - # look for a class or module 'symbol' - case symbol - when /^::/ then - result = @store.find_class_or_module symbol - when /^(\w+):+(.+)$/ - suffix = $2 - top = $1 - searched = self - while searched do - mod = searched.find_module_named(top) - break unless mod - result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" - break if result || searched.is_a?(RDoc::TopLevel) - searched = searched.parent - end - else - searched = self - while searched do - result = searched.find_module_named(symbol) - break if result || searched.is_a?(RDoc::TopLevel) - searched = searched.parent - end - end - - result - end - - ## - # The full name for this context. This method is overridden by subclasses. - - def full_name - '(unknown)' - end - - ## - # Does this context and its methods and constants all have documentation? - # - # (Yes, fully documented doesn't mean everything.) - - def fully_documented? - documented? and - attributes.all? { |a| a.documented? } and - method_list.all? { |m| m.documented? } and - constants.all? { |c| c.documented? } - end - - ## - # URL for this with a +prefix+ - - def http_url(prefix) - path = name_for_path - path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<</ - path = [prefix] + path.split('::') - - File.join(*path.compact) + '.html' - end - - ## - # Instance attributes - - def instance_attributes - @instance_attributes ||= attributes.reject { |a| a.singleton } - end - - ## - # Instance methods - - def instance_methods - @instance_methods ||= method_list.reject { |a| a.singleton } - end - - ## - # Instance methods - #-- - # TODO remove this later - - def instance_method_list - warn '#instance_method_list is obsoleted, please use #instance_methods' - @instance_methods ||= method_list.reject { |a| a.singleton } - end - - ## - # Breaks method_list into a nested hash by type (<tt>'class'</tt> or - # <tt>'instance'</tt>) and visibility (+:public+, +:protected+, +:private+). - # - # If +section+ is provided only methods in that RDoc::Context::Section will - # be returned. - - def methods_by_type section = nil - methods = {} - - TYPES.each do |type| - visibilities = {} - RDoc::VISIBILITIES.each do |vis| - visibilities[vis] = [] - end - - methods[type] = visibilities - end - - each_method do |method| - next if section and not method.section == section - methods[method.type][method.visibility] << method - end - - methods - end - - ## - # Yields AnyMethod and Attr entries matching the list of names in +methods+. - - def methods_matching(methods, singleton = false, &block) - (@method_list + @attributes).each do |m| - yield m if methods.include?(m.name) and m.singleton == singleton - end - - each_ancestor do |parent| - parent.methods_matching(methods, singleton, &block) - end - end - - ## - # Array of modules in this context - - def modules - @modules.values - end - - ## - # Hash of modules keyed by module name - - def modules_hash - @modules - end - - ## - # Name to use to generate the url. - # <tt>#full_name</tt> by default. - - def name_for_path - full_name - end - - ## - # Changes the visibility for new methods to +visibility+ - - def ongoing_visibility=(visibility) - @visibility = visibility - end - - ## - # Record +top_level+ as a file +self+ is in. - - def record_location(top_level) - @in_files << top_level unless @in_files.include?(top_level) - end - - ## - # Should we remove this context from the documentation? - # - # The answer is yes if: - # * #received_nodoc is +true+ - # * #any_content is +false+ (not counting includes) - # * All #includes are modules (not a string), and their module has - # <tt>#remove_from_documentation? == true</tt> - # * All classes and modules have <tt>#remove_from_documentation? == true</tt> - - def remove_from_documentation? - @remove_from_documentation ||= - @received_nodoc && - !any_content(false) && - @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } && - classes_and_modules.all? { |cm| cm.remove_from_documentation? } - end - - ## - # Removes methods and attributes with a visibility less than +min_visibility+. - #-- - # TODO mark the visibility of attributes in the template (if not public?) - - def remove_invisible min_visibility - return if [:private, :nodoc].include? min_visibility - remove_invisible_in @method_list, min_visibility - remove_invisible_in @attributes, min_visibility - remove_invisible_in @constants, min_visibility - end - - ## - # Only called when min_visibility == :public or :private - - def remove_invisible_in array, min_visibility # :nodoc: - if min_visibility == :public then - array.reject! { |e| - e.visibility != :public and not e.force_documentation - } - else - array.reject! { |e| - e.visibility == :private and not e.force_documentation - } - end - end - - ## - # Tries to resolve unmatched aliases when a method or attribute has just - # been added. - - def resolve_aliases added - # resolve any pending unmatched aliases - key = added.pretty_name - unmatched_alias_list = @unmatched_alias_lists[key] - return unless unmatched_alias_list - unmatched_alias_list.each do |unmatched_alias| - added.add_alias unmatched_alias, self - @external_aliases.delete unmatched_alias - end - @unmatched_alias_lists.delete key - end - - ## - # Returns RDoc::Context::Section objects referenced in this context for use - # in a table of contents. - - def section_contents - used_sections = {} - - each_method do |method| - next unless method.display? - - used_sections[method.section] = true - end - - # order found sections - sections = sort_sections.select do |section| - used_sections[section] - end - - # only the default section is used - return [] if - sections.length == 1 and not sections.first.title - - sections - end - - ## - # Sections in this context - - def sections - @sections.values - end - - def sections_hash # :nodoc: - @sections - end - - ## - # Sets the current section to a section with +title+. See also #add_section - - def set_current_section title, comment - @current_section = add_section title, comment - end - - ## - # Given an array +methods+ of method names, set the visibility of each to - # +visibility+ - - def set_visibility_for(methods, visibility, singleton = false) - methods_matching methods, singleton do |m| - m.visibility = visibility - end - end - - ## - # Given an array +names+ of constants, set the visibility of each constant to - # +visibility+ - - def set_constant_visibility_for(names, visibility) - names.each do |name| - constant = @constants_hash[name] or next - constant.visibility = visibility - end - end - - ## - # Sorts sections alphabetically (default) or in TomDoc fashion (none, - # Public, Internal, Deprecated) - - def sort_sections - titles = @sections.map { |title, _| title } - - if titles.length > 1 and - TOMDOC_TITLES_SORT == - (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then - @sections.values_at(*TOMDOC_TITLES).compact - else - @sections.sort_by { |title, _| - title.to_s - }.map { |_, section| - section - } - end - end - - def to_s # :nodoc: - "#{self.class.name} #{self.full_name}" - end - - ## - # Return the TopLevel that owns us - #-- - # FIXME we can be 'owned' by several TopLevel (see #record_location & - # #in_files) - - def top_level - return @top_level if defined? @top_level - @top_level = self - @top_level = @top_level.parent until RDoc::TopLevel === @top_level - @top_level - end - - ## - # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+ - - def upgrade_to_class mod, class_type, enclosing - enclosing.modules_hash.delete mod.name - - klass = RDoc::ClassModule.from_module class_type, mod - klass.store = @store - - # if it was there, then we keep it even if done_documenting - @store.classes_hash[mod.full_name] = klass - enclosing.classes_hash[mod.name] = klass - - klass - end - - autoload :Section, "#{__dir__}/context/section" - -end diff --git a/lib/rdoc/code_object/context/section.rb b/lib/rdoc/code_object/context/section.rb deleted file mode 100644 index aecd4e0213..0000000000 --- a/lib/rdoc/code_object/context/section.rb +++ /dev/null @@ -1,233 +0,0 @@ -# frozen_string_literal: true -require 'cgi/util' - -## -# A section of documentation like: -# -# # :section: The title -# # The body -# -# Sections can be referenced multiple times and will be collapsed into a -# single section. - -class RDoc::Context::Section - - include RDoc::Text - - MARSHAL_VERSION = 0 # :nodoc: - - ## - # Section comment - - attr_reader :comment - - ## - # Section comments - - attr_reader :comments - - ## - # Context this Section lives in - - attr_reader :parent - - ## - # Section title - - attr_reader :title - - ## - # Creates a new section with +title+ and +comment+ - - def initialize parent, title, comment - @parent = parent - @title = title ? title.strip : title - - @comments = [] - - add_comment comment - end - - ## - # Sections are equal when they have the same #title - - def == other - self.class === other and @title == other.title - end - - alias eql? == - - ## - # Adds +comment+ to this section - - def add_comment comment - comment = extract_comment comment - - return if comment.empty? - - case comment - when RDoc::Comment then - @comments << comment - when RDoc::Markup::Document then - @comments.concat comment.parts - when Array then - @comments.concat comment - else - raise TypeError, "unknown comment type: #{comment.inspect}" - end - end - - ## - # Anchor reference for linking to this section - - def aref - title = @title || '[untitled]' - - CGI.escape(title).gsub('%', '-').sub(/^-/, '') - end - - ## - # Extracts the comment for this section from the original comment block. - # If the first line contains :section:, strip it and use the rest. - # Otherwise remove lines up to the line containing :section:, and look - # for those lines again at the end and remove them. This lets us write - # - # # :section: The title - # # The body - - def extract_comment comment - case comment - when Array then - comment.map do |c| - extract_comment c - end - when nil - RDoc::Comment.new '' - when RDoc::Comment then - if comment.text =~ /^#[ \t]*:section:.*\n/ then - start = $` - rest = $' - - comment.text = if start.empty? then - rest - else - rest.sub(/#{start.chomp}\Z/, '') - end - end - - comment - when RDoc::Markup::Document then - comment - else - raise TypeError, "unknown comment #{comment.inspect}" - end - end - - def inspect # :nodoc: - "#<%s:0x%x %p>" % [self.class, object_id, title] - end - - def hash # :nodoc: - @title.hash - end - - ## - # The files comments in this section come from - - def in_files - return [] if @comments.empty? - - case @comments - when Array then - @comments.map do |comment| - comment.file - end - when RDoc::Markup::Document then - @comment.parts.map do |document| - document.file - end - else - raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" - end - end - - ## - # Serializes this Section. The title and parsed comment are saved, but not - # the section parent which must be restored manually. - - def marshal_dump - [ - MARSHAL_VERSION, - @title, - parse, - ] - end - - ## - # De-serializes this Section. The section parent must be restored manually. - - def marshal_load array - @parent = nil - - @title = array[1] - @comments = array[2] - end - - ## - # Parses +comment_location+ into an RDoc::Markup::Document composed of - # multiple RDoc::Markup::Documents with their file set. - - def parse - case @comments - when String then - super - when Array then - docs = @comments.map do |comment, location| - doc = super comment - doc.file = location if location - doc - end - - RDoc::Markup::Document.new(*docs) - when RDoc::Comment then - doc = super @comments.text, comments.format - doc.file = @comments.location - doc - when RDoc::Markup::Document then - return @comments - else - raise ArgumentError, "unknown comment class #{comments.class}" - end - end - - ## - # The section's title, or 'Top Section' if the title is nil. - # - # This is used by the table of contents template so the name is silly. - - def plain_html - @title || 'Top Section' - end - - ## - # Removes a comment from this section if it is from the same file as - # +comment+ - - def remove_comment comment - return if @comments.empty? - - case @comments - when Array then - @comments.delete_if do |my_comment| - my_comment.file == comment.file - end - when RDoc::Markup::Document then - @comments.parts.delete_if do |document| - document.file == comment.file.name - end - else - raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" - end - end - -end diff --git a/lib/rdoc/code_object/extend.rb b/lib/rdoc/code_object/extend.rb deleted file mode 100644 index 7d57433de6..0000000000 --- a/lib/rdoc/code_object/extend.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -## -# A Module extension to a class with \#extend -# -# RDoc::Extend.new 'Enumerable', 'comment ...' - -class RDoc::Extend < RDoc::Mixin - -end diff --git a/lib/rdoc/code_object/ghost_method.rb b/lib/rdoc/code_object/ghost_method.rb deleted file mode 100644 index 25f951e35e..0000000000 --- a/lib/rdoc/code_object/ghost_method.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true -## -# GhostMethod represents a method referenced only by a comment - -class RDoc::GhostMethod < RDoc::AnyMethod -end diff --git a/lib/rdoc/code_object/include.rb b/lib/rdoc/code_object/include.rb deleted file mode 100644 index c3e0d45e47..0000000000 --- a/lib/rdoc/code_object/include.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -## -# A Module included in a class with \#include -# -# RDoc::Include.new 'Enumerable', 'comment ...' - -class RDoc::Include < RDoc::Mixin - -end diff --git a/lib/rdoc/code_object/meta_method.rb b/lib/rdoc/code_object/meta_method.rb deleted file mode 100644 index 8c95a0f78c..0000000000 --- a/lib/rdoc/code_object/meta_method.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true -## -# MetaMethod represents a meta-programmed method - -class RDoc::MetaMethod < RDoc::AnyMethod -end diff --git a/lib/rdoc/code_object/method_attr.rb b/lib/rdoc/code_object/method_attr.rb deleted file mode 100644 index 263780f7c7..0000000000 --- a/lib/rdoc/code_object/method_attr.rb +++ /dev/null @@ -1,430 +0,0 @@ -# frozen_string_literal: true -## -# Abstract class representing either a method or an attribute. - -class RDoc::MethodAttr < RDoc::CodeObject - - include Comparable - - ## - # Name of this method/attribute. - - attr_accessor :name - - ## - # public, protected, private - - attr_accessor :visibility - - ## - # Is this a singleton method/attribute? - - attr_accessor :singleton - - ## - # Source file token stream - - attr_reader :text - - ## - # Array of other names for this method/attribute - - attr_reader :aliases - - ## - # The method/attribute we're aliasing - - attr_accessor :is_alias_for - - #-- - # The attributes below are for AnyMethod only. - # They are left here for the time being to - # allow ri to operate. - # TODO modify ri to avoid calling these on attributes. - #++ - - ## - # Parameters yielded by the called block - - attr_reader :block_params - - ## - # Parameters for this method - - attr_accessor :params - - ## - # Different ways to call this method - - attr_accessor :call_seq - - ## - # The call_seq or the param_seq with method name, if there is no call_seq. - - attr_reader :arglists - - ## - # Pretty parameter list for this method - - attr_reader :param_seq - - - ## - # Creates a new MethodAttr from token stream +text+ and method or attribute - # name +name+. - # - # Usually this is called by super from a subclass. - - def initialize text, name - super() - - @text = text - @name = name - - @aliases = [] - @is_alias_for = nil - @parent_name = nil - @singleton = nil - @visibility = :public - @see = false - - @arglists = nil - @block_params = nil - @call_seq = nil - @param_seq = nil - @params = nil - end - - ## - # Resets cached data for the object so it can be rebuilt by accessor methods - - def initialize_copy other # :nodoc: - @full_name = nil - end - - def initialize_visibility # :nodoc: - super - @see = nil - end - - ## - # Order by #singleton then #name - - def <=>(other) - return unless other.respond_to?(:singleton) && - other.respond_to?(:name) - - [@singleton ? 0 : 1, name_ord_range, name] <=> - [other.singleton ? 0 : 1, other.name_ord_range, other.name] - end - - def == other # :nodoc: - equal?(other) or self.class == other.class and full_name == other.full_name - end - - ## - # A method/attribute is documented if any of the following is true: - # - it was marked with :nodoc:; - # - it has a comment; - # - it is an alias for a documented method; - # - it has a +#see+ method that is documented. - - def documented? - super or - (is_alias_for and is_alias_for.documented?) or - (see and see.documented?) - end - - ## - # A method/attribute to look at, - # in particular if this method/attribute has no documentation. - # - # It can be a method/attribute of the superclass or of an included module, - # including the Kernel module, which is always appended to the included - # modules. - # - # Returns +nil+ if there is no such method/attribute. - # The +#is_alias_for+ method/attribute, if any, is not included. - # - # Templates may generate a "see also ..." if this method/attribute - # has documentation, and "see ..." if it does not. - - def see - @see = find_see if @see == false - @see - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - def find_see # :nodoc: - return nil if singleton || is_alias_for - - # look for the method - other = find_method_or_attribute name - return other if other - - # if it is a setter, look for a getter - return nil unless name =~ /[a-z_]=$/i # avoid == or === - return find_method_or_attribute name[0..-2] - end - - def find_method_or_attribute name # :nodoc: - return nil unless parent.respond_to? :ancestors - - searched = parent.ancestors - kernel = @store.modules_hash['Kernel'] - - searched << kernel if kernel && - parent != kernel && !searched.include?(kernel) - - searched.each do |ancestor| - next if String === ancestor - next if parent == ancestor - - other = ancestor.find_method_named('#' + name) || - ancestor.find_attribute_named(name) - - return other if other - end - - nil - end - - ## - # Abstract method. Contexts in their building phase call this - # to register a new alias for this known method/attribute. - # - # - creates a new AnyMethod/Attribute named <tt>an_alias.new_name</tt>; - # - adds +self+ as an alias for the new method or attribute - # - adds the method or attribute to #aliases - # - adds the method or attribute to +context+. - - def add_alias(an_alias, context) - raise NotImplementedError - end - - ## - # HTML fragment reference for this method - - def aref - type = singleton ? 'c' : 'i' - # % characters are not allowed in html names => dash instead - "#{aref_prefix}-#{type}-#{html_name}" - end - - ## - # Prefix for +aref+, defined by subclasses. - - def aref_prefix - raise NotImplementedError - end - - ## - # Attempts to sanitize the content passed by the Ruby parser: - # remove outer parentheses, etc. - - def block_params=(value) - # 'yield.to_s' or 'assert yield, msg' - return @block_params = '' if value =~ /^[\.,]/ - - # remove trailing 'if/unless ...' - return @block_params = '' if value =~ /^(if|unless)\s/ - - value = $1.strip if value =~ /^(.+)\s(if|unless)\s/ - - # outer parentheses - value = $1 if value =~ /^\s*\((.*)\)\s*$/ - value = value.strip - - # proc/lambda - return @block_params = $1 if value =~ /^(proc|lambda)(\s*\{|\sdo)/ - - # surrounding +...+ or [...] - value = $1.strip if value =~ /^\+(.*)\+$/ - value = $1.strip if value =~ /^\[(.*)\]$/ - - return @block_params = '' if value.empty? - - # global variable - return @block_params = 'str' if value =~ /^\$[&0-9]$/ - - # wipe out array/hash indices - value.gsub!(/(\w)\[[^\[]+\]/, '\1') - - # remove @ from class/instance variables - value.gsub!(/@@?([a-z0-9_]+)/, '\1') - - # method calls => method name - value.gsub!(/([A-Z:a-z0-9_]+)\.([a-z0-9_]+)(\s*\(\s*[a-z0-9_.,\s]*\s*\)\s*)?/) do - case $2 - when 'to_s' then $1 - when 'const_get' then 'const' - when 'new' then - $1.split('::').last. # ClassName => class_name - gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2'). - gsub(/([a-z\d])([A-Z])/, '\1_\2'). - downcase - else - $2 - end - end - - # class prefixes - value.gsub!(/[A-Za-z0-9_:]+::/, '') - - # simple expressions - value = $1 if value =~ /^([a-z0-9_]+)\s*[-*+\/]/ - - @block_params = value.strip - end - - ## - # HTML id-friendly method/attribute name - - def html_name - require 'cgi/util' - - CGI.escape(@name.gsub('-', '-2D')).gsub('%', '-').sub(/^-/, '') - end - - ## - # Full method/attribute name including namespace - - def full_name - @full_name ||= "#{parent_name}#{pretty_name}" - end - - def inspect # :nodoc: - alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil - visibility = self.visibility - visibility = "forced #{visibility}" if force_documentation - "#<%s:0x%x %s (%s)%s>" % [ - self.class, object_id, - full_name, - visibility, - alias_for, - ] - end - - ## - # '::' for a class method/attribute, '#' for an instance method. - - def name_prefix - @singleton ? '::' : '#' - end - - ## - # Name for output to HTML. For class methods the full name with a "." is - # used like +SomeClass.method_name+. For instance methods the class name is - # used if +context+ does not match the parent. - # - # This is to help prevent people from using :: to call class methods. - - def output_name context - return "#{name_prefix}#{@name}" if context == parent - - "#{parent_name}#{@singleton ? '.' : '#'}#{@name}" - end - - ## - # Method/attribute name with class/instance indicator - - def pretty_name - "#{name_prefix}#{@name}" - end - - ## - # Type of method/attribute (class or instance) - - def type - singleton ? 'class' : 'instance' - end - - ## - # Path to this method for use with HTML generator output. - - def path - "#{@parent.path}##{aref}" - end - - ## - # Name of our parent with special handling for un-marshaled methods - - def parent_name - @parent_name || super - end - - def pretty_print q # :nodoc: - alias_for = - if @is_alias_for.respond_to? :name then - "alias for #{@is_alias_for.name}" - elsif Array === @is_alias_for then - "alias for #{@is_alias_for.last}" - end - - q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do - if alias_for then - q.breakable - q.text alias_for - end - - if text then - q.breakable - q.text "text:" - q.breakable - q.pp @text - end - - unless comment.empty? then - q.breakable - q.text "comment:" - q.breakable - q.pp @comment - end - end - end - - ## - # Used by RDoc::Generator::JsonIndex to create a record for the search - # engine. - - def search_record - [ - @name, - full_name, - @name, - @parent.full_name, - path, - params, - snippet(@comment), - ] - end - - def to_s # :nodoc: - if @is_alias_for - "#{self.class.name}: #{full_name} -> #{is_alias_for}" - else - "#{self.class.name}: #{full_name}" - end - end - - def name_ord_range # :nodoc: - case name.ord - when 0..64 # anything below "A" - 1 - when 91..96 # the symbols between "Z" and "a" - 2 - when 123..126 # 7-bit symbols above "z": "{", "|", "}", "~" - 3 - else # everythig else can be sorted as normal - 4 - end - end -end diff --git a/lib/rdoc/code_object/mixin.rb b/lib/rdoc/code_object/mixin.rb deleted file mode 100644 index fa8faefc15..0000000000 --- a/lib/rdoc/code_object/mixin.rb +++ /dev/null @@ -1,120 +0,0 @@ -# frozen_string_literal: true -## -# A Mixin adds features from a module into another context. RDoc::Include and -# RDoc::Extend are both mixins. - -class RDoc::Mixin < RDoc::CodeObject - - ## - # Name of included module - - attr_accessor :name - - ## - # Creates a new Mixin for +name+ with +comment+ - - def initialize(name, comment) - super() - @name = name - self.comment = comment - @module = nil # cache for module if found - end - - ## - # Mixins are sorted by name - - def <=> other - return unless self.class === other - - name <=> other.name - end - - def == other # :nodoc: - self.class === other and @name == other.name - end - - alias eql? == # :nodoc: - - ## - # Full name based on #module - - def full_name - m = self.module - RDoc::ClassModule === m ? m.full_name : @name - end - - def hash # :nodoc: - [@name, self.module].hash - end - - def inspect # :nodoc: - "#<%s:0x%x %s.%s %s>" % [ - self.class, - object_id, - parent_name, self.class.name.downcase, @name, - ] - end - - ## - # Attempts to locate the included module object. Returns the name if not - # known. - # - # The scoping rules of Ruby to resolve the name of an included module are: - # - first look into the children of the current context; - # - if not found, look into the children of included modules, - # in reverse inclusion order; - # - if still not found, go up the hierarchy of names. - # - # This method has <code>O(n!)</code> behavior when the module calling - # include is referencing nonexistent modules. Avoid calling #module until - # after all the files are parsed. This behavior is due to ruby's constant - # lookup behavior. - # - # As of the beginning of October, 2011, no gem includes nonexistent modules. - - def module - return @module if @module - - # search the current context - return @name unless parent - full_name = parent.child_name(@name) - @module = @store.modules_hash[full_name] - return @module if @module - return @name if @name =~ /^::/ - - # search the includes before this one, in reverse order - searched = parent.includes.take_while { |i| i != self }.reverse - searched.each do |i| - inc = i.module - next if String === inc - full_name = inc.child_name(@name) - @module = @store.modules_hash[full_name] - return @module if @module - end - - # go up the hierarchy of names - up = parent.parent - while up - full_name = up.child_name(@name) - @module = @store.modules_hash[full_name] - return @module if @module - up = up.parent - end - - @name - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - def to_s # :nodoc: - "#{self.class.name.downcase} #@name in: #{parent}" - end - -end diff --git a/lib/rdoc/code_object/normal_class.rb b/lib/rdoc/code_object/normal_class.rb deleted file mode 100644 index aa340b5d15..0000000000 --- a/lib/rdoc/code_object/normal_class.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true -## -# A normal class, neither singleton nor anonymous - -class RDoc::NormalClass < RDoc::ClassModule - - ## - # The ancestors of this class including modules. Unlike Module#ancestors, - # this class is not included in the result. The result will contain both - # RDoc::ClassModules and Strings. - - def ancestors - if String === superclass then - super << superclass - elsif superclass then - ancestors = super - ancestors << superclass - ancestors.concat superclass.ancestors - else - super - end - end - - def aref_prefix # :nodoc: - 'class' - end - - ## - # The definition of this class, <tt>class MyClassName</tt> - - def definition - "class #{full_name}" - end - - def direct_ancestors - superclass ? super + [superclass] : super - end - - def inspect # :nodoc: - superclass = @superclass ? " < #{@superclass}" : nil - "<%s:0x%x class %s%s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ - self.class, object_id, - full_name, superclass, @includes, @extends, @attributes, @method_list, @aliases - ] - end - - def to_s # :nodoc: - display = "#{self.class.name} #{self.full_name}" - if superclass - display += ' < ' + (superclass.is_a?(String) ? superclass : superclass.full_name) - end - display += ' -> ' + is_alias_for.to_s if is_alias_for - display - end - - def pretty_print q # :nodoc: - superclass = @superclass ? " < #{@superclass}" : nil - - q.group 2, "[class #{full_name}#{superclass}", "]" do - q.breakable - q.text "includes:" - q.breakable - q.seplist @includes do |inc| q.pp inc end - - q.breakable - q.text "constants:" - q.breakable - q.seplist @constants do |const| q.pp const end - - q.breakable - q.text "attributes:" - q.breakable - q.seplist @attributes do |attr| q.pp attr end - - q.breakable - q.text "methods:" - q.breakable - q.seplist @method_list do |meth| q.pp meth end - - q.breakable - q.text "aliases:" - q.breakable - q.seplist @aliases do |aliaz| q.pp aliaz end - - q.breakable - q.text "comment:" - q.breakable - q.pp comment - end - end - -end diff --git a/lib/rdoc/code_object/normal_module.rb b/lib/rdoc/code_object/normal_module.rb deleted file mode 100644 index 498ec4dde2..0000000000 --- a/lib/rdoc/code_object/normal_module.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true -## -# A normal module, like NormalClass - -class RDoc::NormalModule < RDoc::ClassModule - - def aref_prefix # :nodoc: - 'module' - end - - def inspect # :nodoc: - "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ - self.class, object_id, - full_name, @includes, @extends, @attributes, @method_list, @aliases - ] - end - - ## - # The definition of this module, <tt>module MyModuleName</tt> - - def definition - "module #{full_name}" - end - - ## - # This is a module, returns true - - def module? - true - end - - def pretty_print q # :nodoc: - q.group 2, "[module #{full_name}:", "]" do - q.breakable - q.text "includes:" - q.breakable - q.seplist @includes do |inc| q.pp inc end - q.breakable - - q.breakable - q.text "constants:" - q.breakable - q.seplist @constants do |const| q.pp const end - - q.text "attributes:" - q.breakable - q.seplist @attributes do |attr| q.pp attr end - q.breakable - - q.text "methods:" - q.breakable - q.seplist @method_list do |meth| q.pp meth end - q.breakable - - q.text "aliases:" - q.breakable - q.seplist @aliases do |aliaz| q.pp aliaz end - q.breakable - - q.text "comment:" - q.breakable - q.pp comment - end - end - - ## - # Modules don't have one, raises NoMethodError - - def superclass - raise NoMethodError, "#{full_name} is a module" - end - -end diff --git a/lib/rdoc/code_object/require.rb b/lib/rdoc/code_object/require.rb deleted file mode 100644 index 05e26b84b0..0000000000 --- a/lib/rdoc/code_object/require.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true -## -# A file loaded by \#require - -class RDoc::Require < RDoc::CodeObject - - ## - # Name of the required file - - attr_accessor :name - - ## - # Creates a new Require that loads +name+ with +comment+ - - def initialize(name, comment) - super() - @name = name.gsub(/'|"/, "") #' - @top_level = nil - self.comment = comment - end - - def inspect # :nodoc: - "#<%s:0x%x require '%s' in %s>" % [ - self.class, - object_id, - @name, - parent_file_name, - ] - end - - def to_s # :nodoc: - "require #{name} in: #{parent}" - end - - ## - # The RDoc::TopLevel corresponding to this require, or +nil+ if not found. - - def top_level - @top_level ||= begin - tl = RDoc::TopLevel.all_files_hash[name + '.rb'] - - if tl.nil? and RDoc::TopLevel.all_files.first.full_name =~ %r(^lib/) then - # second chance - tl = RDoc::TopLevel.all_files_hash['lib/' + name + '.rb'] - end - - tl - end - end - -end diff --git a/lib/rdoc/code_object/single_class.rb b/lib/rdoc/code_object/single_class.rb deleted file mode 100644 index dd16529648..0000000000 --- a/lib/rdoc/code_object/single_class.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true -## -# A singleton class - -class RDoc::SingleClass < RDoc::ClassModule - - ## - # Adds the superclass to the included modules. - - def ancestors - superclass ? super + [superclass] : super - end - - def aref_prefix # :nodoc: - 'sclass' - end - - ## - # The definition of this singleton class, <tt>class << MyClassName</tt> - - def definition - "class << #{full_name}" - end - - def pretty_print q # :nodoc: - q.group 2, "[class << #{full_name}", "]" do - next - end - end -end diff --git a/lib/rdoc/code_object/top_level.rb b/lib/rdoc/code_object/top_level.rb deleted file mode 100644 index b93e3802fc..0000000000 --- a/lib/rdoc/code_object/top_level.rb +++ /dev/null @@ -1,291 +0,0 @@ -# frozen_string_literal: true -## -# A TopLevel context is a representation of the contents of a single file - -class RDoc::TopLevel < RDoc::Context - - MARSHAL_VERSION = 0 # :nodoc: - - ## - # This TopLevel's File::Stat struct - - attr_accessor :file_stat - - ## - # Relative name of this file - - attr_accessor :relative_name - - ## - # Absolute name of this file - - attr_accessor :absolute_name - - ## - # All the classes or modules that were declared in - # this file. These are assigned to either +#classes_hash+ - # or +#modules_hash+ once we know what they really are. - - attr_reader :classes_or_modules - - attr_accessor :diagram # :nodoc: - - ## - # The parser class that processed this file - - attr_reader :parser - - ## - # Creates a new TopLevel for the file at +absolute_name+. If documentation - # is being generated outside the source dir +relative_name+ is relative to - # the source directory. - - def initialize absolute_name, relative_name = absolute_name - super() - @name = nil - @absolute_name = absolute_name - @relative_name = relative_name - @file_stat = File.stat(absolute_name) rescue nil # HACK for testing - @diagram = nil - @parser = nil - - @classes_or_modules = [] - end - - ## - # Sets the parser for this toplevel context, also the store. - - def parser=(val) - @parser = val - @store.update_parser_of_file(absolute_name, val) if @store - @parser - end - - ## - # An RDoc::TopLevel is equal to another with the same relative_name - - def == other - self.class === other and @relative_name == other.relative_name - end - - alias eql? == - - ## - # Adds +an_alias+ to +Object+ instead of +self+. - - def add_alias(an_alias) - object_class.record_location self - return an_alias unless @document_self - object_class.add_alias an_alias - end - - ## - # Adds +constant+ to +Object+ instead of +self+. - - def add_constant constant - object_class.record_location self - return constant unless @document_self - object_class.add_constant constant - end - - ## - # Adds +include+ to +Object+ instead of +self+. - - def add_include(include) - object_class.record_location self - return include unless @document_self - object_class.add_include include - end - - ## - # Adds +method+ to +Object+ instead of +self+. - - def add_method(method) - object_class.record_location self - return method unless @document_self - object_class.add_method method - end - - ## - # Adds class or module +mod+. Used in the building phase - # by the Ruby parser. - - def add_to_classes_or_modules mod - @classes_or_modules << mod - end - - ## - # Base name of this file - - def base_name - File.basename @relative_name - end - - alias name base_name - - ## - # Only a TopLevel that contains text file) will be displayed. See also - # RDoc::CodeObject#display? - - def display? - text? and super - end - - ## - # See RDoc::TopLevel::find_class_or_module - #-- - # TODO Why do we search through all classes/modules found, not just the - # ones of this instance? - - def find_class_or_module name - @store.find_class_or_module name - end - - ## - # Finds a class or module named +symbol+ - - def find_local_symbol(symbol) - find_class_or_module(symbol) || super - end - - ## - # Finds a module or class with +name+ - - def find_module_named(name) - find_class_or_module(name) - end - - ## - # Returns the relative name of this file - - def full_name - @relative_name - end - - ## - # An RDoc::TopLevel has the same hash as another with the same - # relative_name - - def hash - @relative_name.hash - end - - ## - # URL for this with a +prefix+ - - def http_url(prefix) - path = [prefix, @relative_name.tr('.', '_')] - - File.join(*path.compact) + '.html' - end - - def inspect # :nodoc: - "#<%s:0x%x %p modules: %p classes: %p>" % [ - self.class, object_id, - base_name, - @modules.map { |n, m| m }, - @classes.map { |n, c| c } - ] - end - - ## - # Time this file was last modified, if known - - def last_modified - @file_stat ? file_stat.mtime : nil - end - - ## - # Dumps this TopLevel for use by ri. See also #marshal_load - - def marshal_dump - [ - MARSHAL_VERSION, - @relative_name, - @parser, - parse(@comment), - ] - end - - ## - # Loads this TopLevel from +array+. - - def marshal_load array # :nodoc: - initialize array[1] - - @parser = array[2] - @comment = array[3] - - @file_stat = nil - end - - ## - # Returns the NormalClass "Object", creating it if not found. - # - # Records +self+ as a location in "Object". - - def object_class - @object_class ||= begin - oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object') - oc.record_location self - oc - end - end - - ## - # Base name of this file without the extension - - def page_name - basename = File.basename @relative_name - basename =~ /\.(rb|rdoc|txt|md)$/i - - $` || basename - end - - ## - # Path to this file for use with HTML generator output. - - def path - http_url @store.rdoc.generator.file_dir - end - - def pretty_print q # :nodoc: - q.group 2, "[#{self.class}: ", "]" do - q.text "base name: #{base_name.inspect}" - q.breakable - - items = @modules.map { |n, m| m } - items.concat @modules.map { |n, c| c } - q.seplist items do |mod| q.pp mod end - end - end - - ## - # Search record used by RDoc::Generator::JsonIndex - - def search_record - return unless @parser < RDoc::Parser::Text - - [ - page_name, - '', - page_name, - '', - path, - '', - snippet(@comment), - ] - end - - ## - # Is this TopLevel from a text file instead of a source code file? - - def text? - @parser and @parser.include? RDoc::Parser::Text - end - - def to_s # :nodoc: - "file #{full_name}" - end - -end |