parser 2.4.0.2 → 2.5.0.0

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.
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