rubocop-packs 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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