Module: WhyClasses::Correctors::StatelessModuleCorrector

Defined in:
lib/why_classes/correctors/stateless_module_corrector.rb

Overview

Rewrites a stateless "class of class-methods" into a module that exposes the same methods via extend self:

class Checksum          =>   module Checksum
def self.calculate(id)         def calculate(id)
  ...                            ...
end                            end
end
                               extend self
                             end

Unsafe-tier: mechanical within the file, but Checksum.new, subclassing, or Checksum.superclass elsewhere would break.

Constant Summary collapse

H =
AST::NodeHelpers

Class Method Summary collapse

Class Method Details

.correctable?(shape) ⇒ Boolean

Convertible only when every class method uses the def self.x form. A class << self block is bailed on (kept as advice).

Returns:

  • (Boolean)


27
28
29
30
31
32
33
34
35
36
# File 'lib/why_classes/correctors/stateless_module_corrector.rb', line 27

def correctable?(shape)
  return false if shape.module?
  return false if shape.superclass?
  return false if shape.uses_metaprogramming?
  return false unless shape.instance_methods.empty?
  return false if shape.singleton_methods.empty?

  body = H.body_statements(H.class_body(shape.node))
  body.none? { |n| H.node?(n) && n.type == :sclass }
end

.corrector(class_node) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/why_classes/correctors/stateless_module_corrector.rb', line 38

def corrector(class_node)
  lambda do |rewriter|
    rewriter.replace(class_node.location.keyword, "module")
    H.singleton_methods(class_node).each do |defs|
      receiver = defs.children[0]
      self_dot = receiver.location.expression.join(defs.location.operator)
      rewriter.remove(self_dot)
    end
    inner = " " * (class_node.location.keyword.column + 2)
    rewriter.insert_before(class_node.location.end, "\n#{inner}extend self\n")
  end
end