parser 2.4.0.2 → 2.5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/CHANGELOG.md +35 -1
  4. data/Gemfile +2 -0
  5. data/README.md +1 -2
  6. data/Rakefile +2 -1
  7. data/bin/ruby-parse +2 -1
  8. data/bin/ruby-rewrite +2 -1
  9. data/lib/gauntlet_parser.rb +2 -0
  10. data/lib/parser.rb +16 -17
  11. data/lib/parser/all.rb +2 -0
  12. data/lib/parser/ast/node.rb +2 -0
  13. data/lib/parser/ast/processor.rb +2 -0
  14. data/lib/parser/base.rb +6 -12
  15. data/lib/parser/builders/default.rb +28 -47
  16. data/lib/parser/clobbering_error.rb +2 -0
  17. data/lib/parser/context.rb +42 -0
  18. data/lib/parser/current.rb +4 -20
  19. data/lib/parser/deprecation.rb +13 -0
  20. data/lib/parser/diagnostic.rb +3 -3
  21. data/lib/parser/diagnostic/engine.rb +2 -0
  22. data/lib/parser/lexer.rl +122 -60
  23. data/lib/parser/lexer/dedenter.rb +2 -0
  24. data/lib/parser/lexer/explanation.rb +2 -0
  25. data/lib/parser/lexer/literal.rb +4 -9
  26. data/lib/parser/lexer/stack_state.rb +4 -1
  27. data/lib/parser/macruby.y +32 -17
  28. data/lib/parser/messages.rb +14 -0
  29. data/lib/parser/meta.rb +2 -0
  30. data/lib/parser/rewriter.rb +30 -44
  31. data/lib/parser/ruby18.y +20 -13
  32. data/lib/parser/ruby19.y +32 -17
  33. data/lib/parser/ruby20.y +33 -18
  34. data/lib/parser/ruby21.y +32 -17
  35. data/lib/parser/ruby22.y +32 -17
  36. data/lib/parser/ruby23.y +32 -17
  37. data/lib/parser/ruby24.y +63 -46
  38. data/lib/parser/ruby25.y +72 -48
  39. data/lib/parser/rubymotion.y +33 -18
  40. data/lib/parser/runner.rb +4 -7
  41. data/lib/parser/runner/ruby_parse.rb +10 -0
  42. data/lib/parser/runner/ruby_rewrite.rb +2 -0
  43. data/lib/parser/source/buffer.rb +19 -24
  44. data/lib/parser/source/comment.rb +2 -0
  45. data/lib/parser/source/comment/associator.rb +2 -0
  46. data/lib/parser/source/map.rb +2 -0
  47. data/lib/parser/source/map/collection.rb +2 -0
  48. data/lib/parser/source/map/condition.rb +2 -0
  49. data/lib/parser/source/map/constant.rb +2 -0
  50. data/lib/parser/source/map/definition.rb +2 -0
  51. data/lib/parser/source/map/for.rb +2 -0
  52. data/lib/parser/source/map/heredoc.rb +2 -0
  53. data/lib/parser/source/map/keyword.rb +2 -0
  54. data/lib/parser/source/map/objc_kwarg.rb +2 -0
  55. data/lib/parser/source/map/operator.rb +2 -0
  56. data/lib/parser/source/map/rescue_body.rb +2 -0
  57. data/lib/parser/source/map/send.rb +2 -0
  58. data/lib/parser/source/map/ternary.rb +2 -0
  59. data/lib/parser/source/map/variable.rb +2 -0
  60. data/lib/parser/source/range.rb +81 -13
  61. data/lib/parser/source/rewriter.rb +48 -10
  62. data/lib/parser/source/rewriter/action.rb +2 -0
  63. data/lib/parser/source/tree_rewriter.rb +301 -0
  64. data/lib/parser/source/tree_rewriter/action.rb +133 -0
  65. data/lib/parser/static_environment.rb +2 -0
  66. data/lib/parser/syntax_error.rb +2 -0
  67. data/lib/parser/tree_rewriter.rb +133 -0
  68. data/lib/parser/version.rb +3 -1
  69. data/parser.gemspec +4 -1
  70. data/test/bug_163/fixtures/input.rb +2 -0
  71. data/test/bug_163/fixtures/output.rb +2 -0
  72. data/test/bug_163/rewriter.rb +2 -0
  73. data/test/helper.rb +7 -7
  74. data/test/parse_helper.rb +57 -10
  75. data/test/racc_coverage_helper.rb +2 -0
  76. data/test/test_base.rb +2 -0
  77. data/test/test_current.rb +2 -4
  78. data/test/test_diagnostic.rb +3 -1
  79. data/test/test_diagnostic_engine.rb +2 -0
  80. data/test/test_encoding.rb +61 -49
  81. data/test/test_lexer.rb +164 -77
  82. data/test/test_lexer_stack_state.rb +2 -0
  83. data/test/test_parse_helper.rb +8 -8
  84. data/test/test_parser.rb +613 -51
  85. data/test/test_runner_rewrite.rb +47 -0
  86. data/test/test_source_buffer.rb +22 -10
  87. data/test/test_source_comment.rb +2 -0
  88. data/test/test_source_comment_associator.rb +2 -0
  89. data/test/test_source_map.rb +2 -0
  90. data/test/test_source_range.rb +92 -45
  91. data/test/test_source_rewriter.rb +3 -1
  92. data/test/test_source_rewriter_action.rb +2 -0
  93. data/test/test_source_tree_rewriter.rb +177 -0
  94. data/test/test_static_environment.rb +2 -0
  95. data/test/using_tree_rewriter/fixtures/input.rb +3 -0
  96. data/test/using_tree_rewriter/fixtures/output.rb +3 -0
  97. data/test/using_tree_rewriter/using_tree_rewriter.rb +9 -0
  98. metadata +21 -10
  99. data/lib/parser/compatibility/ruby1_8.rb +0 -20
  100. data/lib/parser/compatibility/ruby1_9.rb +0 -32
  101. data/test/bug_163/test_runner_rewrite.rb +0 -35
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'benchmark'
2
4
  require 'find'
