class Solargraph::SourceMap

An index of pins and other ApiMap-related data for a Source.

Attributes

locals[R]

@return [Array<Pin::Base>]

pins[R]

@return [Array<Pin::Base>]

source[R]

@return [Source]

Public Class Methods

load(filename) click to toggle source

@param filename [String] @return [SourceMap]

# File lib/solargraph/source_map.rb, line 140
def load filename
  source = Solargraph::Source.load(filename)
  SourceMap.map(source)
end
load_string(code, filename = nil) click to toggle source

@param code [String] @param filename [String, nil] @return [SourceMap]

# File lib/solargraph/source_map.rb, line 148
def load_string code, filename = nil
  source = Solargraph::Source.load_string(code, filename)
  SourceMap.map(source)
end
map(source) click to toggle source

@param source [Source] @return [SourceMap]

# File lib/solargraph/source_map.rb, line 155
def map source
  result = SourceMap::Mapper.map(source)
  new(source, *result)
end
new(source, pins, locals) click to toggle source

@param source [Source] @param pins [Array<Pin::Base>] @param locals [Array<Pin::Base>]

# File lib/solargraph/source_map.rb, line 27
def initialize source, pins, locals
  # HACK: Keep the library from changing this
  @source = source.dup
  @pins = pins
  @locals = locals
  environ.merge Convention.for_local(self) unless filename.nil?
  @pin_class_hash = pins.to_set.classify(&:class).transform_values(&:to_a)
  @pin_select_cache = {}
end

Public Instance Methods

code() click to toggle source

@return [String]

# File lib/solargraph/source_map.rb, line 54
def code
  source.code
end
cursor_at(position) click to toggle source

@param position [Position] @return [Source::Cursor]

# File lib/solargraph/source_map.rb, line 84
def cursor_at position
  Source::Cursor.new(source, position)
end
document_symbols() click to toggle source

@return [Array<Pin::Base>]

# File lib/solargraph/source_map.rb, line 69
def document_symbols
  @document_symbols ||= pins.select { |pin|
    pin.path && !pin.path.empty?
  }
end
environ() click to toggle source

@return [Environ]

# File lib/solargraph/source_map.rb, line 64
def environ
  @environ ||= Environ.new
end
filename() click to toggle source

@return [String]

# File lib/solargraph/source_map.rb, line 49
def filename
  source.filename
end
first_pin(path) click to toggle source

@param path [String] @return [Pin::Base]

# File lib/solargraph/source_map.rb, line 90
def first_pin path
  pins.select { |p| p.path == path }.first
end
locals_at(location) click to toggle source

@param location [Location] @return [Array<Pin::LocalVariable>]

# File lib/solargraph/source_map.rb, line 131
def locals_at(location)
  return [] if location.filename != filename
  closure = locate_named_path_pin(location.range.start.line, location.range.start.character)
  locals.select { |pin| pin.visible_at?(closure, location) }
end
locate_block_pin(line, character) click to toggle source
# File lib/solargraph/source_map.rb, line 105
def locate_block_pin line, character
  _locate_pin line, character, Pin::Namespace, Pin::Method, Pin::Block
end
locate_named_path_pin(line, character) click to toggle source
# File lib/solargraph/source_map.rb, line 101
def locate_named_path_pin line, character
  _locate_pin line, character, Pin::Namespace, Pin::Method
end
locate_pins(location) click to toggle source

@param location [Solargraph::Location] @return [Array<Solargraph::Pin::Base>]

# File lib/solargraph/source_map.rb, line 96
def locate_pins location
  # return nil unless location.start_with?("#{filename}:")
  (pins + locals).select { |pin| pin.location == location }
end
pins_by_class(klass) click to toggle source
# File lib/solargraph/source_map.rb, line 37
def pins_by_class klass
  @pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
end
query_symbols(query) click to toggle source

@param query [String] @return [Array<Pin::Base>]

# File lib/solargraph/source_map.rb, line 77
def query_symbols query
  return document_symbols if query && query.empty?
  document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
end
rebindable_method_names() click to toggle source
# File lib/solargraph/source_map.rb, line 41
def rebindable_method_names
  @rebindable_method_names ||= pins_by_class(Pin::Method)
    .select { |pin| pin.comments && pin.comments.include?('@yieldself') }
    .map(&:name)
    .to_set
end
references(name) click to toggle source

@param name [String] @return [Array<Location>]

# File lib/solargraph/source_map.rb, line 125
def references name
  source.references name
end
requires() click to toggle source

@return [Array<Pin::Reference::Require>]

# File lib/solargraph/source_map.rb, line 59
def requires
  pins_by_class(Pin::Reference::Require)
end
try_merge!(other_map) click to toggle source

@param other_map [SourceMap] @return [Boolean]

# File lib/solargraph/source_map.rb, line 111
def try_merge! other_map
  return false if pins.length != other_map.pins.length || locals.length != other_map.locals.length || requires.map(&:name).uniq.sort != other_map.requires.map(&:name).uniq.sort
  pins.each_index do |i|
    return false unless pins[i].try_merge!(other_map.pins[i])
  end
  locals.each_index do |i|
    return false unless locals[i].try_merge!(other_map.locals[i])
  end
  @source = other_map.source
  true
end

Private Instance Methods

_locate_pin(line, character, *klasses) click to toggle source

@param line [Integer] @param character [Integer] @param klasses [Array<Class>] @return [Pin::Base]

# File lib/solargraph/source_map.rb, line 167
def _locate_pin line, character, *klasses
  position = Position.new(line, character)
  found = nil
  pins.each do |pin|
    # @todo Attribute pins should not be treated like closures, but
    #   there's probably a better way to handle it
    next if pin.is_a?(Pin::Method) && pin.attribute?
    found = pin if (klasses.empty? || klasses.any? { |kls| pin.is_a?(kls) } ) && pin.location.range.contain?(position)
    break if pin.location.range.start.line > line
  end
  # Assuming the root pin is always valid
  found || pins.first
end
fuzzy_string_match(str1, str2) click to toggle source

@param str1 [String] @param str2 [String] @return [Boolean]

# File lib/solargraph/source_map.rb, line 184
def fuzzy_string_match str1, str2
  JaroWinkler.distance(str1, str2) > 0.6
end