A Context is something that can hold modules, classes, methods, attributes, aliases, requires, and includes. Classes, modules, and files are all Contexts.
Creates an unnamed empty context with public current visibility
# File lib/rdoc/context.rb, line 104
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
Contexts are sorted by #full_name
# File lib/rdoc/context.rb, line 146
def <=>(other)
full_name <=> other.full_name
end
Adds an_alias
that is automatically resolved
# File lib/rdoc/context.rb, line 153
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,
attr_reader :foo
will not be registered if method
foo
exists, but attr_accessor :foo
will be
registered if method foo
exists, but foo=
does
not.
# File lib/rdoc/context.rb, line 180
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 class Container::Item
RDoc
assumes Container
is a module unless it later sees class
Container
. add_class
automatically upgrades
given_name
to a class in this case.
# File lib/rdoc/context.rb, line 243
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 =~ %r^:+(\w+)$/ then
full_name = $1
enclosing = top_level
name = full_name.split(%r:+/).last
else
full_name = child_name given_name
if full_name =~ %r^(.+)::(\w+)$/ then
name = $2
ename = $1
enclosing = RDoc::TopLevel.classes_hash[ename] ||
RDoc::TopLevel.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 = RDoc::TopLevel.classes_hash[given_name] || RDoc::TopLevel.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
superclass = nil if full_name == 'BasicObject'
superclass = nil if full_name == 'Object' and defined?(::BasicObject)
superclass = '::BasicObject' if
defined?(::BasicObject) and full_name == 'Object'
# find the superclass full name
if superclass then
if superclass =~ %r^:+/ then
superclass = $' #'
else
if superclass =~ %r^(\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 = RDoc::TopLevel.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 = RDoc::TopLevel.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 = RDoc::TopLevel.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,
RDoc::TopLevel.classes_hash)
end
end
klass
end
Adds the class or module mod
to the modules or classes Hash
self_hash
, and to all_hash
(either
TopLevel::modules_hash
or
TopLevel::classes_hash
), unless done_documenting is
true
. Sets the parent of mod
to
self
, and its section to current_section. Returns
mod
.
# File lib/rdoc/context.rb, line 356
def add_class_or_module mod, self_hash, all_hash
mod.section = current_section # TODO declaring context? something is
# wrong here...
mod.parent = self
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
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.
# File lib/rdoc/context.rb, line 375
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
# File lib/rdoc/context.rb, line 400
def add_include include
add_to @includes, include
include
end
Adds method
if not already there. If it is (as method or
attribute), updates the comment if it was empty.
# File lib/rdoc/context.rb, line 410
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
known.comment = method.comment if known.comment.empty?
else
@methods_hash[key] = method
method.visibility = @visibility
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.
# File lib/rdoc/context.rb, line 433
def add_module(class_type, name)
mod = @classes[name] || @modules[name]
return mod if mod
full_name = child_name name
mod = RDoc::TopLevel.modules_hash[full_name] || class_type.new(name)
add_class_or_module(mod, @modules, RDoc::TopLevel.modules_hash)
end
Adds an alias from from
(a class or module) to
name
which was defined in file
.
# File lib/rdoc/context.rb, line 447
def add_module_alias from, name, file
return from if @done_documenting
to_name = child_name(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 as a class when we find
# BasicObject = BlankSlate
return from if RDoc::TopLevel.find_class_or_module(to_name)
if from.module? then
RDoc::TopLevel.modules_hash[to_name] = from
@modules[name] = from
else
RDoc::TopLevel.classes_hash[to_name] = from
@classes[name] = from
end
# HACK: register a constant for this alias:
# constant value and comment will be updated after,
# when the Ruby parser adds the constant
const = RDoc::Constant.new name, nil, ''
const.record_location file
const.is_alias_for = from
add_constant const
from
end
Adds require
to this context’s top level
# File lib/rdoc/context.rb, line 480
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
# File lib/rdoc/context.rb, line 498
def add_section title, comment = nil
if section = @sections[title] then
section.comment = comment if comment
else
section = Section.new self, title, comment
@sections[title] = section
end
section
end
Adds thing
to the collection array
# File lib/rdoc/context.rb, line 512
def add_to(array, thing)
array << thing if @document_self
thing.parent = self
thing.section = current_section
end
Is there any content?
This means any of: comment, aliases, methods, attributes, external aliases, require, constant.
Includes are also checked unless includes == false
.
# File lib/rdoc/context.rb, line 526
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.empty?)
end
Creates the full name for a child with name
# File lib/rdoc/context.rb, line 542
def child_name name
if name =~ %r^:+/
$' #'
elsif RDoc::TopLevel === self then
name
else
"#{self.full_name}::#{name}"
end
end
Class attributes
# File lib/rdoc/context.rb, line 555
def class_attributes
@class_attributes ||= attributes.select { |a| a.singleton }
end
Class methods
# File lib/rdoc/context.rb, line 562
def class_method_list
@class_method_list ||= method_list.select { |a| a.singleton }
end
Array of classes in this context
# File lib/rdoc/context.rb, line 569
def classes
@classes.values
end
All classes and modules in this namespace
# File lib/rdoc/context.rb, line 576
def classes_and_modules
classes + modules
end
Hash of classes keyed by class name
# File lib/rdoc/context.rb, line 583
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.
# File lib/rdoc/context.rb, line 591
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
?
# File lib/rdoc/context.rb, line 604
def defined_in?(file)
@in_files.include?(file)
end
Iterator for attributes
# File lib/rdoc/context.rb, line 626
def each_attribute # :yields: attribute
@attributes.each { |a| yield a }
end
Iterator for classes and modules
# File lib/rdoc/context.rb, line 633
def each_classmodule(&block) # :yields: module
classes_and_modules.sort.each(&block)
end
Iterator for constants
# File lib/rdoc/context.rb, line 640
def each_constant # :yields: constant
@constants.each {|c| yield c}
end
Iterator for included modules
# File lib/rdoc/context.rb, line 647
def each_include # :yields: include
@includes.each do |i| yield i end
end
Iterator for methods
# File lib/rdoc/context.rb, line 654
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
# File lib/rdoc/context.rb, line 670
def each_section # :yields: section, constants, attributes
return enum_for __method__ unless block_given?
constants = @constants.group_by do |constant| constant.section end
constants.default = []
attributes = @attributes.group_by do |attribute| attribute.section end
attributes.default = []
sort_sections.each do |section|
yield section, constants[section].sort, attributes[section].sort
end
end
Finds an attribute name
with singleton value
singleton
.
# File lib/rdoc/context.rb, line 687
def find_attribute(name, singleton)
name = $1 if name =~ %r^(.*)=$/
@attributes.find { |a| a.name == name && a.singleton == singleton }
end
Finds an attribute with name
in this context
# File lib/rdoc/context.rb, line 695
def find_attribute_named(name)
case name
when %r\A#/ then
find_attribute name[1..-1], false
when %r\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
# File lib/rdoc/context.rb, line 709
def find_class_method_named(name)
@method_list.find { |meth| meth.singleton && meth.name == name }
end
Finds a constant with name
in this context
# File lib/rdoc/context.rb, line 716
def find_constant_named(name)
@constants.find {|m| m.name == name}
end
Find a module at a higher scope
# File lib/rdoc/context.rb, line 723
def find_enclosing_module_named(name)
parent && parent.find_module_named(name)
end
Finds an external alias name
with singleton value
singleton
.
# File lib/rdoc/context.rb, line 730
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
# File lib/rdoc/context.rb, line 737
def find_external_alias_named(name)
case name
when %r\A#/ then
find_external_alias name[1..-1], false
when %r\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
# File lib/rdoc/context.rb, line 751
def find_file_named(name)
top_level.class.find_file_named(name)
end
Finds an instance method with name
in this context
# File lib/rdoc/context.rb, line 758
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.
# File lib/rdoc/context.rb, line 766
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
.
# File lib/rdoc/context.rb, line 778
def find_method(name, singleton)
@method_list.find { |m| m.name == name && m.singleton == singleton }
end
Finds a instance or module method with name
in this context
# File lib/rdoc/context.rb, line 785
def find_method_named(name)
case name
when %r\A#/ then
find_method name[1..-1], false
when %r\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
# File lib/rdoc/context.rb, line 799
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.
# File lib/rdoc/context.rb, line 809
def find_symbol(symbol)
find_symbol_module(symbol) || find_local_symbol(symbol)
end
Look up a module named symbol
.
# File lib/rdoc/context.rb, line 816
def find_symbol_module(symbol)
result = nil
# look for a class or module 'symbol'
case symbol
when %r^::/ then
result = RDoc::TopLevel.find_class_or_module(symbol)
when %r^(\w+):+(.+)$/
suffix = $2
top = $1
searched = self
loop do
mod = searched.find_module_named(top)
break unless mod
result = RDoc::TopLevel.find_class_or_module(mod.full_name + '::' + suffix)
break if result || searched.is_a?(RDoc::TopLevel)
searched = searched.parent
end
else
searched = self
loop 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.
# File lib/rdoc/context.rb, line 849
def full_name
'(unknown)'
end
Does this context and its methods and constants all have documentation?
(Yes, fully documented doesn’t mean everything.)
# File lib/rdoc/context.rb, line 858
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
# File lib/rdoc/context.rb, line 868
def http_url(prefix)
path = name_for_path
path = path.gsub(%r<<\s*(\w*)/, 'from-\1') if path =~ %r<</
path = [prefix] + path.split('::')
File.join(*path.compact) + '.html'
end
Sets the defaults for methods and so-forth
# File lib/rdoc/context.rb, line 126
def initialize_methods_etc
@method_list = []
@attributes = []
@aliases = []
@requires = []
@includes = []
@constants = []
@external_aliases = []
# 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 = {}
end
Instance attributes
# File lib/rdoc/context.rb, line 879
def instance_attributes
@instance_attributes ||= attributes.reject { |a| a.singleton }
end
Instance methods
# File lib/rdoc/context.rb, line 888
def instance_method_list
@instance_method_list ||= method_list.reject { |a| a.singleton }
end
Breaks #method_list into
a nested hash by type ('class'
or 'instance'
) and
visibility (:public
, :protected
,
:private
).
If section
is provided only methods in that RDoc::Context::Section will be returned.
# File lib/rdoc/context.rb, line 899
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
.
# File lib/rdoc/context.rb, line 922
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
# File lib/rdoc/context.rb, line 935
def modules
@modules.values
end
Hash of modules keyed by module name
# File lib/rdoc/context.rb, line 942
def modules_hash
@modules
end
Name to use to generate the url. #full_name
by default.
# File lib/rdoc/context.rb, line 950
def name_for_path
full_name
end
Changes the visibility for new methods to visibility
# File lib/rdoc/context.rb, line 957
def ongoing_visibility=(visibility)
@visibility = visibility
end
Record top_level
as a file self
is in.
# File lib/rdoc/context.rb, line 964
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 #remove_from_documentation? ==
true
All classes and modules have #remove_from_documentation? ==
true
# File lib/rdoc/context.rb, line 978
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
.
# File lib/rdoc/context.rb, line 991
def remove_invisible(min_visibility)
return if min_visibility == :private
remove_invisible_in @method_list, min_visibility
remove_invisible_in @attributes, min_visibility
end
Tries to resolve unmatched aliases when a method or attribute has just been added.
# File lib/rdoc/context.rb, line 1016
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.
# File lib/rdoc/context.rb, line 1032
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
# File lib/rdoc/context.rb, line 1056
def sections
@sections.values
end
Sets the current section to a section with title
. See also add_section
# File lib/rdoc/context.rb, line 1067
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
# File lib/rdoc/context.rb, line 1075
def set_visibility_for(methods, visibility, singleton = false)
methods_matching methods, singleton do |m|
m.visibility = visibility
end
end
Sorts sections alphabetically (default) or in TomDoc fasion (none, Public, Internal, Deprecated)
# File lib/rdoc/context.rb, line 1085
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
Return the TopLevel that owns us
# File lib/rdoc/context.rb, line 1111
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
# File lib/rdoc/context.rb, line 1121
def upgrade_to_class mod, class_type, enclosing
enclosing.modules_hash.delete mod.name
klass = RDoc::ClassModule.from_module class_type, mod
# if it was there, then we keep it even if done_documenting
RDoc::TopLevel.classes_hash[mod.full_name] = klass
enclosing.classes_hash[mod.name] = klass
klass
end
/ | Search |
---|---|
? | Show this help |