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

[Fix #5054] Lint/UnneededSplatExpansion: Array.new inside literal #5071

Conversation

akhramov
Copy link

@akhramov akhramov commented Nov 18, 2017

Currently Lint/UnneededSplatExpansion reports an offense when
Array.new is used inside array literal:

foo = [1, 2, *Array.new(foo), 6]

Moreover, cop autocorrects this code to following:

foo = [1, 2, [Array.new(foo)], 6]

This change adds a check whether Array.new resides in an array
literal, and if it does, the cop acts as following depending on
amount of elements in the literal:

Example Offense reported? Autocorrects to
[*Array.new(foo)] Yes Array.new(foo)
[*Array.new(foo), 1] No N/A

Before submitting the PR make sure the following are checked:

  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Used the same coding conventions as the rest of the project.
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Added an entry to the Changelog if the new code introduces user-observable changes. See changelog entry format.
  • All tests(rake spec) are passing.
  • The new code doesn't generate RuboCop offenses that are checked by rake internal_investigation.
  • The PR relates to only one subject with a clear title
    and description in grammatically correct, complete sentences.
  • Updated cop documentation with rake generate_cops_documentation (required only when you've added a new cop or changed the configuration/documentation of an existing cop).

@akhramov akhramov changed the title [Fix #5054] UnneededSplatExpansion: Array.new inside literal [Fix #5054] Lint/UnneededSplatExpansion: Array.new inside literal Nov 18, 2017
@akhramov akhramov force-pushed the fix/unneeded-splat-expansion-array-new-in-literal branch from cc6f8f3 to 78fe952 Compare November 18, 2017 12:16
grandparent.array_type? && grandparent.children.count > 1
end

# rubocop:disable Metrics/AbcSize
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. This actually exceeds the ABC size (which is already inflated) of any other method in the entire application. We should probably think about whether this method can be simplified, extracted, or factored differently. 🙂

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

That's a tough one. I'm not very happy with my current solution, because we have to use corrector.replace(loc.operator, '') instead of corrector.remove(loc.operator)...

if object.send_type?
return unless ASSIGNMENT_TYPES.include?(node.parent.parent.type)
end
def_node_matcher :array_new?, ARRAY_NEW_PATTERN
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change, I would inline the pattern in #array_new? and call refer to that within #literal_expansion? instead. 🙂 (Might need to reorder the two pattern definitions.)

@@ -80,12 +78,36 @@ def on_splat(node)

private

def unneeded_splat_expansion(node)
literal_expansion?(node) do |object|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change "object" to something more meaningful. 🙂

@akhramov akhramov force-pushed the fix/unneeded-splat-expansion-array-new-in-literal branch from 78fe952 to d52f7f4 Compare November 20, 2017 17:42
return false unless array_new?(array_new_node)

grandparent = array_new_node.parent.parent
grandparent.array_type? && grandparent.children.count > 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use size instead of count. It is more efficient with no arguments.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, thanks!


context 'when Array.new is expanded' do
context 'and the array contains more than one element' do
it 'does not autocorrect' do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't normally test that something isn't auto-corrected. This is redundant because autocorrect will not be called if there isn't an offense.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks!

Currently `Lint/UnneededSplatExpansion` reports an offense when
`Array.new` is used inside array literal:

```ruby
foo = [1, 2, *Array.new(foo), 6]
```
Moreover, cop autocorrects this code to following:

```ruby
foo = [1, 2, [Array.new(foo)], 6]
```

This change adds a check whether `Array.new` resides in an array
literal, and if it does, the cop acts as following depending on
amount of elements in the literal:

| Example                | Offense reported?  | Autocorrects to  |
|------------------------|--------------------|------------------|
| `[*Array.new(foo)]`    | Yes                | `Array.new(foo)` |
| `[*Array.new(foo), 1]` | No                 |  N/A             |
@akhramov akhramov force-pushed the fix/unneeded-splat-expansion-array-new-in-literal branch from d52f7f4 to 2c20986 Compare November 21, 2017 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants