A set of ri data.
The store manages reading and writing ri data for a project (gem, path, etc.) and maintains a cache of methods, classes and ancestors in the store.
The store maintains a cache of its contents for faster lookup. After adding items to the store it must be flushed using save_cache. The cache contains the following structures:
@cache = { :class_methods => {}, # class name => class methods :instance_methods => {}, # class name => instance methods :attributes => {}, # class name => attributes :modules => [], # classes and modules in this store :ancestors => {}, # class name => ancestor names }
The contents of the Store
If true this Store will not write any files
The encoding of the contents in the Store
Path this store reads or writes
Type of ri datastore this was loaded from. See RDoc::RI::Driver, RDoc::RI::Paths.
Creates a new Store of type
that will
load or save to path
# File lib/rdoc/ri/store.rb, line 55
def initialize path, type = nil
@dry_run = false
@type = type
@path = path
@encoding = nil
@cache = {
:ancestors => {},
:attributes => {},
:class_methods => {},
:encoding => @encoding,
:instance_methods => {},
:modules => [],
}
end
Ancestors cache accessor. Maps a klass name to an Array of its ancestors in this store. If Foo in this store inherits from Object, Kernel won’t be listed (it will be included from ruby’s ri store).
# File lib/rdoc/ri/store.rb, line 76
def ancestors
@cache[:ancestors]
end
Attributes cache accessor. Maps a class to an Array of its attributes.
# File lib/rdoc/ri/store.rb, line 83
def attributes
@cache[:attributes]
end
Path to the cache file
# File lib/rdoc/ri/store.rb, line 90
def cache_path
File.join @path, 'cache.ri'
end
Path to the ri data for klass_name
# File lib/rdoc/ri/store.rb, line 97
def class_file klass_name
name = klass_name.split('::').last
File.join class_path(klass_name), "cdesc-#{name}.ri"
end
Class methods cache accessor. Maps a class to an Array of its class methods (not full name).
# File lib/rdoc/ri/store.rb, line 106
def class_methods
@cache[:class_methods]
end
Path where data for klass_name
will be stored (methods or
class data)
# File lib/rdoc/ri/store.rb, line 113
def class_path klass_name
File.join @path, *klass_name.split('::')
end
Friendly rendition of path
# File lib/rdoc/ri/store.rb, line 136
def friendly_path
case type
when :gem then
sep = Regexp.union(*['/', File::ALT_SEPARATOR].compact)
@path =~ %r#{sep}doc#{sep}(.*?)#{sep}ri$/
"gem #{$1}"
when :home then '~/.ri'
when :site then 'ruby site'
when :system then 'ruby core'
else @path
end
end
Instance methods cache accessor. Maps a class to an Array of its instance methods (not full name).
# File lib/rdoc/ri/store.rb, line 157
def instance_methods
@cache[:instance_methods]
end
Loads cache file for this store
# File lib/rdoc/ri/store.rb, line 164
def load_cache
#orig_enc = @encoding
open cache_path, 'rb' do |io|
@cache = Marshal.load io.read
end
load_enc = @cache[:encoding]
# TODO this feature will be time-consuming to add:
# a) Encodings may be incompatible but transcodeable
# b) Need to warn in the appropriate spots, wherever they may be
# c) Need to handle cross-cache differences in encodings
# d) Need to warn when generating into a cache with diffent encodings
#
#if orig_enc and load_enc != orig_enc then
# warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
# "from #{path}/cache.ri" unless
# Encoding.compatible? orig_enc, load_enc
#end
@encoding = load_enc unless @encoding
@cache
rescue Errno::ENOENT
end
Loads ri data for klass_name
# File lib/rdoc/ri/store.rb, line 194
def load_class klass_name
open class_file(klass_name), 'rb' do |io|
Marshal.load io.read
end
end
Loads ri data for method_name
in klass_name
# File lib/rdoc/ri/store.rb, line 203
def load_method klass_name, method_name
open method_file(klass_name, method_name), 'rb' do |io|
Marshal.load io.read
end
end
Path to the ri data for method_name
in klass_name
# File lib/rdoc/ri/store.rb, line 212
def method_file klass_name, method_name
method_name = method_name.split('::').last
method_name =~ %r#(.*)/
method_type = $1 ? 'i' : 'c'
method_name = $1 if $1
method_name = if ''.respond_to? :ord then
method_name.gsub(%r\W/) { "%%%02x" % $&[0].ord }
else
method_name.gsub(%r\W/) { "%%%02x" % $&[0] }
end
File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
end
Modules cache accessor. An Array of all the modules (and classes) in the store.
# File lib/rdoc/ri/store.rb, line 231
def modules
@cache[:modules]
end
Writes the cache file for this store
# File lib/rdoc/ri/store.rb, line 238
def save_cache
clean_cache_collection @cache[:ancestors]
clean_cache_collection @cache[:attributes]
clean_cache_collection @cache[:class_methods]
clean_cache_collection @cache[:instance_methods]
@cache[:modules].uniq!
@cache[:modules].sort!
@cache[:encoding] = @encoding # this gets set twice due to assert_cache
return if @dry_run
marshal = Marshal.dump @cache
open cache_path, 'wb' do |io|
io.write marshal
end
end
Writes the ri data for klass
# File lib/rdoc/ri/store.rb, line 260
def save_class klass
full_name = klass.full_name
FileUtils.mkdir_p class_path(full_name) unless @dry_run
@cache[:modules] << full_name
path = class_file full_name
begin
disk_klass = load_class full_name
klass = disk_klass.merge klass
rescue Errno::ENOENT
end
# BasicObject has no ancestors
ancestors = klass.ancestors.compact.map do |ancestor|
# HACK for classes we don't know about (class X < RuntimeError)
String === ancestor ? ancestor : ancestor.full_name
end
@cache[:ancestors][full_name] ||= []
@cache[:ancestors][full_name].concat ancestors
attributes = klass.attributes.map do |attribute|
"#{attribute.definition} #{attribute.name}"
end
unless attributes.empty? then
@cache[:attributes][full_name] ||= []
@cache[:attributes][full_name].concat attributes
end
to_delete = []
unless klass.method_list.empty? then
@cache[:class_methods][full_name] ||= []
@cache[:instance_methods][full_name] ||= []
class_methods, instance_methods =
klass.method_list.partition { |meth| meth.singleton }
class_methods = class_methods. map { |method| method.name }
instance_methods = instance_methods.map { |method| method.name }
old = @cache[:class_methods][full_name] - class_methods
to_delete.concat old.map { |method|
method_file full_name, "#{full_name}::#{method}"
}
old = @cache[:instance_methods][full_name] - instance_methods
to_delete.concat old.map { |method|
method_file full_name, "#{full_name}##{method}"
}
@cache[:class_methods][full_name] = class_methods
@cache[:instance_methods][full_name] = instance_methods
end
return if @dry_run
FileUtils.rm_f to_delete
marshal = Marshal.dump klass
open path, 'wb' do |io|
io.write marshal
end
end
Writes the ri data for method
on klass
# File lib/rdoc/ri/store.rb, line 334
def save_method klass, method
full_name = klass.full_name
FileUtils.mkdir_p class_path(full_name) unless @dry_run
cache = if method.singleton then
@cache[:class_methods]
else
@cache[:instance_methods]
end
cache[full_name] ||= []
cache[full_name] << method.name
return if @dry_run
marshal = Marshal.dump method
open method_file(full_name, method.full_name), 'wb' do |io|
io.write marshal
end
end
/ | Search |
---|---|
? | Show this help |