rubocop-packs 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfc93294dd3f42e1dece0b632adba1a4a9ac811d0328c682dd121f2f11063d98
4
- data.tar.gz: df7a631fa820a30b672461e106882e7221555ddd3f64ba690dd8f7407d172ca4
3
+ metadata.gz: 7e2e2567a37e676f5c1ebf7a890057a542e4a5bbd667ab537ab0f82b24151a38
4
+ data.tar.gz: d19311bdf95df46ce37b93fe7bb898791b0a63b7804e418d77b300206ca818ba
5
5
  SHA512:
6
- metadata.gz: ff8d5fbd4ab6233223b705ab097bed58aa9e45139e148c084c071a299720a12759fe2173ba6f557d5794b7e097c5dbc0ef87db3744bd47903662721fb4a8831e
7
- data.tar.gz: cf7e59a3a2aa75057cee35ed0d5938b0c3131eff0d5c9657d9705833f26bff636ebc2d2ecf21fe69d04a49121e4772fa32457fe70225345587b3baaca77e1350
6
+ metadata.gz: 35941a67c992fc6afa9959d11c1c9d4929d48cb110329bea2ad3810458a769aeedc295c4e96bc1314cbc5ab3d1619b033e2314b8559753ce28827cbf329ebeeb
7
+ data.tar.gz: 1240836b6a4e0dff104815f1b7871102a2224abb3c80b2e8efa616d2dd251124149bc8efa4fcad31f63d300715e5853472090daa097cbaaa756bc635166172c5
data/config/default.yml CHANGED
@@ -6,11 +6,11 @@ Packs/ClassMethodsAsPublicApis:
6
6
  - Struct
7
7
  - OpenStruct
8
8
 
9
- Packs/NamespacedUnderPackageName:
10
- Enabled: false
9
+ Packs/NamespaceConvention:
10
+ Enabled: true
11
11
 
12
12
  Packs/TypedPublicApi:
13
- Enabled: false
13
+ Enabled: true
14
14
 
15
15
  Packs/RequireDocumentedPublicApis:
16
- Enabled: false
16
+ Enabled: true
@@ -7,6 +7,10 @@ module RuboCop
7
7
  # This cop states that public API should live on class methods, which are more easily statically analyzable,
8
8
  # searchable, and typically hold less state.
9
9
  #
10
+ # Options:
11
+ #
12
+ # * `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)
13
+ #
10
14
  # @example
11
15
  #
12
16
  # # bad
@@ -23,16 +27,6 @@ module RuboCop
23
27
  # end
24
28
  # end
25
29
  #
26
- # @example AcceptableParentClasses: [T::Enum, T::Struct, Struct, OpenStruct] (default)
27
- # You can define `AcceptableParentClasses` which are a list of classes that, if inherited from, non-class methods are permitted.
28
- # This is useful when value objects are a part of your public API.
29
- #
30
- # # good
31
- # # packs/foo/app/public/foo.rb
32
- # class Foo < T::Enum
33
- # const :blah
34
- # end
35
- #
36
30
  class ClassMethodsAsPublicApis < Base
37
31
  extend T::Sig
38
32
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Packs
6
- class NamespacedUnderPackageName < Base
6
+ class NamespaceConvention < Base
7
7
  #
8
8
  # This is a private class that represents API that we would prefer to be available somehow in Zeitwerk.
9
9
  #
@@ -12,6 +12,7 @@ module RuboCop
12
12
 
13
13
  class NamespaceContext < T::Struct
14
14
  const :current_namespace, String
15
+ const :current_fully_qualified_constant, String
15
16
  const :expected_namespace, String
16
17
  const :expected_filepath, String
17
18
  end
@@ -72,7 +73,8 @@ module RuboCop
72
73
  relative_desired_path = absolute_desired_path.relative_path_from(root_pathname)
73
74
 
74
75
  NamespaceContext.new(
75
- current_namespace: actual_namespace,
76
+ current_namespace: T.must(actual_namespace.split('::').first),
77
+ current_fully_qualified_constant: actual_namespace,
76
78
  expected_namespace: get_pack_based_namespace(package_for_path),
77
79
  expected_filepath: relative_desired_path.to_s
78
80
  )
@@ -99,7 +101,7 @@ module RuboCop
99
101
  def get_actual_namespace(remaining_file_path, package_name)
100
102
  # If the remaining file path is a ruby file (not a directory), then it establishes a global namespace
101
103
  # Otherwise, per Zeitwerk's conventions as listed above, its a directory that establishes another global namespace
102
- T.must(remaining_file_path.split('/').first).gsub('.rb', '').camelize
104
+ remaining_file_path.split('/').map { |entry| entry.gsub('.rb', '').camelize }.join('::')
103
105
  end
104
106
  end
105
107
 
@@ -2,12 +2,14 @@
2
2
 
3
3
  # For String#camelize
4
4
  require 'active_support/core_ext/string/inflections'
5
- require 'rubocop/cop/packs/namespaced_under_package_name/desired_zeitwerk_api'
5
+ require 'rubocop/cop/packs/namespace_convention/desired_zeitwerk_api'
6
6
 
7
7
  module RuboCop
