Class: RuboCop::Cop::Packs::RootNamespaceIsPackName

Inherits:
Base
  • Object
show all
Extended by:
T::Sig
Includes:
RangeHelp
Defined in:
lib/rubocop/cop/packs/root_namespace_is_pack_name.rb,
lib/rubocop/cop/packs/root_namespace_is_pack_name/desired_zeitwerk_api.rb

Overview

This cop helps ensure that each pack exposes one namespace. Note that this cop doesn’t necessarily expect you to be using packs-rails (github.com/rubyatscale/packs-rails), but it does expect packs to live in the organizational structure as described in the README.md of that gem.

This allows packs to opt in and also prevent other files from sitting in their namespace.

Examples:


# bad
# packs/foo/app/services/blah/bar.rb
class Blah::Bar; end

# good
# packs/foo/app/services/foo/blah/bar.rb
class Foo::Blah::Bar; end

Instance Method Summary collapse

Instance Method Details

#on_new_investigationObject



32
33
34
35
36
37
38
39
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
66
67
68
69
70
71
72
73
74
# File 'lib/rubocop/cop/packs/root_namespace_is_pack_name.rb', line 32

def on_new_investigation
  absolute_filepath = Pathname.new(processed_source.file_path)
  relative_filepath = absolute_filepath.relative_path_from(Pathname.pwd)
  relative_filename = relative_filepath.to_s

  return if relative_filepath.extname != '.rb'
  return if relative_filename.include?('spec/')
  return if !relative_filename.include?('app/')

  relative_filename = relative_filepath.to_s
  package_for_path = ::Packs.for_file(relative_filename)

  return if package_for_path.nil?

  namespace_context = desired_zeitwerk_api.for_file(relative_filename, package_for_path)
  return if namespace_context.nil?

  allowed_global_namespaces = Set.new([
                                        namespace_context.expected_namespace,
                                        *RuboCop::Packs.config.globally_permitted_namespaces
                                      ])

  package_name = package_for_path.name
  actual_namespace = namespace_context.current_namespace
  current_fully_qualified_constant = namespace_context.current_fully_qualified_constant

  if allowed_global_namespaces.include?(actual_namespace)
    # No problem!
  else
    expected_namespace = namespace_context.expected_namespace
    relative_desired_path = namespace_context.expected_filepath
    add_offense(
      source_range(processed_source.buffer, 1, 0),
      message: format(
        'Based on the filepath, this file defines `%<current_fully_qualified_constant>s`, but it should be namespaced as `%<expected_namespace>s::%<current_fully_qualified_constant>s` with path `%<expected_path>s`.',
        package_name: package_name,
        expected_namespace: expected_namespace,
        expected_path: relative_desired_path,
        current_fully_qualified_constant: current_fully_qualified_constant
      )
    )
  end
end

#support_autocorrect?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/rubocop/cop/packs/root_namespace_is_pack_name.rb', line 79

def support_autocorrect?
  false
end