Class: RuboCop::Cop::Naming::PredicateMethod
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::RuboCop::Cop::Base ,
::RuboCop::ExcludeLimit ,
NodePattern::Macros,
RuboCop::AST::Sexp
|
|
Instance Chain:
self,
::RuboCop::Cop::AllowedMethods ,
::RuboCop::Cop::Base ,
::RuboCop::Cop::AutocorrectLogic ,
::RuboCop::Cop::IgnoredNode ,
::RuboCop::Util ,
RuboCop::AST::Sexp
|
|
Inherits: |
RuboCop::Cop::Base
|
Defined in: | lib/rubocop/cop/naming/predicate_method.rb |
Overview
Checks that predicate methods end with ?
and non-predicate methods do not.
The names of predicate methods (methods that return a boolean value) should end in a question mark. Methods that don’t return a boolean, shouldn’t end in a question mark.
The cop assesses a predicate method as one that returns boolean values. Likewise, a method that only returns literal values is assessed as non-predicate. The cop does not make an assessment if the return type is unknown (method calls, variables, etc.).
Note
|
Operator methods (def == , etc.) are ignored.
|
By default, the cop runs in conservative
mode, which allows a method to be named
with a question mark as long as at least one return value is boolean. In aggressive
mode, methods with a question mark will register an offense if any known non-boolean
return values are detected.
The cop also has ::RuboCop::Cop::AllowedMethods
configuration in order to prevent the cop from
registering an offense from a method name that does not confirm to the naming
guidelines. By default, call
is allowed.
Constant Summary
-
MSG_NON_PREDICATE =
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 80'Non-predicate method names should not end with `?`.'
-
MSG_PREDICATE =
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 79'Predicate method names should end with `?`.'
::RuboCop::Cop::Base
- Inherited
Class Attribute Summary
::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
- #conservative? ⇒ Boolean readonly private
::RuboCop::Cop::AllowedMethods
- Included
::RuboCop::Cop::Base
- Inherited
::RuboCop::Cop::AutocorrectLogic
- Included
Instance Method Summary
- #on_def(node) (also: #on_defs)
-
#on_defs(node)
Alias for #on_def.
- #acceptable?(return_values) ⇒ Boolean private
- #all_return_values_boolean?(return_values) ⇒ Boolean private
- #allowed?(node) ⇒ Boolean private
- #and_or?(node) ⇒ Boolean private
- #boolean_return?(value) ⇒ Boolean private
- #extract_and_or_clauses(node) private
- #extract_conditional_branches(node) private
- #extract_return_value(node) private
- #last_value(node) private
- #non_comparison_call?(value) ⇒ Boolean private
- #potential_non_predicate?(return_values) ⇒ Boolean private
- #process_return_values(return_values) private
- #return_values(node) private
::RuboCop::Cop::AllowedMethods
- Included
::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 Attribute Details
#conservative? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 210
def conservative? cop_config.fetch('Mode', :conservative).to_sym == :conservative end
Instance Method Details
#acceptable?(return_values) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 104
def acceptable?(return_values) # In `conservative` mode, if the method returns `super`, `zsuper`, or a # non-comparison method call, the method name is acceptable. return false unless conservative? return_values.any? do |value| value.type?(:super, :zsuper) || non_comparison_call?(value) end end
#all_return_values_boolean?(return_values) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 132
def all_return_values_boolean?(return_values) values = return_values.reject { |value| value.type?(:super, :zsuper) } return false if values.empty? values.all? { |value| boolean_return?(value) } end
#allowed?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 98
def allowed?(node) allowed_method?(node.method_name) || node.operator_method? || node.body.nil? end
#and_or?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 187
def and_or?(node) node.type?(:and, :or) end
#boolean_return?(value) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 139
def boolean_return?(value) value.boolean_type? || (value.call_type? && value.comparison_method?) end
#extract_and_or_clauses(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 191
def extract_and_or_clauses(node) # Recursively traverse an `and` or `or` node to collect all clauses within return node unless and_or?(node) [extract_and_or_clauses(node.lhs), extract_and_or_clauses(node.rhs)].flatten end
#extract_conditional_branches(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 198
def extract_conditional_branches(node) return node unless node.conditional? if node.type?(:while, :until) # If there is no body, act as implicit `nil`. node.body ? [last_value(node.body)] : [s(:nil)] else # Branches with no value act as an implicit `nil`. node.branches.filter_map { |branch| branch ? last_value(branch) : s(:nil) } end end
#extract_return_value(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 157
def extract_return_value(node) return node unless node.return_type? # `return` without a value is a `nil` return. return s(:nil) if node.arguments.empty? # When there's a multiple return, it cannot be a predicate # so just return an `array` sexp for simplicity. return s(:array) unless node.arguments.one? node.first_argument end
#last_value(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 170
def last_value(node) value = node.begin_type? ? node.children.last : node value.return_type? ? extract_return_value(value) : value end
#non_comparison_call?(value) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 114
def non_comparison_call?(value) value.call_type? && !value.comparison_method? end
#on_def(node) Also known as: #on_defs
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 82
def on_def(node) return if allowed?(node) return_values = return_values(node.body) return if acceptable?(return_values) if node.predicate_method? && potential_non_predicate?(return_values) add_offense(node.loc.name, message: MSG_NON_PREDICATE) elsif !node.predicate_method? && all_return_values_boolean?(return_values) add_offense(node.loc.name, message: MSG_PREDICATE) end end
#on_defs(node)
Alias for #on_def.
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 94
alias on_defs on_def
#potential_non_predicate?(return_values) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/naming/predicate_method.rb', line 143
def potential_non_predicate?(return_values) # Assumes a method to be non-predicate if all return values are non-boolean literals. # # In `Mode: conservative`, if any of the return values is a boolean, # the method name is acceptable. # In `Mode: aggressive`, all return values must be booleans for a predicate # method, or else an offense will be registered. return false if conservative? && return_values.any? { |value| boolean_return?(value) } return_values.any? do |value| value.literal? && !value.boolean_type? end end
#process_return_values(return_values) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 175
def process_return_values(return_values) return_values.flat_map do |value| if value.conditional? process_return_values(extract_conditional_branches(value)) elsif and_or?(value) process_return_values(extract_and_or_clauses(value)) else value end end end
#return_values(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/naming/predicate_method.rb', line 118
def return_values(node) # Collect all the (implicit and explicit) return values of a node return_values = Set.new(node.begin_type? ? [] : [extract_return_value(node)]) node.each_descendant(:return) do |return_node| return_values << extract_return_value(return_node) end last_value = last_value(node) return_values << last_value if last_value process_return_values(return_values) end