8
8
  module Cop
9
9
  module Packs
10
10
  # This cop helps ensure that each pack exposes one namespace.
11
+ # Note that this cop doesn't necessarily expect you to be using stimpack (https://github.com/rubyatscale/stimpack),
12
+ # but it does expect packs to live in the organizational structure as described in the README.md of that gem.
11
13
  #
12
14
  # @example
13
15
  #
@@ -19,7 +21,7 @@ module RuboCop
19
21
  # # packs/foo/app/services/foo/blah/bar.rb
20
22
  # class Foo::Blah::Bar; end
21
23
  #
22
- class NamespacedUnderPackageName < Base
24
+ class NamespaceConvention < Base
23
25
  extend T::Sig
24
26
 
25
27
  include RangeHelp
@@ -47,6 +49,7 @@ module RuboCop
47
49
 
48
50
  package_name = package_for_path.name
49
51
  actual_namespace = namespace_context.current_namespace
52
+ current_fully_qualified_constant = namespace_context.current_fully_qualified_constant
50
53
 
51
54
  if allowed_global_namespaces.include?(actual_namespace)
52
55
  # No problem!
@@ -60,21 +63,23 @@ module RuboCop
60
63
  add_offense(
61
64
  source_range(processed_source.buffer, 1, 0),
62
65
  message: format(
63
- '`%<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.',
66
+ '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`.',
64
67
  package_name: package_name,
65
68
  expected_namespace: expected_namespace,
66
- expected_path: relative_desired_path
69
+ expected_path: relative_desired_path,
70
+ current_fully_qualified_constant: current_fully_qualified_constant
67
71
  )
68
72
  )
69
73
  elsif pack_owning_this_namespace
70
74
  add_offense(
71
75
  source_range(processed_source.buffer, 1, 0),
72
76
  message: format(
73
- '`%<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.',
77
+ 'Based on the filepath, this file defines `%<current_fully_qualified_constant>s`. `%<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`.',
74
78
  package_name: package_name,
75
79
  pack_owning_this_namespace: pack_owning_this_namespace,
76
80
  expected_namespace: expected_namespace,
77
81
  actual_namespace: actual_namespace,
82
+ current_fully_qualified_constant: current_fully_qualified_constant,
78
83
  expected_path: relative_desired_path
79
84
  )
80
85
  )
@@ -3,7 +3,35 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Packs
6
+ # This cop helps ensure that each pack has a documented public API
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # # packs/foo/app/public/foo.rb
12
+ # class Foo
13
+ # sig { void }
14
+ # def bar
15
+ # end
16
+ #
17
+ # # packs/foo/app/public/foo.rb
18
+ # class Foo
19
+ # # This is a documentation comment.
20
+ # # It can live below or below a sorbet type signature.
21
+ # sig { void }
22
+ # def bar
23
+ # end
24
+ #
6
25
  class RequireDocumentedPublicApis < Style::DocumentationMethod
26
+ # This cop does two things:
27
+ # 1) It only activates for things in the public folder
28
+ # 2) It allows `Style/DocumentationMethod` to work with sigs as expected.
29
+ #
30
+ # An alternate approach would be to monkey patch the existing cop, as `rubocop-sorbet` did here:
31
+ # https://github.com/Shopify/rubocop-sorbet/blob/6634f033611604cd76eeb73eae6d8728ec82d504/lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb
32
+ # This monkey-patched cop could/should probably be upstreamed to `rubocop-sorbet`, and then `config/default.yml` could simply set `packs/*/app/public/**/*`
33
+ # in the default include paths. However, that strategy has the downside of resulting in more configuration for the consumer if they only want to
34
+ # support this for some packs.
7
35
  extend T::Sig
8
36
 
9
37
  sig { returns(T::Boolean) }
data/lib/rubocop-packs.rb CHANGED
@@ -7,7 +7,7 @@ require 'parse_packwerk'
7
7
  require_relative 'rubocop/packs'
8
8
  require_relative 'rubocop/packs/inject'
9
9
 
10
- require 'rubocop/cop/packs/namespaced_under_package_name'
10
+ require 'rubocop/cop/packs/namespace_convention'
11
11
  require 'rubocop/cop/packs/typed_public_api'
12
12
  require 'rubocop/cop/packs/class_methods_as_public_apis'
13
13
  require 'rubocop/cop/packs/require_documented_public_apis'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-packs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
@@ -189,8 +189,8 @@ files:
189
189
  - config/default.yml
190
190
  - lib/rubocop-packs.rb
191
191
  - lib/rubocop/cop/packs/class_methods_as_public_apis.rb
192
- - lib/rubocop/cop/packs/namespaced_under_package_name.rb
193
- - lib/rubocop/cop/packs/namespaced_under_package_name/desired_zeitwerk_api.rb
192
+ - lib/rubocop/cop/packs/namespace_convention.rb
193
+ - lib/rubocop/cop/packs/namespace_convention/desired_zeitwerk_api.rb
194
194
  - lib/rubocop/cop/packs/require_documented_public_apis.rb
195
195
  - lib/rubocop/cop/packs/typed_public_api.rb
196
196
  - lib/rubocop/packs.rb