Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cop Idea: Replace #send(LITERAL, ...) with method call #12842

Open
jdufresne opened this issue Apr 13, 2024 · 2 comments · May be fixed by #12850
Open

Cop Idea: Replace #send(LITERAL, ...) with method call #12842

jdufresne opened this issue Apr 13, 2024 · 2 comments · May be fixed by #12850

Comments

@jdufresne
Copy link
Contributor

Is your feature request related to a problem? Please describe.

In projects I've worked on, I've seen cases where #send was called with a literal symbol or string. This can come about due to heavy refactoring where the send was once more dynamic.

For example:

# bad
send(:puts)
send('puts')
obj.send(:nil?)
obj.send('nil?')

# good
puts
obj.nil?

Describe the solution you'd like

A new cop that detects #send(LITERAL, ...) and replaces it with the method call named by the literal.

Describe alternatives you've considered

The alternative is not implementing the cop and closing this issue. As I discover these by inspection, I manually fix them.

Additional context

N/A

@Earlopain
Copy link
Contributor

send ignores method visibility. This would only really work for public_send I think.

@jdufresne
Copy link
Contributor Author

That is a good point. I suppose the cop could be configurable to apply dangerously to all send or safely to only public_send. Be default, it could be safe.

koic added a commit to koic/rubocop that referenced this issue Apr 16, 2024
Fixes rubocop#12842.

## Summary

Detects the use of the `public_send` method with a static method name argument.
Since the `send` method can be used to call private methods, by default,
only the `public_send` method is detected.

```ruby
# bad
obj.public_send(:static_name)
obj.public_send('static_name')

# good
obj.static_name
```

## Safety

This cop is not safe because it can incorrectly detect based on the receiver.
Additionally, when `AllowSend` is set to `true`, it cannot determine whether
the `send` method being detected is calling a private method.

## `AllowSend` option

This cop has `AllowSend` option.

### AllowSend: true (default)

```ruby
# good
obj.send(:static_name)
obj.send('static_name')
obj.__send__(:static_name)
obj.__send__('static_name')
```

### AllowSend: false

```ruby
# bad
obj.send(:static_name)
obj.send('static_name')
obj.__send__(:static_name)
obj.__send__('static_name')

# good
obj.static_name
```
@koic koic linked a pull request Apr 16, 2024 that will close this issue
8 tasks
koic added a commit to koic/rubocop that referenced this issue Apr 16, 2024
Fixes rubocop#12842.

## Summary

Detects the use of the `public_send` method with a static method name argument.
Since the `send` method can be used to call private methods, by default,
only the `public_send` method is detected.

```ruby
# bad
obj.public_send(:static_name)
obj.public_send('static_name')

# good
obj.static_name
```

## Safety

This cop is not safe because it can incorrectly detect based on the receiver.
Additionally, when `AllowSend` is set to `true`, it cannot determine whether
the `send` method being detected is calling a private method.

## `AllowSend` option

This cop has `AllowSend` option.

### AllowSend: true (default)

```ruby
# good
obj.send(:static_name)
obj.send('static_name')
obj.__send__(:static_name)
obj.__send__('static_name')
```

### AllowSend: false

```ruby
# bad
obj.send(:static_name)
obj.send('static_name')
obj.__send__(:static_name)
obj.__send__('static_name')

# good
obj.static_name
```
koic added a commit to koic/rubocop that referenced this issue May 2, 2024
Fixes rubocop#12842.

## Summary

Detects the use of the `public_send` method with a literal method name argument.
Since the `send` method can be used to call private methods, by default,
only the `public_send` method is detected.

```ruby
# bad
obj.public_send(:method_name)
obj.public_send('method_name')

# good
obj.method_name
```

## Safety

This cop is not safe because it can incorrectly detect based on the receiver.
Additionally, when `AllowSend` is set to `true`, it cannot determine whether
the `send` method being detected is calling a private method.

## `AllowSend` option

This cop has `AllowSend` option.

### AllowSend: true (default)

```ruby
# good
obj.send(:method_name)
obj.send('method_name')
obj.__send__(:method_name)
obj.__send__('method_name')
```

### AllowSend: false

```ruby
# bad
obj.send(:method_name)
obj.send('method_name')
obj.__send__(:method_name)
obj.__send__('method_name')

# good
obj.method_name
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants