class Rookout::Services::PositionResolver

Public Class Methods

new(tracer) click to toggle source
# File lib/rookout/services/position.rb, line 18
def initialize tracer
  @tracer = tracer
  @augs = {}
  @iseqs = []
  @trace_point = TracePoint.new :script_compiled do |tp|
    begin
      begin
        iseq = tp.instruction_sequence
        # Ignore script without sources
        if iseq.absolute_path
          @iseqs << iseq
          evaluate_script iseq
        end
      rescue Exception => e
        Logger.instance.exception "Exception while evaluating script", e
      end
    rescue
    end
  end

  @trace_point.enable
end

Public Instance Methods

add_aug(location) click to toggle source
# File lib/rookout/services/position.rb, line 41
def add_aug location
  positions = evaluate_all_scripts_to_location location
  @tracer.add_breakpoint_aug positions, location unless positions.empty?
  @augs[location.id] = location
end
clear_augs() click to toggle source
# File lib/rookout/services/position.rb, line 55
def clear_augs
  @augs.values.each do |aug_id|
    remove_aug aug_id
  end

  @augs = {}
end
close() click to toggle source
# File lib/rookout/services/position.rb, line 63
def close
  clear_augs
  @trace_point.disable
end
remove_aug(aug_id) click to toggle source
# File lib/rookout/services/position.rb, line 47
def remove_aug aug_id
  location = @augs[aug_id]
  return if location.nil?

  @augs.delete [aug_id]
  location.notify_removed
end

Private Instance Methods

crc_line(line) click to toggle source
# File lib/rookout/services/position.rb, line 171
def crc_line line
  (Zlib.crc32(line) & 0xffffffff).to_s 16
end
evaluate_all_scripts_to_location(location) click to toggle source
# File lib/rookout/services/position.rb, line 84
def evaluate_all_scripts_to_location location
  positions = []
  @iseqs.each do |iseq|
    position = evaluate_script_to_location iseq, iseq.absolute_path, location
    next if position.nil?

    positions << position
  end

  positions
end
evaluate_script(iseq) click to toggle source

ISEQ comparison Section

# File lib/rookout/services/position.rb, line 72
def evaluate_script iseq
  filename = iseq.absolute_path
  return if filename.nil?

  @augs.each_value do |location|
    position = evaluate_script_to_location iseq, filename, location
    next if position.nil?

    @tracer.add_breakpoint_aug [position], location
  end
end
evaluate_script_to_location(iseq, filename, location) click to toggle source
# File lib/rookout/services/position.rb, line 96
def evaluate_script_to_location iseq, filename, location
  if exact_match? location.filename, filename
    lineno = find_updated_line filename, location
    return if lineno == -1

    PositionMarker.new lineno, iseq
  elsif suggested_match? location, filename
    warning = Exceptions::RookSourceFilePathSuggestion.new location.filename, filename
    location.notify_warning warning
    # Must return nil in order to skip this script
    nil
  end
end
exact_match?(location_filename, script_filename) click to toggle source

Utils

# File lib/rookout/services/position.rb, line 112
def exact_match? location_filename, script_filename
  return unless script_filename.end_with? location_filename
  File.basename(script_filename) == File.basename(location_filename)
end
find_updated_line(filename, location) click to toggle source
# File lib/rookout/services/position.rb, line 153
def find_updated_line filename, location
  return location.lineno if location.line_crc.nil?

  lines = File.readlines filename, chomp: true
  line_crc32 = lines.length >= location.lineno ? crc_line(lines[location.lineno - 1]) : nil
  return location.lineno if location.line_crc == line_crc32

  if location.line_unique
    updated_line = handle_unique_line lines, location, filename
    unless updated_line.nil?
      return updated_line
    end
  end

  location.notify_error Exceptions::RookCrcMismatchException.new(filename, location.line_crc, line_crc32)
  -1
end
get_hash(filename) click to toggle source
# File lib/rookout/services/position.rb, line 122
def get_hash filename
  content = File.read filename
  content.gsub!(/(?:\r\n|\r|\n)/, "\n")
  Digest::SHA2.new(256).hexdigest content
end
handle_unique_line(lines, location, filename) click to toggle source
# File lib/rookout/services/position.rb, line 128
def handle_unique_line lines, location, filename
  first_line = nil
  second_found = false

  lines.each_with_index do |line, index|
    if crc_line(line) == location.line_crc
      if first_line.nil?
        first_line = index
      else
        second_found = true
        break
      end
    end
  end

  if first_line && !second_found
    updated_line = first_line + 1
    location.notify_warning Processor::RookError.new Exceptions::RookLineMoved.new(filename,
                                                                                   location.lineno,
                                                                                   updated_line)
    return updated_line
  end
  nil
end
suggested_match?(location, filename) click to toggle source
# File lib/rookout/services/position.rb, line 117
def suggested_match? location, filename
  return unless File.basename(location.filename) == File.basename(filename)
  location.file_hash == get_hash(filename)
end