rubocop / rubocop-performance

An extension of RuboCop focused on code performance checks.
https://docs.rubocop.org/rubocop-performance
MIT License
687 stars 81 forks source link

Support Prism as a Ruby parser #446

Closed koic closed 9 months ago

koic commented 9 months ago

Follow up https://github.com/rubocop/rubocop-ast/pull/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:

$ 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:

$ 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: https://github.com/whitequark/parser/issues/69#issuecomment-19506391

Prism

Returns an send node:

$ 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:

$ 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))

Before submitting the PR make sure the following are checked: