Class: Solargraph::ApiMap

Inherits:
Object
  • Object
show all
Extended by:
Logging
Includes:
Logging
Defined in:
lib/solargraph/api_map.rb,
lib/solargraph/api_map/cache.rb,
lib/solargraph/api_map/index.rb,
lib/solargraph/api_map/store.rb,
lib/solargraph/api_map/constants.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, Constants, Index, Store

Constant Summary collapse

@@core_map =
RbsMap::CoreMap.new

Constants included from Logging

Logging::DEFAULT_LOG_LEVEL, Logging::LOG_LEVELS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

logger

Constructor Details

#initialize(pins: []) ⇒ ApiMap

Returns a new instance of ApiMap.

Parameters:



27
28
29
30
31
# File 'lib/solargraph/api_map.rb', line 27

def initialize pins: []
  @source_map_hash = {}
  @cache = Cache.new
  index pins
end

Instance Attribute Details

#missing_docsArray<String> (readonly)

Returns:

  • (Array<String>)


24
25
26
# File 'lib/solargraph/api_map.rb', line 24

def missing_docs
  @missing_docs
end

#unresolved_requiresArray<String> (readonly)

Returns:

  • (Array<String>)


19
20
21
# File 'lib/solargraph/api_map.rb', line 19

def unresolved_requires
  @unresolved_requires
end

Class Method Details

.load(directory) ⇒ ApiMap

Create an ApiMap with a workspace in the specified directory.

Parameters:

  • directory (String)

Returns:



185
186
187
188
189
190
191
192
193
# File 'lib/solargraph/api_map.rb', line 185

def self.load directory
  api_map = new
  workspace = Solargraph::Workspace.new(directory)
  # api_map.catalog Bench.new(workspace: workspace)

  library = Library.new(workspace)
  library.map!
  api_map.catalog library.bench
  api_map
end

.load_with_cache(directory, out) ⇒ ApiMap

Create an ApiMap with a workspace in the specified directory and cache any missing gems.

Parameters:

  • directory (String)
  • out (IO)

    The output stream for messages

Returns:



221
222
223
224
225
226
227
228
229
230
# File 'lib/solargraph/api_map.rb', line 221

def self.load_with_cache directory, out
  api_map = load(directory)
  if api_map.uncached_gemspecs.empty?
    logger.info { "All gems cached for #{directory}" }
    return api_map
  end

  api_map.cache_all!(out)
  load(directory)
end

Instance Method Details

#==(other) ⇒ Object

Parameters:

  • other (Object)


47
48
49
# File 'lib/solargraph/api_map.rb', line 47

def ==(other)
  self.eql?(other)
end

#bundled?(filename) ⇒ Boolean

True if the specified file was included in a bundle, i.e., it’s either included in a workspace or open in a library.

Parameters:

  • filename (String)

Returns:

  • (Boolean)


624
625
626
# File 'lib/solargraph/api_map.rb', line 624

def bundled? filename
  source_map_hash.keys.include?(filename)
end

#cache_all!(out) ⇒ void

This method returns an undefined value.

Parameters:

  • out (IO, nil)


197
198
199
# File 'lib/solargraph/api_map.rb', line 197

def cache_all!(out)
  @doc_map.cache_all!(out)
end

#cache_gem(gemspec, rebuild: false, out: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • gemspec (Gem::Specification)
  • rebuild (Boolean) (defaults to: false)
  • out (IO, nil) (defaults to: nil)


205
206
207
# File 'lib/solargraph/api_map.rb', line 205

def cache_gem(gemspec, rebuild: false, out: nil)
  @doc_map.cache(gemspec, rebuild: rebuild, out: out)
end

#catalog(bench) ⇒ self

Catalog a bench.

Parameters:

Returns:

  • (self)


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/solargraph/api_map.rb', line 91

