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
- SELECT_METHODS =
i[select filter find_all].freeze
- REGEXP_METHODS =
i[match? =~].to_set.freeze
- REGEXP_METHODS_NEGATED =
i[!~].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
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 86 def_node_matcher :calls_lvar?, "{\n (send (lvar %1) ...)\n (send ... (lvar %1))\n (match-with-lvasgn regexp (lvar %1))\n (send (send (lvar %1) ...) :!)\n (send (send ... (lvar %1)) :!)\n (send (match-with-lvasgn regexp (lvar %1)) :!)\n (send (begin (send (lvar %1) ...)) :!)\n (send (begin (send ... (lvar %1))) :!)\n (send (begin (match-with-lvasgn regexp (lvar %1))) :!)\n}\n" |
#creates_hash?(node) ⇒ Object
Returns true if a node appears to return a hash
72 73 74 75 76 77 78 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 72 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
81 82 83 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 81 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
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 101 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.include?('grep_v') regexp = find_regexp(regexp_method_send_node, block_node) register_offense(node, block_node, regexp, replacement) end |
#regexp_match?(node) ⇒ Object
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/rubocop/cop/style/select_by_regexp.rb', line 59 def_node_matcher :regexp_match?, "{\n (block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) (send _ %REGEXP_METHODS_NEGATED _) match-with-lvasgn})\n (block call (args (arg $_)) ${(send (send _ %REGEXP_METHODS _) :!) (send (begin (send _ %REGEXP_METHODS _)) :!) (send match-with-lvasgn :!) (send (begin match-with-lvasgn) :!)})\n (numblock call $1 ${(send _ %REGEXP_METHODS _) (send _ %REGEXP_METHODS_NEGATED _) match-with-lvasgn})\n (numblock call $1 ${(send (send _ %REGEXP_METHODS _) :!) (send (begin (send _ %REGEXP_METHODS _)) :!) (send match-with-lvasgn :!) (send (begin match-with-lvasgn) :!)})\n (itblock call $_ ${(send _ %REGEXP_METHODS _) (send _ %REGEXP_METHODS_NEGATED _) match-with-lvasgn})\n (itblock call $_ ${(send (send _ %REGEXP_METHODS _) :!) (send (begin (send _ %REGEXP_METHODS _)) :!) (send match-with-lvasgn :!) (send (begin match-with-lvasgn) :!)})\n}\n" |