Class: FastRI::RiIndex
- Inherits:
-
Object
- Object
- FastRI::RiIndex
- Defined in:
- lib/fastri/ri_index.rb
Overview
This class provides the same functionality as RiReader, with some improvements:
-
lower memory consumption
-
ability to handle information from different sources separately.
Some operations can be restricted to a given “scope”, that is, a “RI DB directory”. This allows you to e.g. look for all the instance methods in String defined by a package.
Such operations take a scope
argument, which is either an integer which indexes the source in #paths, or a name identifying the source (either “system” or a package name). If scope == nil
, the information from all sources is merged.
Defined Under Namespace
Classes: ClassEntry, MethodEntry, TopLevelEntry
Constant Summary collapse
- MAGIC =
"FastRI index #{FASTRI_INDEX_FORMAT}"
Instance Attribute Summary collapse
-
#paths ⇒ Object
readonly
Returns the value of attribute paths.
Class Method Summary collapse
Instance Method Summary collapse
-
#all_names(scope = nil) ⇒ Object
Return a list of all classes, modules, and methods.
-
#dump(anIO) ⇒ Object
Serializes index to the given IO.
-
#find_class_by_name(full_name, scope = nil) ⇒ Object
Returns the ClassDescription associated to the given
full_name
. -
#find_method_by_name(full_name, scope = nil) ⇒ Object
Returns the MethodDescription associated to the given
full_name
. -
#find_methods(name, is_class_method, namespaces) ⇒ Object
Returns an array of MethodEntry objects, corresponding to the methods in the ClassEntry objects in the
namespaces
array. -
#full_class_names(scope = nil) ⇒ Object
Return the names of all classes and modules.
-
#full_method_names(scope = nil) ⇒ Object
Return the names of all methods.
-
#get_class(class_entry) ⇒ Object
Return a ClassDescription for a given ClassEntry.
-
#get_class_entry(full_name, scope = nil) ⇒ Object
Returns the ClassEntry associated to the given
full_name
. -
#get_method(method_entry) ⇒ Object
Return the MethodDescription for a given MethodEntry by deserializing the YAML.
-
#get_method_entry(full_name, scope = nil) ⇒ Object
Returns the MethodEntry associated to the given
full_name
. -
#load(anIO) ⇒ Object
Load the index from the given IO.
-
#lookup_namespace_in(target, namespaces) ⇒ Object
Returns an array of ClassEntry objects whose names match
target
, and which correspond to the namespaces contained innamespaces
. -
#methods_under(class_entry_or_name, recursive, scope = nil) ⇒ Object
Returns array of MethodEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy.
-
#methods_under_matching(class_entry_or_name, regexp, recursive, scope = nil) ⇒ Object
Returns array of MethodEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy whose
full_name
matches the given regexp. -
#namespaces_under(class_entry_or_name, recursive, scope = nil) ⇒ Object
Returns array of ClassEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy.
-
#namespaces_under_matching(class_entry_or_name, regexp, recursive, scope = nil) ⇒ Object
Returns array of ClassEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy whose
full_name
matches the given regexp. -
#num_methods ⇒ Object
Returns the number of methods in the index.
-
#num_namespaces ⇒ Object
Returns the number of namespaces in the index.
- #rebuild_index(paths = nil) ⇒ Object
-
#source_paths_for(entry_or_name) ⇒ Object
Returns array of Strings corresponding to the base directories of all the sources fo the given entry_or_name.
-
#top_level_namespace(scope = nil) ⇒ Object
Returns an array with the top level namespace.
Instance Attribute Details
#paths ⇒ Object (readonly)
Returns the value of attribute paths.
199 200 201 |
# File 'lib/fastri/ri_index.rb', line 199 def paths @paths end |
Class Method Details
.new_from_IO(anIO) ⇒ Object
209 210 211 212 213 |
# File 'lib/fastri/ri_index.rb', line 209 def self.new_from_IO(anIO) obj = new obj.load(anIO) obj end |
.new_from_paths(paths = nil) ⇒ Object
203 204 205 206 207 |
# File 'lib/fastri/ri_index.rb', line 203 def self.new_from_paths(paths = nil) obj = new obj.rebuild_index(paths) obj end |
Instance Method Details
#all_names(scope = nil) ⇒ Object
Return a list of all classes, modules, and methods.
375 376 377 |
# File 'lib/fastri/ri_index.rb', line 375 def all_names(scope = nil) full_class_names(scope).concat(full_method_names(scope)) end |
#dump(anIO) ⇒ Object
Serializes index to the given IO.
287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/fastri/ri_index.rb', line 287 def dump(anIO) anIO.puts MAGIC anIO.puts "Sources:" @paths.zip(@gem_names).each{|p,g| anIO.puts "%-30s %s" % [g, p]} anIO.puts "=" * 80 anIO.puts "Namespaces:" anIO.puts @namespace_array anIO.puts "=" * 80 anIO.puts "Methods:" anIO.puts @method_array anIO.puts "=" * 80 end |
#find_class_by_name(full_name, scope = nil) ⇒ Object
Returns the ClassDescription associated to the given full_name
.
318 319 320 321 322 |
# File 'lib/fastri/ri_index.rb', line 318 def find_class_by_name(full_name, scope = nil) entry = get_entry(@namespace_array, full_name, ClassEntry, scope) return nil unless entry && entry.full_name == full_name get_class(entry) end |
#find_method_by_name(full_name, scope = nil) ⇒ Object
Returns the MethodDescription associated to the given full_name
. Only the first definition is returned when scope = nil
.
326 327 328 329 330 |
# File 'lib/fastri/ri_index.rb', line 326 def find_method_by_name(full_name, scope = nil) entry = get_entry(@method_array, full_name, MethodEntry, scope) return nil unless entry && entry.full_name == full_name get_method(entry) end |
#find_methods(name, is_class_method, namespaces) ⇒ Object
Returns an array of MethodEntry objects, corresponding to the methods in the ClassEntry objects in the namespaces
array.
334 335 336 337 338 339 340 |
# File 'lib/fastri/ri_index.rb', line 334 def find_methods(name, is_class_method, namespaces) result = [] namespaces.each do |ns| result.concat ns.methods_matching(name, is_class_method) end result end |
#full_class_names(scope = nil) ⇒ Object
Return the names of all classes and modules.
365 366 367 |
# File 'lib/fastri/ri_index.rb', line 365 def full_class_names(scope = nil) all_entries(@namespace_array, scope) end |
#full_method_names(scope = nil) ⇒ Object
Return the names of all methods.
370 371 372 |
# File 'lib/fastri/ri_index.rb', line 370 def full_method_names(scope = nil) all_entries(@method_array, scope) end |
#get_class(class_entry) ⇒ Object
Return a ClassDescription for a given ClassEntry.
350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/fastri/ri_index.rb', line 350 def get_class(class_entry) result = nil for path in class_entry.path_names path = RI::RiWriter.class_desc_path(path, class_entry) desc = File.open(path) {|f| RI::Description.deserialize(f) } if result result.merge_in(desc) else result = desc end end result end |
#get_class_entry(full_name, scope = nil) ⇒ Object
Returns the ClassEntry associated to the given full_name
.
392 393 394 395 396 |
# File 'lib/fastri/ri_index.rb', line 392 def get_class_entry(full_name, scope = nil) entry = get_entry(@namespace_array, full_name, ClassEntry, scope) return nil unless entry && entry.full_name == full_name entry end |
#get_method(method_entry) ⇒ Object
Return the MethodDescription for a given MethodEntry by deserializing the YAML.
344 345 346 347 |
# File 'lib/fastri/ri_index.rb', line 344 def get_method(method_entry) path = method_entry.path_name File.open(path) { |f| RI::Description.deserialize(f) } end |
#get_method_entry(full_name, scope = nil) ⇒ Object
Returns the MethodEntry associated to the given full_name
.
399 400 401 402 403 |
# File 'lib/fastri/ri_index.rb', line 399 def get_method_entry(full_name, scope = nil) entry = get_entry(@method_array, full_name, MethodEntry, scope) return nil unless entry && entry.full_name == full_name entry end |
#load(anIO) ⇒ Object
Load the index from the given IO. It must contain a textual representation generated by #dump.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/fastri/ri_index.rb', line 259 def load(anIO) header = anIO.gets raise "Invalid format." unless header.chomp == MAGIC anIO.gets # discard "Sources:" paths = [] gem_names = [] until (line = anIO.gets).index("=" * 80) == 0 gemname, path = line.strip.split(/\s+/) paths << path gem_names << gemname end anIO.gets # discard "Namespaces:" namespace_array = [] until (line = anIO.gets).index("=" * 80) == 0 namespace_array << line end anIO.gets # discard "Methods:" method_array = [] until (line = anIO.gets).index("=" * 80) == 0 method_array << line end @paths = paths @gem_names = gem_names @namespace_array = namespace_array @method_array = method_array end |
#lookup_namespace_in(target, namespaces) ⇒ Object
Returns an array of ClassEntry objects whose names match target
, and which correspond to the namespaces contained in namespaces
. namespaces
is an array of ClassEntry objects.
309 310 311 312 313 314 315 |
# File 'lib/fastri/ri_index.rb', line 309 def lookup_namespace_in(target, namespaces) result = [] namespaces.each do |ns| result.concat(ns.contained_modules_matching(target)) end result end |
#methods_under(class_entry_or_name, recursive, scope = nil) ⇒ Object
Returns array of MethodEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy.
446 447 448 |
# File 'lib/fastri/ri_index.rb', line 446 def methods_under(class_entry_or_name, recursive, scope = nil) methods_under_matching(class_entry_or_name, //, recursive, scope) end |
#methods_under_matching(class_entry_or_name, regexp, recursive, scope = nil) ⇒ Object
Returns array of MethodEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy whose full_name
matches the given regexp.
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/fastri/ri_index.rb', line 453 def methods_under_matching(class_entry_or_name, regexp, recursive, scope = nil) case class_entry_or_name when ClassEntry full_name = class_entry_or_name.full_name else full_name = class_entry_or_name end method_entry = get_entry(@method_array, full_name, MethodEntry) return [] unless method_entry ret = [] re1, re2 = matching_regexps_method(full_name) (method_entry.index...@method_array.size).each do |i| entry = @method_array[i] break unless re1 =~ entry next if !recursive && re2 !~ entry full_name = entry[/\S+/] next unless regexp =~ full_name if scope sources = method_sources(i) if sources.include?(sindex = scope_to_sindex(scope)) ret << MethodEntry.new(self, full_name, i, sindex) end else ret << MethodEntry.new(self, full_name, i, nil) end end ret end |
#namespaces_under(class_entry_or_name, recursive, scope = nil) ⇒ Object
Returns array of ClassEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy.
407 408 409 |
# File 'lib/fastri/ri_index.rb', line 407 def namespaces_under(class_entry_or_name, recursive, scope = nil) namespaces_under_matching(class_entry_or_name, //, recursive, scope) end |
#namespaces_under_matching(class_entry_or_name, regexp, recursive, scope = nil) ⇒ Object
Returns array of ClassEntry objects under class_entry_or_name (either String or ClassEntry) in the hierarchy whose full_name
matches the given regexp.
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/fastri/ri_index.rb', line 414 def namespaces_under_matching(class_entry_or_name, regexp, recursive, scope = nil) case class_entry_or_name when ClassEntry class_entry = class_entry_or_name when "" class_entry = top_level_namespace(scope)[0] else class_entry = get_entry(@namespace_array, class_entry_or_name, ClassEntry, scope) end return [] unless class_entry ret = [] re1, re2 = matching_regexps_namespace(class_entry.full_name) (class_entry.index+1...@namespace_array.size).each do |i| entry = @namespace_array[i] break unless re1 =~ entry next if !recursive && re2 !~ entry full_name = entry[/\S+/] next unless regexp =~ full_name if scope sources = namespace_sources(i) if sources.include?(sindex = scope_to_sindex(scope)) ret << ClassEntry.new(self, full_name, i, sindex) end else ret << ClassEntry.new(self, full_name, i, nil) end end ret end |
#num_methods ⇒ Object
Returns the number of methods in the index.
382 383 384 |
# File 'lib/fastri/ri_index.rb', line 382 def num_methods @method_array.size end |
#num_namespaces ⇒ Object
Returns the number of namespaces in the index.
387 388 389 |
# File 'lib/fastri/ri_index.rb', line 387 def num_namespaces @namespace_array.size end |
#rebuild_index(paths = nil) ⇒ Object
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/fastri/ri_index.rb', line 215 def rebuild_index(paths = nil) @paths = paths || RI::Paths::PATH @gem_names = paths.map do |p| fullp = File.(p) gemname = nil begin require 'rubygems' Gem.path.each do |gempath| re = %r!^#{Regexp.escape(File.(gempath))}/doc/! if re =~ fullp gemname = fullp.gsub(re,"")[%r{^[^/]+}] break end end rescue LoadError # no RubyGems, no gems installed, skip it end gemname ? gemname : "system" end methods = Hash.new{|h,k| h[k] = []} namespaces = methods.clone @paths.each_with_index do |path, source_index| ri_reader = RI::RiReader.new(RI::RiCache.new(path)) obtain_classes(ri_reader.top_level_namespace.first).each{|name| namespaces[name] << source_index } obtain_methods(ri_reader.top_level_namespace.first).each{|name| methods[name] << source_index } end @method_array = methods.sort_by{|h,k| h}.map do |name, sources| "#{name} #{sources.map{|x| x.to_s}.join(' ')}" end @namespace_array = namespaces.sort_by{|h,k| h}.map do |name, sources| "#{name} #{sources.map{|x| x.to_s}.join(' ')}" end =begin puts "@method_array: #{@method_array.size}" puts "@namespace_array: #{@namespace_array.size}" puts @method_array.inject(0){|s,x| s + x.size} puts @namespace_array.inject(0){|s,x| s + x.size} =end end |
#source_paths_for(entry_or_name) ⇒ Object
Returns array of Strings corresponding to the base directories of all the sources fo the given entry_or_name.
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/fastri/ri_index.rb', line 484 def source_paths_for(entry_or_name) case entry_or_name when ClassEntry namespace_sources(entry_or_name.index).map{|i| @paths[i] } when MethodEntry method_sources(entry_or_name.index).map{|i| @paths[i]} when nil [] else case entry_or_name when /[#.]\S+/ method_entry = get_entry(@method_array, entry_or_name, MethodEntry, nil) source_paths_for(method_entry) when "" [] else class_entry = get_entry(@namespace_array, entry_or_name, ClassEntry, nil) source_paths_for(class_entry) end end end |
#top_level_namespace(scope = nil) ⇒ Object
Returns an array with the top level namespace.
302 303 304 |
# File 'lib/fastri/ri_index.rb', line 302 def top_level_namespace(scope = nil) [TopLevelEntry.new(self, "", -1, scope ? scope_to_sindex(scope) : nil)] end |