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

Add support for itblock node for Ruby 3.4 #365

Merged
merged 1 commit into from
Mar 20, 2025
Merged

Conversation

Earlopain
Copy link
Contributor

@Earlopain Earlopain commented Mar 19, 2025

In tests, prism will always be used for Ruby 3.4+ and tests that don't pass with parser get marked as broken.

Needs whitequark/parser#1071, draft for now. The minimum parser version must be bumped in this PR, as otherwise itblock_type? method is not available.

@koic
Copy link
Member

koic commented Mar 20, 2025

Parser 3.3.7.2 has been released. Hopefully, this can move things forward.
https://rubygems.org/gems/parser/versions/3.3.7.2

@Earlopain
Copy link
Contributor Author

That should indeed be very useful, thanks! I bumped the required parser version to pull that in.

@Earlopain Earlopain marked this pull request as ready for review March 20, 2025 09:05
max_param = children[1]
1.upto(max_param).map do |i|
ArgNode.new(:arg, [:"_#{i}"])
end.freeze
end

def it_arguments
Copy link
Member

Choose a reason for hiding this comment

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

Nits, considering the it syntax, it is probably singular, isn't it?

Suggested change
def it_arguments
def it_argument

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, but it returns an array so I was a bit conflicted.

max_param = children[1]
1.upto(max_param).map do |i|
ArgNode.new(:arg, [:"_#{i}"])
end.freeze
end

def it_arguments
[ArgNode.new(:arg, [:it])].freeze
Copy link
Member

Choose a reason for hiding this comment

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

It may be possible to consider making it a constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That works, sure

@@ -170,6 +170,8 @@ The following fields are given when relevant to nodes in the source code:

|numblock|Block that has numbered arguments (`_1`) referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is an `int` (the number of numeric arguments) and the third child is a body statement.|proc { _1 + _3 }|https://rubydoc.info/github/rubocop/rubocop-ast/RuboCop/AST/BlockNode[BlockNode]

|itblock|Block that has the implicit it parameter (`it`) referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
|itblock|Block that has the implicit it parameter (`it`) referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A
|itblock|Block that has the implicit `it` parameter (`it`) referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A

max_param = children[1]
1.upto(max_param).map do |i|
ArgNode.new(:arg, [:"_#{i}"])
end.freeze
end

IMPLICIT_IT_ARGUMENT = [ArgNode.new(:arg, [:it])].freeze
private_constant :IMPLICIT_IT_ARGUMENT
Copy link
Member

@koic koic Mar 20, 2025

Choose a reason for hiding this comment

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

Can you move this constant definition above method definitions?

       include MethodIdentifierPredicates

+      IMPLICIT_IT_ARGUMENT = [ArgNode.new(:arg, [:it])].freeze
+      private_constant :IMPLICIT_IT_ARGUMENT
       VOID_CONTEXT_METHODS = %i[each tap].freeze
       private_constant :VOID_CONTEXT_METHODS

Copy link
Member

Choose a reason for hiding this comment

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

And IT_BLOCK_ARGUMENT might be a clearer name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I rather like this where it is now because it is locally close to the the numbered parameter method. Should I still move it?

Copy link
Member

Choose a reason for hiding this comment

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

Thank you for explaining the intention. However, constants are generally expected to be at the top, so please move it accordingly. This will also maintain consistency with how existing constants are handled in this file.


include RuboCop::AST::Traversal
def on_itblock(node)
(@calls ||= []) << node.children.first&.type
Copy link
Member

@koic koic Mar 20, 2025

Choose a reason for hiding this comment

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

Safe navigation seems unnecessary for this test case.

Suggested change
(@calls ||= []) << node.children.first&.type
(@calls ||= []) << node.children.first.type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it

Comment on lines 81 to 83
foo { bar(it) }
xxx { _1 }
yyy { |zzz| }
Copy link
Member

Choose a reason for hiding this comment

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

This example might be slightly adjustable. e.g.,:

Suggested change
foo { bar(it) }
xxx { _1 }
yyy { |zzz| }
it_block { do_something(it) }
numbered_block { do_something(_1) }
normal_block { |arg| do_something(arg) }

@@ -170,6 +170,8 @@ The following fields are given when relevant to nodes in the source code:

|numblock|Block that has numbered arguments (`_1`) referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is an `int` (the number of numeric arguments) and the third child is a body statement.|proc { _1 + _3 }|https://rubydoc.info/github/rubocop/rubocop-ast/RuboCop/AST/BlockNode[BlockNode]

|itblock|Block that has the implicit `it` parameter referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A
Copy link
Member

Choose a reason for hiding this comment

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

This is just a terminology adjustment for the PR overall, "implicit it parameter" doesn't seem to be a commonly used term. How about simply using "it block parameter"?

Suggested change
|itblock|Block that has the implicit `it` parameter referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A
|itblock|Block that has the `it` block parameter referenced inside it.|Three children. First child is a `send`/`csend` node representing the way the block is created, second child is the symbol `it` and the third child is a body statement.|proc { it }|N/A

The naming seems to be intended to contrast with the traditional explicit do |it|. However, when "it block parameter" is mentioned, it typically refers to the "it block parameter" introduced in Ruby 3.4.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, updated.

In tests, `parser` will be capped to Ruby 3.3 and tests
that don't pass with get marked as broken.
@koic koic merged commit 7c71213 into rubocop:master Mar 20, 2025
22 checks passed
@koic
Copy link
Member

koic commented Mar 20, 2025

Looks good to me. Thanks!

@koic
Copy link
Member

koic commented Mar 20, 2025

This change affects existing cops that use any_block, for users who have set ParserEngine: parser_prism. For now, I've confirmed that the latest build passes based on the rubocop/rubocop repository. Let's proceed with the release and monitor the situation. If any feedback arises, it will likely be directed at rubocop/rubocop rather than rubocop/rubocop-ast.

I will proceed with the minor version release of this PR. @marcandre @bbatsov

@bbatsov
Copy link
Contributor

bbatsov commented Mar 20, 2025

Sounds good!

@koic
Copy link
Member

koic commented Mar 20, 2025

RuboCop AST 1.41.0 has been released:
https://github.com/rubocop/rubocop-ast/releases/tag/v1.41.0

@Earlopain
Copy link
Contributor Author

Great, thank you!

@Earlopain Earlopain deleted the itblock branch March 20, 2025 16:06
koic added a commit to whitequark/parser that referenced this pull request Mar 21, 2025
Follow-up to rubocop/rubocop-ast#365 (comment)

"implicit `it` parameter" doesn't seem to be a commonly used term. Use "`it` block parameter" instead.
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

3 participants