Class: RuboCop::Cop::Packs::ClassMethodsAsPublicApis

Inherits:
Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/rubocop/cop/packs/class_methods_as_public_apis.rb

Overview

This cop states that public API should live on class methods, which are more easily statically analyzable, searchable, and typically hold less state.

Options:

  • ‘AcceptableParentClasses`: A list of classes that, if inherited from, non-class methods are permitted (useful when value objects are a part of your public API)

  • ‘AcceptableMixins`: A list of modules that, if included, non-class methods are permitted

Examples:


# bad
# packs/foo/app/public/foo.rb
module Foo
  def blah
  end
end

# good
# packs/foo/app/public/foo.rb
module Foo
  def self.blah
  end
end

Instance Method Summary collapse

Instance Method Details

#on_def(node) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rubocop/cop/packs/class_methods_as_public_apis.rb', line 40

def on_def(node)
  # This cop only applies for ruby files in `app/public`
  return if !processed_source.file_path.include?('app/public')

  # Looked at https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/MissingSuper source code as inspiration for htis part.
  class_node = node.each_ancestor(:class).first
  module_node = node.each_ancestor(:module).first
  parent_class = class_node&.parent_class || module_node&.parent

  acceptable_parent_classes = cop_config['AcceptableParentClasses'] || []

  uses_implicit_static_methods = node.each_ancestor(:sclass).first&.identifier&.source == 'self'
  class_is_allowed_to_have_instance_methods = acceptable_parent_classes.include?(parent_class&.const_name)
  return if uses_implicit_static_methods || class_is_allowed_to_have_instance_methods

  is_sorbet_interface_or_abstract_class = !module_node.nil? && module_node.descendants.any? { |d| d.is_a?(RuboCop::AST::SendNode) && (d.method_name == :interface! || d.method_name == :abstract!) }
  return if is_sorbet_interface_or_abstract_class
  return if node_includes_acceptable_mixin?(class_node || module_node)

  add_offense(
    node.source_range,
    message: format(
      "Public API method must be a class method (e.g. `self.#{node.method_name}(...)`)"
    )
  )
end

#support_autocorrect?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/rubocop/cop/packs/class_methods_as_public_apis.rb', line 35

def support_autocorrect?
  false
end