summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rdoc/method_attr.rb
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rdoc/method_attr.rb
Fresh start
Diffstat (limited to 'jni/ruby/lib/rdoc/method_attr.rb')
-rw-r--r--jni/ruby/lib/rdoc/method_attr.rb418
1 files changed, 418 insertions, 0 deletions
diff --git a/jni/ruby/lib/rdoc/method_attr.rb b/jni/ruby/lib/rdoc/method_attr.rb
new file mode 100644
index 0000000..a0ea851
--- /dev/null
+++ b/jni/ruby/lib/rdoc/method_attr.rb
@@ -0,0 +1,418 @@
+##
+# 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] <=>
+ [other.singleton ? 0 : 1, 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'
+
+ 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
+
+end
+