123456789_123456789_123456789_123456789_123456789_

Class: RDoc::CrossReference

Relationships & Source Files
Inherits: Object
Defined in: lib/rdoc/cross_reference.rb

Overview

CrossReference is a reusable way to create cross references for names.

Constant Summary

  • ALL_CROSSREF_REGEXP =

    Version of CROSSREF_REGEXP used when --hyperlink-all is specified.

    # File 'lib/rdoc/cross_reference.rb', line 92
    /
    (?:^|[\s()])
    (
     (?:
      # A::B::C.meth
      #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
    
      # A::B::C
      | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
    
      # Stand-alone method
      | \\?#{METHOD_REGEXP_STR}
    
      # Things that look like filenames
      | (?:\.\.\/)*[-\/\w][_\/.][-\w\/.]
    
      # Things that have markup suppressed
      | \\[^\s<]
     )
    
     # labels for headings
     (?:@[\w%-])?
    )/x
  • CLASS_REGEXP_STR =

    Regular expression to match class references

    1. There can be a '\' in front of text to suppress the cross-reference
    2. There can be a '::' in front of class names to reference from the top-level namespace.
    3. The method can be followed by parenthesis (not recommended)
    # File 'lib/rdoc/cross_reference.rb', line 16
    '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
  • CROSSREF_REGEXP =

    Regular expressions matching text that should potentially have cross-reference links generated are passed to add_regexp_handling. Note that these expressions are meant to pick up text for which cross-references have been suppressed, since the suppression characters are removed by the code that is triggered.

    # File 'lib/rdoc/cross_reference.rb', line 45
    /(?:^|[\s()])
    (
     (?:
      # A::B::C.meth
      #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
    
      # A::B::C
      # The stuff after CLASS_REGEXP_STR is a
      # nasty hack.  CLASS_REGEXP_STR unfortunately matches
      # words like dog and cat (these are legal "class"
      # names in Fortran 95).  When a word is flagged as a
      # potential cross-reference, limitations in the markup
      # engine suppress other processing, such as typesetting.
      # This is particularly noticeable for contractions.
      # In order that words like "can't" not
      # be flagged as potential cross-references, only
      # flag potential class cross-references if the character
      # after the cross-reference is a space, sentence
      # punctuation, tag start character, or attribute
      # marker.
      | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
    
      # Stand-alone method (preceded by a #)
      | \\?\##{METHOD_REGEXP_STR}
    
      # Stand-alone method (preceded by ::)
      | ::#{METHOD_REGEXP_STR}
    
      # Things that look like filenames
      # The key thing is that there must be at least
      # one special character (period, slash, or
      # underscore).
      | (?:\.\.\/)*[-\/\w][_\/.][-\w\/.]
    
      # Things that have markup suppressed
      # Don't process things like '\<' in \<tt>, though.
      # TODO: including < is a hack, not very satisfying.
      | \\[^\s<]
     )
    
     # labels for headings
     (?:@[\w%-](?:\.[\w|%-]+)?)?
    )/x
  • METHOD_ARGS_REGEXP_STR =

    Regular expression to match method arguments.

    # File 'lib/rdoc/cross_reference.rb', line 26
    /(?:\((?:#{METHOD_ARG_REGEXP_STR}(?:,\s*#{METHOD_ARG_REGEXP_STR})*)?\))?/.source
  • METHOD_ARG_REGEXP_STR =

    Regular expression to match a single method argument.

    # File 'lib/rdoc/cross_reference.rb', line 21
    '[\w.*/=<>-]'
  • METHOD_REGEXP_STR =

    Regular expression to match method references.

    See CLASS_REGEXP_STR

    # File 'lib/rdoc/cross_reference.rb', line 33
    /(
      (?!\d)[\w]+[!?=]?|
      %|=(?:==?|~)|![=~]|\[\]=?|<(?:<|=>?)?|>[>=]?|[-+!]@?|\*\*?|[\/%\`|&^~]
    )#{METHOD_ARGS_REGEXP_STR}/.source.delete("\n ").freeze

Class Method Summary

Instance Attribute Summary

  • #seen rw

    Hash of references that have been looked-up to their replacements.

Instance Method Summary

Constructor Details

.new(context) ⇒ CrossReference

Allows cross-references to be created based on the given context (RDoc::Context).

[ GitHub ]

  
# File 'lib/rdoc/cross_reference.rb', line 125

def initialize(context)
  @context = context
  @store   = context.store

  @seen = {}
end

Instance Attribute Details

#seen (rw)

Hash of references that have been looked-up to their replacements

[ GitHub ]

  
# File 'lib/rdoc/cross_reference.rb', line 119

attr_accessor :seen

Instance Method Details

#resolve(name)

Returns a reference to name.

If the reference is found and name is not documented nil will be returned. If name is not found nil is returned.

[ GitHub ]

  
# File 'lib/rdoc/cross_reference.rb', line 196

def resolve(name)
  return @seen[name] if @seen.include? name

  ref = @context.find_symbol name

  ref = resolve_local_symbol name unless ref

  # Try a page name
  ref = @store.page name if not ref and name =~ /^[\w.\/]+$/

  ref = nil if RDoc::Alias === ref # external alias, can't link to it

  ref = nil unless ref&.display?

  @seen[name] = ref

  ref
end

#resolve_local_symbol(name)

Returns a method, attribute or constant reference to name if it exists in the containing context object. It returns nil otherwise.

For example, this method would decompose name = 'A::CONSTANT' into a container object A and a symbol 'CONSTANT', and it would try to find 'CONSTANT' in A.

[ GitHub ]

  
# File 'lib/rdoc/cross_reference.rb', line 141

def resolve_local_symbol(name)
  ref = nil
  type = nil
  container = nil

  case name
  when /#{CLASS_REGEXP_STR}::([A-Z]\w*)\z/o then
    symbol = $2
    container = @context.find_symbol_module($1)
  when /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o then
    type = $2
    if '.' == type # will find either #method or ::method
      symbol = $3
    else
      symbol = "#{type}#{$3}"
    end
    container = @context.find_symbol_module($1)
  when /^([.#]|::)#{METHOD_REGEXP_STR}/o then
    type = $1
    if '.' == type
      symbol = $2
    else
      symbol = "#{type}#{$2}"
    end
    container = @context
  end

  if container then
    unless RDoc::TopLevel === container then
      if '.' == type then
        if 'new' == symbol then # AnyClassName.new will be class method
          ref = container.find_local_symbol symbol
          ref = container.find_ancestor_local_symbol symbol unless ref
        else
          ref = container.find_local_symbol "::#{symbol}"
          ref = container.find_ancestor_local_symbol "::#{symbol}" unless ref
          ref = container.find_local_symbol "##{symbol}" unless ref
          ref = container.find_ancestor_local_symbol "##{symbol}" unless ref
        end
      else
        ref = container.find_local_symbol symbol
        ref = container.find_ancestor_local_symbol symbol unless ref
      end
    end
  end

  ref
end