puppet-debugger 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- # `Pry::Code` is a class that encapsulates lines of source code and their
6
- # line numbers and formats them for terminal output. It can read from a file
7
- # or method definition or be instantiated with a `String` or an `Array`.
8
- #
9
- # In general, the formatting methods in `Code` return a new `Code` object
10
- # which will format the text as specified when `#to_s` is called. This allows
11
- # arbitrary chaining of formatting methods without mutating the original
12
- # object.
13
- class DebuggerCode
14
- class << self
15
- # include MethodSource::CodeHelpers
16
-
17
- # Instantiate a `Code` object containing code loaded from a file or
18
- # Pry's line buffer.
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
- # @yield [LOC]
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 select(&block)
82
- alter do
83
- @lines = @lines.select(&block)
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
- # Remove all lines that aren't in the given range, expressed either as a
88
- # `Range` object or a first and last line number (inclusive). Negative
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 [Range, Integer] start_line
92
- # @param [Integer?] end_line
32
+ # @param [String] source code".
33
+ # @param [Symbol] code_type The type of code the file contains.
93
34
  # @return [Code]
94
- def between(start_line, end_line = nil)
95
- return self unless start_line
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
- # Remove all lines except for the +lines+ up to and excluding +lineno+.
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
- select do |loc|
131
- loc.lineno >= lineno - lines && loc.lineno < lineno
132
- end
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
- # Remove all lines except for the +lines+ on either side of and including
136
- # +lineno+.
137
- #
138
- # @param [Integer] lineno
139
- # @param [Integer] lines
140
- # @return [Code]
141
- def around(lineno, lines = 1)
142
- return self unless lineno
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
- select do |loc|
145
- loc.lineno >= lineno - lines && loc.lineno <= lineno + lines
146
- end
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
- # Remove all lines except for the +lines+ after and excluding +lineno+.
150
- #
151
- # @param [Integer] lineno
152
- # @param [Integer] lines
153
- # @return [Code]
154
- def after(lineno, lines = 1)
155
- return self unless lineno
156
-
157
- select do |loc|
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
- # Remove all lines that don't match the given `pattern`.
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
- select do |loc|
171
- loc.line =~ pattern
172
- end
97
+ alter do
98
+ @lines = @lines[code_range.indices_range(@lines)] || []
173
99
  end
100
+ end
174
101
 
175
- # Format output with line numbers next to it, unless `y_n` is falsy.
176
- #
177
- # @param [Boolean?] y_n
178
- # @return [Code]
179
- def with_line_numbers(y_n = true)
180
- alter do
181
- @with_line_numbers = y_n
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
- # Format output with line numbers next to it, unless `y_n` is falsy.
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
- # Format output with a marker next to the given +lineno+, unless +lineno+ is
196
- # falsy.
197
- #
198
- # @param [Integer?] lineno
199
- # @return [Code]
200
- def with_marker(lineno = 1)
201
- alter do
202
- @with_marker = !!lineno
203
- @marker_lineno = lineno
204
- end
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
- # Format output with the specified number of spaces in front of every line,
208
- # unless `spaces` is falsy.
209
- #
210
- # @param [Integer?] spaces
211
- # @return [Code]
212
- def with_indentation(spaces = 0)
213
- alter do
214
- @with_indentation = !!spaces
215
- @indentation_num = spaces
216
- end
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
- # @return [String]
220
- def inspect
221
- Object.instance_method(:to_s).bind(self).call
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
- # @return [Integer] the number of digits in the last line.
225
- def max_lineno_width
226
- @lines.length > 0 ? @lines.last.lineno.to_s.length : 0
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
- # @return [String] a formatted representation (based on the configuration of
230
- # the object).
231
- def to_s
232
- print_to_output("", false)
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
- # @return [String] a (possibly highlighted) copy of the source code.
236
- def highlighted
237
- print_to_output("", true)
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
- def add_file_reference
241
- "From file: #{File.basename(filename)}\n"
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
- # Writes a formatted representation (based on the configuration of the
245
- # object) to the given output, which must respond to `#<<`.
246
- def print_to_output(output, color=false)
247
- output << add_file_reference if @with_file_reference
248
- @lines.each do |loc|
249
- loc = loc.dup
250
- loc.add_line_number(max_lineno_width) if @with_line_numbers
251
- loc.add_marker(@marker_lineno) if @with_marker
252
- loc.indent(@indentation_num) if @with_indentation
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
- # Get the comment that describes the expression on the given line number.
260
- #
261
- # @param [Integer] line_number (1-based)
262
- # @return [String] the code.
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
- # Get the multiline expression that starts on the given line number.
268
- #
269
- # @param [Integer] line_number (1-based)
270
- # @return [String] the code.
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
- # Get the multiline expression that starts on the given line number.
276
- #
277
- # @param [Integer] line_number (1-based)
278
- # @return [String] the code.
279
- def self.expression_at(raw, line_number, consume = 0)
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
- # Get the (approximate) Module.nesting at the give line number.
285
- #
286
- # @param [Integer] line_number line number starting from 1
287
- # @param [Module] top_module the module in which this code exists
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
- # Return an unformatted String of the code.
294
- #
295
- # @return [String]
296
- def raw
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
- # Return the number of lines stored.
301
- #
302
- # @return [Integer]
303
- def length
304
- @lines ? @lines.length : 0
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
- # Two `Code` objects are equal if they contain the same lines with the same
308
- # numbers. Otherwise, call `to_s` and `chomp` and compare as Strings.
309
- #
310
- # @param [Code, Object] other
311
- # @return [Boolean]
312
- def ==(other)
313
- if other.is_a?(Code)
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
- # Forward any missing methods to the output of `#to_s`.
322
- def method_missing(name, *args, &block)
323
- to_s.send(name, *args, &block)
324
- end
325
- undef =~
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
- protected
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
- # An abstraction of the `dup.instance_eval` pattern used throughout this
330
- # class.
331
- def alter(&block)
332
- dup.tap { |o| o.instance_eval(&block) }
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