rubocop-modularization 0.0.3 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +11 -0
- data/lib/rubocop/cop/modularization/class_methods_as_public_apis.rb +71 -0
- data/lib/rubocop/cop/modularization/require_documented_public_apis.rb +34 -0
- data/lib/rubocop-modularization.rb +2 -0
- metadata +3 -2
- data/lib/rubocop/cop/modularization_cops.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b05e1b9669412cab4e323d4495bb2c0bd928874432d80accb97f21ef664c4fe3
|
4
|
+
data.tar.gz: d899d18f541eab5ed57021a57b6807033551a01e38f9f693b2448e6c949a28a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43b17bd5a5254cb14d8506034abfdbf4edd9e84ad13fd8b4f45cfd4132a094974f54a023aaa0f706af2f4b00a3c52407d9aa349651c3c0fd96a45e617e9f58c2
|
7
|
+
data.tar.gz: bdb1bd61127bb3b904419d46588caade2af35e3ff8831e00b94c13b63fbb624d9c4628cc2b2b098ee578bba520d31c8106ecbe44c7c164224848a3cb4d57bdfc
|
data/README.md
CHANGED
data/config/default.yml
CHANGED
@@ -1,5 +1,16 @@
|
|
1
|
+
Modularization/ClassMethodsAsPublicApis:
|
2
|
+
Enabled: true
|
3
|
+
AcceptableParentClasses:
|
4
|
+
- T::Enum
|
5
|
+
- T::Struct
|
6
|
+
- Struct
|
7
|
+
- OpenStruct
|
8
|
+
|
1
9
|
Modularization/NamespacedUnderPackageName:
|
2
10
|
Enabled: false
|
3
11
|
|
4
12
|
Modularization/TypedPublicApi:
|
5
13
|
Enabled: false
|
14
|
+
|
15
|
+
RequireDocumentedPublicApis:
|
16
|
+
Enabled: false
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Modularization
|
7
|
+
# This cop states that public API should live on class methods, which are more easily statically analyzable,
|
8
|
+
# searchable, and typically hold less state.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# # packs/foo/app/public/foo.rb
|
14
|
+
# module Foo
|
15
|
+
# def blah
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# # packs/foo/app/public/foo.rb
|
21
|
+
# module Foo
|
22
|
+
# def self.blah
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
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
|
+
class ClassMethodsAsPublicApis < Base
|
37
|
+
extend T::Sig
|
38
|
+
|
39
|
+
sig { returns(T::Boolean) }
|
40
|
+
def support_autocorrect?
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
sig { params(node: T.untyped).void }
|
45
|
+
def on_def(node)
|
46
|
+
# This cop only applies for ruby files in `app/public`
|
47
|
+
return if !processed_source.file_path.include?('app/public')
|
48
|
+
|
49
|
+
# Looked at https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/MissingSuper source code as inspiration for htis part.
|
50
|
+
class_node = node.each_ancestor(:class).first
|
51
|
+
module_node = node.each_ancestor(:module).first
|
52
|
+
parent_class = class_node&.parent_class || module_node&.parent
|
53
|
+
|
54
|
+
acceptable_parent_classes = cop_config['AcceptableParentClasses'] || []
|
55
|
+
|
56
|
+
# Used this PR as inspiration to check if we're within a `class << self` block
|
57
|
+
uses_implicit_static_methods = node.each_ancestor(:sclass).first&.identifier&.source == 'self'
|
58
|
+
class_is_allowed_to_have_instance_methods = acceptable_parent_classes.include?(parent_class&.const_name)
|
59
|
+
return if uses_implicit_static_methods || class_is_allowed_to_have_instance_methods
|
60
|
+
|
61
|
+
add_offense(
|
62
|
+
node.source_range,
|
63
|
+
message: format(
|
64
|
+
'Top-level files in the public/ folder may only define class methods.'
|
65
|
+
)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Modularization
|
6
|
+
class RequireDocumentedPublicApis < Style::DocumentationMethod
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { returns(T::Boolean) }
|
10
|
+
def support_autocorrect?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
sig { params(node: T.untyped).void }
|
15
|
+
def check(node)
|
16
|
+
# This cop only applies for ruby files in `app/public`
|
17
|
+
return if !processed_source.file_path.include?('app/public')
|
18
|
+
return if non_public?(node) && !require_for_non_public_methods?
|
19
|
+
|
20
|
+
left_sibling = node.left_sibling
|
21
|
+
left_sibling_is_sig = left_sibling && (left_sibling.source.include?('sig do') || left_sibling.source.include?('sig {'))
|
22
|
+
# Is there a better way to check if the left sibling is a sorbet signature? Probably!
|
23
|
+
if left_sibling_is_sig
|
24
|
+
return if documentation_comment?(node.left_sibling)
|
25
|
+
elsif documentation_comment?(node)
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
add_offense(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -9,5 +9,7 @@ require_relative 'rubocop/modularization/inject'
|
|
9
9
|
|
10
10
|
require 'rubocop/cop/modularization/namespaced_under_package_name'
|
11
11
|
require 'rubocop/cop/modularization/typed_public_api'
|
12
|
+
require 'rubocop/cop/modularization/class_methods_as_public_apis'
|
13
|
+
require 'rubocop/cop/modularization/require_documented_public_apis'
|
12
14
|
|
13
15
|
RuboCop::Modularization::Inject.defaults!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-modularization
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gusto Engineers
|
@@ -188,10 +188,11 @@ files:
|
|
188
188
|
- README.md
|
189
189
|
- config/default.yml
|
190
190
|
- lib/rubocop-modularization.rb
|
191
|
+
- lib/rubocop/cop/modularization/class_methods_as_public_apis.rb
|
191
192
|
- lib/rubocop/cop/modularization/namespaced_under_package_name.rb
|
192
193
|
- lib/rubocop/cop/modularization/namespaced_under_package_name/desired_zeitwerk_api.rb
|
194
|
+
- lib/rubocop/cop/modularization/require_documented_public_apis.rb
|
193
195
|
- lib/rubocop/cop/modularization/typed_public_api.rb
|
194
|
-
- lib/rubocop/cop/modularization_cops.rb
|
195
196
|
- lib/rubocop/modularization.rb
|
196
197
|
- lib/rubocop/modularization/inject.rb
|
197
198
|
- lib/rubocop/modularization/private.rb
|