Class: NPlusInsight::SourceLocation

Inherits:
Struct
  • Object
show all
Defined in:
lib/n_plus_insight/source_location.rb

Constant Summary collapse

FRAME_PATTERN =
/\A(.+?):(\d+)(?::in [`'](.+)[`'])?\z/
MAX_BACKTRACE_FRAMES =
30

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#backtraceObject

Returns the value of attribute backtrace

Returns:

  • (Object)

    the current value of backtrace



2
3
4
# File 'lib/n_plus_insight/source_location.rb', line 2

def backtrace
  @backtrace
end

#labelObject

Returns the value of attribute label

Returns:

  • (Object)

    the current value of label



2
3
4
# File 'lib/n_plus_insight/source_location.rb', line 2

def label
  @label
end

#lineObject

Returns the value of attribute line

Returns:

  • (Object)

    the current value of line



2
3
4
# File 'lib/n_plus_insight/source_location.rb', line 2

def line
  @line
end

#pathObject

Returns the value of attribute path

Returns:

  • (Object)

    the current value of path



2
3
4
# File 'lib/n_plus_insight/source_location.rb', line 2

def path
  @path
end

#snippetObject

Returns the value of attribute snippet

Returns:

  • (Object)

    the current value of snippet



2
3
4
# File 'lib/n_plus_insight/source_location.rb', line 2

def snippet
  @snippet
end

Class Method Details

.from(caller_lines) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/n_plus_insight/source_location.rb', line 6

def self.from(caller_lines)
  root = defined?(Rails) && Rails.respond_to?(:root) && Rails.root ? Rails.root.to_s.tr("\\", "/") : nil
  frames = caller_lines.filter_map do |entry|
    path = entry.to_s.tr("\\", "/")
    next unless root ? path.start_with?("#{root}/app/", "#{root}/lib/") : !path.include?("/gems/")

    match = FRAME_PATTERN.match(entry.to_s)
    next unless match

    path, line, label = match.captures
    { path: path, line: line.to_i, label: label }
  end.first(MAX_BACKTRACE_FRAMES)
  return if frames.empty?

  frame = frames.first
  new(
    path: frame[:path],
    line: frame[:line],
    label: frame[:label],
    snippet: read_snippet(frame[:path], frame[:line]),
    backtrace: frames
  )
end

.read_snippet(path, line) ⇒ Object



30
31
32
33
34
35
36
37
38
# File 'lib/n_plus_insight/source_location.rb', line 30

def self.read_snippet(path, line)
  lines = File.readlines(path)
  first = [line - 3, 0].max
  lines[first, 5].to_a.each_with_index.map do |text, index|
    { line: first + index + 1, text: text.chomp, active: first + index + 1 == line }
  end
rescue SystemCallError, ArgumentError
  []
end

Instance Method Details

#as_jsonObject



40
41
42
# File 'lib/n_plus_insight/source_location.rb', line 40

def as_json(*)
  { path: path, line: line, label: label, snippet: snippet, backtrace: backtrace }
end