Class: Solargraph::ApiMap
- Inherits:
-
Object
- Object
- Solargraph::ApiMap
- Includes:
- SourceToYard
- Defined in:
- lib/solargraph/api_map.rb,
lib/solargraph/api_map/cache.rb,
lib/solargraph/api_map/store.rb,
lib/solargraph/api_map/source_to_yard.rb
Overview
An aggregate provider for information about workspaces, sources, gems, and the Ruby core.
Defined Under Namespace
Modules: SourceToYard Classes: Cache, Store
Instance Attribute Summary collapse
-
#live_map ⇒ Solargraph::LiveMap
readonly
Get a LiveMap associated with the current workspace.
- #unresolved_requires ⇒ Array<String> readonly
Class Method Summary collapse
-
.keywords ⇒ Array<Solargraph::Pin::Keyword>
An array of pins based on Ruby keywords (‘if`, `end`, etc.).
-
.load(directory) ⇒ ApiMap
Create an ApiMap with a workspace in the specified directory.
Instance Method Summary collapse
-
#catalog(bundle) ⇒ self
Catalog a bundle.
- #clip(cursor) ⇒ SourceMap::Clip
-
#clip_at(filename, position) ⇒ SourceMap::Clip
Get a clip by filename and position.
- #cursor_at(filename, position) ⇒ Source::Cursor
-
#document(path) ⇒ Array<YARD::CodeObject::Base>
Get YARD documentation for the specified path.
-
#document_symbols(filename) ⇒ Array<Pin::Symbol>
Get an array of document symbols from a file.
-
#get_class_variable_pins(namespace) ⇒ Array<Solargraph::Pin::ClassVariable>
Get an array of class variable pins for a namespace.
-
#get_complex_type_methods(type, context = '', internal = false) ⇒ Array<Solargraph::Pin::Base>
Get an array of public methods for a complex type.
-
#get_constants(namespace, context = '') ⇒ Array<Solargraph::Pin::Base>
Get suggestions for constants in the specified namespace.
- #get_global_variable_pins ⇒ Array<Solargraph::Pin::GlobalVariable>
-
#get_instance_variable_pins(namespace, scope = :instance) ⇒ Array<Solargraph::Pin::InstanceVariable>
Get an array of instance variable pins defined in specified namespace and scope.
-
#get_method_stack(fqns, name, scope: :instance) ⇒ Array<Solargraph::Pin::Base>
Get a stack of method pins for a method name in a namespace.
-
#get_methods(fqns, scope: :instance, visibility: [:public], deep: true) ⇒ Array<Solargraph::Pin::Base>
Get an array of methods available in a particular context.
-
#get_path_pins(path) ⇒ Array<Pin::Base>
Get an array of pins that match the specified path.
-
#get_path_suggestions(path) ⇒ Array<Solargraph::Pin::Base>
deprecated
Deprecated.
Use #get_path_pins instead.
- #get_symbols ⇒ Array<Solargraph::Pin::Base>
- #index(pins) ⇒ self
-
#initialize(pins: []) ⇒ ApiMap
constructor
A new instance of ApiMap.
- #locate_pin(location) ⇒ Solargraph::Pin::Base
-
#map(source) ⇒ self
Map a single source.
- #named_macro(name) ⇒ Object
-
#namespace_exists?(name, context = '') ⇒ Boolean
True if the namespace exists.
-
#namespaces ⇒ Array<String>
An array of namespace names defined in the ApiMap.
- #pins ⇒ Array<Solargraph::Pin::Base>
-
#qualify(namespace, context = '') ⇒ String
Get a fully qualified namespace name.
-
#query_symbols(query) ⇒ Array<Pin::Base>
Get an array of all symbols in the workspace that match the query.
-
#search(query) ⇒ Array<String>
Get a list of documented paths that match the query.
-
#source_map(filename) ⇒ SourceMap
Get a source map by filename.
Methods included from SourceToYard
#code_object_at, #code_object_paths, #rake_yard
Constructor Details
Instance Attribute Details
#live_map ⇒ Solargraph::LiveMap (readonly)
Get a LiveMap associated with the current workspace.
18 19 20 |
# File 'lib/solargraph/api_map.rb', line 18 def live_map @live_map end |
#unresolved_requires ⇒ Array<String> (readonly)
21 22 23 |
# File 'lib/solargraph/api_map.rb', line 21 def unresolved_requires @unresolved_requires end |
Class Method Details
.keywords ⇒ Array<Solargraph::Pin::Keyword>
An array of pins based on Ruby keywords (‘if`, `end`, etc.).
156 157 158 159 160 |
# File 'lib/solargraph/api_map.rb', line 156 def self.keywords @keywords ||= CoreFills::KEYWORDS.map{ |s| Pin::Keyword.new(s) }.freeze end |
.load(directory) ⇒ ApiMap
Create an ApiMap with a workspace in the specified directory.
140 141 142 143 144 145 146 |
# File 'lib/solargraph/api_map.rb', line 140 def self.load directory # @todo How should this work? api_map = self.new #(Solargraph::Workspace.new(directory)) workspace = Solargraph::Workspace.new(directory) api_map.catalog Bundle.new(workspace: workspace) api_map end |
Instance Method Details
#catalog(bundle) ⇒ self
Catalog a bundle.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/solargraph/api_map.rb', line 63 def catalog bundle new_map_hash = {} # Bundle always needs to be merged if it adds or removes sources merged = (bundle.sources.length == source_map_hash.values.length) bundle.sources.each do |source| if source_map_hash.has_key?(source.filename) if source_map_hash[source.filename].code == source.code new_map_hash[source.filename] = source_map_hash[source.filename] else map = Solargraph::SourceMap.map(source) if source_map_hash[source.filename].try_merge!(map) new_map_hash[source.filename] = source_map_hash[source.filename] else new_map_hash[source.filename] = map merged = false end end else map = Solargraph::SourceMap.map(source) new_map_hash[source.filename] = map merged = false end end return self if merged pins = [] reqs = [] # @param map [SourceMap] new_map_hash.values.each do |map| pins.concat map.pins reqs.concat map.requires.map(&:name) end reqs.concat bundle.workspace.config.required unless bundle.workspace.require_paths.empty? reqs.delete_if do |r| result = false bundle.workspace.require_paths.each do |l| if new_map_hash.keys.include?(File.join(l, "#{r}.rb")) result = true break end end result end end yard_map.change(reqs) new_store = Store.new(pins + yard_map.pins) @mutex.synchronize { @cache.clear @source_map_hash = new_map_hash @store = new_store @unresolved_requires = yard_map.unresolved_requires } resolve_method_aliases self end |
#clip(cursor) ⇒ SourceMap::Clip
434 435 436 437 |
# File 'lib/solargraph/api_map.rb', line 434 def clip cursor raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.has_key?(cursor.filename) SourceMap::Clip.new(self, cursor) end |
#clip_at(filename, position) ⇒ SourceMap::Clip
Get a clip by filename and position.
132 133 134 |
# File 'lib/solargraph/api_map.rb', line 132 def clip_at filename, position SourceMap::Clip.new(self, cursor_at(filename, position)) end |
#cursor_at(filename, position) ⇒ Source::Cursor
122 123 124 125 |
# File 'lib/solargraph/api_map.rb', line 122 def cursor_at filename, position raise "File not found: #{filename}" unless source_map_hash.has_key?(filename) source_map_hash[filename].cursor_at(position) end |
#document(path) ⇒ Array<YARD::CodeObject::Base>
Get YARD documentation for the specified path.
405 406 407 408 409 410 |
# File 'lib/solargraph/api_map.rb', line 405 def document path rake_yard(store) docs = [] docs.push code_object_at(path) unless code_object_at(path).nil? docs end |
#document_symbols(filename) ⇒ Array<Pin::Symbol>
Get an array of document symbols from a file.
443 444 445 446 |
# File 'lib/solargraph/api_map.rb', line 443 def document_symbols filename return [] unless source_map_hash.has_key?(filename) # @todo Raise error? source_map_hash[filename].document_symbols end |
#get_class_variable_pins(namespace) ⇒ Array<Solargraph::Pin::ClassVariable>
Get an array of class variable pins for a namespace.
251 252 253 |
# File 'lib/solargraph/api_map.rb', line 251 def get_class_variable_pins(namespace) prefer_non_nil_variables(store.get_class_variables(namespace)) end |
#get_complex_type_methods(type, context = '', internal = false) ⇒ Array<Solargraph::Pin::Base>
Get an array of public methods for a complex type.
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 331 |
# File 'lib/solargraph/api_map.rb', line 305 def get_complex_type_methods type, context = '', internal = false return [] if type.undefined? || type.void? result = [] if type.duck_type? type.select(&:duck_type?).each do |t| result.push Pin::DuckMethod.new(nil, t.tag[1..-1]) end result.concat get_methods('Object') else unless type.nil? || type.name == 'void' # @todo This method does not qualify the complex type's namespace # because it can cause namespace conflicts, e.g., `Foo` vs. # `Other::Foo`. It still takes a context argument because it # uses context to determine whether protected and private methods # are visible. # namespace = qualify(type.namespace, context) namespace = type.namespace visibility = [:public] if namespace == context || super_and_sub?(namespace, context) visibility.push :protected visibility.push :private if internal end result.concat get_methods(namespace, scope: type.scope, visibility: visibility) end end result end |
#get_constants(namespace, context = '') ⇒ Array<Solargraph::Pin::Base>
Get suggestions for constants in the specified namespace. The result may contain both constant and namespace pins.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/solargraph/api_map.rb', line 184 def get_constants namespace, context = '' namespace ||= '' cached = cache.get_constants(namespace, context) return cached.clone unless cached.nil? skip = [] result = [] bases = context.split('::') while bases.length > 0 built = bases.join('::') fqns = qualify(namespace, built) visibility = [:public] visibility.push :private if fqns == context result.concat inner_get_constants(fqns, visibility, skip) bases.pop end fqns = qualify(namespace, '') visibility = [:public] visibility.push :private if fqns == context result.concat inner_get_constants(fqns, visibility, skip) cache.set_constants(namespace, context, result) result end |
#get_global_variable_pins ⇒ Array<Solargraph::Pin::GlobalVariable>
261 262 263 264 |
# File 'lib/solargraph/api_map.rb', line 261 def get_global_variable_pins # @todo Slow version pins.select{|p| p.kind == Pin::GLOBAL_VARIABLE} end |
#get_instance_variable_pins(namespace, scope = :instance) ⇒ Array<Solargraph::Pin::InstanceVariable>
Get an array of instance variable pins defined in specified namespace and scope.
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/solargraph/api_map.rb', line 236 def get_instance_variable_pins(namespace, scope = :instance) result = [] result.concat store.get_instance_variables(namespace, scope) sc = qualify(store.get_superclass(namespace), namespace) until sc.nil? result.concat store.get_instance_variables(sc, scope) sc = qualify(store.get_superclass(sc), sc) end result end |
#get_method_stack(fqns, name, scope: :instance) ⇒ Array<Solargraph::Pin::Base>
Get a stack of method pins for a method name in a namespace. The order of the pins corresponds to the ancestry chain, with highest precedence first.
345 346 347 348 349 350 351 352 353 |
# File 'lib/solargraph/api_map.rb', line 345 def get_method_stack fqns, name, scope: :instance # @todo This cache is still causing problems, but only when using # Solargraph on Solargraph itself. # cached = cache.get_method_stack(fqns, name, scope) # return cached unless cached.nil? result = get_methods(fqns, scope: scope, visibility: [:private, :protected, :public]).select{|p| p.name == name} # cache.set_method_stack(fqns, name, scope, result) # result end |
#get_methods(fqns, scope: :instance, visibility: [:public], deep: true) ⇒ Array<Solargraph::Pin::Base>
Get an array of methods available in a particular context.
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 |
# File 'lib/solargraph/api_map.rb', line 273 def get_methods fqns, scope: :instance, visibility: [:public], deep: true cached = cache.get_methods(fqns, scope, visibility, deep) return cached.clone unless cached.nil? result = [] skip = [] if fqns == '' # @todo Implement domains # domains.each do |domain| # type = ComplexType.parse(domain).first # result.concat inner_get_methods(type.name, type.scope, [:public], deep, skip) # end result.concat inner_get_methods(fqns, :class, visibility, deep, skip) result.concat inner_get_methods(fqns, :instance, visibility, deep, skip) result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip) else result.concat inner_get_methods(fqns, scope, visibility, deep, skip) end # live = live_map.get_methods(fqns, '', scope.to_s, visibility.include?(:private)) # unless live.empty? # exist = result.map(&:name) # result.concat live.reject{|p| exist.include?(p.name)} # end cache.set_methods(fqns, scope, visibility, deep, result) result end |
#get_path_pins(path) ⇒ Array<Pin::Base>
Get an array of pins that match the specified path.
376 377 378 |
# File 'lib/solargraph/api_map.rb', line 376 def get_path_pins path get_path_suggestions(path) end |
#get_path_suggestions(path) ⇒ Array<Solargraph::Pin::Base>
Use #get_path_pins instead.
Get an array of all suggestions that match the specified path.
361 362 363 364 365 366 367 368 369 370 |
# File 'lib/solargraph/api_map.rb', line 361 def get_path_suggestions path return [] if path.nil? result = [] result.concat store.get_path_pins(path) # if result.empty? # lp = live_map.get_path_pin(path) # result.push lp unless lp.nil? # end result end |
#get_symbols ⇒ Array<Solargraph::Pin::Base>
256 257 258 |
# File 'lib/solargraph/api_map.rb', line 256 def get_symbols store.get_symbols end |
#index(pins) ⇒ self
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/solargraph/api_map.rb', line 35 def index pins @mutex.synchronize { @source_map_hash.clear @cache.clear @store = Store.new(pins + YardMap.new.pins) @unresolved_requires = [] } resolve_method_aliases self end |
#locate_pin(location) ⇒ Solargraph::Pin::Base
426 427 428 429 |
# File 'lib/solargraph/api_map.rb', line 426 def locate_pin location return nil if location.nil? || !source_map_hash.has_key?(location.filename) source_map_hash[location.filename].locate_pin(location) end |
#map(source) ⇒ self
Map a single source.
50 51 52 53 |
# File 'lib/solargraph/api_map.rb', line 50 def map source catalog Bundle.new(opened: [source]) self end |
#named_macro(name) ⇒ Object
55 56 57 |
# File 'lib/solargraph/api_map.rb', line 55 def named_macro name store.named_macros[name] end |
#namespace_exists?(name, context = '') ⇒ Boolean
True if the namespace exists.
174 175 176 |
# File 'lib/solargraph/api_map.rb', line 174 def namespace_exists? name, context = '' !qualify(name, context).nil? end |
#namespaces ⇒ Array<String>
An array of namespace names defined in the ApiMap.
165 166 167 |
# File 'lib/solargraph/api_map.rb', line 165 def namespaces store.namespaces end |
#pins ⇒ Array<Solargraph::Pin::Base>
149 150 151 |
# File 'lib/solargraph/api_map.rb', line 149 def pins store.pins end |
#qualify(namespace, context = '') ⇒ String
Get a fully qualified namespace name. This method will start the search in the specified context until it finds a match for the name.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/solargraph/api_map.rb', line 213 def qualify namespace, context = '' # @todo The return for self might work better elsewhere return nil if namespace.nil? return qualify(context) if namespace == 'self' cached = cache.get_qualified_namespace(namespace, context) return cached.clone unless cached.nil? # result = inner_qualify(namespace, context, []) # result = result[2..-1] if !result.nil? && result.start_with?('::') if namespace.start_with?('::') result = inner_qualify(namespace[2..-1], '', []) else result = inner_qualify(namespace, context, []) end cache.set_qualified_namespace(namespace, context, result) result end |
#query_symbols(query) ⇒ Array<Pin::Base>
Get an array of all symbols in the workspace that match the query.
416 417 418 419 420 421 422 |
# File 'lib/solargraph/api_map.rb', line 416 def query_symbols query result = [] source_map_hash.values.each do |s| result.concat s.query_symbols(query) end result end |
#search(query) ⇒ Array<String>
Get a list of documented paths that match the query.
387 388 389 390 391 392 393 394 395 396 |
# File 'lib/solargraph/api_map.rb', line 387 def search query rake_yard(store) found = [] code_object_paths.each do |k| if found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#')) found.push k if k.downcase.include?(query.downcase) end end found end |
#source_map(filename) ⇒ SourceMap
Get a source map by filename.
452 453 454 455 |
# File 'lib/solargraph/api_map.rb', line 452 def source_map filename raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.has_key?(filename) source_map_hash[filename] end |