rubocop-packs 0.0.26 → 0.0.28
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 +4 -4
- data/config/default.yml +1 -0
- data/lib/rubocop/cop/packs/class_methods_as_public_apis.rb +21 -1
- data/lib/rubocop/packs/private.rb +8 -16
- data/lib/rubocop/packs.rb +12 -8
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4888c0b36e59d1da1aaa62d1390da897fce811909d99c5e1189bca0efd36050
|
4
|
+
data.tar.gz: 7d1957e8c598a6acbcfa3b0b8f49578dcb3424d01c20178c2045459654a2478f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b55558140df2b0d0e68f64668a94e814c30a6ac42b144d0dc7fbc7118bdf982fb87b45085592ca219946ae6a2df73bb22562a83ae888fb021343ec0cea7c685c
|
7
|
+
data.tar.gz: fa54dc58358e0f32104c2acfa0536ff6239430c287a75e5ad0a346ae9979360f59a67037a34599e98a1df525cbe6c31c7350af95b6c33dba1dcdacb02cbdfe88
|
data/config/default.yml
CHANGED
@@ -10,6 +10,7 @@ module RuboCop
|
|
10
10
|
# Options:
|
11
11
|
#
|
12
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
|
+
# * `AcceptableMixins`: A list of modules that, if included, non-class methods are permitted
|
13
14
|
#
|
14
15
|
# @example
|
15
16
|
#
|
@@ -47,11 +48,14 @@ module RuboCop
|
|
47
48
|
|
48
49
|
acceptable_parent_classes = cop_config['AcceptableParentClasses'] || []
|
49
50
|
|
50
|
-
# Used this PR as inspiration to check if we're within a `class << self` block
|
51
51
|
uses_implicit_static_methods = node.each_ancestor(:sclass).first&.identifier&.source == 'self'
|
52
52
|
class_is_allowed_to_have_instance_methods = acceptable_parent_classes.include?(parent_class&.const_name)
|
53
53
|
return if uses_implicit_static_methods || class_is_allowed_to_have_instance_methods
|
54
54
|
|
55
|
+
is_sorbet_interface_or_abstract_class = !module_node.nil? && module_node.descendants.any? { |d| d.is_a?(RuboCop::AST::SendNode) && (d.method_name == :interface! || d.method_name == :abstract!) }
|
56
|
+
return if is_sorbet_interface_or_abstract_class
|
57
|
+
return if node_includes_acceptable_mixin?(class_node || module_node)
|
58
|
+
|
55
59
|
add_offense(
|
56
60
|
node.source_range,
|
57
61
|
message: format(
|
@@ -59,6 +63,22 @@ module RuboCop
|
|
59
63
|
)
|
60
64
|
)
|
61
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
sig { params(node: T.untyped).returns(T::Boolean) }
|
70
|
+
def node_includes_acceptable_mixin?(node)
|
71
|
+
acceptable_mixins = cop_config['AcceptableMixins'] || []
|
72
|
+
return false if node.nil?
|
73
|
+
|
74
|
+
node.descendants.any? do |d|
|
75
|
+
d.is_a?(RuboCop::AST::SendNode) &&
|
76
|
+
d.method_name == :include &&
|
77
|
+
d.arguments.count == 1 &&
|
78
|
+
d.arguments.first.is_a?(RuboCop::AST::ConstNode) &&
|
79
|
+
acceptable_mixins.include?(d.arguments.first.const_name)
|
80
|
+
end
|
81
|
+
end
|
62
82
|
end
|
63
83
|
end
|
64
84
|
end
|
@@ -148,20 +148,22 @@ module RuboCop
|
|
148
148
|
errors
|
149
149
|
end
|
150
150
|
|
151
|
-
sig { params(args: T.untyped).
|
151
|
+
sig { params(args: T.untyped).void }
|
152
152
|
def self.execute_rubocop(args)
|
153
|
-
|
154
|
-
RuboCop::CLI.new.run(args)
|
155
|
-
end
|
153
|
+
RuboCop::CLI.new.run(args)
|
156
154
|
end
|
157
155
|
|
158
156
|
sig { params(paths: T::Array[String], cop_names: T::Array[String]).returns(T::Array[Offense]) }
|
159
157
|
def self.offenses_for(paths:, cop_names:)
|
160
158
|
cop_arguments = cop_names.join(',')
|
161
159
|
# I think we can potentially use `RuboCop::CLI.new(args)` for this to avoid shelling out and starting another process that needs to reload the bundle
|
162
|
-
args = [*paths, "--only=#{cop_arguments}", '--format=json']
|
160
|
+
args = [*paths, "--only=#{cop_arguments}", '--format=json', '--out=tmp/rubocop-output']
|
161
|
+
FileUtils.mkdir_p('tmp')
|
163
162
|
puts "Executing: bundle exec rubocop #{args.join(' ')}"
|
164
|
-
|
163
|
+
Private.execute_rubocop(args)
|
164
|
+
output = Pathname.new('tmp/rubocop-output')
|
165
|
+
json = JSON.parse(Pathname.new('tmp/rubocop-output').read)
|
166
|
+
output.delete
|
165
167
|
offenses = T.let([], T::Array[Offense])
|
166
168
|
json['files'].each do |file_hash|
|
167
169
|
filepath = file_hash['path']
|
@@ -175,16 +177,6 @@ module RuboCop
|
|
175
177
|
|
176
178
|
offenses
|
177
179
|
end
|
178
|
-
|
179
|
-
sig { params(block: T.untyped).returns(String) }
|
180
|
-
def self.with_captured_stdout(&block)
|
181
|
-
original_stdout = $stdout # capture previous value of $stdout
|
182
|
-
$stdout = StringIO.new # assign a string buffer to $stdout
|
183
|
-
yield # perform the body of the user code
|
184
|
-
$stdout.string # return the contents of the string buffer
|
185
|
-
ensure
|
186
|
-
$stdout = original_stdout # restore $stdout to its previous value
|
187
|
-
end
|
188
180
|
end
|
189
181
|
|
190
182
|
private_constant :Private
|
data/lib/rubocop/packs.rb
CHANGED
@@ -28,6 +28,12 @@ module RuboCop
|
|
28
28
|
#
|
29
29
|
sig { params(packs: T::Array[ParsePackwerk::Package], files: T::Array[String]).void }
|
30
30
|
def self.regenerate_todo(packs: [], files: [])
|
31
|
+
# Delete the old pack-level rubocop todo files so that we can regenerate the new one from scratch
|
32
|
+
packs.each do |pack|
|
33
|
+
rubocop_todo_yml = pack.directory.join(PACK_LEVEL_RUBOCOP_TODO_YML)
|
34
|
+
rubocop_todo_yml.delete if rubocop_todo_yml.exist?
|
35
|
+
end
|
36
|
+
|
31
37
|
paths = packs.empty? ? files : packs.map(&:name).reject { |name| name == ParsePackwerk::ROOT_PACKAGE_NAME }
|
32
38
|
offenses = Private.offenses_for(
|
33
39
|
paths: paths,
|
@@ -39,19 +45,17 @@ module RuboCop
|
|
39
45
|
next if !pack.directory.join(PACK_LEVEL_RUBOCOP_YML).exist?
|
40
46
|
|
41
47
|
rubocop_todo_yml = pack.directory.join(PACK_LEVEL_RUBOCOP_TODO_YML)
|
42
|
-
|
43
|
-
if packs.any? && rubocop_todo_yml.exist?
|
44
|
-
rubocop_todo_yml.delete
|
45
|
-
rubocop_todo = {}
|
46
|
-
elsif rubocop_todo_yml.exist?
|
48
|
+
if rubocop_todo_yml.exist?
|
47
49
|
rubocop_todo = YAML.load_file(rubocop_todo_yml)
|
48
50
|
else
|
49
51
|
rubocop_todo = {}
|
50
52
|
end
|
51
53
|
|
52
|
-
offenses_for_pack.each do |
|
53
|
-
|
54
|
-
|
54
|
+
offenses_for_pack.group_by(&:filepath).each do |filepath, offenses_by_filepath|
|
55
|
+
offenses_by_filepath.map(&:cop_name).uniq.each do |cop_name|
|
56
|
+
rubocop_todo[cop_name] ||= { 'Exclude' => [] }
|
57
|
+
rubocop_todo[cop_name]['Exclude'] << filepath
|
58
|
+
end
|
55
59
|
end
|
56
60
|
|
57
61
|
next if rubocop_todo.empty?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gusto Engineers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -178,7 +178,7 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
-
description:
|
181
|
+
description: A collection of Rubocop rules for gradually modularizing a ruby codebase
|
182
182
|
email:
|
183
183
|
- dev@gusto.com
|
184
184
|
executables: []
|
@@ -230,5 +230,5 @@ requirements: []
|
|
230
230
|
rubygems_version: 3.1.6
|
231
231
|
signing_key:
|
232
232
|
specification_version: 4
|
233
|
-
summary:
|
233
|
+
summary: A collection of Rubocop rules for gradually modularizing a ruby codebase
|
234
234
|
test_files: []
|