Class: RuboCop::Cop::Lint::RedundantTypeConversion
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
::RuboCop::Cop::AutoCorrector,
::RuboCop::Cop::Base,
::RuboCop::ExcludeLimit,
NodePattern::Macros,
RuboCop::AST::Sexp
|
|
|
Instance Chain:
self,
::RuboCop::Cop::Base,
::RuboCop::Cop::AutocorrectLogic,
::RuboCop::Cop::IgnoredNode,
::RuboCop::Util,
RuboCop::AST::Sexp
|
|
| Inherits: |
RuboCop::Cop::Base
|
| Defined in: | lib/rubocop/cop/lint/redundant_type_conversion.rb |
Overview
Checks for redundant uses of to_s, to_sym, to_i, to_f, to_d, to_r, to_c,
to_a, to_h, and to_set.
When one of these methods is called on an object of the same type, that object
is returned, making the call unnecessary. The cop detects conversion methods called
on object literals, class constructors, class [] methods, and the Kernel methods
String(), Integer(), Float(), BigDecimal(), Rational(), Complex(), and Array().
Specifically, these cases are detected for each conversion method:
-
to_swhen called on a string literal, interpolated string, heredoc, or withString.neworString(). -
to_symwhen called on a symbol literal or interpolated symbol. -
to_iwhen called on an integer literal or withInteger(). -
to_fwhen called on a float literal of withFloat(). -
to_rwhen called on a rational literal or withRational(). -
to_cwhen called on a complex literal of withComplex(). -
to_awhen called on an array literal, or withArray.new,Array()orArray[]. -
to_hwhen called on a hash literal, or withHash.new,Hash()orHash[]. -
to_setwhen called onSet.neworSet[].
In all cases, chaining one same to_* conversion methods listed above is redundant.
The cop can also register an offense for chaining conversion methods on methods that are
expected to return a specific type regardless of receiver (eg. foo.inspect.to_s and
foo.to_json.to_s).
Constant Summary
-
CONSTRUCTOR_MAPPING =
private
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 100
Maps each conversion method to the pattern matcher for that type’s constructors Not every type has a constructor, for instance Symbol.
{ to_s: 'string_constructor?', to_i: 'integer_constructor?', to_f: 'float_constructor?', to_d: 'bigdecimal_constructor?', to_r: 'rational_constructor?', to_c: 'complex_constructor?', to_a: 'array_constructor?', to_h: 'hash_constructor?', to_set: 'set_constructor?' }.freeze -
CONVERSION_METHODS =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 116Set[*LITERAL_NODE_TYPES.keys].freeze
-
LITERAL_NODE_TYPES =
private
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 86
Maps conversion methods to the node types for the literals of that type
{ to_s: %i[str dstr], to_sym: %i[sym dsym], to_i: %i[int], to_f: %i[float], to_r: %i[rational], to_c: %i[complex], to_a: %i[array], to_h: %i[hash], to_set: [] # sets don't have a literal or node type }.freeze -
MSG =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 83'Redundant `%<method>s` detected.' -
RESTRICT_ON_SEND =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 117CONVERSION_METHODS + [:to_d]
-
TYPED_METHODS =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 114
Methods that already are expected to return a given type, which makes a further conversion redundant.
{ to_s: %i[inspect to_json] }.freeze
::RuboCop::Cop::Base - Inherited
Class Attribute Summary
::RuboCop::Cop::AutoCorrector - Extended
::RuboCop::Cop::Base - Inherited
| .gem_requirements, .lint?, | |
| .support_autocorrect? | Returns if class supports autocorrect. |
| .support_multiple_source? | Override if your cop should be called repeatedly for multiple investigations Between calls to |
Class Method Summary
::RuboCop::Cop::Base - Inherited
| .autocorrect_incompatible_with | List of cops that should not try to autocorrect at the same time as this cop. |
| .badge | Naming. |
| .callbacks_needed, .cop_name, .department, | |
| .documentation_url | Returns a url to view this cops documentation online. |
| .exclude_from_registry | Call for abstract Cop classes. |
| .inherited, | |
| .joining_forces | Override and return the Force class(es) you need to join. |
| .match? | Returns true if the cop name or the cop namespace matches any of the given names. |
| .new, | |
| .requires_gem | Register a version requirement for the given gem name. |
| .restrict_on_send | |
::RuboCop::ExcludeLimit - Extended
| exclude_limit | Sets up a configuration option to have an exclude limit tracked. |
| transform | |
Instance Attribute Summary
::RuboCop::Cop::Base - Inherited
::RuboCop::Cop::AutocorrectLogic - Included
Instance Method Summary
- #array_constructor?(node)
- #bigdecimal_constructor?(node)
- #complex_constructor?(node)
- #exception_false_keyword_argument?(node)
- #float_constructor?(node)
- #hash_constructor?(node)
- #integer_constructor?(node)
-
#on_csend(node)
Alias for #on_send.
-
#on_send(node)
(also: #on_csend)
Metrics/CyclomaticComplexity.
- #rational_constructor?(node)
- #set_constructor?(node)
- #string_constructor?(node)
- #type_constructor?(node, type_symbol)
- #chained_conversion?(node, receiver) ⇒ Boolean private
- #chained_to_typed_method?(node, receiver) ⇒ Boolean private
- #constructor?(node, receiver) ⇒ Boolean private
- #constructor_suppresses_exceptions?(receiver) ⇒ Boolean private
- #find_receiver(node) private
- #hash_or_set_with_block?(node) ⇒ Boolean private
- #literal_receiver?(node, receiver) ⇒ Boolean private
::RuboCop::Cop::Base - Inherited
| #add_global_offense | Adds an offense that has no particular location. |
| #add_offense | Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense. |
| #begin_investigation | Called before any investigation. |
| #callbacks_needed, | |
| #cop_config | Configuration Helpers. |
| #cop_name, #excluded_file?, | |
| #external_dependency_checksum | This method should be overridden when a cop’s behavior depends on state that lives outside of these locations: |
| #inspect, | |
| #message | Gets called if no message is specified when calling |
| #name | Alias for Base#cop_name. |
| #offenses, | |
| #on_investigation_end | Called after all on_… |
| #on_new_investigation | Called before all on_… |
| #on_other_file | Called instead of all on_… |
| #parse | There should be very limited reasons for a Cop to do it’s own parsing. |
| #parser_engine, | |
| #ready | Called between investigations. |
| #relevant_file?, | |
| #target_gem_version | Returns a gems locked versions (i.e. |
| #target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction, | |
| #callback_argument | Reserved for Cop::Cop. |
| #complete_investigation | Called to complete an investigation. |
| #correct, #current_corrector, | |
| #current_offense_locations | Reserved for Commissioner: |
| #current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?, #file_name_matches_any?, #find_message, #find_severity, #range_for_original, #range_from_node_or_range, | |
| #reset_investigation | Actually private methods. |
| #use_corrector | |
::RuboCop::Cop::AutocorrectLogic - Included
::RuboCop::Cop::IgnoredNode - Included
Constructor Details
This class inherits a constructor from RuboCop::Cop::Base
Instance Method Details
#array_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 160
def_node_matcher :array_constructor?, <<~PATTERN { (send (const {cbase nil?} :Array) {:new :[]} ...) #type_constructor?(:Array) } PATTERN
#bigdecimal_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 145
def_node_matcher :bigdecimal_constructor?, <<~PATTERN #type_constructor?(:BigDecimal) PATTERN
#chained_conversion?(node, receiver) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 247
def chained_conversion?(node, receiver) return false unless receiver&.call_type? receiver.method?(node.method_name) end
#chained_to_typed_method?(node, receiver) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 253
def chained_to_typed_method?(node, receiver) return false unless receiver&.call_type? TYPED_METHODS.fetch(node.method_name, []).include?(receiver.method_name) end
#complex_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 155
def_node_matcher :complex_constructor?, <<~PATTERN #type_constructor?(:Complex) PATTERN
#constructor?(node, receiver) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 234
def constructor?(node, receiver) matcher = CONSTRUCTOR_MAPPING[node.method_name] return false unless matcher public_send(matcher, receiver) && !constructor_suppresses_exceptions?(receiver) end
#constructor_suppresses_exceptions?(receiver) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 241
def constructor_suppresses_exceptions?(receiver) # If the constructor suppresses exceptions with `exception: false`, it is possible # it could return `nil`, and therefore a chained conversion is not redundant. receiver.arguments.any? { |arg| exception_false_keyword_argument?(arg) } end
#exception_false_keyword_argument?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 184
def_node_matcher :exception_false_keyword_argument?, <<~PATTERN (hash (pair (sym :exception) false)) PATTERN
#find_receiver(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 215
def find_receiver(node) receiver = node.receiver return unless receiver while receiver.begin_type? break unless receiver.children.one? receiver = receiver.children.first end receiver end
#float_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 140
def_node_matcher :float_constructor?, <<~PATTERN #type_constructor?(:Float) PATTERN
#hash_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 168
def_node_matcher :hash_constructor?, <<~PATTERN { (block (send (const {cbase nil?} :Hash) :new) ...) (send (const {cbase nil?} :Hash) {:new :[]} ...) (send {nil? (const {cbase nil?} :Kernel)} :Hash ...) } PATTERN
#hash_or_set_with_block?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 209
def hash_or_set_with_block?(node) return false if !node.method?(:to_h) && !node.method?(:to_set) node.parent&.any_block_type? || node.last_argument&.block_pass_type? end
#integer_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 135
def_node_matcher :integer_constructor?, <<~PATTERN #type_constructor?(:Integer) PATTERN
#literal_receiver?(node, receiver) ⇒ Boolean (private)
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 228
def literal_receiver?(node, receiver) return false unless receiver receiver.type?(*LITERAL_NODE_TYPES[node.method_name]) end
#on_csend(node)
Alias for #on_send.
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 205
alias on_csend on_send
#on_send(node) Also known as: #on_csend
Metrics/CyclomaticComplexity
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 189
def on_send(node) return if node.arguments.any? || hash_or_set_with_block?(node) receiver = find_receiver(node) return unless literal_receiver?(node, receiver) || constructor?(node, receiver) || chained_conversion?(node, receiver) || chained_to_typed_method?(node, receiver) = format(MSG, method: node.method_name) add_offense(node.loc.selector, message: ) do |corrector| corrector.remove(node.loc.dot.join(node.loc.end || node.loc.selector)) end end
#rational_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 150
def_node_matcher :rational_constructor?, <<~PATTERN #type_constructor?(:Rational) PATTERN
#set_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 177
def_node_matcher :set_constructor?, <<~PATTERN { (send (const {cbase nil?} :Set) {:new :[]} ...) } PATTERN
#string_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 127
def_node_matcher :string_constructor?, <<~PATTERN { (send (const {cbase nil?} :String) :new ...) #type_constructor?(:String) } PATTERN
#type_constructor?(node, type_symbol)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 122
def_node_matcher :type_constructor?, <<~PATTERN (send {nil? (const {cbase nil?} :Kernel)} %1 ...) PATTERN