def catalog bench
  @source_map_hash = bench.source_map_hash
  iced_pins = bench.icebox.flat_map(&:pins)
  live_pins = bench.live_map&.all_pins || []
  conventions_environ.clear
  source_map_hash.each_value do |map|
    conventions_environ.merge map.conventions_environ
  end
  unresolved_requires = (bench.external_requires + conventions_environ.requires + bench.workspace.config.required).to_a.compact.uniq
  recreate_docmap = @unresolved_requires != unresolved_requires ||
                 @doc_map&.uncached_yard_gemspecs&.any? ||
                 @doc_map&.uncached_rbs_collection_gemspecs&.any? ||
                 @doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path
  if recreate_docmap
    @doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences

    @unresolved_requires = @doc_map.unresolved_requires
  end
  @cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins)
  @missing_docs = [] # @todo Implement missing docs

  self
end

#clip(cursor) ⇒ SourceMap::Clip

Parameters:

Returns:

Raises:



591
592
593
594
595
# File 'lib/solargraph/api_map.rb', line 591

def clip cursor
  raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.key?(cursor.filename)

  SourceMap::Clip.new(self, cursor)
end

#clip_at(filename, position) ⇒ SourceMap::Clip

Get a clip by filename and position.

Parameters:

  • filename (String)
  • position (Position, Array(Integer, Integer))

Returns:



175
176
177
178
# File 'lib/solargraph/api_map.rb', line 175

def clip_at filename, position
  position = Position.normalize(position)
  clip(cursor_at(filename, position))
end

#conventions_environEnviron

Returns:



157
158
159
# File 'lib/solargraph/api_map.rb', line 157

def conventions_environ
  @conventions_environ ||= Environ.new
end

#core_pinsEnumerable<Pin::Base>

Returns:



141
142
143
# File 'lib/solargraph/api_map.rb', line 141

def core_pins
  @@core_map.pins
end

#cursor_at(filename, position) ⇒ Source::Cursor

Parameters:

  • filename (String)
  • position (Position, Array(Integer, Integer))

Returns:

Raises:



164
165
166
167
168
# File 'lib/solargraph/api_map.rb', line 164

def cursor_at filename, position
  position = Position.normalize(position)
  raise FileNotFoundError, "File not found: #{filename}" unless source_map_hash.key?(filename)
  source_map_hash[filename].cursor_at(position)
end

#dereference(pin) ⇒ String?

Get a fully qualified namespace from a reference pin.

Parameters:

Returns:

  • (String, nil)


309
310
311
# File 'lib/solargraph/api_map.rb', line 309

def dereference(pin)
  store.constants.dereference(pin)
end

#doc_mapDocMap

Returns:



121
122
123
# File 'lib/solargraph/api_map.rb', line 121

def doc_map
  @doc_map ||= DocMap.new([], [])
end

#document(path) ⇒ Enumerable<Pin::Base>

Deprecated.

This method is likely superfluous. Calling #get_path_pins directly should be sufficient.

Parameters:

  • path (String)

    The path to find

Returns:



566
567
568
# File 'lib/solargraph/api_map.rb', line 566

def document path
  get_path_pins(path)
end

#document_symbols(filename) ⇒ Array<Pin::Symbol>

Get an array of document symbols from a file.

Parameters:

  • filename (String)

Returns:



601
602
603
604
# File 'lib/solargraph/api_map.rb', line 601

def document_symbols filename
  return [] unless source_map_hash.key?(filename) # @todo Raise error?

  resolve_method_aliases source_map_hash[filename].document_symbols
end

#eql?(other) ⇒ Boolean

Parameters:

  • other (Object)

Returns:

  • (Boolean)


40
41
42
43
44
# File 'lib/solargraph/api_map.rb', line 40

def eql?(other)
  self.class == other.class &&
    # @sg-ignore Flow sensitive typing needs to handle self.class == other.class

    equality_fields == other.equality_fields
end

#get_block_pinsEnumerable<Solargraph::Pin::Block>

Returns:



368
369
370
# File 'lib/solargraph/api_map.rb', line 368

def get_block_pins
  store.pins_by_class(Pin::Block)
end

#get_class_variable_pins(namespace) ⇒ Enumerable<Solargraph::Pin::ClassVariable>

Get an array of class variable pins for a namespace.

Parameters:

  • namespace (String)

    A fully qualified namespace

Returns:



353
354
355
# File 'lib/solargraph/api_map.rb', line 353

def get_class_variable_pins(namespace)
  prefer_non_nil_variables(store.get_class_variables(namespace))
