-
Notifications
You must be signed in to change notification settings - Fork 127
/
source_repository.rb
150 lines (128 loc) · 3.3 KB
/
source_repository.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
require_relative 'color'
module DEBUGGER__
class SourceRepository
include Color
def file_src iseq
if (path = (iseq.absolute_path || iseq.path)) && File.exist?(path)
File.readlines(path, chomp: true)
end
end
def get iseq
return unless iseq
if CONFIG[:show_evaledsrc]
orig_src(iseq) || file_src(iseq)
else
file_src(iseq) || orig_src(iseq)
end
end
if defined?(RubyVM.keep_script_lines)
# Ruby 3.1 and later
RubyVM.keep_script_lines = true
require 'objspace'
def initialize
# cache
@cmap = ObjectSpace::WeakMap.new
@loaded_file_map = {} # path => nil
end
def add iseq, src
# only manage loaded file names
if (path = (iseq.absolute_path || iseq.path)) && File.exist?(path)
if @loaded_file_map.has_key? path
return path, true # reloaded
else
@loaded_file_map[path] = path
return path, false
end
end
end
def orig_src iseq
lines = iseq.script_lines&.map(&:chomp)
line = iseq.first_line
if line > 1
[*([''] * (line - 1)), *lines]
else
lines
end
end
def get_colored iseq
if lines = @cmap[iseq]
lines
else
if src_lines = get(iseq)
@cmap[iseq] = colorize_code(src_lines.join("\n")).lines
else
nil
end
end
end
else
# ruby 3.0 or earlier
SrcInfo = Struct.new(:src, :colored)
def initialize
@files = {} # filename => SrcInfo
end
def add iseq, src
path = (iseq.absolute_path || iseq.path)
if path && File.exist?(path)
reloaded = @files.has_key? path
if src
add_iseq iseq, src
return path, reloaded
else
add_path path
return path, reloaded
end
else
add_iseq iseq, src
nil
end
end
private def all_iseq iseq, rs = []
rs << iseq
iseq.each_child{|ci|
all_iseq(ci, rs)
}
rs
end
private def add_iseq iseq, src
line = iseq.first_line
if line > 1
src = ("\n" * (line - 1)) + src
end
si = SrcInfo.new(src.each_line.map{|l| l.chomp})
all_iseq(iseq).each{|e|
e.instance_variable_set(:@debugger_si, si)
e.freeze
}
end
private def add_path path
src_lines = File.readlines(path, chomp: true)
@files[path] = SrcInfo.new(src_lines)
rescue SystemCallError
end
private def get_si iseq
return unless iseq
if iseq.instance_variable_defined?(:@debugger_si)
iseq.instance_variable_get(:@debugger_si)
elsif @files.has_key?(path = (iseq.absolute_path || iseq.path))
@files[path]
elsif path
add_path(path)
end
end
def orig_src iseq
if si = get_si(iseq)
si.src
end
end
def get_colored iseq
if si = get_si(iseq)
si.colored || begin
si.colored = colorize_code(si.src.join("\n")).lines
end
end
end
end
end
end