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 =
# File 'lib/rdoc/cross_reference.rb', line 94
Version of CROSSREF_REGEXP used when
--hyperlink-allis specified./ (?:^|[\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 =
# File 'lib/rdoc/cross_reference.rb', line 18
Regular expression to match class references
-
There can be a ‘\’ in front of text to suppress the cross-reference
-
There can be a ‘::’ in front of class names to reference from the top-level namespace.
-
The method can be followed by parenthesis (not recommended)
'\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' -
-
CROSSREF_REGEXP =
# File 'lib/rdoc/cross_reference.rb', line 47
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.
/(?:^|[\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 =
# File 'lib/rdoc/cross_reference.rb', line 28
Regular expression to match method arguments.
/(?:\((?:#{METHOD_ARG_REGEXP_STR}(?:,\s*#{METHOD_ARG_REGEXP_STR})*)?\))?/.source
-
METHOD_ARG_REGEXP_STR =
# File 'lib/rdoc/cross_reference.rb', line 23
Regular expression to match a single method argument.
'[\w.*/=<>-]' -
METHOD_REGEXP_STR =
# File 'lib/rdoc/cross_reference.rb', line 35
Regular expression to match method references.
See CLASS_REGEXP_STR
/( (?!\d)[\w#{RDoc::Markup::AttributeManager::PROTECT_ATTR}]+[!?=]?| %|=(?:==?|~)|![=~]|\[\]=?|<(?:<|=>?)?|>[>=]?|[-+!]@?|\*\*?|[\/%\`|&^~] )#{METHOD_ARGS_REGEXP_STR}/.source.delete("\n ").freeze
Class Method Summary
-
.new(context) ⇒ CrossReference
constructor
Allows cross-references to be created based on the given
context(RDoc::Context).
Instance Attribute Summary
-
#seen
rw
Hash of references that have been looked-up to their replacements.
Instance Method Summary
-
#resolve(name, text)
Returns a reference to
name. -
#resolve_local_symbol(name)
Returns a method, attribute or constant reference to
nameif it exists in the containing context object.
Constructor Details
.new(context) ⇒ CrossReference
Allows cross-references to be created based on the given context (RDoc::Context).
# File 'lib/rdoc/cross_reference.rb', line 127
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
# File 'lib/rdoc/cross_reference.rb', line 121
attr_accessor :seen
Instance Method Details
#resolve(name, text)
Returns a reference to name.
If the reference is found and name is not documented text will be returned. If name is escaped name is returned. If name is not found text is returned.
# File 'lib/rdoc/cross_reference.rb', line 199
def resolve(name, text) return @seen[name] if @seen.include? name ref = case name when /^\\(#{CLASS_REGEXP_STR})$/o then @context.find_symbol $1 else @context.find_symbol name end 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 out = if name == '\\' then name elsif name =~ /^\\/ then # we remove the \ only in front of what we know: # other backslashes are treated later, only outside of <tt> ref ? $' : name elsif ref then if ref.display? then ref else text end else text end @seen[name] = out out 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.
# File 'lib/rdoc/cross_reference.rb', line 143
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