Class: RuboCop::Cop::Modularization::NamespacedUnderPackageName

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

Overview

This cop helps ensure that each pack exposes one 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



28
29
30
31
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
75
76
77
78
79
80
81
82
83
# File 'lib/rubocop/cop/modularization/namespaced_under_package_name.rb', line 28

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

  # This cop only works for files ruby files in `app`
  return if !relative_filename.include?('app/') || relative_filepath.extname != '.rb'

  relative_filename = relative_filepath.to_s
  package_for_path = ParsePackwerk.package_from_path(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,
                                        *cop_config['GloballyPermittedNamespaces']
                                      ])

  package_name = package_for_path.name
  actual_namespace = namespace_context.current_namespace

  if allowed_global_namespaces.include?(actual_namespace)
    # No problem!
  else
    package_enforces_namespaces = cop_config['IncludePacks'].include?(package_for_path.name)
    expected_namespace = namespace_context.expected_namespace
    relative_desired_path = namespace_context.expected_filepath
    pack_owning_this_namespace = namespaces_to_packs[actual_namespace]

    if package_enforces_namespaces
      add_offense(
        source_range(processed_source.buffer, 1, 0),
        message: format(
          '`%<package_name>s` prevents modules/classes that are not submodules of the package namespace. Should be namespaced under `%<expected_namespace>s` with path `%<expected_path>s`. See https://go/packwerk_cheatsheet_namespaces for more info.',
          package_name: package_name,
          expected_namespace: expected_namespace,
          expected_path: relative_desired_path
        )
      )
    elsif pack_owning_this_namespace
      add_offense(
        source_range(processed_source.buffer, 1, 0),
        message: format(
          '`%<pack_owning_this_namespace>s` prevents other packs from sitting in the `%<actual_namespace>s` namespace. This should be namespaced under `%<expected_namespace>s` with path `%<expected_path>s`. See https://go/packwerk_cheatsheet_namespaces for more info.',
          package_name: package_name,
          pack_owning_this_namespace: pack_owning_this_namespace,
          expected_namespace: expected_namespace,
          actual_namespace: actual_namespace,
          expected_path: relative_desired_path
        )
      )
    end
  end
end

#support_autocorrect?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/rubocop/cop/modularization/namespaced_under_package_name.rb', line 88

def support_autocorrect?
  false
end