packwerk 1.0.2 → 1.2.0
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/.github/workflows/ci.yml +14 -5
- data/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +129 -111
- data/README.md +8 -1
- data/USAGE.md +39 -17
- data/dev.yml +1 -1
- data/exe/packwerk +1 -1
- data/gemfiles/Gemfile-rails-6-0 +22 -0
- data/lib/packwerk.rb +73 -34
- data/lib/packwerk/application_load_paths.rb +3 -2
- data/lib/packwerk/application_validator.rb +85 -69
- data/lib/packwerk/association_inspector.rb +23 -11
- data/lib/packwerk/checker.rb +4 -7
- data/lib/packwerk/cli.rb +36 -93
- data/lib/packwerk/configuration.rb +10 -2
- data/lib/packwerk/const_node_inspector.rb +13 -14
- data/lib/packwerk/constant_discovery.rb +2 -0
- data/lib/packwerk/constant_name_inspector.rb +0 -1
- data/lib/packwerk/dependency_checker.rb +12 -17
- data/lib/packwerk/deprecated_references.rb +25 -8
- data/lib/packwerk/file_processor.rb +0 -4
- data/lib/packwerk/formatters/offenses_formatter.rb +43 -0
- data/lib/packwerk/formatters/progress_formatter.rb +9 -4
- data/lib/packwerk/generators/configuration_file.rb +0 -1
- data/lib/packwerk/inflector.rb +0 -2
- data/lib/packwerk/node.rb +9 -2
- data/lib/packwerk/node_processor.rb +15 -32
- data/lib/packwerk/node_processor_factory.rb +0 -5
- data/lib/packwerk/node_visitor.rb +1 -4
- data/lib/packwerk/offense.rb +2 -8
- data/lib/packwerk/offense_collection.rb +84 -0
- data/lib/packwerk/offenses_formatter.rb +15 -0
- data/lib/packwerk/output_style.rb +20 -0
- data/lib/packwerk/output_styles/coloured.rb +29 -0
- data/lib/packwerk/output_styles/plain.rb +26 -0
- data/lib/packwerk/package.rb +8 -0
- data/lib/packwerk/package_set.rb +8 -5
- data/lib/packwerk/parse_run.rb +104 -0
- data/lib/packwerk/parsed_constant_definitions.rb +2 -4
- data/lib/packwerk/parsers.rb +0 -2
- data/lib/packwerk/parsers/erb.rb +4 -2
- data/lib/packwerk/parsers/factory.rb +10 -3
- data/lib/packwerk/privacy_checker.rb +22 -17
- data/lib/packwerk/reference_extractor.rb +0 -8
- data/lib/packwerk/reference_offense.rb +49 -0
- data/lib/packwerk/result.rb +9 -0
- data/lib/packwerk/run_context.rb +4 -20
- data/lib/packwerk/sanity_checker.rb +1 -3
- data/lib/packwerk/spring_command.rb +1 -1
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk/violation_type.rb +0 -2
- data/library.yml +1 -1
- data/packwerk.gemspec +1 -0
- data/service.yml +1 -4
- data/shipit.rubygems.yml +5 -1
- data/sorbet/rbi/gems/{actioncable@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actioncable@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +56 -36
- data/sorbet/rbi/gems/{actionmailbox@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailbox@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +25 -28
- data/sorbet/rbi/gems/{actionmailer@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailer@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +43 -24
- data/sorbet/rbi/gems/{actionpack@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionpack@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +382 -284
- data/sorbet/rbi/gems/{actiontext@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actiontext@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +76 -40
- data/sorbet/rbi/gems/{actionview@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionview@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +206 -195
- data/sorbet/rbi/gems/{activejob@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activejob@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +64 -75
- data/sorbet/rbi/gems/{activemodel@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activemodel@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +103 -56
- data/sorbet/rbi/gems/{activerecord@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activerecord@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1250 -898
- data/sorbet/rbi/gems/{activestorage@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activestorage@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +92 -120
- data/sorbet/rbi/gems/{activesupport@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activesupport@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +292 -193
- data/sorbet/rbi/gems/{ast@2.4.1.rbi → ast@2.4.2.rbi} +2 -1
- data/sorbet/rbi/gems/{better_html@1.0.15.rbi → better_html@1.0.16.rbi} +2 -2
- data/sorbet/rbi/gems/{concurrent-ruby@1.1.6.rbi → concurrent-ruby@1.1.8.rbi} +12 -9
- data/sorbet/rbi/gems/{erubi@1.9.0.rbi → erubi@1.10.0.rbi} +3 -1
- data/sorbet/rbi/gems/{i18n@1.8.2.rbi → i18n@1.8.10.rbi} +19 -52
- data/sorbet/rbi/gems/{loofah@2.5.0.rbi → loofah@2.9.0.rbi} +3 -1
- data/sorbet/rbi/gems/marcel@1.0.0.rbi +70 -0
- data/sorbet/rbi/gems/{mini_mime@1.0.2.rbi → mini_mime@1.0.3.rbi} +6 -6
- data/sorbet/rbi/gems/{mini_portile2@2.4.0.rbi → minitest-focus@1.2.1.rbi} +2 -2
- data/sorbet/rbi/gems/{minitest@5.14.0.rbi → minitest@5.14.4.rbi} +31 -29
- data/sorbet/rbi/gems/{mocha@1.11.2.rbi → mocha@1.12.0.rbi} +25 -36
- data/sorbet/rbi/gems/{nio4r@2.5.2.rbi → nio4r@2.5.7.rbi} +21 -20
- data/sorbet/rbi/gems/{nokogiri@1.10.9.rbi → nokogiri@1.11.2.rbi} +193 -154
- data/sorbet/rbi/gems/parallel@1.20.1.rbi +117 -0
- data/sorbet/rbi/gems/parlour@6.0.0.rbi +1272 -0
- data/sorbet/rbi/gems/{parser@2.7.1.4.rbi → parser@3.0.0.0.rbi} +287 -174
- data/sorbet/rbi/gems/{pry@0.13.1.rbi → pry@0.14.0.rbi} +1 -1
- data/sorbet/rbi/gems/racc@1.5.2.rbi +57 -0
- data/sorbet/rbi/gems/{rack@2.2.2.rbi → rack@2.2.3.rbi} +23 -35
- data/sorbet/rbi/gems/{rails@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → rails@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1 -1
- data/sorbet/rbi/gems/{railties@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → railties@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +132 -121
- data/sorbet/rbi/gems/{rake@13.0.1.rbi → rake@13.0.3.rbi} +16 -20
- data/sorbet/rbi/gems/{parallel@1.19.1.rbi → regexp_parser@2.1.1.rbi} +2 -2
- data/sorbet/rbi/gems/rubocop-ast@1.4.1.rbi +8 -0
- data/sorbet/rbi/gems/{rubocop-performance@1.5.2.rbi → rubocop-performance@1.10.2.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop-shopify@1.0.2.rbi → rubocop-shopify@2.0.1.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop-sorbet@0.3.7.rbi → rubocop-sorbet@0.6.1.rbi} +1 -1
- data/sorbet/rbi/gems/{rubocop@0.82.0.rbi → rubocop@1.12.0.rbi} +1 -1
- data/sorbet/rbi/gems/{ruby-progressbar@1.10.1.rbi → ruby-progressbar@1.11.0.rbi} +1 -1
- data/sorbet/rbi/gems/spoom@1.1.0.rbi +1061 -0
- data/sorbet/rbi/gems/{spring@2.1.0.rbi → spring@2.1.1.rbi} +7 -7
- data/sorbet/rbi/gems/{sprockets-rails@3.2.1.rbi → sprockets-rails@3.2.2.rbi} +88 -68
- data/sorbet/rbi/gems/{sprockets@4.0.0.rbi → sprockets@4.0.2.rbi} +8 -7
- data/sorbet/rbi/gems/{tapioca@0.4.5.rbi → tapioca@0.4.19.rbi} +109 -24
- data/sorbet/rbi/gems/{thor@1.0.1.rbi → thor@1.1.0.rbi} +16 -15
- data/sorbet/rbi/gems/{tzinfo@2.0.2.rbi → tzinfo@2.0.4.rbi} +21 -2
- data/sorbet/rbi/gems/{unicode-display_width@1.7.0.rbi → unicode-display_width@2.0.0.rbi} +1 -1
- data/sorbet/rbi/gems/{websocket-driver@0.7.1.rbi → websocket-driver@0.7.3.rbi} +29 -29
- data/sorbet/rbi/gems/{websocket-extensions@0.1.4.rbi → websocket-extensions@0.1.5.rbi} +2 -2
- data/sorbet/rbi/gems/zeitwerk@2.4.2.rbi +177 -0
- data/sorbet/tapioca/require.rb +1 -0
- metadata +78 -57
- data/lib/packwerk/checking_deprecated_references.rb +0 -40
- data/lib/packwerk/output_styles.rb +0 -41
- data/lib/packwerk/reference_lister.rb +0 -23
- data/lib/packwerk/updating_deprecated_references.rb +0 -51
- data/sorbet/rbi/gems/jaro_winkler@1.5.4.rbi +0 -8
- data/sorbet/rbi/gems/marcel@0.3.3.rbi +0 -30
- data/sorbet/rbi/gems/mimemagic@0.3.5.rbi +0 -47
- data/sorbet/rbi/gems/parlour@4.0.1.rbi +0 -561
- data/sorbet/rbi/gems/spoom@1.0.4.rbi +0 -418
- data/sorbet/rbi/gems/zeitwerk@2.3.0.rbi +0 -8
data/lib/packwerk/checker.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "sorbet-runtime"
|
5
|
-
require "packwerk/reference_lister"
|
6
|
-
|
7
4
|
module Packwerk
|
8
5
|
module Checker
|
9
6
|
extend T::Sig
|
@@ -11,10 +8,10 @@ module Packwerk
|
|
11
8
|
|
12
9
|
interface!
|
13
10
|
|
14
|
-
sig {
|
15
|
-
def
|
11
|
+
sig { returns(ViolationType).abstract }
|
12
|
+
def violation_type; end
|
16
13
|
|
17
|
-
sig { params(reference: Reference).returns(
|
18
|
-
def
|
14
|
+
sig { params(reference: Reference).returns(T::Boolean).abstract }
|
15
|
+
def invalid_reference?(reference); end
|
19
16
|
end
|
20
17
|
end
|
data/lib/packwerk/cli.rb
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
|
-
require "benchmark"
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
require "packwerk/application_validator"
|
7
|
-
require "packwerk/configuration"
|
8
|
-
require "packwerk/files_for_processing"
|
9
|
-
require "packwerk/formatters/progress_formatter"
|
10
|
-
require "packwerk/inflector"
|
11
|
-
require "packwerk/output_styles"
|
12
|
-
require "packwerk/run_context"
|
13
|
-
require "packwerk/updating_deprecated_references"
|
14
|
-
require "packwerk/checking_deprecated_references"
|
15
3
|
|
16
4
|
module Packwerk
|
17
5
|
class Cli
|
18
6
|
extend T::Sig
|
19
7
|
|
20
|
-
|
8
|
+
sig do
|
9
|
+
params(
|
10
|
+
configuration: T.nilable(Configuration),
|
11
|
+
out: T.any(StringIO, IO),
|
12
|
+
err_out: T.any(StringIO, IO),
|
13
|
+
style: Packwerk::OutputStyle,
|
14
|
+
offenses_formatter: T.nilable(Packwerk::OffensesFormatter)
|
15
|
+
).void
|
16
|
+
end
|
17
|
+
def initialize(
|
18
|
+
configuration: nil,
|
19
|
+
out: $stdout,
|
20
|
+
err_out: $stderr,
|
21
|
+
style: OutputStyles::Plain.new,
|
22
|
+
offenses_formatter: nil
|
23
|
+
)
|
21
24
|
@out = out
|
22
25
|
@err_out = err_out
|
23
26
|
@style = style
|
24
27
|
@configuration = configuration || Configuration.from_path
|
25
|
-
@run_context = run_context || Packwerk::RunContext.from_configuration(
|
26
|
-
@configuration,
|
27
|
-
reference_lister: ::Packwerk::CheckingDeprecatedReferences.new(@configuration.root_path),
|
28
|
-
)
|
29
28
|
@progress_formatter = Formatters::ProgressFormatter.new(@out, style: style)
|
29
|
+
@offenses_formatter = offenses_formatter || Formatters::OffensesFormatter.new(style: @style)
|
30
30
|
end
|
31
31
|
|
32
32
|
sig { params(args: T::Array[String]).returns(T.noreturn) }
|
@@ -44,11 +44,13 @@ module Packwerk
|
|
44
44
|
when "generate_configs"
|
45
45
|
generate_configs
|
46
46
|
when "check"
|
47
|
-
|
47
|
+
output_result(parse_run(args).check)
|
48
|
+
when "detect-stale-violations"
|
49
|
+
output_result(parse_run(args).detect_stale_violations)
|
48
50
|
when "update"
|
49
51
|
update(args)
|
50
52
|
when "update-deprecations"
|
51
|
-
|
53
|
+
output_result(parse_run(args).update_deprecations)
|
52
54
|
when "validate"
|
53
55
|
validate(args)
|
54
56
|
when nil, "help"
|
@@ -96,7 +98,7 @@ module Packwerk
|
|
96
98
|
|
97
99
|
def generate_configs
|
98
100
|
configuration_file = Packwerk::Generators::ConfigurationFile.generate(
|
99
|
-
load_paths:
|
101
|
+
load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths,
|
100
102
|
root: @configuration.root_path,
|
101
103
|
out: @out
|
102
104
|
)
|
@@ -125,60 +127,13 @@ module Packwerk
|
|
125
127
|
|
126
128
|
def update(paths)
|
127
129
|
warn("`packwerk update` is deprecated in favor of `packwerk update-deprecations`.")
|
128
|
-
|
130
|
+
output_result(parse_run(paths).update_deprecations)
|
129
131
|
end
|
130
132
|
|
131
|
-
def
|
132
|
-
|
133
|
-
@
|
134
|
-
|
135
|
-
reference_lister: updating_deprecated_references
|
136
|
-
)
|
137
|
-
|
138
|
-
files = fetch_files_to_process(paths)
|
139
|
-
|
140
|
-
@progress_formatter.started(files)
|
141
|
-
|
142
|
-
all_offenses = T.let([], T.untyped)
|
143
|
-
execution_time = Benchmark.realtime do
|
144
|
-
all_offenses = files.flat_map do |path|
|
145
|
-
@run_context.process_file(file: path).tap { |offenses| mark_progress(offenses) }
|
146
|
-
end
|
147
|
-
|
148
|
-
updating_deprecated_references.dump_deprecated_references_files
|
149
|
-
end
|
150
|
-
|
151
|
-
@out.puts # put a new line after the progress dots
|
152
|
-
show_offenses(all_offenses)
|
153
|
-
@progress_formatter.finished(execution_time)
|
154
|
-
@out.puts("✅ `deprecated_references.yml` has been updated.")
|
155
|
-
|
156
|
-
all_offenses.empty?
|
157
|
-
end
|
158
|
-
|
159
|
-
def check(paths)
|
160
|
-
files = fetch_files_to_process(paths)
|
161
|
-
|
162
|
-
@progress_formatter.started(files)
|
163
|
-
|
164
|
-
all_offenses = T.let([], T.untyped)
|
165
|
-
execution_time = Benchmark.realtime do
|
166
|
-
files.each do |path|
|
167
|
-
@run_context.process_file(file: path).tap do |offenses|
|
168
|
-
mark_progress(offenses)
|
169
|
-
all_offenses.concat(offenses)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
rescue Interrupt
|
173
|
-
@out.puts
|
174
|
-
@out.puts("Manually interrupted. Violations caught so far are listed below:")
|
175
|
-
end
|
176
|
-
|
177
|
-
@out.puts # put a new line after the progress dots
|
178
|
-
show_offenses(all_offenses)
|
179
|
-
@progress_formatter.finished(execution_time)
|
180
|
-
|
181
|
-
all_offenses.empty?
|
133
|
+
def output_result(result)
|
134
|
+
@out.puts
|
135
|
+
@out.puts(result.message)
|
136
|
+
result.status
|
182
137
|
end
|
183
138
|
|
184
139
|
def fetch_files_to_process(paths)
|
@@ -188,14 +143,6 @@ module Packwerk
|
|
188
143
|
files
|
189
144
|
end
|
190
145
|
|
191
|
-
def mark_progress(offenses)
|
192
|
-
if offenses.empty?
|
193
|
-
@progress_formatter.mark_as_inspected
|
194
|
-
else
|
195
|
-
@progress_formatter.mark_as_failed
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
146
|
def validate(_paths)
|
200
147
|
warn("`packwerk validate` should be run within the application. "\
|
201
148
|
"Generate the bin script using `packwerk init` and"\
|
@@ -214,19 +161,6 @@ module Packwerk
|
|
214
161
|
end
|
215
162
|
end
|
216
163
|
|
217
|
-
def show_offenses(offenses)
|
218
|
-
if offenses.empty?
|
219
|
-
@out.puts("No offenses detected 🎉")
|
220
|
-
else
|
221
|
-
offenses.each do |offense|
|
222
|
-
@out.puts(offense.to_s(@style))
|
223
|
-
end
|
224
|
-
|
225
|
-
offenses_string = Inflector.default.pluralize("offense", offenses.length)
|
226
|
-
@out.puts("#{offenses.length} #{offenses_string} detected")
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
164
|
def list_validation_errors(result)
|
231
165
|
@out.puts
|
232
166
|
if result.ok?
|
@@ -245,5 +179,14 @@ module Packwerk
|
|
245
179
|
false
|
246
180
|
end
|
247
181
|
end
|
182
|
+
|
183
|
+
def parse_run(paths)
|
184
|
+
ParseRun.new(
|
185
|
+
files: fetch_files_to_process(paths),
|
186
|
+
configuration: @configuration,
|
187
|
+
progress_formatter: @progress_formatter,
|
188
|
+
offenses_formatter: @offenses_formatter
|
189
|
+
)
|
190
|
+
end
|
248
191
|
end
|
249
192
|
end
|
@@ -22,7 +22,10 @@ module Packwerk
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def from_packwerk_config(path)
|
25
|
-
new(
|
25
|
+
new(
|
26
|
+
YAML.load_file(path) || {},
|
27
|
+
config_path: path
|
28
|
+
)
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
@@ -42,10 +45,15 @@ module Packwerk
|
|
42
45
|
@root_path = File.expand_path(root)
|
43
46
|
@package_paths = configs["package_paths"] || "**/"
|
44
47
|
@custom_associations = configs["custom_associations"] || []
|
45
|
-
@load_paths = configs["load_paths"]
|
48
|
+
@load_paths = configs["load_paths"] || []
|
46
49
|
@inflections_file = File.expand_path(configs["inflections_file"] || "config/inflections.yml", @root_path)
|
50
|
+
@parallel = configs.key?("parallel") ? configs["parallel"] : true
|
47
51
|
|
48
52
|
@config_path = config_path
|
49
53
|
end
|
54
|
+
|
55
|
+
def parallel?
|
56
|
+
@parallel
|
57
|
+
end
|
50
58
|
end
|
51
59
|
end
|
@@ -1,20 +1,24 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/constant_name_inspector"
|
5
|
-
|
6
4
|
module Packwerk
|
7
5
|
# Extracts a constant name from an AST node of type :const
|
8
6
|
class ConstNodeInspector
|
7
|
+
extend T::Sig
|
9
8
|
include ConstantNameInspector
|
10
9
|
|
10
|
+
sig do
|
11
|
+
override
|
12
|
+
.params(node: AST::Node, ancestors: T::Array[AST::Node])
|
13
|
+
.returns(T.nilable(String))
|
14
|
+
end
|
11
15
|
def constant_name_from_node(node, ancestors:)
|
12
16
|
return nil unless Node.constant?(node)
|
13
17
|
parent = ancestors.first
|
14
18
|
return nil unless root_constant?(parent)
|
15
19
|
|
16
20
|
if parent && constant_in_module_or_class_definition?(node, parent: parent)
|
17
|
-
fully_qualify_constant(
|
21
|
+
fully_qualify_constant(ancestors)
|
18
22
|
else
|
19
23
|
begin
|
20
24
|
Node.constant_name(node)
|
@@ -28,27 +32,22 @@ module Packwerk
|
|
28
32
|
|
29
33
|
# Only process the root `const` node for namespaced constant references. For example, in the
|
30
34
|
# reference `Spam::Eggs::Thing`, we only process the const node associated with `Spam`.
|
35
|
+
sig { params(parent: T.nilable(AST::Node)).returns(T::Boolean) }
|
31
36
|
def root_constant?(parent)
|
32
37
|
!(parent && Node.constant?(parent))
|
33
38
|
end
|
34
39
|
|
40
|
+
sig { params(node: AST::Node, parent: AST::Node).returns(T.nilable(T::Boolean)) }
|
35
41
|
def constant_in_module_or_class_definition?(node, parent:)
|
36
42
|
parent_name = Node.module_name_from_definition(parent)
|
37
43
|
parent_name && parent_name == Node.constant_name(node)
|
38
44
|
end
|
39
45
|
|
40
|
-
|
46
|
+
sig { params(ancestors: T::Array[AST::Node]).returns(String) }
|
47
|
+
def fully_qualify_constant(ancestors)
|
41
48
|
# We're defining a class with this name, in which case the constant is implicitly fully qualified by its
|
42
49
|
# enclosing namespace
|
43
|
-
|
44
|
-
name ||= generate_qualified_constant(node, ancestors)
|
45
|
-
"::" + name
|
46
|
-
end
|
47
|
-
|
48
|
-
def generate_qualified_constant(node, ancestors:)
|
49
|
-
namespace_path = Node.enclosing_namespace_path(node, ancestors: ancestors)
|
50
|
-
constant_name = Node.constant_name(node)
|
51
|
-
namespace_path.push(constant_name).join("::")
|
50
|
+
"::" + Node.parent_module_name(ancestors: ancestors)
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "constant_resolver"
|
5
|
+
|
4
6
|
module Packwerk
|
5
7
|
# Get information about (partially qualified) constants without loading the application code.
|
6
8
|
# Information gathered: Fully qualified name, path to file containing the definition, package,
|
@@ -1,31 +1,26 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "packwerk/violation_type"
|
5
|
-
require "packwerk/checker"
|
6
|
-
|
7
4
|
module Packwerk
|
8
5
|
class DependencyChecker
|
6
|
+
extend T::Sig
|
9
7
|
include Checker
|
10
8
|
|
9
|
+
sig { override.returns(ViolationType) }
|
11
10
|
def violation_type
|
12
11
|
ViolationType::Dependency
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
return if reference_lister.listed?(reference, violation_type: violation_type)
|
20
|
-
true
|
14
|
+
sig do
|
15
|
+
override
|
16
|
+
.params(reference: Packwerk::Reference)
|
17
|
+
.returns(T::Boolean)
|
21
18
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
"Are we missing an abstraction?\n" \
|
28
|
-
"Is the code making the reference, and the referenced constant, in the right packages?\n"
|
19
|
+
def invalid_reference?(reference)
|
20
|
+
return false unless reference.source_package
|
21
|
+
return false unless reference.source_package.enforce_dependencies?
|
22
|
+
return false if reference.source_package.dependency?(reference.constant.package)
|
23
|
+
true
|
29
24
|
end
|
30
25
|
end
|
31
26
|
end
|
@@ -1,18 +1,13 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "sorbet-runtime"
|
5
4
|
require "yaml"
|
6
5
|
|
7
|
-
require "packwerk/reference"
|
8
|
-
require "packwerk/reference_lister"
|
9
|
-
require "packwerk/violation_type"
|
10
|
-
|
11
6
|
module Packwerk
|
12
7
|
class DeprecatedReferences
|
13
8
|
extend T::Sig
|
14
|
-
include ReferenceLister
|
15
9
|
|
10
|
+
sig { params(package: Packwerk::Package, filepath: String).void }
|
16
11
|
def initialize(package, filepath)
|
17
12
|
@package = package
|
18
13
|
@filepath = filepath
|
@@ -22,7 +17,6 @@ module Packwerk
|
|
22
17
|
sig do
|
23
18
|
params(reference: Packwerk::Reference, violation_type: ViolationType)
|
24
19
|
.returns(T::Boolean)
|
25
|
-
.override
|
26
20
|
end
|
27
21
|
def listed?(reference, violation_type:)
|
28
22
|
violated_constants_found = deprecated_references.dig(reference.constant.package.name, reference.constant.name)
|
@@ -34,19 +28,40 @@ module Packwerk
|
|
34
28
|
violated_constants_found.fetch("violations", []).include?(violation_type.serialize)
|
35
29
|
end
|
36
30
|
|
31
|
+
sig { params(reference: Packwerk::Reference, violation_type: Packwerk::ViolationType).returns(T::Boolean) }
|
37
32
|
def add_entries(reference, violation_type)
|
38
33
|
package_violations = @new_entries.fetch(reference.constant.package.name, {})
|
39
34
|
entries_for_file = package_violations[reference.constant.name] ||= {}
|
40
35
|
|
41
36
|
entries_for_file["violations"] ||= []
|
42
|
-
entries_for_file["violations"] << violation_type
|
37
|
+
entries_for_file["violations"] << violation_type.serialize
|
43
38
|
|
44
39
|
entries_for_file["files"] ||= []
|
45
40
|
entries_for_file["files"] << reference.relative_path.to_s
|
46
41
|
|
47
42
|
@new_entries[reference.constant.package.name] = package_violations
|
43
|
+
listed?(reference, violation_type: violation_type)
|
44
|
+
end
|
45
|
+
|
46
|
+
sig { returns(T::Boolean) }
|
47
|
+
def stale_violations?
|
48
|
+
prepare_entries_for_dump
|
49
|
+
deprecated_references.any? do |package, package_violations|
|
50
|
+
package_violations.any? do |constant_name, entries_for_file|
|
51
|
+
new_entries_violation_types = @new_entries.dig(package, constant_name, "violations")
|
52
|
+
return true if new_entries_violation_types.nil?
|
53
|
+
if entries_for_file["violations"].all? { |type| new_entries_violation_types.include?(type) }
|
54
|
+
stale_violations =
|
55
|
+
entries_for_file["files"] - Array(@new_entries.dig(package, constant_name, "files"))
|
56
|
+
stale_violations.present?
|
57
|
+
else
|
58
|
+
return true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
48
62
|
end
|
49
63
|
|
64
|
+
sig { void }
|
50
65
|
def dump
|
51
66
|
if @new_entries.empty?
|
52
67
|
File.delete(@filepath) if File.exist?(@filepath)
|
@@ -69,6 +84,7 @@ module Packwerk
|
|
69
84
|
|
70
85
|
private
|
71
86
|
|
87
|
+
sig { returns(Hash) }
|
72
88
|
def prepare_entries_for_dump
|
73
89
|
@new_entries.each do |package_name, package_violations|
|
74
90
|
package_violations.each do |_, entries_for_file|
|
@@ -81,6 +97,7 @@ module Packwerk
|
|
81
97
|
@new_entries = @new_entries.sort.to_h
|
82
98
|
end
|
83
99
|
|
100
|
+
sig { returns(Hash) }
|
84
101
|
def deprecated_references
|
85
102
|
@deprecated_references ||= if File.exist?(@filepath)
|
86
103
|
YAML.load_file(@filepath) || {}
|