end

#get_complex_type_methods(complex_type, context = '', internal = false) ⇒ Array<Solargraph::Pin::Base>

Get an array of method pins for a complex type.

The type’s namespace and the context should be fully qualified. If the context matches the namespace type or is a subclass of the type, protected methods are included in the results. If protected methods are included and internal is true, private methods are also included.

Examples:

api_map = Solargraph::ApiMap.new
type = Solargraph::ComplexType.parse('String')
api_map.get_complex_type_methods(type)

Parameters:

  • complex_type (Solargraph::ComplexType)

    The complex type of the namespace

  • context (String) (defaults to: '')

    The context from which the type is referenced

  • internal (Boolean) (defaults to: false)

    True to include private methods

Returns:



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'lib/solargraph/api_map.rb', line 470

def get_complex_type_methods complex_type, context = '', internal = false
  # This method does not qualify the complex type's namespace because

  # it can cause conflicts between similar names, e.g., `Foo` vs.

  # `Other::Foo`. It still takes a context argument to determine whether

  # protected and private methods are visible.

  return [] if complex_type.undefined? || complex_type.void?
  result = Set.new
  complex_type.each do |type|
    if type.duck_type?
      result.add Pin::DuckMethod.new(name: type.to_s[1..-1], source: :api_map)
      result.merge get_methods('Object')
    else
      unless type.nil? || type.name == 'void'
        visibility = [:public]
        if type.namespace == context || super_and_sub?(type.namespace, context)
          visibility.push :protected
          visibility.push :private if internal
        end
        result.merge get_methods(type.tag, scope: type.scope, visibility: visibility)
      end
    end
  end
  result.to_a
end

#get_constants(namespace, *contexts) ⇒ Array<Solargraph::Pin::Constant, Solargraph::Pin::Namespace>

Get suggestions for constants in the specified namespace. The result may contain both constant and namespace pins.

Parameters:

  • namespace (String)

    The namespace

  • contexts (Array<String>)

    The contexts

Returns:



259
260
261
262
263
264
265
266
267
268
# File 'lib/solargraph/api_map.rb', line 259

def get_constants namespace, *contexts
  namespace ||= ''
  gates = contexts.clone
  gates.push '' if contexts.empty? && namespace.empty?
  gates.push namespace unless namespace.empty?
  store.constants
       .collect(gates)
       .select { |pin| namespace.empty? || contexts.empty? || pin.namespace == namespace }
       .select { |pin| pin.visibility == :public || pin.namespace == namespace }
end

#get_extends(fqns) ⇒ Array<Pin::Reference::Extend>

Parameters:

  • fqns (String)

Returns:



315
316
317
# File 'lib/solargraph/api_map.rb', line 315

def get_extends(fqns)
  store.get_extends(fqns)
end

#get_global_variable_pinsEnumerable<Solargraph::Pin::GlobalVariable>

Returns:



363
364
365
# File 'lib/solargraph/api_map.rb', line 363

def get_global_variable_pins
  store.pins_by_class(Pin::GlobalVariable)
end

#get_includes(fqns) ⇒ Array<Pin::Reference::Include>

Parameters:

  • fqns (String)

Returns:



321
322
323
# File 'lib/solargraph/api_map.rb', line 321

def get_includes(fqns)
  store.get_includes(fqns)
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.

Parameters:

  • namespace (String)

    A fully qualified namespace

  • scope (Symbol) (defaults to: :instance)

    :instance or :class

Returns:



331
332
333
334
335
336
337
338
339
340
341
# File 'lib/solargraph/api_map.rb', line 331

def get_instance_variable_pins(namespace, scope = :instance)
  result = []
  used = [namespace]
  result.concat store.get_instance_variables(namespace, scope)
  sc_fqns = namespace
  while (sc = store.get_superclass(sc_fqns))
    sc_fqns = store.constants.dereference(sc)
    result.concat store.get_instance_variables(sc_fqns, scope)
  end
  result
end

#get_method_stack(rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false) ⇒ Array<Solargraph::Pin::Method>

Get a stack of method pins for a method name in a potentially parameterized namespace. The order of the pins corresponds to the ancestry chain, with highest precedence first.

