Class: RuboCop::Cop::Style::SelectByRegexp
- Extended by:
- AutoCorrector
- Includes:
- RangeHelp
- Defined in:
- lib/rubocop/cop/style/select_by_regexp.rb
Overview
Looks for places where a subset of an Enumerable (array, range, set, etc.; see note below) is calculated based on a Regexp match, and suggests grep or grep_v instead.
NOTE: Hashes do not behave as you may expect with grep, which means that hash.grep is not equivalent to hash.select. Although RuboCop is limited by static analysis, this cop attempts to avoid registering an offense when the receiver is a hash (hash literal, Hash.new, ‘Hash#[]`, or to_h/to_hash).
NOTE: grep and grep_v were optimized when used without a block in Ruby 3.0, but may be slower in previous versions. See bugs.ruby-lang.org/issues/17030
Constant Summary collapse
- MSG =
'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'- RESTRICT_ON_SEND =
i[select filter find_all reject].freeze
- REPLACEMENTS =
{ select: 'grep', filter: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
- OPPOSITE_REPLACEMENTS =
{ select: 'grep_v', filter: 'grep_v', find_all: 'grep_v', reject: 'grep' }.freeze
- REGEXP_METHODS =
i[match? =~ !~].to_set.freeze
Constants included from RangeHelp
RangeHelp::BYTE_ORDER_MARK, RangeHelp::NOT_GIVEN
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
- #calls_lvar?(node, name) ⇒ Object
-
#creates_hash?(node) ⇒ Object
Returns true if a node appears to return a hash.
- #env_const?(node) ⇒ Object
-
#on_send(node) ⇒ Object
(also: #on_csend)
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #regexp_match?(node) ⇒ Object
Methods included from AutoCorrector
Methods inherited from Base
#active_support_extensions_enabled?, #add_global_offense, #add_offense, #always_autocorrect?, autocorrect_incompatible_with, badge, #begin_investigation, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #contextual_autocorrect?, #cop_config, #cop_name, cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #parser_engine, #ready, #relevant_file?, requires_gem, #string_literals_frozen_by_default?, support_autocorrect?, support_multiple_source?, #target_gem_version, #target_rails_version, #target_ruby_version
Methods included from ExcludeLimit
Methods included from AutocorrectLogic
#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?
Methods included from IgnoredNode
#ignore_node, #ignored_node?, #part_of_ignored_node?
Methods included from Util
Constructor Details
This class inherits a constructor from RuboCop::Cop::Base
Instance Method Details
#calls_lvar?(node, name) ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 82 def_node_matcher :calls_lvar?, "{\n (send (lvar %1) ...)\n (send ... (lvar %1))\n (match-with-lvasgn regexp (lvar %1))\n}\n" |
#creates_hash?(node) ⇒ Object
Returns true if a node appears to return a hash
68 69 70 71 72 73 74 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 68 def_node_matcher :creates_hash?, "{\n (call (const _ :Hash) {:new :[]} ...)\n (block (call (const _ :Hash) :new ...) ...)\n (call _ { :to_h :to_hash } ...)\n}\n" |
#env_const?(node) ⇒ Object
77 78 79 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 77 def_node_matcher :env_const?, "(const {nil? cbase} :ENV)\n" |
#on_send(node) ⇒ Object Also known as: on_csend
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 91 def on_send(node) return if target_ruby_version < 2.6 && node.method?(:filter) return unless (block_node = node.block_node) return if block_node.body&.begin_type? return if receiver_allowed?(block_node.receiver) return unless (regexp_method_send_node = extract_send_node(block_node)) return if match_predicate_without_receiver?(regexp_method_send_node) replacement = replacement(regexp_method_send_node, node) return if target_ruby_version <= 2.2 && replacement == 'grep_v' regexp = find_regexp(regexp_method_send_node, block_node) register_offense(node, block_node, regexp, replacement) end |
#regexp_match?(node) ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 58 def_node_matcher :regexp_match?, "{\n (block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})\n (numblock call $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})\n (itblock call $_ ${(send _ %REGEXP_METHODS _) match-with-lvasgn})\n}\n" |