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 or withFloat(). -
to_dwhen called withBigDecimal(). -
to_rwhen called on a rational literal or withRational(). -
to_cwhen called on a complex literal or 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 of the 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 107
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 123Set[*LITERAL_NODE_TYPES.keys].freeze
-
LITERAL_NODE_TYPES =
private
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 93
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 90'Redundant `%<method>s` detected.' -
RESTRICT_ON_SEND =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 124CONVERSION_METHODS + [:to_d]
-
TYPED_METHODS =
# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 121
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 167
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 152
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 254
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 260
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 162
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 241
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 248
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 191
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 222
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 147
def_node_matcher :float_constructor?, <<~PATTERN #type_constructor?(:Float) PATTERN
#hash_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 175
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 216
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 142
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 235
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 212
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 196
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 157
def_node_matcher :rational_constructor?, <<~PATTERN #type_constructor?(:Rational) PATTERN
#set_constructor?(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/redundant_type_conversion.rb', line 184
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 134
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 129
def_node_matcher :type_constructor?, <<~PATTERN (send {nil? (const {cbase nil?} :Kernel)} %1 ...) PATTERN