Examples:

api_map.get_method_stack('Subclass', 'method_name')
  #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]

Parameters:

  • rooted_tag (String)

    Parameterized namespace, fully qualified

  • name (String)

    Method name to look up

  • scope (Symbol) (defaults to: :instance)

    :instance or :class

  • visibility (Array<Symbol>) (defaults to: [:private, :protected, :public])

    :public, :protected, and/or :private

  • preserve_generics (Boolean) (defaults to: false)

    True to preserve any unresolved generic parameters, false to erase them

Returns:



510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
# File 'lib/solargraph/api_map.rb', line 510

def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false
  rooted_type = ComplexType.parse(rooted_tag)
  fqns = rooted_type.namespace
  namespace_pin = store.get_path_pins(fqns).first
  methods = if namespace_pin.is_a?(Pin::Constant)
              type = namespace_pin.infer(self)
              if type.defined?
                namespace_pin = store.get_path_pins(type.namespace).first
                get_methods(type.namespace, scope: scope, visibility: visibility).select { |p| p.name == name }
              else
                []
              end
            else
              get_methods(rooted_tag, scope: scope, visibility: visibility).select { |p| p.name == name }
            end
  methods = erase_generics(namespace_pin, rooted_type, methods) unless preserve_generics
  methods
end

#get_methods(rooted_tag, scope: :instance, visibility: [:public], deep: true) ⇒ Array<Solargraph::Pin::Method>

Get an array of methods available in a particular context.

Parameters:

  • rooted_tag (String)

    The fully qualified namespace to search for methods

  • scope (Symbol) (defaults to: :instance)

    :class or :instance

  • visibility (Array<Symbol>) (defaults to: [:public])

    :public, :protected, and/or :private

  • deep (Boolean) (defaults to: true)

    True to include superclasses, mixins, etc.

Returns:



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
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
443
444
445
446
447
448
449
450
451
452
# File 'lib/solargraph/api_map.rb', line 379

def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
  if rooted_tag.start_with? 'Array('
    # Array() are really tuples - use our fill, as the RBS repo

    # does not give us definitions for it

    rooted_tag = "Solargraph::Fills::Tuple(#{rooted_tag[6..-2]})"
  end
  rooted_type = ComplexType.try_parse(rooted_tag)
  fqns = rooted_type.namespace
  namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
  cached = cache.get_methods(rooted_tag, scope, visibility, deep)
  return cached.clone unless cached.nil?
  # @type [Array<Solargraph::Pin::Method>]

  result = []
  skip = Set.new
  if rooted_tag == ''
    # @todo Implement domains

    conventions_environ.domains.each do |domain|
      type = ComplexType.try_parse(domain)
      next if type.undefined?
      result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
    end
    result.concat inner_get_methods(rooted_tag, :class, visibility, deep, skip)
    result.concat inner_get_methods(rooted_tag, :instance, visibility, deep, skip)
    result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
  else
    result.concat inner_get_methods(rooted_tag, scope, visibility, deep, skip)
    unless %w[Class Class<Class>].include?(rooted_tag)
      result.map! do |pin|
        next pin unless pin.path == 'Class#new'
        init_pin = get_method_stack(rooted_tag, 'initialize').first
        next pin unless init_pin

        type = ComplexType::SELF
        new_pin = Pin::Method.new(
          name: 'new',
          scope: :class,
          location: init_pin.location,
          return_type: type,
          comments: init_pin.comments,
          closure: init_pin.closure,
          source: init_pin.source,
          type_location: init_pin.type_location,
        )
        new_pin.parameters = init_pin.parameters.map do |init_param|
          param = init_param.clone
          param.closure = new_pin
          param.reset_generated!
          param
        end.freeze
        new_pin.signatures = init_pin.signatures.map do |init_sig|
          sig = init_sig.proxy(type)
          sig.parameters = init_sig.parameters.map do |param|
            param = param.clone
            param.closure = new_pin
            param.reset_generated!
            param
          end.freeze
          sig.closure = new_pin
          sig.reset_generated!
          sig
        end.freeze
        new_pin
      end
    end
    result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
    result.concat inner_get_methods('Module', scope, visibility, deep, skip) if scope == :module
  end
  result = resolve_method_aliases(result, visibility)
  if namespace_pin && rooted_tag != rooted_type.name
    result = result.map { |method_pin| method_pin.resolve_generics(namespace_pin, rooted_type) }
  end
  cache.set_methods(rooted_tag, scope, visibility, deep, result)
  result
