-
Notifications
You must be signed in to change notification settings - Fork 199
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
Handling of special nodes in conditional context #69
Comments
Flip-flops I don't care about, they were going to be removed anyway from what I remember. Magic matches are something I've never seen before so I can't really comment on those either. |
@yorickpeterse Removed? Link? Magic matches...
|
Flip-flops discussion can be found here: http://www.ruby-forum.com/topic/2713360. |
Well, they stay until 3.0. |
I'd like Parser to recognize flip-flop nodes - mostly because I'd like it to be easy for tool authors to write checks that advise Ruby hackers against their use. As for the node names - I'd suggest
|
@bbatsov ASTs are called syntactic for a reason. If there is no Oh, match local variables are indeed just local variables. It's just that, as I've already shown you, Ruby source can be parsed very differently depending on whether a particular token is a local variable or not; therefore, a compliant parser is required to discover these variables. |
I'm indifferent. I very rarely use flip-flops/magic-matches and would accept both the current behavior or having the parser recognizing them. |
@whitequark Fair point. Furthermore my suggestion would have made it harder to differentiate |
Done with everything except lvar-injecting magic matches. They're so fucked up. For example, there is a ton of preconditions:
You also need to parse the regexp itself to figure out how to parse the remaining parts of ruby source.
Yeah a single dot changes everything. |
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
This PR fixes the following incompatibility AST for regexp match between Parser gem and Prism: ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` ## Prism (`Prism::Translation::Parser`) ### Before Returns an `send` node: ```console $ bundle exec ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` ### After Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` ## Background Found due to incompatibility with RuboCop's `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops. ## Note This is the incompatibility when the receiver is a regular expression literal and `=~` is used. Based on the node name `:match_with_lvasgn`, it appears that Prism's AST becomes more accurate in cases like `visit_match_write_node` only. However, as shown in the background, the current behavior of Parser gem is not like this. Considering compatibility with the published AST of Parser gem, the AST incompatibility will be addressed. This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) There seems to be no indication that it will be supported. This PR prioritizes AST compatibility between the Parser gem and Prism. However, it is unclear whether this is the best approach.
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
…slation::Parser` This PR fixes the following incompatibility AST for regexp match between Parser gem and Prism: ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision ruby/prism@5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` ## Prism (`Prism::Translation::Parser`) ### Before Returns an `send` node: ```console $ bundle exec ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision ruby/prism@5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` ### After Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision ruby/prism@5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` ## Background Found due to incompatibility with RuboCop's `Performance/EndWith`, `Performance/StringInclude, and `Performance/StartWith` cops. ## Note This is the incompatibility when the receiver is a regular expression literal and `=~` is used. Based on the node name `:match_with_lvasgn`, it appears that Prism's AST becomes more accurate in cases like `visit_match_write_node` only. However, as shown in the background, the current behavior of Parser gem is not like this. Considering compatibility with the published AST of Parser gem, the AST incompatibility will be addressed. This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) There seems to be no indication that it will be supported. This PR prioritizes AST compatibility between the Parser gem and Prism. However, it is unclear whether this is the best approach. ruby/prism@dff4abb170
Follow up rubocop/rubocop-ast#277 In Prism (`Prism::Translation::Parser`), `match-with-lvasgn` can be distinctly differentiated. It is unclear whether to conform to the current behavior of the Parser gem, but initially, `def_node_matcher` has been updated to accept the following incompatibilities for `Performance/EndWith`, `Performance/StringInclude`, and `Performance/StartWith` cops to ensure it works with Prism 0.24.0 as well. ## Parser gem Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "foo"), s(:regopt)), s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -rparser/ruby33 -ve 'p Parser::Ruby33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ``` This lvar-injecting feature appears to have not been supported by Parser gem for a long time: whitequark/parser#69 (comment) ## Prism Returns an `send` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:send, s(:regexp, s(:str, "foo"), s(:regopt)), :=~, s(:send, nil, :bar)) ``` Returns an `match_with_lvasgn` node: ```console $ bundle exec ruby -Ilib -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("/(?<foo>)foo/ =~ bar")' ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:match_with_lvasgn, s(:regexp, s(:str, "(?<foo>)foo"), s(:regopt)), s(:send, nil, :bar)) ```
It came to my attention that parser currently does not handle special nodes in a conditional context (https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md#open-questions):
This must be handled before 2.0 release.
So the question is:
Invited for discussion: @yorickpeterse @mbj @judofyr @bbatsov
The text was updated successfully, but these errors were encountered: