Class: RDoc::RI::Store
- Inherits:
-
Object
- Object
- RDoc::RI::Store
- Defined in:
- lib/rdoc/ri/store.rb
Overview
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
}
-- TODO need to store the list of files and prune classes
Instance Attribute Summary collapse
-
#cache ⇒ Object
readonly
The contents of the Store.
-
#dry_run ⇒ Object
If true this Store will not write any files.
-
#encoding ⇒ Object
The encoding of the contents in the Store.
-
#path ⇒ Object
Path this store reads or writes.
-
#type ⇒ Object
Type of ri datastore this was loaded from.
Instance Method Summary collapse
-
#ancestors ⇒ Object
Ancestors cache accessor.
-
#attributes ⇒ Object
Attributes cache accessor.
-
#cache_path ⇒ Object
Path to the cache file.
-
#class_file(klass_name) ⇒ Object
Path to the ri data for
klass_name
. -
#class_methods ⇒ Object
Class methods cache accessor.
-
#class_path(klass_name) ⇒ Object
Path where data for
klass_name
will be stored (methods or class data). -
#clean_cache_collection(collection) ⇒ Object
Removes empty items and ensures item in each collection are unique and sorted.
-
#friendly_path ⇒ Object
Friendly rendition of #path.
-
#initialize(path, type = nil) ⇒ Store
constructor
Creates a new Store of
type
that will load or save topath
. -
#inspect ⇒ Object
:nodoc:.
-
#instance_methods ⇒ Object
Instance methods cache accessor.
-
#load_cache ⇒ Object
Loads cache file for this store.
-
#load_class(klass_name) ⇒ Object
Loads ri data for
klass_name
. -
#load_method(klass_name, method_name) ⇒ Object
Loads ri data for
method_name
inklass_name
. -
#method_file(klass_name, method_name) ⇒ Object
Path to the ri data for
method_name
inklass_name
. -
#modules ⇒ Object
Modules cache accessor.
-
#save_cache ⇒ Object
Writes the cache file for this store.
-
#save_class(klass) ⇒ Object
Writes the ri data for
klass
. -
#save_method(klass, method) ⇒ Object
Writes the ri data for
method
onklass
.
Constructor Details
#initialize(path, type = nil) ⇒ Store
Creates a new Store of type
that will load or save to path
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/rdoc/ri/store.rb', line 56 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 |
Instance Attribute Details
#cache ⇒ Object (readonly)
The contents of the Store
46 47 48 |
# File 'lib/rdoc/ri/store.rb', line 46 def cache @cache end |
#dry_run ⇒ Object
If true this Store will not write any files
30 31 32 |
# File 'lib/rdoc/ri/store.rb', line 30 def dry_run @dry_run end |
#encoding ⇒ Object
The encoding of the contents in the Store
51 52 53 |
# File 'lib/rdoc/ri/store.rb', line 51 def encoding @encoding end |
#path ⇒ Object
Path this store reads or writes
35 36 37 |
# File 'lib/rdoc/ri/store.rb', line 35 def path @path end |
#type ⇒ Object
Type of ri datastore this was loaded from. See RDoc::RI::Driver, RDoc::RI::Paths.
41 42 43 |
# File 'lib/rdoc/ri/store.rb', line 41 def type @type end |
Instance Method Details
#ancestors ⇒ Object
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).
77 78 79 |
# File 'lib/rdoc/ri/store.rb', line 77 def ancestors @cache[:ancestors] end |
#attributes ⇒ Object
Attributes cache accessor. Maps a class to an Array of its attributes.
84 85 86 |
# File 'lib/rdoc/ri/store.rb', line 84 def attributes @cache[:attributes] end |
#cache_path ⇒ Object
Path to the cache file
91 92 93 |
# File 'lib/rdoc/ri/store.rb', line 91 def cache_path File.join @path, 'cache.ri' end |
#class_file(klass_name) ⇒ Object
Path to the ri data for klass_name
98 99 100 101 |
# File 'lib/rdoc/ri/store.rb', line 98 def class_file klass_name name = klass_name.split('::').last File.join class_path(klass_name), "cdesc-#{name}.ri" end |
#class_methods ⇒ Object
Class methods cache accessor. Maps a class to an Array of its class methods (not full name).
107 108 109 |
# File 'lib/rdoc/ri/store.rb', line 107 def class_methods @cache[:class_methods] end |
#class_path(klass_name) ⇒ Object
Path where data for klass_name
will be stored (methods or class data)
114 115 116 |
# File 'lib/rdoc/ri/store.rb', line 114 def class_path klass_name File.join @path, *klass_name.split('::') end |
#clean_cache_collection(collection) ⇒ Object
Removes empty items and ensures item in each collection are unique and sorted
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/rdoc/ri/store.rb', line 122 def clean_cache_collection collection # :nodoc: collection.each do |name, item| if item.empty? then collection.delete name else # HACK mongrel-1.1.5 documents its files twice item.uniq! item.sort! end end end |
#friendly_path ⇒ Object
Friendly rendition of #path
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rdoc/ri/store.rb', line 137 def friendly_path case type when :gem then sep = Regexp.union(*['/', File::ALT_SEPARATOR].compact) @path =~ /#{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 |
#inspect ⇒ Object
:nodoc:
150 151 152 |
# File 'lib/rdoc/ri/store.rb', line 150 def inspect # :nodoc: "#<%s:0x%x %s %p>" % [self.class, object_id, @path, modules.sort] end |
#instance_methods ⇒ Object
Instance methods cache accessor. Maps a class to an Array of its instance methods (not full name).
158 159 160 |
# File 'lib/rdoc/ri/store.rb', line 158 def instance_methods @cache[:instance_methods] end |
#load_cache ⇒ Object
Loads cache file for this store
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/rdoc/ri/store.rb', line 165 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 |
#load_class(klass_name) ⇒ Object
Loads ri data for klass_name
195 196 197 198 199 |
# File 'lib/rdoc/ri/store.rb', line 195 def load_class klass_name open class_file(klass_name), 'rb' do |io| Marshal.load io.read end end |
#load_method(klass_name, method_name) ⇒ Object
Loads ri data for method_name
in klass_name
204 205 206 207 208 |
# File 'lib/rdoc/ri/store.rb', line 204 def load_method klass_name, method_name open method_file(klass_name, method_name), 'rb' do |io| Marshal.load io.read end end |
#method_file(klass_name, method_name) ⇒ Object
Path to the ri data for method_name
in klass_name
213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/rdoc/ri/store.rb', line 213 def method_file klass_name, method_name method_name = method_name.split('::').last method_name =~ /#(.*)/ method_type = $1 ? 'i' : 'c' method_name = $1 if $1 method_name = if ''.respond_to? :ord then method_name.gsub(/\W/) { "%%%02x" % $&[0].ord } else method_name.gsub(/\W/) { "%%%02x" % $&[0] } end File.join class_path(klass_name), "#{method_name}-#{method_type}.ri" end |
#modules ⇒ Object
Modules cache accessor. An Array of all the modules (and classes) in the store.
232 233 234 |
# File 'lib/rdoc/ri/store.rb', line 232 def modules @cache[:modules] end |
#save_cache ⇒ Object
Writes the cache file for this store
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/rdoc/ri/store.rb', line 239 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 |
#save_class(klass) ⇒ Object
Writes the ri data for klass
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/rdoc/ri/store.rb', line 261 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].push(*ancestors) attributes = klass.attributes.map do |attribute| "#{attribute.definition} #{attribute.name}" end unless attributes.empty? then @cache[:attributes][full_name] ||= [] @cache[:attributes][full_name].push(*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 |
#save_method(klass, method) ⇒ Object
Writes the ri data for method
on klass
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
# File 'lib/rdoc/ri/store.rb', line 335 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 |