puppet-debugger 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +25 -2
- data/.release_me.yaml +11 -0
- data/.rubocop.yml +239 -0
- data/.rubocop_todo.yml +196 -0
- data/.ruby-version +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +17 -1
- data/bin/pdb +1 -0
- data/lib/awesome_print/ext/awesome_puppet.rb +6 -5
- data/lib/puppet/application/debugger.rb +24 -24
- data/lib/puppet-debugger/cli.rb +76 -81
- data/lib/puppet-debugger/code/code_file.rb +82 -82
- data/lib/puppet-debugger/code/code_range.rb +56 -57
- data/lib/puppet-debugger/code/loc.rb +68 -70
- data/lib/puppet-debugger/debugger_code.rb +279 -280
- data/lib/puppet-debugger/support/compiler.rb +1 -1
- data/lib/puppet-debugger/support/environment.rb +2 -2
- data/lib/puppet-debugger/support/errors.rb +3 -4
- data/lib/puppet-debugger/support/facts.rb +7 -7
- data/lib/puppet-debugger/support/functions.rb +4 -5
- data/lib/puppet-debugger/support/input_responders.rb +26 -28
- data/lib/puppet-debugger/support/node.rb +7 -6
- data/lib/puppet-debugger/support/play.rb +16 -24
- data/lib/puppet-debugger/support/scope.rb +3 -4
- data/lib/puppet-debugger/support.rb +38 -40
- data/lib/puppet-debugger.rb +38 -17
- data/lib/version.rb +2 -1
- data/spec/facts_spec.rb +7 -6
- data/spec/pdb_spec.rb +1 -0
- data/spec/puppet/application/debugger_spec.rb +2 -3
- data/spec/{puppet-debugger_spec.rb → puppet_debugger_spec.rb} +27 -33
- data/spec/remote_node_spec.rb +13 -14
- data/spec/spec_helper.rb +8 -7
- data/spec/support_spec.rb +19 -24
- data/test_matrix.rb +4 -3
- metadata +6 -2
@@ -1,334 +1,333 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'code/loc'
|
2
3
|
require_relative 'code/code_range'
|
3
4
|
require_relative 'code/code_file'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
# @param [String] filename The name of a file, or "(pry)".
|
21
|
-
# @param [Symbol] code_type The type of code the file contains.
|
22
|
-
# @return [Code]
|
23
|
-
def from_file(filename, code_type = nil)
|
24
|
-
code_file = CodeFile.new(filename, code_type)
|
25
|
-
new(code_file.code, 1, code_file.code_type, filename)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Instantiate a `Code` object containing code loaded from a file or
|
29
|
-
# Pry's line buffer.
|
30
|
-
#
|
31
|
-
# @param [String] source code".
|
32
|
-
# @param [Symbol] code_type The type of code the file contains.
|
33
|
-
# @return [Code]
|
34
|
-
def from_string(code, code_type = nil)
|
35
|
-
new(code, 1, code_type)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# @return [Symbol] The type of code stored in this wrapper.
|
40
|
-
attr_accessor :code_type, :filename
|
41
|
-
|
42
|
-
# Instantiate a `Code` object containing code from the given `Array`,
|
43
|
-
# `String`, or `IO`. The first line will be line 1 unless specified
|
44
|
-
# otherwise. If you need non-contiguous line numbers, you can create an
|
45
|
-
# empty `Code` object and then use `#push` to insert the lines.
|
46
|
-
#
|
47
|
-
# @param [Array<String>, String, IO] lines
|
48
|
-
# @param [Integer?] start_line
|
49
|
-
# @param [Symbol?] code_type
|
50
|
-
def initialize(lines = [], start_line = 1, code_type = :ruby, filename=nil)
|
51
|
-
if lines.is_a? String
|
52
|
-
lines = lines.lines
|
53
|
-
end
|
54
|
-
@lines = lines.each_with_index.map { |line, lineno|
|
55
|
-
LOC.new(line, lineno + start_line.to_i) }
|
56
|
-
@code_type = code_type
|
57
|
-
@filename = filename
|
58
|
-
@with_file_reference = nil
|
59
|
-
@with_marker = @with_indentation = nil
|
60
|
-
end
|
61
|
-
|
62
|
-
# Append the given line. +lineno+ is one more than the last existing
|
63
|
-
# line, unless specified otherwise.
|
64
|
-
#
|
65
|
-
# @param [String] line
|
66
|
-
# @param [Integer?] lineno
|
67
|
-
# @return [String] The inserted line.
|
68
|
-
def push(line, lineno = nil)
|
69
|
-
if lineno.nil?
|
70
|
-
lineno = @lines.last.lineno + 1
|
71
|
-
end
|
72
|
-
@lines.push(LOC.new(line, lineno))
|
73
|
-
line
|
74
|
-
end
|
75
|
-
alias << push
|
76
|
-
|
77
|
-
# Filter the lines using the given block.
|
6
|
+
# `Pry::Code` is a class that encapsulates lines of source code and their
|
7
|
+
# line numbers and formats them for terminal output. It can read from a file
|
8
|
+
# or method definition or be instantiated with a `String` or an `Array`.
|
9
|
+
#
|
10
|
+
# In general, the formatting methods in `Code` return a new `Code` object
|
11
|
+
# which will format the text as specified when `#to_s` is called. This allows
|
12
|
+
# arbitrary chaining of formatting methods without mutating the original
|
13
|
+
# object.
|
14
|
+
class DebuggerCode
|
15
|
+
class << self
|
16
|
+
# include MethodSource::CodeHelpers
|
17
|
+
|
18
|
+
# Instantiate a `Code` object containing code loaded from a file or
|
19
|
+
# Pry's line buffer.
|
78
20
|
#
|
79
|
-
# @
|
21
|
+
# @param [String] filename The name of a file, or "(pry)".
|
22
|
+
# @param [Symbol] code_type The type of code the file contains.
|
80
23
|
# @return [Code]
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
end
|
24
|
+
def from_file(filename, code_type = nil)
|
25
|
+
code_file = CodeFile.new(filename, code_type)
|
26
|
+
new(code_file.code, 1, code_file.code_type, filename)
|
85
27
|
end
|
86
28
|
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# indices count from the end of the array of lines.
|
29
|
+
# Instantiate a `Code` object containing code loaded from a file or
|
30
|
+
# Pry's line buffer.
|
90
31
|
#
|
91
|
-
# @param [
|
92
|
-
# @param [
|
32
|
+
# @param [String] source code".
|
33
|
+
# @param [Symbol] code_type The type of code the file contains.
|
93
34
|
# @return [Code]
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
code_range = CodeRange.new(start_line, end_line)
|
98
|
-
|
99
|
-
alter do
|
100
|
-
@lines = @lines[code_range.indices_range(@lines)] || []
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Take `num_lines` from `start_line`, forward or backwards.
|
105
|
-
#
|
106
|
-
# @param [Integer] start_line
|
107
|
-
# @param [Integer] num_lines
|
108
|
-
# @return [Code]
|
109
|
-
def take_lines(start_line, num_lines)
|
110
|
-
start_idx =
|
111
|
-
if start_line >= 0
|
112
|
-
@lines.index { |loc| loc.lineno >= start_line } || @lines.length
|
113
|
-
else
|
114
|
-
[@lines.length + start_line, 0].max
|
115
|
-
end
|
116
|
-
|
117
|
-
alter do
|
118
|
-
@lines = @lines.slice(start_idx, num_lines)
|
119
|
-
end
|
35
|
+
def from_string(code, code_type = nil)
|
36
|
+
new(code, 1, code_type)
|
120
37
|
end
|
38
|
+
end
|
121
39
|
|
122
|
-
|
123
|
-
|
124
|
-
# @param [Integer] lineno
|
125
|
-
# @param [Integer] lines
|
126
|
-
# @return [Code]
|
127
|
-
def before(lineno, lines = 1)
|
128
|
-
return self unless lineno
|
40
|
+
# @return [Symbol] The type of code stored in this wrapper.
|
41
|
+
attr_accessor :code_type, :filename
|
129
42
|
|
130
|
-
|
131
|
-
|
132
|
-
|
43
|
+
# Instantiate a `Code` object containing code from the given `Array`,
|
44
|
+
# `String`, or `IO`. The first line will be line 1 unless specified
|
45
|
+
# otherwise. If you need non-contiguous line numbers, you can create an
|
46
|
+
# empty `Code` object and then use `#push` to insert the lines.
|
47
|
+
#
|
48
|
+
# @param [Array<String>, String, IO] lines
|
49
|
+
# @param [Integer?] start_line
|
50
|
+
# @param [Symbol?] code_type
|
51
|
+
def initialize(lines = [], start_line = 1, code_type = :ruby, filename = nil)
|
52
|
+
lines = lines.lines if lines.is_a? String
|
53
|
+
@lines = lines.each_with_index.map do |line, lineno|
|
54
|
+
LOC.new(line, lineno + start_line.to_i)
|
133
55
|
end
|
56
|
+
@code_type = code_type
|
57
|
+
@filename = filename
|
58
|
+
@with_file_reference = nil
|
59
|
+
@with_marker = @with_indentation = nil
|
60
|
+
end
|
134
61
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
62
|
+
# Append the given line. +lineno+ is one more than the last existing
|
63
|
+
# line, unless specified otherwise.
|
64
|
+
#
|
65
|
+
# @param [String] line
|
66
|
+
# @param [Integer?] lineno
|
67
|
+
# @return [String] The inserted line.
|
68
|
+
def push(line, lineno = nil)
|
69
|
+
lineno = @lines.last.lineno + 1 if lineno.nil?
|
70
|
+
@lines.push(LOC.new(line, lineno))
|
71
|
+
line
|
72
|
+
end
|
73
|
+
alias << push
|
143
74
|
|
144
|
-
|
145
|
-
|
146
|
-
|
75
|
+
# Filter the lines using the given block.
|
76
|
+
#
|
77
|
+
# @yield [LOC]
|
78
|
+
# @return [Code]
|
79
|
+
def select(&block)
|
80
|
+
alter do
|
81
|
+
@lines = @lines.select(&block)
|
147
82
|
end
|
83
|
+
end
|
148
84
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
loc.lineno > lineno && loc.lineno <= lineno + lines
|
159
|
-
end
|
160
|
-
end
|
85
|
+
# Remove all lines that aren't in the given range, expressed either as a
|
86
|
+
# `Range` object or a first and last line number (inclusive). Negative
|
87
|
+
# indices count from the end of the array of lines.
|
88
|
+
#
|
89
|
+
# @param [Range, Integer] start_line
|
90
|
+
# @param [Integer?] end_line
|
91
|
+
# @return [Code]
|
92
|
+
def between(start_line, end_line = nil)
|
93
|
+
return self unless start_line
|
161
94
|
|
162
|
-
|
163
|
-
#
|
164
|
-
# @param [Regexp] pattern
|
165
|
-
# @return [Code]
|
166
|
-
def grep(pattern)
|
167
|
-
return self unless pattern
|
168
|
-
pattern = Regexp.new(pattern)
|
95
|
+
code_range = CodeRange.new(start_line, end_line)
|
169
96
|
|
170
|
-
|
171
|
-
|
172
|
-
end
|
97
|
+
alter do
|
98
|
+
@lines = @lines[code_range.indices_range(@lines)] || []
|
173
99
|
end
|
100
|
+
end
|
174
101
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
102
|
+
# Take `num_lines` from `start_line`, forward or backwards.
|
103
|
+
#
|
104
|
+
# @param [Integer] start_line
|
105
|
+
# @param [Integer] num_lines
|
106
|
+
# @return [Code]
|
107
|
+
def take_lines(start_line, num_lines)
|
108
|
+
start_idx =
|
109
|
+
if start_line >= 0
|
110
|
+
@lines.index { |loc| loc.lineno >= start_line } || @lines.length
|
111
|
+
else
|
112
|
+
[@lines.length + start_line, 0].max
|
182
113
|
end
|
183
|
-
end
|
184
114
|
|
185
|
-
|
186
|
-
|
187
|
-
# @param [Boolean?] y_n
|
188
|
-
# @return [Code]
|
189
|
-
def with_file_reference(y_n = true)
|
190
|
-
alter do
|
191
|
-
@with_file_reference = y_n
|
192
|
-
end
|
115
|
+
alter do
|
116
|
+
@lines = @lines.slice(start_idx, num_lines)
|
193
117
|
end
|
118
|
+
end
|
194
119
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
120
|
+
# Remove all lines except for the +lines+ up to and excluding +lineno+.
|
121
|
+
#
|
122
|
+
# @param [Integer] lineno
|
123
|
+
# @param [Integer] lines
|
124
|
+
# @return [Code]
|
125
|
+
def before(lineno, lines = 1)
|
126
|
+
return self unless lineno
|
127
|
+
|
128
|
+
select do |loc|
|
129
|
+
loc.lineno >= lineno - lines && loc.lineno < lineno
|
205
130
|
end
|
131
|
+
end
|
206
132
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
133
|
+
# Remove all lines except for the +lines+ on either side of and including
|
134
|
+
# +lineno+.
|
135
|
+
#
|
136
|
+
# @param [Integer] lineno
|
137
|
+
# @param [Integer] lines
|
138
|
+
# @return [Code]
|
139
|
+
def around(lineno, lines = 1)
|
140
|
+
return self unless lineno
|
141
|
+
|
142
|
+
select do |loc|
|
143
|
+
loc.lineno >= lineno - lines && loc.lineno <= lineno + lines
|
217
144
|
end
|
145
|
+
end
|
218
146
|
|
219
|
-
|
220
|
-
|
221
|
-
|
147
|
+
# Remove all lines except for the +lines+ after and excluding +lineno+.
|
148
|
+
#
|
149
|
+
# @param [Integer] lineno
|
150
|
+
# @param [Integer] lines
|
151
|
+
# @return [Code]
|
152
|
+
def after(lineno, lines = 1)
|
153
|
+
return self unless lineno
|
154
|
+
|
155
|
+
select do |loc|
|
156
|
+
loc.lineno > lineno && loc.lineno <= lineno + lines
|
222
157
|
end
|
158
|
+
end
|
223
159
|
|
224
|
-
|
225
|
-
|
226
|
-
|
160
|
+
# Remove all lines that don't match the given `pattern`.
|
161
|
+
#
|
162
|
+
# @param [Regexp] pattern
|
163
|
+
# @return [Code]
|
164
|
+
def grep(pattern)
|
165
|
+
return self unless pattern
|
166
|
+
pattern = Regexp.new(pattern)
|
167
|
+
|
168
|
+
select do |loc|
|
169
|
+
loc.line =~ pattern
|
227
170
|
end
|
171
|
+
end
|
228
172
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
173
|
+
# Format output with line numbers next to it, unless `y_n` is falsy.
|
174
|
+
#
|
175
|
+
# @param [Boolean?] y_n
|
176
|
+
# @return [Code]
|
177
|
+
def with_line_numbers(y_n = true)
|
178
|
+
alter do
|
179
|
+
@with_line_numbers = y_n
|
233
180
|
end
|
181
|
+
end
|
234
182
|
|
235
|
-
|
236
|
-
|
237
|
-
|
183
|
+
# Format output with line numbers next to it, unless `y_n` is falsy.
|
184
|
+
#
|
185
|
+
# @param [Boolean?] y_n
|
186
|
+
# @return [Code]
|
187
|
+
def with_file_reference(y_n = true)
|
188
|
+
alter do
|
189
|
+
@with_file_reference = y_n
|
238
190
|
end
|
191
|
+
end
|
239
192
|
|
240
|
-
|
241
|
-
|
193
|
+
# Format output with a marker next to the given +lineno+, unless +lineno+ is
|
194
|
+
# falsy.
|
195
|
+
#
|
196
|
+
# @param [Integer?] lineno
|
197
|
+
# @return [Code]
|
198
|
+
def with_marker(lineno = 1)
|
199
|
+
alter do
|
200
|
+
@with_marker = !!lineno
|
201
|
+
@marker_lineno = lineno
|
242
202
|
end
|
203
|
+
end
|
243
204
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
output << loc.line
|
254
|
-
output << "\n"
|
255
|
-
end
|
256
|
-
output
|
205
|
+
# Format output with the specified number of spaces in front of every line,
|
206
|
+
# unless `spaces` is falsy.
|
207
|
+
#
|
208
|
+
# @param [Integer?] spaces
|
209
|
+
# @return [Code]
|
210
|
+
def with_indentation(spaces = 0)
|
211
|
+
alter do
|
212
|
+
@with_indentation = !!spaces
|
213
|
+
@indentation_num = spaces
|
257
214
|
end
|
215
|
+
end
|
258
216
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
def comment_describing(line_number)
|
264
|
-
self.class.comment_describing(raw, line_number)
|
265
|
-
end
|
217
|
+
# @return [String]
|
218
|
+
def inspect
|
219
|
+
Object.instance_method(:to_s).bind(self).call
|
220
|
+
end
|
266
221
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
def expression_at(line_number, consume = 0)
|
272
|
-
self.class.expression_at(raw, line_number, :consume => consume)
|
273
|
-
end
|
222
|
+
# @return [Integer] the number of digits in the last line.
|
223
|
+
def max_lineno_width
|
224
|
+
!@lines.empty? ? @lines.last.lineno.to_s.length : 0
|
225
|
+
end
|
274
226
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
#self.class.expression_at(raw, line_number, :consume => consume)
|
281
|
-
raw
|
282
|
-
end
|
227
|
+
# @return [String] a formatted representation (based on the configuration of
|
228
|
+
# the object).
|
229
|
+
def to_s
|
230
|
+
print_to_output('', false)
|
231
|
+
end
|
283
232
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
# @return [Array<Module>] a list of open modules.
|
289
|
-
def nesting_at(line_number, top_module = Object)
|
290
|
-
Indent.nesting_at(raw, line_number)
|
291
|
-
end
|
233
|
+
# @return [String] a (possibly highlighted) copy of the source code.
|
234
|
+
def highlighted
|
235
|
+
print_to_output('', true)
|
236
|
+
end
|
292
237
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
@lines.map(&:line).join("\n") << "\n"
|
298
|
-
end
|
238
|
+
def add_file_reference
|
239
|
+
return "From inline code: \n" unless filename
|
240
|
+
"From file: #{File.basename(filename)}\n"
|
241
|
+
end
|
299
242
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
243
|
+
# Writes a formatted representation (based on the configuration of the
|
244
|
+
# object) to the given output, which must respond to `#<<`.
|
245
|
+
def print_to_output(output, _color = false)
|
246
|
+
output << add_file_reference if @with_file_reference
|
247
|
+
@lines.each do |loc|
|
248
|
+
loc = loc.dup
|
249
|
+
loc.add_line_number(max_lineno_width) if @with_line_numbers
|
250
|
+
loc.add_marker(@marker_lineno) if @with_marker
|
251
|
+
loc.indent(@indentation_num) if @with_indentation
|
252
|
+
output << loc.line
|
253
|
+
output << "\n"
|
305
254
|
end
|
255
|
+
output
|
256
|
+
end
|
306
257
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
other_lines = other.instance_variable_get(:@lines)
|
315
|
-
@lines.each_with_index.all? { |loc, i| loc == other_lines[i] }
|
316
|
-
else
|
317
|
-
to_s.chomp == other.to_s.chomp
|
318
|
-
end
|
319
|
-
end
|
258
|
+
# Get the comment that describes the expression on the given line number.
|
259
|
+
#
|
260
|
+
# @param [Integer] line_number (1-based)
|
261
|
+
# @return [String] the code.
|
262
|
+
def comment_describing(line_number)
|
263
|
+
self.class.comment_describing(raw, line_number)
|
264
|
+
end
|
320
265
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
266
|
+
# Get the multiline expression that starts on the given line number.
|
267
|
+
#
|
268
|
+
# @param [Integer] line_number (1-based)
|
269
|
+
# @return [String] the code.
|
270
|
+
def expression_at(line_number, consume = 0)
|
271
|
+
self.class.expression_at(raw, line_number, consume: consume)
|
272
|
+
end
|
273
|
+
|
274
|
+
# Get the multiline expression that starts on the given line number.
|
275
|
+
#
|
276
|
+
# @param [Integer] line_number (1-based)
|
277
|
+
# @return [String] the code.
|
278
|
+
def self.expression_at(raw, _line_number, _consume = 0)
|
279
|
+
# self.class.expression_at(raw, line_number, :consume => consume)
|
280
|
+
raw
|
281
|
+
end
|
282
|
+
|
283
|
+
# Get the (approximate) Module.nesting at the give line number.
|
284
|
+
#
|
285
|
+
# @param [Integer] line_number line number starting from 1
|
286
|
+
# @param [Module] top_module the module in which this code exists
|
287
|
+
# @return [Array<Module>] a list of open modules.
|
288
|
+
def nesting_at(line_number, _top_module = Object)
|
289
|
+
Indent.nesting_at(raw, line_number)
|
290
|
+
end
|
326
291
|
|
327
|
-
|
292
|
+
# Return an unformatted String of the code.
|
293
|
+
#
|
294
|
+
# @return [String]
|
295
|
+
def raw
|
296
|
+
@lines.map(&:line).join("\n") << "\n"
|
297
|
+
end
|
328
298
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
299
|
+
# Return the number of lines stored.
|
300
|
+
#
|
301
|
+
# @return [Integer]
|
302
|
+
def length
|
303
|
+
@lines ? @lines.length : 0
|
304
|
+
end
|
305
|
+
|
306
|
+
# Two `Code` objects are equal if they contain the same lines with the same
|
307
|
+
# numbers. Otherwise, call `to_s` and `chomp` and compare as Strings.
|
308
|
+
#
|
309
|
+
# @param [Code, Object] other
|
310
|
+
# @return [Boolean]
|
311
|
+
def ==(other)
|
312
|
+
if other.is_a?(Code)
|
313
|
+
other_lines = other.instance_variable_get(:@lines)
|
314
|
+
@lines.each_with_index.all? { |loc, i| loc == other_lines[i] }
|
315
|
+
else
|
316
|
+
to_s.chomp == other.to_s.chomp
|
333
317
|
end
|
334
318
|
end
|
319
|
+
|
320
|
+
# Forward any missing methods to the output of `#to_s`.
|
321
|
+
def method_missing(name, *args, &block)
|
322
|
+
to_s.send(name, *args, &block)
|
323
|
+
end
|
324
|
+
undef =~
|
325
|
+
|
326
|
+
protected
|
327
|
+
|
328
|
+
# An abstraction of the `dup.instance_eval` pattern used throughout this
|
329
|
+
# class.
|
330
|
+
def alter(&block)
|
331
|
+
dup.tap { |o| o.instance_eval(&block) }
|
332
|
+
end
|
333
|
+
end
|