rubocop-packs 0.0.7 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +4 -4
- data/lib/rubocop/cop/packs/class_methods_as_public_apis.rb +4 -10
- data/lib/rubocop/cop/packs/{namespaced_under_package_name → namespace_convention}/desired_zeitwerk_api.rb +5 -3
- data/lib/rubocop/cop/packs/{namespaced_under_package_name.rb → namespace_convention.rb} +13 -5
- data/lib/rubocop/cop/packs/require_documented_public_apis.rb +28 -0
- data/lib/rubocop-packs.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3aa6a83103635cffaf57bbe3187211f14b0981633a55cf04cd73f6261df3d83a
|
4
|
+
data.tar.gz: 8816eab16fe3dd069a3327b8f1569e910ea07a012bb97bead1baf0f7f6cdfc66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37e828c802da1563049ce07a05e224187bfe8a3d61861f0cc05e774c311a3627d66d6ff116480d44100a9d31ef756bde1ea16777e02e5517e8f31fb0aab77595
|
7
|
+
data.tar.gz: 2e54cf17766e69bfd81663a488f1171a74335dd71c55fbfc55f9d1334f6eeae5d0b0fd5e7134349b42fb61c749520a760fd1902f0dfe19c457c311cba55f10ca
|
data/config/default.yml
CHANGED
@@ -6,11 +6,11 @@ Packs/ClassMethodsAsPublicApis:
|
|
6
6
|
- Struct
|
7
7
|
- OpenStruct
|
8
8
|
|
9
|
-
Packs/
|
10
|
-
Enabled:
|
9
|
+
Packs/NamespaceConvention:
|
10
|
+
Enabled: true
|
11
11
|
|
12
12
|
Packs/TypedPublicApi:
|
13
|
-
Enabled:
|
13
|
+
Enabled: true
|
14
14
|
|
15
15
|
Packs/RequireDocumentedPublicApis:
|
16
|
-
Enabled:
|
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
|
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
|
-
|
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/
|
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
|
24
|
+
class NamespaceConvention < Base
|
23
25
|
extend T::Sig
|
24
26
|
|
25
27
|
include RangeHelp
|
@@ -35,6 +37,9 @@ module RuboCop
|
|
35
37
|
|
36
38
|
relative_filename = relative_filepath.to_s
|
37
39
|
package_for_path = ParsePackwerk.package_from_path(relative_filename)
|
40
|
+
# If a pack is using automatic pack namespaces, this protection is a no-op since zeitwerk will enforce single namespaces in that case.
|
41
|
+
return if package_for_path.metadata['automatic_pack_namespace']
|
42
|
+
|
38
43
|
return if package_for_path.nil?
|
39
44
|
|
40
45
|
namespace_context = desired_zeitwerk_api.for_file(relative_filename, package_for_path)
|
@@ -47,6 +52,7 @@ module RuboCop
|
|
47
52
|
|
48
53
|
package_name = package_for_path.name
|
49
54
|
actual_namespace = namespace_context.current_namespace
|
55
|
+
current_fully_qualified_constant = namespace_context.current_fully_qualified_constant
|
50
56
|
|
51
57
|
if allowed_global_namespaces.include?(actual_namespace)
|
52
58
|
# No problem!
|
@@ -60,21 +66,23 @@ module RuboCop
|
|
60
66
|
add_offense(
|
61
67
|
source_range(processed_source.buffer, 1, 0),
|
62
68
|
message: format(
|
63
|
-
'
|
69
|
+
'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
70
|
package_name: package_name,
|
65
71
|
expected_namespace: expected_namespace,
|
66
|
-
expected_path: relative_desired_path
|
72
|
+
expected_path: relative_desired_path,
|
73
|
+
current_fully_qualified_constant: current_fully_qualified_constant
|
67
74
|
)
|
68
75
|
)
|
69
76
|
elsif pack_owning_this_namespace
|
70
77
|
add_offense(
|
71
78
|
source_range(processed_source.buffer, 1, 0),
|
72
79
|
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`.
|
80
|
+
'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
81
|
package_name: package_name,
|
75
82
|
pack_owning_this_namespace: pack_owning_this_namespace,
|
76
83
|
expected_namespace: expected_namespace,
|
77
84
|
actual_namespace: actual_namespace,
|
85
|
+
current_fully_qualified_constant: current_fully_qualified_constant,
|
78
86
|
expected_path: relative_desired_path
|
79
87
|
)
|
80
88
|
)
|
@@ -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/
|
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.
|
4
|
+
version: 0.0.10
|
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/
|
193
|
-
- lib/rubocop/cop/packs/
|
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
|