Skip to content

Commit 5459734

Browse files
Earlopainmarcandre
authored andcommitted
[Fix #360] Fix an error when the Array core class contains a writer method
This is a syntax error: ``` def foo=(...) end ``` So it must use `public_send` instead in that case. It's caused by https://github.com/rubocop/rubocop-ast/blob/47e0eead4b84c3d28d7251a548e152f914219773/lib/rubocop/ast/node/mixin/collection_node.rb#L9-L10 By default the `Array` class doesn't contain such methods but when something like spring is in use, code can be evaluated before rubocop. I thought about simply rejecting such methods but supporting it is easy enough
1 parent 47e0eea commit 5459734

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

changelog/fix_array_writer_method.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#360](https://github.com/rubocop/rubocop-ast/pull/360): Fix an error when the `Array` core class contains a writer method before `rubocop-ast` loaded. ([@earlopain][])

lib/rubocop/ast/utilities/simple_forwardable.rb

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,22 @@ module RuboCop
55
module SimpleForwardable
66
def def_delegators(accessor, *methods)
77
methods.each do |method|
8-
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
9-
def #{method}(...) # def example(...)
10-
#{accessor}.#{method}(...) # foo.example(...)
11-
end # end
12-
RUBY
8+
if method.end_with?('=') && method.to_s != '[]='
9+
# Defining a delegator for `foo=` can't use `foo=(...)` because it is a
10+
# syntax error. Fall back to doing a slower `public_send` instead.
11+
# TODO: Use foo(method, ...) when Ruby 3.1 is required.
12+
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
13+
def #{method}(*args, **kwargs, &blk) # def example=(*args, **kwargs, &blk)
14+
#{accessor}.public_send(:#{method}, *args, **kwargs, &blk) # foo.public_send(:example=, *args, **kwargs, &blk)
15+
end # end
16+
RUBY
17+
else
18+
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
19+
def #{method}(...) # def example(...)
20+
#{accessor}.#{method}(...) # foo.example(...)
21+
end # end
22+
RUBY
23+
end
1324
end
1425
end
1526
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe RuboCop::SimpleForwardable do
4+
let(:delegator) do
5+
Class.new do
6+
attr_reader :target
7+
8+
def initialize
9+
@target = Struct.new(:foo).new
10+
end
11+
12+
extend RuboCop::SimpleForwardable
13+
14+
def_delegators :target, :foo=, :foo
15+
end
16+
end
17+
18+
it 'correctly delegates to writer methods' do
19+
d = delegator.new
20+
d.foo = 123
21+
expect(d.foo).to eq(123)
22+
end
23+
end

0 commit comments

Comments
 (0)