3
5
  require 'optparse'
@@ -176,9 +178,7 @@ module Parser
176
178
 
177
179
  def process_fragments
178
180
  @fragments.each_with_index do |fragment, index|
179
- if fragment.respond_to? :force_encoding
180
- fragment = fragment.dup.force_encoding(@parser.default_encoding)
181
- end
181
+ fragment = fragment.dup.force_encoding(@parser.default_encoding)
182
182
 
183
183
  buffer = Source::Buffer.new("(fragment:#{index})")
184
184
  buffer.source = fragment
@@ -189,10 +189,7 @@ module Parser
189
189
 
190
190
  def process_files
191
191
  @files.each do |filename|
192
- source = File.read(filename)
193
- if source.respond_to? :force_encoding
194
- source.force_encoding(@parser.default_encoding)
195
- end
192
+ source = File.read(filename).force_encoding(@parser.default_encoding)
196
193
 
197
194
  buffer = Parser::Source::Buffer.new(filename)
198
195
 
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'parser/runner'
2
4
  require 'parser/lexer/explanation'
5
+ require 'json'
3
6
 
4
7
  module Parser
5
8
 
@@ -94,6 +97,7 @@ module Parser
94
97
 
95
98
  @locate = false
96
99
  @emit_ruby = false
100
+ @emit_json = false
97
101
  end
98
102
 
99
103
  private
@@ -118,6 +122,10 @@ module Parser
118
122
  opts.on '--emit-ruby', 'Emit S-expressions as valid Ruby code' do
119
123
  @emit_ruby = true
120
124
  end
125
+
126
+ opts.on '--emit-json', 'Emit S-expressions as valid JSON' do
127
+ @emit_json = true
128
+ end
121
129
  end
122
130
 
123
131
  def process_all_input
@@ -136,6 +144,8 @@ module Parser
136
144
  elsif !@benchmark
137
145
  if @emit_ruby
138
146
  puts ast.inspect