end

#get_namespace_pins(namespace, context) ⇒ Array<Pin::Namespace>

Parameters:

  • namespace (String)
  • context (String)

Returns:



273
274
275
# File 'lib/solargraph/api_map.rb', line 273

def get_namespace_pins namespace, context
  store.fqns_pins(qualify(namespace, context))
end

#get_path_pins(path) ⇒ Array<Pin::Base>

Get an array of pins that match the specified path.

Parameters:

  • path (String)

Returns:



544
545
546
# File 'lib/solargraph/api_map.rb', line 544

def get_path_pins path
  get_path_suggestions(path)
end

#get_path_suggestions(path) ⇒ Array<Solargraph::Pin::Base>

Deprecated.

Use #get_path_pins instead.

Get an array of all suggestions that match the specified path.

Parameters:

  • path (String)

    The path to find

Returns:



535
536
537
538
# File 'lib/solargraph/api_map.rb', line 535

def get_path_suggestions path
  return [] if path.nil?
  resolve_method_aliases store.get_path_pins(path)
end

#get_symbolsEnumerable<Solargraph::Pin::Base>

Returns:



358
359
360
# File 'lib/solargraph/api_map.rb', line 358

def get_symbols
  store.get_symbols
end

#hashObject



51
52
53
# File 'lib/solargraph/api_map.rb', line 51

def hash
  equality_fields.hash
end

#index(pins) ⇒ self

Parameters:

Returns:

  • (self)


66
67
68
69
70
71
72
73
74
# File 'lib/solargraph/api_map.rb', line 66

def index pins
  # @todo This implementation is incomplete. It should probably create a

  #   Bench.

  @source_map_hash = {}
  conventions_environ.clear
  cache.clear
  store.update @@core_map.pins, pins
  self
end

#inner_get_methods_from_reference(fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core) ⇒ Array<Pin::Base>

Parameters:

  • fq_reference_tag (String)

    A fully qualified whose method should be pulled in

  • namespace_pin (Pin::Base)

    Namespace pin for the rooted_type parameter - used to pull generics information

  • type (ComplexType)

    The type which is having its methods supplemented from fq_reference_tag

  • scope (Symbol)

    :class or :instance

  • visibility (Array<Symbol>)

    :public, :protected, and/or :private

  • deep (Boolean)
  • skip (Set<String>)
  • no_core (Boolean)

    Skip core classes if true

Returns:



690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# File 'lib/solargraph/api_map.rb', line 690

def inner_get_methods_from_reference(fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core)
  logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) starting" }

  # Ensure the types returned by the methods in the referenced

  # type are relative to the generic values passed in the

  # reference.  e.g., Foo<String> might include Enumerable<String>

  #

  # @todo perform the same translation in the other areas

  #  here after adding a spec and handling things correctly

  #  in ApiMap::Store and RbsMap::Conversions for each

  resolved_reference_type = ComplexType.parse(fq_reference_tag).force_rooted.resolve_generics(namespace_pin, type)
  # @todo Can inner_get_methods be cached?  Lots of lookups of base types going on.

  methods = inner_get_methods(resolved_reference_type.tag, scope, visibility, deep, skip, no_core)
  if namespace_pin && !resolved_reference_type.all_params.empty?
    reference_pin = store.get_path_pins(resolved_reference_type.name).select { |p| p.is_a?(Pin::Namespace) }.first
    # logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolving generics with #{reference_pin.generics}, #{resolved_reference_type.rooted_tags}" }

    methods = methods.map do |method_pin|
      method_pin.resolve_generics(reference_pin, resolved_reference_type)
    end
  end
  # logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolved_reference_type: #{resolved_reference_type} for type=#{type}: #{methods.map(&:name)}" }

  methods
end

#inspectObject

avoid enormous dump



