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 +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} +10 -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: 7e2e2567a37e676f5c1ebf7a890057a542e4a5bbd667ab537ab0f82b24151a38
|
4
|
+
data.tar.gz: d19311bdf95df46ce37b93fe7bb898791b0a63b7804e418d77b300206ca818ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
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
|
@@ -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
|
-
'
|
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`.
|
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/
|
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.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/
|
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
|