147
+ elsif @emit_json
148
+ puts JSON.generate(ast.to_sexp_array)
139
149
  else
140
150
  puts ast.to_s
141
151
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'parser/runner'
2
4
  require 'tempfile'
3
5
 
@@ -1,4 +1,5 @@
1
1
  # encoding: ascii-8bit
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Parser
4
5
  module Source
@@ -28,7 +29,7 @@ module Parser
28
29
  # @api private
29
30
  #
30
31
  ENCODING_RE =
31
- /\#.*coding\s*[:=]\s*
32
+ /\A\#\s*(en)?coding\s*[:=]\s*
32
33
  (
33
34
  # Special-case: there's a UTF8-MAC encoding.
34
35
  (utf8-mac)
@@ -63,7 +64,7 @@ module Parser
63
64
  end
64
65
 
65
66
  if (result = ENCODING_RE.match(encoding_line))
66
- Encoding.find(result[2] || result[3] || result[5])
67
+ Encoding.find(result[3] || result[4] || result[6])
67
68
  else
68
69
  nil
69
70
  end
@@ -156,13 +157,11 @@ module Parser
156
157
  # @return [String]
157
158
  #
158
159
  def source=(input)
159
- if defined?(Encoding)
160
- input = input.dup if input.frozen?
161
- input = self.class.reencode_string(input)
160
+ input = input.dup if input.frozen?
161
+ input = self.class.reencode_string(input)
162
162
 
163
- unless input.valid_encoding?
164
- raise EncodingError, "invalid byte sequence in #{input.encoding.name}"
165
- end
163
+ unless input.valid_encoding?
164
+ raise EncodingError, "invalid byte sequence in #{input.encoding.name}"
166
165
  end
167
166
 
168
167
  self.raw_source = input
@@ -182,8 +181,7 @@ module Parser
182
181
 
183
182
  @source = input.gsub("\r\n".freeze, "\n".freeze).freeze
184
183
 
185
- if defined?(Encoding) &&
186
- !@source.ascii_only? &&
184
+ if !@source.ascii_only? &&
187
185
  @source.encoding != Encoding::UTF_32LE &&
188
186
  @source.encoding != Encoding::BINARY
189
187
  @slice_source = @source.encode(Encoding::UTF_32LE)
@@ -246,7 +244,7 @@ module Parser
246
244
  def source_lines
247
245
  @lines ||= begin
248
246
  lines = @source.lines.to_a
249
- lines << '' if @source.end_with?("\n".freeze)
247
+ lines << ''.dup if @source.end_with?("\n".freeze)
250
248
 
251
249
  lines.each do |line|
252
250
  line.chomp!("\n".freeze)
@@ -288,6 +286,13 @@ module Parser
288
286
  end
289
287
  end
290
288
 
289
+ ##
290
+ # @return [Range] A range covering the whole source
291
+ #
292
+ def source_range
293
+ @source_range ||= Range.new(self, 0, source.size)
294
+ end
295
+
291
296
  ##
292
297
  # Number of last line in the buffer
293
298
  #
@@ -312,19 +317,9 @@ module Parser
312
317
  @line_begins
313
318
  end
314
319
 
315
- if [].respond_to?(:bsearch)
316
- def line_for(position)
317
- # Fast O(log n) variant for Ruby >=2.0.
318
- line_begins.bsearch do |line, line_begin|
319
- line_begin <= position
320
- end
321
- end
322
- else
323
- def line_for(position)
324
- # Slower O(n) variant for Ruby <2.0.
325
- line_begins.find do |line, line_begin|
326
- line_begin <= position
327
- end
320
+ def line_for(position)
321
+ line_begins.bsearch do |line, line_begin|
322
+ line_begin <= position
328
323
  end
329
324
  end
330
325
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
@@ -22,6 +24,8 @@ module Parser
22
24
  # @api public
23
25
  #
24
26
  class Range
27
+ include Comparable
28
+
25
29
  attr_reader :source_buffer
26
30
  attr_reader :begin_pos, :end_pos
27
31
 
@@ -49,7 +53,7 @@ module Parser
49
53
  # of this range.
50
54
  #
51
55
  def begin
52
- Range.new(@source_buffer, @begin_pos, @begin_pos)
56
+ with(end_pos: @begin_pos)
53
57
  end
54
58
 
55
59
  ##
@@ -57,7 +61,7 @@ module Parser
57
61
  # of this range.
58
62
  #
59
63
  def end
60
- Range.new(@source_buffer, @end_pos, @end_pos)
64
+ with(begin_pos: @end_pos)
61
65
  end
62
66
 
63
67
  ##
@@ -165,12 +169,30 @@ module Parser
165
169
  [@source_buffer.name, line, column + 1].join(':')
166
170
  end
167
171
 
172
+ ##
173
+ # @param [Hash] Endpoint(s) to change, any combination of :begin_pos or :end_pos
174
+ # @return [Range] the same range as this range but with the given end point(s) changed
175
+ # to the given value(s).
176
+ #
177
+ def with(begin_pos: @begin_pos, end_pos: @end_pos)
178
+ Range.new(@source_buffer, begin_pos, end_pos)
179
+ end
180
+
181
+ ##
182
+ # @param [Hash] Endpoint(s) to change, any combination of :begin_pos or :end_pos
183
+ # @return [Range] the same range as this range but with the given end point(s) adjusted
184
+ # by the given amount(s)
185
+ #
186
+ def adjust(begin_pos: 0, end_pos: 0)
187
+ Range.new(@source_buffer, @begin_pos + begin_pos, @end_pos + end_pos)
188
+ end
189
+
168
190
  ##
169
191
  # @param [Integer] new_size
170
192
  # @return [Range] a range beginning at the same point as this range and length `new_size`.
171
193
  #
172
194
  def resize(new_size)
173
- Range.new(@source_buffer, @begin_pos, @begin_pos + new_size)
195
+ with(end_pos: @begin_pos + new_size)
174
196
  end
175
197
 
176
198
  ##
@@ -197,19 +219,66 @@ module Parser
197
219
  end
198
220
 
199
221
  ##
222
+ # Return `true` iff this range and `other` are disjoint.
223
+ #
224
+ # Two ranges must be one and only one of ==, disjoint?, contains?, contained? or crossing?
225
+ #
200
226
  # @param [Range] other
201
- # @return [Boolean] `true` if this range and `other` do not overlap
227
+ # @return [Boolean]
202
228
  #
203
229
  def disjoint?(other)
204
- @begin_pos >= other.end_pos || other.begin_pos >= @end_pos
230
+ if empty? && other.empty?
231
+ @begin_pos != other.begin_pos
232
+ else
233
+ @begin_pos >= other.end_pos || other.begin_pos >= @end_pos
234
+ end
205
235
  end
206
236
 
207
237
  ##
238
+ # Return `true` iff this range is not disjoint from `other`.
239
+ #
208
240
  # @param [Range] other
209
241
  # @return [Boolean] `true` if this range and `other` overlap
210
242
  #
211
243
  def overlaps?(other)
212
- @begin_pos < other.end_pos && other.begin_pos < @end_pos
244
+ !disjoint?(other)
245
+ end
246
+
247
+ ##
248
+ # Returns true iff this range contains (strictly) `other`.
249
+ #
250
+ # Two ranges must be one and only one of ==, disjoint?, contains?, contained? or crossing?
251
+ #
252
+ # @param [Range] other
253
+ # @return [Boolean]
254
+ #
255
+ def contains?(other)
256
+ (other.begin_pos <=> @begin_pos) + (@end_pos <=> other.end_pos) >= (other.empty? ? 2 : 1)
257
+ end
258
+
259
+ ##
260
+ # Return `other.contains?(self)`
261
+ #
262
+ # Two ranges must be one and only one of ==, disjoint?, contains?, contained? or crossing?
263
+ #
264
+ # @param [Range] other
265
+ # @return [Boolean]
266
+ #
267
+ def contained?(other)
268
+ other.contains?(self)
269
+ end
270
+
271
+ ##
272
+ # Returns true iff both ranges intersect and also have different elements from one another.
273
+ #
274
+ # Two ranges must be one and only one of ==, disjoint?, contains?, contained? or crossing?
275
+ #
276
+ # @param [Range] other
277
+ # @return [Boolean]
278
+ #
279
+ def crossing?(other)
280
+ return false unless overlaps?(other)
281
+ (@begin_pos <=> other.begin_pos) * (@end_pos <=> other.end_pos) == 1
213
282
  end
214
283
 
215
284
  ##
@@ -220,14 +289,13 @@ module Parser
220
289
  end
221
290
 
222
291
  ##
223
- # Compares ranges.
224
- # @return [Boolean]
292
+ # Compare ranges, first by begin_pos, then by end_pos.
225
293
  #
226
- def ==(other)
227
- other.is_a?(Range) &&
228
- @source_buffer == other.source_buffer &&
229
- @begin_pos == other.begin_pos &&
230
- @end_pos == other.end_pos
294
+ def <=>(other)
295
+ return nil unless other.is_a?(::Parser::Source::Range) &&
296
+ @source_buffer == other.source_buffer
297
+ (@begin_pos <=> other.begin_pos).nonzero? ||
298
+ (@end_pos <=> other.end_pos)
231
299
  end
232
300
 
233
301
  ##
@@ -1,18 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  module Source
3
5
 
4
6
  ##
5
- # {Rewriter} performs the heavy lifting in the source rewriting process.
6
- # It schedules code updates to be performed in the correct order and
7
- # verifies that no two updates _clobber_ each other, that is, attempt to
8
- # modify the same section of code. (However, if two updates modify the
9
- # same section in exactly the same way, they are merged.)
7
+ # {Rewriter} is deprecated. Use {TreeRewriter} instead.
10
8
  #
11
- # If it is detected that one update clobbers another one, an `:error` and
12
- # a `:note` diagnostics describing both updates are generated and passed to
13
- # the diagnostic engine. After that, an exception is raised.
9
+ # TreeRewriter has simplified semantics, and customizable policies
10
+ # with regards to clobbering. Please read the documentation.
14
11
  #
15
- # The default diagnostic engine consumer simply prints the diagnostics to `stderr`.
12
+ # Keep in mind:
13
+ # - Rewriter was discarding the `end_pos` of the given range for `insert_before`,
14
+ # and the `begin_pos` for `insert_after`. These are meaningful in TreeRewriter.
15
+ # - TreeRewriter's wrap/insert_before/insert_after are multiple by default, while
16
+ # Rewriter would raise clobbering errors if the non '_multi' version was called.
17
+ # - The TreeRewriter policy closest to Rewriter's behavior is:
18
+ # different_replacements: :raise,
19
+ # swallowed_insertions: :raise,
20
+ # overlapping_deletions: :accept
16
21
  #
17
22
  # @!attribute [r] source_buffer
18
23
  # @return [Source::Buffer]
@@ -21,6 +26,7 @@ module Parser
21
26
  # @return [Diagnostic::Engine]
22
27
  #
23
28
  # @api public
29
+ # @deprecated Use {TreeRewriter}
24
30
  #
25
31
  class Rewriter
26
32
  attr_reader :source_buffer
@@ -28,8 +34,10 @@ module Parser
28
34
 
29
35
  ##
30
36
  # @param [Source::Buffer] source_buffer
37
+ # @deprecated Use {TreeRewriter}
31
38
  #
32
39
  def initialize(source_buffer)
40
+ self.class.warn_of_deprecation
33
41
  @diagnostics = Diagnostic::Engine.new
34
42
  @diagnostics.consumer = lambda do |diag|
35
43
  $stderr.puts diag.render
@@ -54,6 +62,7 @@ module Parser
54
62
  # @param [Range] range
55
63
  # @return [Rewriter] self
56
64
  # @raise [ClobberingError] when clobbering is detected
65
+ # @deprecated Use {TreeRewriter#remove}
57
66
  #
58
67
  def remove(range)
59
68
  append Rewriter::Action.new(range, ''.freeze)
@@ -66,11 +75,27 @@ module Parser
66
75
  # @param [String] content
67
76
  # @return [Rewriter] self
68
77
  # @raise [ClobberingError] when clobbering is detected
78
+ # @deprecated Use {TreeRewriter#insert_before}
69
79
  #
70
80
  def insert_before(range, content)
71
81
  append Rewriter::Action.new(range.begin, content)
72
82
  end
73
83
 
84
+ ##
85
+ # Inserts new code before and after the given source range.
86
+ #
87
+ # @param [Range] range
88
+ # @param [String] before
89
+ # @param [String] after
90
+ # @return [Rewriter] self
91
+ # @raise [ClobberingError] when clobbering is detected
92
+ # @deprecated Use {TreeRewriter#wrap}
93
+ #
94
+ def wrap(range, before, after)
95
+ append Rewriter::Action.new(range.begin, before)
96
+ append Rewriter::Action.new(range.end, after)
97
+ end
98
+
74
99
  ##
75
100
  # Inserts new code before the given source range by allowing other
76
101
  # insertions at the same position.
@@ -87,6 +112,7 @@ module Parser
87
112
  # @param [String] content
88
113
  # @return [Rewriter] self
89
114
  # @raise [ClobberingError] when clobbering is detected
115
+ # @deprecated Use {TreeRewriter#insert_before}
90
116
  #
91
117
  def insert_before_multi(range, content)
92
118
  @insert_before_multi_order -= 1
@@ -100,6 +126,7 @@ module Parser
100
126
  # @param [String] content
101
127
  # @return [Rewriter] self
102
128
  # @raise [ClobberingError] when clobbering is detected
129
+ # @deprecated Use {TreeRewriter#insert_after}
103
130
  #
104
131
  def insert_after(range, content)
105
132
  append Rewriter::Action.new(range.end, content)
@@ -121,6 +148,7 @@ module Parser
121
148
  # @param [String] content
122
149
  # @return [Rewriter] self
123
150
  # @raise [ClobberingError] when clobbering is detected
151
+ # @deprecated Use {TreeRewriter#insert_after}
124
152
  #
125
153
  def insert_after_multi(range, content)
126
154
  @insert_after_multi_order += 1
@@ -134,6 +162,7 @@ module Parser
134
162
  # @param [String] content
135
163
  # @return [Rewriter] self
136
164
  # @raise [ClobberingError] when clobbering is detected
165
+ # @deprecated Use {TreeRewriter#replace}
137
166
  #
138
167
  def replace(range, content)
139
168
  append Rewriter::Action.new(range, content)
@@ -144,6 +173,7 @@ module Parser
144
173
  # modified source as a new string.
145
174
  #
146
175
  # @return [String]
176
+ # @deprecated Use {TreeRewriter#process}
147
177
  #
148
178
  def process
149
179
  if in_transaction?
@@ -181,6 +211,7 @@ module Parser
181
211
  #
182
212
  # @raise [RuntimeError] when no block is passed
183
213
  # @raise [RuntimeError] when already in a transaction
214
+ # @deprecated Use {TreeRewriter#transaction}
184
215
  #
185
216
  def transaction
186
217
  unless block_given?
@@ -392,7 +423,7 @@ module Parser
392
423
  end
393
424
 
394
425
  def merge_replacements(actions)
395
- result = ''
426
+ result = ''.dup
396
427
  prev_act = nil
397
428
 
398
429
  actions.each do |act|
@@ -469,6 +500,13 @@ module Parser
469
500
  def adjacent?(range1, range2)
470
501
  range1.begin_pos <= range2.end_pos && range2.begin_pos <= range1.end_pos
471
502
  end
503
+
504
+ DEPRECATION_WARNING = [
505
+ 'Parser::Source::Rewriter is deprecated.',
506
+ 'Please update your code to use Parser::Source::TreeRewriter instead'
507
+ ].join("\n").freeze
508
+
509
+ extend Deprecation
472
510
  end
473
511
 
474
512
  end