diff options
author | Koichi ITO <koic.ito@gmail.com> | 2024-03-04 21:10:47 +0900 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2024-03-04 16:26:46 +0000 |
commit | a03f92923b61a64098ea9313f4e70ac3a4553414 (patch) | |
tree | b72ea960a061bf6c61316be5a5aabd48d039294b /lib/prism/translation/parser | |
parent | 26507b92e069e999f1ef965516e8f901c7ce2479 (diff) |
[ruby/prism] Fix incompatibility AST for regexp match in `Prism::Translation::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 https://github.com/ruby/prism/commit/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 https://github.com/ruby/prism/commit/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 https://github.com/ruby/prism/commit/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:
https://github.com/whitequark/parser/issues/69#issuecomment-19506391
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.
https://github.com/ruby/prism/commit/dff4abb170
Diffstat (limited to 'lib/prism/translation/parser')
-rw-r--r-- | lib/prism/translation/parser/compiler.rb | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 0025e4697d..9dd20baeb4 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -254,6 +254,10 @@ module Prism end when :! return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block) + when :=~ + if (receiver = node.receiver).type == :regular_expression_node + return builder.match_op(visit(receiver), token(node.message_loc), visit(node.arguments.arguments.first)) + end when :[] return visit_block(builder.index(visit(node.receiver), token(node.opening_loc), visit_all(arguments), token(node.closing_loc)), block) when :[]= |