60
61
62
# File 'lib/solargraph/api_map.rb', line 60

def inspect
  to_s
end

#keyword_pinsEnumerable<Solargraph::Pin::Keyword>

An array of pins based on Ruby keywords (‘if`, `end`, etc.).

Returns:



240
241
242
# File 'lib/solargraph/api_map.rb', line 240

def keyword_pins
  store.pins_by_class(Pin::Keyword)
end

#locate_pins(location) ⇒ Array<Solargraph::Pin::Base>

Parameters:

Returns:



583
584
585
586
# File 'lib/solargraph/api_map.rb', line 583

def locate_pins location
  return [] if location.nil? || !source_map_hash.key?(location.filename)
  resolve_method_aliases source_map_hash[location.filename].locate_pins(location)
end

#map(source, live: false) ⇒ self

Map a single source.

Parameters:

  • source (Source)
  • live (Boolean) (defaults to: false)

    True for live source map (active editor file)

Returns:

  • (self)


81
82
83
84
85
# File 'lib/solargraph/api_map.rb', line 81

def map source, live: false
  map = Solargraph::SourceMap.map(source)
  catalog Bench.new(source_maps: [map], live_map: live ? map : nil)
  self
end

#named_macro(name) ⇒ YARD::Tags::MacroDirective?

Parameters:

  • name (String)

Returns:

  • (YARD::Tags::MacroDirective, nil)


147
148
149
# File 'lib/solargraph/api_map.rb', line 147

def named_macro name
  store.named_macros[name]
end

#namespace_exists?(name, context = '') ⇒ Boolean

True if the namespace exists.

Parameters:

  • name (String)

    The namespace to match

  • context (String) (defaults to: '')

    The context to search

Returns:

  • (Boolean)


249
250
251
# File 'lib/solargraph/api_map.rb', line 249

def namespace_exists? name, context = ''
  !qualify(name, context).nil?
end

#pinsArray<Solargraph::Pin::Base>

Returns:



233
234
235
# File 'lib/solargraph/api_map.rb', line 233

def pins
  store.pins.clone.freeze
end

#qualify(tag, *gates) ⇒ String?

Determine fully qualified tag for a given tag used inside the definition of another tag (“context”). This method will start the search in the specified context until it finds a match for the tag.

Does not recurse into qualifying the type parameters, but returns any which were passed in unchanged.

Parameters:

  • tag (String, nil)

    The namespace to match, complete with generic parameters set to appropriate values if available

  • gates (Array<String>)

    The fully qualified context in which the tag was referenced; start from here to resolve the name. Should not be prefixed with ‘::’.

Returns:

  • (String, nil)

    fully qualified tag



292
293
294
# File 'lib/solargraph/api_map.rb', line 292

def qualify tag, *gates
  store.constants.qualify(tag, *gates)
end

#query_symbols(query) ⇒ Array<Pin::Base>

Get an array of all symbols in the workspace that match the query.

Parameters:

  • query (String)

Returns:



574
575
576
577
578
579
# File 'lib/solargraph/api_map.rb', line 574

def query_symbols query
  Pin::Search.new(
    source_map_hash.values.flat_map(&:document_symbols),
    query
  ).results
end

#requiredSet<String>

Returns:

  • (Set<String>)


152
153
154
# File 'lib/solargraph/api_map.rb', line 152

def required
  @required ||= Set.new
end

#resolve(name, *gates) ⇒ String?

Parameters:

  • name (String)
  • gates (Array<String, Array<String>>)

Returns:

  • (String, nil)

See Also:

  • Store::Constants#resolve


301
302
303
# File 'lib/solargraph/api_map.rb', line 301

def resolve name, *gates
  store.constants.resolve(name, *gates)
end

#resolve_method_aliases(pins, visibility = [:public, :private, :protected]) ⇒ Array<Pin::Base>

Parameters:

  • pins (Enumerable<Pin::Base>)
  • visibility (Enumerable<Symbol>) (defaults to: [:public, :private, :protected])

Returns:



668
669
670
671
672
673
674
675
676
677
# File 'lib/solargraph/api_map.rb', line 668

def resolve_method_aliases pins, visibility = [:public, :private, :protected]
  with_resolved_aliases = pins.map do |pin|
    next pin unless pin.is_a?(Pin::MethodAlias)
    resolved = resolve_method_alias(pin)
    next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
    resolved
  end.compact
  logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" }
  GemPins.combine_method_pins_by_path(with_resolved_aliases)
end

#search(query) ⇒ Array<String>

Get a list of documented paths that match the query.

Examples:

api_map.query('str') # Results will include `String` and `Struct`

Parameters:

  • query (String)

    The text to match

Returns:

  • (Array<String>)


555
556
557
558
559
# File 'lib/solargraph/api_map.rb', line 555

def search query
  pins.map(&:path)
      .compact
      .select { |path| path.downcase.include?(query.downcase) }
end

#source_map(filename) ⇒ SourceMap

Get a source map by filename.

Parameters:

  • filename (String)

Returns:

Raises:



615
616
617
618
# File 'lib/solargraph/api_map.rb', line 615

def source_map filename
  raise FileNotFoundError, "Source map for `#{filename}` not found" unless source_map_hash.key?(filename)
  source_map_hash[filename]
end

#source_mapsArray<SourceMap>

Returns:



607
608
609
# File 'lib/solargraph/api_map.rb', line 607

def source_maps
  source_map_hash.values
end

#super_and_sub?(sup, sub) ⇒ Boolean

Check if a class is a superclass of another class.

Parameters:

  • sup (String)

    The superclass

  • sub (String)

    The subclass

Returns:

  • (Boolean)


633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
# File 'lib/solargraph/api_map.rb', line 633

def super_and_sub?(sup, sub)
  sup = ComplexType.try_parse(sup)
  sub = ComplexType.try_parse(sub)
  # @todo If two literals are different values of the same type, it would

  #   make more sense for super_and_sub? to return true, but there are a

  #   few callers that currently expect this to be false.

  return false if sup.literal? && sub.literal? && sup.to_s != sub.to_s
  sup = sup.simplify_literals.to_s
  sub = sub.simplify_literals.to_s
  return true if sup == sub
  sc_fqns = sub
  while (sc = store.get_superclass(sc_fqns))
    sc_new = store.constants.dereference(sc)
    # Cyclical inheritance is invalid

    return false if sc_new == sc_fqns
    sc_fqns = sc_new
    return true if sc_fqns == sup
  end
  false
end

#to_sObject



55
56
57
# File 'lib/solargraph/api_map.rb', line 55

def to_s
  self.class.to_s
end

#type_include?(host_ns, module_ns) ⇒ Boolean

Check if the host class includes the specified module, ignoring type parameters used.

Parameters:

  • host_ns (String)

    The class namesapce (no type parameters)

  • module_ns (String)

    The module namespace (no type parameters)

Returns:

  • (Boolean)


661
662
663
# File 'lib/solargraph/api_map.rb', line 661

def type_include?(host_ns, module_ns)
  store.get_includes(host_ns).map { |inc_tag| inc_tag.type.name }.include?(module_ns)
end

#uncached_gemspecs::Array<Gem::Specification>

Returns:

  • (::Array<Gem::Specification>)


126
127
128
# File 'lib/solargraph/api_map.rb', line 126

def uncached_gemspecs
  @doc_map&.uncached_gemspecs || []
end

#uncached_rbs_collection_gemspecs::Array<Gem::Specification>

Returns:

  • (::Array<Gem::Specification>)


131
132
133
# File 'lib/solargraph/api_map.rb', line 131

def uncached_rbs_collection_gemspecs
  @doc_map.uncached_rbs_collection_gemspecs
end

#uncached_yard_gemspecs::Array<Gem::Specification>

Returns:

  • (::Array<Gem::Specification>)


136
137
138
# File 'lib/solargraph/api_map.rb', line 136

def uncached_yard_gemspecs
  @doc_map.uncached_yard_gemspecs
end

#visible_pins(*args, **kwargs, &blk) ⇒ Object

@sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins

See Also:

  • Parser::FlowSensitiveTyping#visible_pins


345
346
347
# File 'lib/solargraph/api_map.rb', line 345

def visible_pins(*args, **kwargs, &blk)
  Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk)
end