Class: Reek::SmellDetectors::MissingSafeMethod
- Inherits:
-
BaseDetector
- Object
- BaseDetector
- Reek::SmellDetectors::MissingSafeMethod
- Defined in:
- lib/reek/smell_detectors/missing_safe_method.rb
Overview
Excerpt from: dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist since this sums it up really well:
The ! in method names that end with ! means, "This method is dangerous"
-- or, more precisely, this method is the "dangerous" version of an
equivalent method, with the same name minus the !. "Danger" is
relative; the ! doesn't mean anything at all unless the method name
it's in corresponds to a similar but bang-less method name.
Don't add ! to your destructive (receiver-changing) methods' names,
unless you consider the changing to be "dangerous" and you have a
"non-dangerous" equivalent method without the !. If some arbitrary
subset of destructive methods end with !, then the whole point of !
gets distorted and diluted, and ! ceases to convey any information
whatsoever.
Such a method is called MissingSafeMethod and is reported as a smell.
See Missing-Safe-Method for details.
Constant Summary
Constants inherited from BaseDetector
BaseDetector::DEFAULT_EXCLUDE_SET, BaseDetector::EXCLUDE_KEY
Instance Attribute Summary
Attributes inherited from BaseDetector
Class Method Summary collapse
-
.contexts ⇒ Object
:nodoc:.
Instance Method Summary collapse
- #ignore_method?(method_node) ⇒ Boolean private
-
#ignore_method_names ⇒ Object
private
e.g.
- #missing_safe_method?(method_sexp) ⇒ Boolean private
-
#sniff ⇒ Array<SmellWarning>
Given this code:.
- #version_without_bang_exists?(method_sexp) ⇒ Boolean private
Methods inherited from BaseDetector
#config_for, configuration_keys, default_config, descendants, #enabled?, #exception?, #expression, inherited, #initialize, #run, #smell_type, smell_type, #smell_warning, #source_line, to_detector, todo_configuration_for, #value
Constructor Details
This class inherits a constructor from Reek::SmellDetectors::BaseDetector
Class Method Details
.contexts ⇒ Object
:nodoc:
28 29 30 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 28 def self.contexts # :nodoc: [:class] end |
Instance Method Details
#ignore_method?(method_node) ⇒ Boolean (private)
82 83 84 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 82 def ignore_method?(method_node) ignore_method_names.include? method_node.name.to_s # method_node.name is e.g.: :bravo! end |
#ignore_method_names ⇒ Object (private)
e.g. [“bravo!”]
87 88 89 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 87 def ignore_method_names @ignore_method_names ||= value(EXCLUDE_KEY, context) end |
#missing_safe_method?(method_sexp) ⇒ Boolean (private)
63 64 65 66 67 68 69 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 63 def missing_safe_method?(method_sexp) return false unless method_sexp.ends_with_bang? return false if ignore_method? method_sexp return false if version_without_bang_exists? method_sexp true end |
#sniff ⇒ Array<SmellWarning>
Given this code:
class Alfa
def bravo!
end
end
An example context could look like this:
s(:class,
s(:const, nil, :Alfa), nil,
s(:def, :bravo!,
s(:args), nil))
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 49 def sniff context.node_instance_methods.select do |method_sexp| missing_safe_method?(method_sexp) end.map do |method_sexp| name = method_sexp.name smell_warning( lines: [method_sexp.line], message: "has missing safe method '#{name}'", parameters: { name: name.to_s }) end end |
#version_without_bang_exists?(method_sexp) ⇒ Boolean (private)
71 72 73 74 75 |
# File 'lib/reek/smell_detectors/missing_safe_method.rb', line 71 def version_without_bang_exists?(method_sexp) context.node_instance_methods.find do |sexp_item| sexp_item.name.to_s == method_sexp.name_without_bang end end |