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

Update RuboCop and use children matching #804

Merged

Conversation

pirj
Copy link
Member

@pirj pirj commented Aug 11, 2019

Children matching was introduced in RuboCop 0.68.0.
This is a conservative update of RuboCop dependency to 0.68.1 (that has some minor bug fixes compared to 0.68.0).

A couple of our cops were updated to use children matching.
It allowed to convert iterations with that new pattern syntax, and reduce the amount of code.

Focus cop is intentionally left unchanged, there are improvements for it in #777 that are making use of the new syntax as well.

As per #777 (comment) and #773 (comment).

It seems I just had a stroke of image syndrome.


Before submitting the PR make sure the following are checked:

  • 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.
  • The build (bundle exec rake) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).

@pirj pirj force-pushed the update-rubocop-and-use-children-matching branch from 5e52386 to 59401bb Compare August 11, 2019 20:49
@pirj pirj changed the title Update RuboCop and use hash children matching where possible Update RuboCop and use children matching where possible Aug 11, 2019
@pirj pirj force-pushed the update-rubocop-and-use-children-matching branch from 8161102 to 3d908ff Compare August 11, 2019 21:06
@pirj pirj changed the title Update RuboCop and use children matching where possible Update RuboCop and use children matching Aug 11, 2019
@pirj pirj force-pushed the update-rubocop-and-use-children-matching branch from 6a5b595 to d711a3b Compare August 11, 2019 22:10
(block {
(send _ _ <(sym :aggregate_failures) ...>)
(send _ _ ... (hash <(pair (sym :aggregate_failures) _) ...>))
} ...)
Copy link
Member Author

Choose a reason for hiding this comment

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

Appreciate a hint how to collapse the two above node patterns into one with % syntax.

Tried replacing them with:

        def_node_matcher :aggregate_failures?, <<-PATTERN
          (block {
              (send _ _ <(sym :aggregate_failures) ...>)
              (send _ _ ... (hash <(pair (sym :aggregate_failures) %) ...>))
            } ...)
        PATTERN

and using as aggregate_failures?(node, true), aggregate_failures?(node, :true), and aggregate_failures?(node, 'true') - none of those variants worked.

Copy link
Member

Choose a reason for hiding this comment

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

How about just capturing the argument, then in the block that checks for aggregate_failures you just need to check whether the node matched and if there is a captured value - it is true?

Copy link
Member Author

@pirj pirj Aug 12, 2019

Choose a reason for hiding this comment

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

It turns out to become quite hacky for two reasons:

  • I have to also capture from the other {} branch
  • in the latter branch it's expected to be a boolean, for the former it will be a symbol

so I have to check it like that:

def_node_matcher :aggregate_failures?, <<-PATTERN
  (block {
    (send _ _ <$(sym :aggregate_failures) ...>)
    (send _ _ ... (hash <(pair (sym :aggregate_failures) $_) ...>))
  } ...)
PATTERN

def example_with_aggregate_failures?(example_node)
  node_with_aggregate_failures = find_aggregate_failures(example_node)
  return false unless node_with_aggregate_failures

  aggregate_failures = aggregate_failures?(node_with_aggregate_failures)
  aggregate_failures.true_type? || aggregate_failures.sym_type?
end

it works, but it's hard to understand.
Tried reading RuboCop's own usages of %-syntax, still can't understand how it works, and if it's possible to pass it an _ with no success.

I'd rather keep this as is, it's easier to spot the redundancy like that and address in the future. WDYT?

On the other note, I added a line to the changelog, but there were no user-facing changes, so just mentioning that RuboCop version dependency has been updated.

Copy link
Member Author

Choose a reason for hiding this comment

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

@marcandre Do you happen to know if it's possible to pass a boolean or an any as a node matcher argument (to substitute %)? I think I tried with booleans and failed.

Copy link
Contributor

@marcandre marcandre Jun 11, 2020

Choose a reason for hiding this comment

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

Super interesting question. Turns out you won't be able to because the check is that node == your_arg. We should revert that order for more flexibility, so it is possible to define an any matcher (ANY = Object.new.tap {|o| def o.==(_); true; end})
I'm thinking of something even a bit nicer, PR incoming

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it, thanks!
Please keep in mind it's a pretty narrow case with just one potential usage I know if. Other cops here in rubocop-rspec using % provide symbols, and it's quite sufficient for them.

And this cop works as well, I just keep it somewhere in my mind's dirty corner that it might be improved.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a simple change, but so much more powerful https://github.com/rubocop-hq/rubocop-ast/pull/31. You could have ANY = ->(_) { true } and pass that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Two node patterns easily collapsed into one with this new generic parameters #930

@bquorning bquorning mentioned this pull request Aug 12, 2019
5 tasks
Copy link
Member

@Darhazer Darhazer left a comment

Choose a reason for hiding this comment

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

You also need to add a changelog entry

@pirj pirj force-pushed the update-rubocop-and-use-children-matching branch from 406978b to 13787e7 Compare August 12, 2019 08:58
@pirj
Copy link
Member Author

pirj commented Aug 17, 2019

@bquorning @Darhazer @dgollahon Is there anything that needs to be addressed here?

Speaking of aggregate_failures?/aggregate_failures_present? - I would rather keep two very similar patterns in hope to collapse them into one in the moment of enlightenment rather than to build support code around an improperly collapsed one to work around the difference in its application.

@pirj pirj force-pushed the update-rubocop-and-use-children-matching branch from 13787e7 to ddb6a12 Compare August 18, 2019 20:43
@pirj
Copy link
Member Author

pirj commented Aug 18, 2019

Fixed CHANGELOG conflict.

@bquorning
Copy link
Collaborator

@dgollahon Would you have time to review this PR?

@pirj
Copy link
Member Author

pirj commented Sep 6, 2019

@dgollahon Appreciate if you could take a look. Those changes are very similar to what you did in #777.

Copy link
Collaborator

@bquorning bquorning left a comment

Choose a reason for hiding this comment

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

I’m inclined to just merge this – the changes look fine, as far as I can see, and I’m pretty confident that the spec suite covers what I didn’t see :-)

def factory_key?(hash_node)
hash_node.keys.any? { |key| key.sym_type? && key.value == :factory }
end
def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
Copy link
Collaborator

Choose a reason for hiding this comment

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

❤️ It’s so concise! I just hope people (we) will find it readable in the future.

@bquorning bquorning merged commit 59dc17b into rubocop:master Sep 7, 2019
@pirj pirj deleted the update-rubocop-and-use-children-matching branch September 20, 2019 19:03
pirj added a commit that referenced this pull request Jun 11, 2020
#804 (comment)
Support introduced in rubocop/rubocop-ast#31
Presumably this will land in RuboCop 1.0 or 1.0.1 worst case.
pirj added a commit that referenced this pull request Jul 15, 2020
#804 (comment)
Support introduced in rubocop/rubocop-ast#31
Presumably this will land in RuboCop 1.0 or 1.0.1 worst case.
pirj added a commit that referenced this pull request Jul 15, 2020
#804 (comment)
Support introduced in rubocop/rubocop-ast#31
Presumably this will land in RuboCop 1.0 or 1.0.1 worst case.
pirj added a commit that referenced this pull request Jul 15, 2020
#804 (comment)
Support introduced in rubocop/rubocop-ast#31
Presumably this will land in RuboCop 1.0 or 1.0.1 worst case.
pirj added a commit that referenced this pull request Jul 15, 2020
#804 (comment)
Support introduced in rubocop/rubocop-ast#31
Presumably this will land in RuboCop 1.0 or 1.0.1 worst case.
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.

None yet

4 participants