packwerk 1.0.1 → 1.1.3

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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +8 -7
  3. data/.github/workflows/ci.yml +14 -5
  4. data/.ruby-version +1 -1
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +130 -110
  7. data/README.md +8 -1
  8. data/USAGE.md +23 -2
  9. data/dev.yml +1 -1
  10. data/exe/packwerk +1 -1
  11. data/gemfiles/Gemfile-rails-6-0 +22 -0
  12. data/lib/packwerk.rb +4 -2
  13. data/lib/packwerk/application_load_paths.rb +68 -0
  14. data/lib/packwerk/application_validator.rb +94 -74
  15. data/lib/packwerk/association_inspector.rb +24 -9
  16. data/lib/packwerk/cache_deprecated_references.rb +55 -0
  17. data/lib/packwerk/checker.rb +3 -0
  18. data/lib/packwerk/checking_deprecated_references.rb +5 -2
  19. data/lib/packwerk/cli.rb +56 -55
  20. data/lib/packwerk/commands/detect_stale_violations_command.rb +60 -0
  21. data/lib/packwerk/commands/offense_progress_marker.rb +24 -0
  22. data/lib/packwerk/commands/result.rb +13 -0
  23. data/lib/packwerk/commands/update_deprecations_command.rb +81 -0
  24. data/lib/packwerk/configuration.rb +5 -37
  25. data/lib/packwerk/const_node_inspector.rb +28 -17
  26. data/lib/packwerk/dependency_checker.rb +13 -5
  27. data/lib/packwerk/deprecated_references.rb +23 -0
  28. data/lib/packwerk/detect_stale_deprecated_references.rb +14 -0
  29. data/lib/packwerk/file_processor.rb +4 -4
  30. data/lib/packwerk/formatters/offenses_formatter.rb +48 -0
  31. data/lib/packwerk/formatters/progress_formatter.rb +6 -2
  32. data/lib/packwerk/inflector.rb +17 -8
  33. data/lib/packwerk/node.rb +61 -38
  34. data/lib/packwerk/node_processor.rb +4 -4
  35. data/lib/packwerk/node_processor_factory.rb +39 -0
  36. data/lib/packwerk/node_visitor.rb +1 -1
  37. data/lib/packwerk/offense.rb +4 -6
  38. data/lib/packwerk/output_style.rb +20 -0
  39. data/lib/packwerk/output_styles/coloured.rb +29 -0
  40. data/lib/packwerk/output_styles/plain.rb +26 -0
  41. data/lib/packwerk/package_set.rb +9 -3
  42. data/lib/packwerk/parsed_constant_definitions.rb +4 -4
  43. data/lib/packwerk/parsers/erb.rb +4 -0
  44. data/lib/packwerk/parsers/factory.rb +10 -1
  45. data/lib/packwerk/privacy_checker.rb +23 -5
  46. data/lib/packwerk/run_context.rb +69 -46
  47. data/lib/packwerk/sanity_checker.rb +1 -1
  48. data/lib/packwerk/spring_command.rb +1 -1
  49. data/lib/packwerk/updating_deprecated_references.rb +2 -39
  50. data/lib/packwerk/version.rb +1 -1
  51. data/library.yml +1 -1
  52. data/packwerk.gemspec +1 -1
  53. data/service.yml +2 -2
  54. data/shipit.rubygems.yml +5 -1
  55. data/sorbet/rbi/gems/{actioncable@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actioncable@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +56 -36
  56. data/sorbet/rbi/gems/{actionmailbox@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailbox@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +25 -28
  57. data/sorbet/rbi/gems/{actionmailer@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionmailer@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +43 -24
  58. data/sorbet/rbi/gems/{actionpack@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionpack@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +382 -284
  59. data/sorbet/rbi/gems/{actiontext@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actiontext@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +76 -40
  60. data/sorbet/rbi/gems/{actionview@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → actionview@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +206 -195
  61. data/sorbet/rbi/gems/{activejob@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activejob@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +64 -75
  62. data/sorbet/rbi/gems/{activemodel@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activemodel@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +103 -56
  63. data/sorbet/rbi/gems/{activerecord@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activerecord@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1250 -898
  64. data/sorbet/rbi/gems/{activestorage@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activestorage@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +92 -120
  65. data/sorbet/rbi/gems/{activesupport@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → activesupport@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +292 -193
  66. data/sorbet/rbi/gems/{ast@2.4.1.rbi → ast@2.4.2.rbi} +2 -1
  67. data/sorbet/rbi/gems/{better_html@1.0.15.rbi → better_html@1.0.16.rbi} +2 -2
  68. data/sorbet/rbi/gems/{concurrent-ruby@1.1.6.rbi → concurrent-ruby@1.1.8.rbi} +12 -9
  69. data/sorbet/rbi/gems/{erubi@1.9.0.rbi → erubi@1.10.0.rbi} +3 -1
  70. data/sorbet/rbi/gems/{i18n@1.8.2.rbi → i18n@1.8.10.rbi} +19 -52
  71. data/sorbet/rbi/gems/{loofah@2.5.0.rbi → loofah@2.9.0.rbi} +3 -1
  72. data/sorbet/rbi/gems/marcel@1.0.0.rbi +70 -0
  73. data/sorbet/rbi/gems/{mini_mime@1.0.2.rbi → mini_mime@1.0.3.rbi} +6 -6
  74. data/sorbet/rbi/gems/{mini_portile2@2.4.0.rbi → minitest-focus@1.2.1.rbi} +2 -2
  75. data/sorbet/rbi/gems/{minitest@5.14.0.rbi → minitest@5.14.4.rbi} +31 -29
  76. data/sorbet/rbi/gems/{mocha@1.11.2.rbi → mocha@1.12.0.rbi} +25 -36
  77. data/sorbet/rbi/gems/{nio4r@2.5.2.rbi → nio4r@2.5.7.rbi} +21 -20
  78. data/sorbet/rbi/gems/{nokogiri@1.10.9.rbi → nokogiri@1.11.2.rbi} +193 -154
  79. data/sorbet/rbi/gems/{parallel@1.19.1.rbi → parallel@1.20.1.rbi} +1 -1
  80. data/sorbet/rbi/gems/parlour@6.0.0.rbi +1272 -0
  81. data/sorbet/rbi/gems/{parser@2.7.1.4.rbi → parser@3.0.0.0.rbi} +287 -174
  82. data/sorbet/rbi/gems/{pry@0.13.1.rbi → pry@0.14.0.rbi} +1 -1
  83. data/sorbet/rbi/gems/racc@1.5.2.rbi +57 -0
  84. data/sorbet/rbi/gems/{rack@2.2.2.rbi → rack@2.2.3.rbi} +23 -35
  85. data/sorbet/rbi/gems/{rails@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → rails@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +1 -1
  86. data/sorbet/rbi/gems/{railties@6.1.0.alpha-d80c18a391e33552ae2d943e68af56946f883f65.rbi → railties@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi} +132 -121
  87. data/sorbet/rbi/gems/{rake@13.0.1.rbi → rake@13.0.3.rbi} +16 -20
  88. data/sorbet/rbi/gems/regexp_parser@2.1.1.rbi +8 -0
  89. data/sorbet/rbi/gems/rubocop-ast@1.4.1.rbi +8 -0
  90. data/sorbet/rbi/gems/{rubocop-performance@1.5.2.rbi → rubocop-performance@1.10.2.rbi} +1 -1
  91. data/sorbet/rbi/gems/{rubocop-shopify@1.0.2.rbi → rubocop-shopify@2.0.1.rbi} +1 -1
  92. data/sorbet/rbi/gems/{rubocop-sorbet@0.3.7.rbi → rubocop-sorbet@0.6.1.rbi} +1 -1
  93. data/sorbet/rbi/gems/{rubocop@0.82.0.rbi → rubocop@1.12.0.rbi} +1 -1
  94. data/sorbet/rbi/gems/{ruby-progressbar@1.10.1.rbi → ruby-progressbar@1.11.0.rbi} +1 -1
  95. data/sorbet/rbi/gems/spoom@1.1.0.rbi +1061 -0
  96. data/sorbet/rbi/gems/{spring@2.1.0.rbi → spring@2.1.1.rbi} +7 -7
  97. data/sorbet/rbi/gems/{sprockets-rails@3.2.1.rbi → sprockets-rails@3.2.2.rbi} +88 -68
  98. data/sorbet/rbi/gems/{sprockets@4.0.0.rbi → sprockets@4.0.2.rbi} +8 -7
  99. data/sorbet/rbi/gems/{tapioca@0.4.5.rbi → tapioca@0.4.19.rbi} +109 -24
  100. data/sorbet/rbi/gems/{thor@1.0.1.rbi → thor@1.1.0.rbi} +16 -15
  101. data/sorbet/rbi/gems/{tzinfo@2.0.2.rbi → tzinfo@2.0.4.rbi} +21 -2
  102. data/sorbet/rbi/gems/{unicode-display_width@1.7.0.rbi → unicode-display_width@2.0.0.rbi} +1 -1
  103. data/sorbet/rbi/gems/{websocket-driver@0.7.1.rbi → websocket-driver@0.7.3.rbi} +29 -29
  104. data/sorbet/rbi/gems/{websocket-extensions@0.1.4.rbi → websocket-extensions@0.1.5.rbi} +2 -2
  105. data/sorbet/rbi/gems/zeitwerk@2.4.2.rbi +177 -0
  106. metadata +66 -58
  107. data/lib/packwerk/output_styles.rb +0 -41
  108. data/sorbet/rbi/gems/jaro_winkler@1.5.4.rbi +0 -8
  109. data/sorbet/rbi/gems/marcel@0.3.3.rbi +0 -30
  110. data/sorbet/rbi/gems/mimemagic@0.3.5.rbi +0 -47
  111. data/sorbet/rbi/gems/parlour@4.0.1.rbi +0 -561
  112. data/sorbet/rbi/gems/spoom@1.0.4.rbi +0 -418
  113. data/sorbet/rbi/gems/zeitwerk@2.3.0.rbi +0 -8
  114. data/static/packwerk-check-demo.png +0 -0
  115. data/static/packwerk_check.gif +0 -0
  116. data/static/packwerk_check_violation.gif +0 -0
  117. data/static/packwerk_update.gif +0 -0
  118. data/static/packwerk_validate.gif +0 -0
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "packwerk/constant_name_inspector"
@@ -7,20 +7,32 @@ require "packwerk/node"
7
7
  module Packwerk
8
8
  # Extracts the implicit constant reference from an active record association
9
9
  class AssociationInspector
10
+ extend T::Sig
10
11
  include ConstantNameInspector
11
12
 
12
- RAILS_ASSOCIATIONS = %i(
13
- belongs_to
14
- has_many
15
- has_one
16
- has_and_belongs_to_many
17
- ).to_set
13
+ CustomAssociations = T.type_alias { T.any(T::Array[Symbol], T::Set[Symbol]) }
18
14
 
19
- def initialize(inflector: Inflector.new, custom_associations: Set.new)
15
+ RAILS_ASSOCIATIONS = T.let(
16
+ %i(
17
+ belongs_to
18
+ has_many
19
+ has_one
20
+ has_and_belongs_to_many
21
+ ).to_set,
22
+ CustomAssociations
23
+ )
24
+
25
+ sig { params(inflector: Inflector, custom_associations: CustomAssociations).void }
26
+ def initialize(inflector:, custom_associations: Set.new)
20
27
  @inflector = inflector
21
- @associations = RAILS_ASSOCIATIONS + custom_associations
28
+ @associations = T.let(RAILS_ASSOCIATIONS + custom_associations, CustomAssociations)
22
29
  end
23
30
 
31
+ sig do
32
+ override
33
+ .params(node: AST::Node, ancestors: T::Array[AST::Node])
34
+ .returns(T.nilable(String))
35
+ end
24
36
  def constant_name_from_node(node, ancestors:)
25
37
  return unless Node.method_call?(node)
26
38
  return unless association?(node)
@@ -38,11 +50,13 @@ module Packwerk
38
50
 
39
51
  private
40
52
 
53
+ sig { params(node: AST::Node).returns(T::Boolean) }
41
54
  def association?(node)
42
55
  method_name = Node.method_name(node)
43
56
  @associations.include?(method_name)
44
57
  end
45
58
 
59
+ sig { params(arguments: T::Array[AST::Node]).returns(T.nilable(AST::Node)) }
46
60
  def custom_class_name(arguments)
47
61
  association_options = arguments.detect { |n| Node.hash?(n) }
48
62
  return unless association_options
@@ -50,6 +64,7 @@ module Packwerk
50
64
  Node.value_from_hash(association_options, :class_name)
51
65
  end
52
66
 
67
+ sig { params(arguments: T::Array[AST::Node]).returns(T.any(T.nilable(Symbol), T.nilable(String))) }
53
68
  def association_name(arguments)
54
69
  return unless Node.symbol?(arguments[0])
55
70
 
@@ -0,0 +1,55 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "sorbet-runtime"
5
+
6
+ require "packwerk/deprecated_references"
7
+ require "packwerk/reference"
8
+ require "packwerk/reference_lister"
9
+ require "packwerk/violation_type"
10
+
11
+ module Packwerk
12
+ class CacheDeprecatedReferences
13
+ extend T::Sig
14
+ extend T::Helpers
15
+ include ReferenceLister
16
+ abstract!
17
+
18
+ sig do
19
+ params(
20
+ root_path: String,
21
+ deprecated_references: T::Hash[Packwerk::Package, Packwerk::DeprecatedReferences]
22
+ ).void
23
+ end
24
+ def initialize(root_path, deprecated_references = {})
25
+ @root_path = root_path
26
+ @deprecated_references = T.let(deprecated_references, T::Hash[Packwerk::Package, Packwerk::DeprecatedReferences])
27
+ end
28
+
29
+ sig do
30
+ params(reference: Packwerk::Reference, violation_type: ViolationType)
31
+ .returns(T::Boolean)
32
+ .override
33
+ end
34
+ def listed?(reference, violation_type:)
35
+ deprecated_references = deprecated_references_for(reference.source_package)
36
+ deprecated_references.add_entries(reference, violation_type.serialize)
37
+ true
38
+ end
39
+
40
+ private
41
+
42
+ sig { params(package: Packwerk::Package).returns(Packwerk::DeprecatedReferences) }
43
+ def deprecated_references_for(package)
44
+ @deprecated_references[package] ||= Packwerk::DeprecatedReferences.new(
45
+ package,
46
+ deprecated_references_file_for(package),
47
+ )
48
+ end
49
+
50
+ sig { params(package: Packwerk::Package).returns(String) }
51
+ def deprecated_references_file_for(package)
52
+ File.join(@root_path, package.name, "deprecated_references.yml")
53
+ end
54
+ end
55
+ end
@@ -11,6 +11,9 @@ module Packwerk
11
11
 
12
12
  interface!
13
13
 
14
+ sig { returns(ViolationType).abstract }
15
+ def violation_type; end
16
+
14
17
  sig { params(reference: Reference, reference_lister: ReferenceLister).returns(T::Boolean).abstract }
15
18
  def invalid_reference?(reference, reference_lister); end
16
19
 
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -10,9 +10,10 @@ module Packwerk
10
10
  extend T::Sig
11
11
  include ReferenceLister
12
12
 
13
+ sig { params(root_path: String).void }
13
14
  def initialize(root_path)
14
15
  @root_path = root_path
15
- @deprecated_references = {}
16
+ @deprecated_references = T.let({}, T::Hash[Packwerk::Package, Packwerk::DeprecatedReferences])
16
17
  end
17
18
 
18
19
  sig do
@@ -26,6 +27,7 @@ module Packwerk
26
27
 
27
28
  private
28
29
 
30
+ sig { params(source_package: Packwerk::Package).returns(Packwerk::DeprecatedReferences) }
29
31
  def deprecated_references_for(source_package)
30
32
  @deprecated_references[source_package] ||= Packwerk::DeprecatedReferences.new(
31
33
  source_package,
@@ -33,6 +35,7 @@ module Packwerk
33
35
  )
34
36
  end
35
37
 
38
+ sig { params(package: Packwerk::Package).returns(String) }
36
39
  def deprecated_references_file_for(package)
37
40
  File.join(@root_path, package.name, "deprecated_references.yml")
38
41
  end
data/lib/packwerk/cli.rb CHANGED
@@ -3,25 +3,45 @@
3
3
  require "benchmark"
4
4
  require "sorbet-runtime"
5
5
 
6
+ require "packwerk/application_load_paths"
6
7
  require "packwerk/application_validator"
7
8
  require "packwerk/configuration"
8
9
  require "packwerk/files_for_processing"
10
+ require "packwerk/formatters/offenses_formatter"
9
11
  require "packwerk/formatters/progress_formatter"
10
12
  require "packwerk/inflector"
11
- require "packwerk/output_styles"
13
+ require "packwerk/output_style"
14
+ require "packwerk/output_styles/plain"
12
15
  require "packwerk/run_context"
13
16
  require "packwerk/updating_deprecated_references"
17
+ require "packwerk/checking_deprecated_references"
18
+ require "packwerk/commands/detect_stale_violations_command"
19
+ require "packwerk/commands/update_deprecations_command"
20
+ require "packwerk/commands/offense_progress_marker"
14
21
 
15
22
  module Packwerk
16
23
  class Cli
17
24
  extend T::Sig
18
-
19
- def initialize(run_context: nil, configuration: nil, out: $stdout, err_out: $stderr, style: OutputStyles::Plain)
25
+ include OffenseProgressMarker
26
+
27
+ sig do
28
+ params(
29
+ run_context: T.nilable(Packwerk::RunContext),
30
+ configuration: T.nilable(Configuration),
31
+ out: T.any(StringIO, IO),
32
+ err_out: T.any(StringIO, IO),
33
+ style: Packwerk::OutputStyle
34
+ ).void
35
+ end
36
+ def initialize(run_context: nil, configuration: nil, out: $stdout, err_out: $stderr, style: OutputStyles::Plain.new)
20
37
  @out = out
21
38
  @err_out = err_out
22
39
  @style = style
23
40
  @configuration = configuration || Configuration.from_path
24
- @run_context = run_context || Packwerk::RunContext.from_configuration(@configuration)
41
+ @run_context = run_context || Packwerk::RunContext.from_configuration(
42
+ @configuration,
43
+ reference_lister: ::Packwerk::CheckingDeprecatedReferences.new(@configuration.root_path),
44
+ )
25
45
  @progress_formatter = Formatters::ProgressFormatter.new(@out, style: style)
26
46
  end
27
47
 
@@ -41,6 +61,8 @@ module Packwerk
41
61
  generate_configs
42
62
  when "check"
43
63
  check(args)
64
+ when "detect-stale-violations"
65
+ detect_stale_violations(args)
44
66
  when "update"
45
67
  update(args)
46
68
  when "update-deprecations"
@@ -92,7 +114,7 @@ module Packwerk
92
114
 
93
115
  def generate_configs
94
116
  configuration_file = Packwerk::Generators::ConfigurationFile.generate(
95
- load_paths: @configuration.load_paths,
117
+ load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths,
96
118
  root: @configuration.root_path,
97
119
  out: @out
98
120
  )
@@ -125,31 +147,16 @@ module Packwerk
125
147
  end
126
148
 
127
149
  def update_deprecations(paths)
128
- updating_deprecated_references = ::Packwerk::UpdatingDeprecatedReferences.new(@configuration.root_path)
129
- @run_context = Packwerk::RunContext.from_configuration(
130
- @configuration,
131
- reference_lister: updating_deprecated_references
150
+ update_deprecations = Commands::UpdateDeprecationsCommand.new(
151
+ files: fetch_files_to_process(paths),
152
+ configuration: @configuration,
153
+ offenses_formatter: offenses_formatter,
154
+ progress_formatter: @progress_formatter
132
155
  )
133
-
134
- files = fetch_files_to_process(paths)
135
-
136
- @progress_formatter.started(files)
137
-
138
- all_offenses = T.let([], T.untyped)
139
- execution_time = Benchmark.realtime do
140
- all_offenses = files.flat_map do |path|
141
- @run_context.file_processor.call(path).tap { |offenses| mark_progress(offenses) }
142
- end
143
-
144
- updating_deprecated_references.dump_deprecated_references_files
145
- end
146
-
147
- @out.puts # put a new line after the progress dots
148
- show_offenses(all_offenses)
149
- @progress_formatter.finished(execution_time)
150
- @out.puts("✅ `deprecated_references.yml` has been updated.")
151
-
152
- all_offenses.empty?
156
+ result = update_deprecations.run
157
+ @out.puts
158
+ @out.puts(result.message)
159
+ result.status
153
160
  end
154
161
 
155
162
  def check(paths)
@@ -160,8 +167,8 @@ module Packwerk
160
167
  all_offenses = T.let([], T.untyped)
161
168
  execution_time = Benchmark.realtime do
162
169
  files.each do |path|
163
- @run_context.file_processor.call(path).tap do |offenses|
164
- mark_progress(offenses)
170
+ @run_context.process_file(file: path).tap do |offenses|
171
+ mark_progress(offenses: offenses, progress_formatter: @progress_formatter)
165
172
  all_offenses.concat(offenses)
166
173
  end
167
174
  end
@@ -170,13 +177,25 @@ module Packwerk
170
177
  @out.puts("Manually interrupted. Violations caught so far are listed below:")
171
178
  end
172
179
 
173
- @out.puts # put a new line after the progress dots
174
- show_offenses(all_offenses)
175
180
  @progress_formatter.finished(execution_time)
181
+ @out.puts
182
+ @out.puts(offenses_formatter.show_offenses(all_offenses))
176
183
 
177
184
  all_offenses.empty?
178
185
  end
179
186
 
187
+ def detect_stale_violations(paths)
188
+ detect_stale_violations = Commands::DetectStaleViolationsCommand.new(
189
+ files: fetch_files_to_process(paths),
190
+ configuration: @configuration,
191
+ progress_formatter: @progress_formatter
192
+ )
193
+ result = detect_stale_violations.run
194
+ @out.puts
195
+ @out.puts(result.message)
196
+ result.status
197
+ end
198
+
180
199
  def fetch_files_to_process(paths)
181
200
  files = FilesForProcessing.fetch(paths: paths, configuration: @configuration)
182
201
  abort("No files found or given. "\
@@ -184,14 +203,6 @@ module Packwerk
184
203
  files
185
204
  end
186
205
 
187
- def mark_progress(offenses)
188
- if offenses.empty?
189
- @progress_formatter.mark_as_inspected
190
- else
191
- @progress_formatter.mark_as_failed
192
- end
193
- end
194
-
195
206
  def validate(_paths)
196
207
  warn("`packwerk validate` should be run within the application. "\
197
208
  "Generate the bin script using `packwerk init` and"\
@@ -200,7 +211,6 @@ module Packwerk
200
211
  @progress_formatter.started_validation do
201
212
  checker = Packwerk::ApplicationValidator.new(
202
213
  config_file_path: @configuration.config_path,
203
- application_load_paths: @configuration.all_application_autoload_paths,
204
214
  configuration: @configuration
205
215
  )
206
216
  result = checker.check_all
@@ -211,19 +221,6 @@ module Packwerk
211
221
  end
212
222
  end
213
223
 
214
- def show_offenses(offenses)
215
- if offenses.empty?
216
- @out.puts("No offenses detected 🎉")
217
- else
218
- offenses.each do |offense|
219
- @out.puts(offense.to_s(@style))
220
- end
221
-
222
- offenses_string = Inflector.default.pluralize("offense", offenses.length)
223
- @out.puts("#{offenses.length} #{offenses_string} detected")
224
- end
225
- end
226
-
227
224
  def list_validation_errors(result)
228
225
  @out.puts
229
226
  if result.ok?
@@ -242,5 +239,9 @@ module Packwerk
242
239
  false
243
240
  end
244
241
  end
242
+
243
+ def offenses_formatter
244
+ @offenses_formatter ||= Formatters::OffensesFormatter.new(style: @style)
245
+ end
245
246
  end
246
247
  end
@@ -0,0 +1,60 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require "sorbet-runtime"
4
+ require "benchmark"
5
+ require "packwerk/run_context"
6
+ require "packwerk/detect_stale_deprecated_references"
7
+ require "packwerk/commands/offense_progress_marker"
8
+ require "packwerk/commands/result"
9
+
10
+ module Packwerk
11
+ module Commands
12
+ class DetectStaleViolationsCommand
13
+ extend T::Sig
14
+ include OffenseProgressMarker
15
+ def initialize(files:, configuration:, run_context: nil, progress_formatter: nil, reference_lister: nil)
16
+ @configuration = configuration
17
+ @run_context = run_context
18
+ @reference_lister = reference_lister
19
+ @progress_formatter = progress_formatter
20
+ @files = files
21
+ end
22
+
23
+ sig { returns(Result) }
24
+ def run
25
+ @progress_formatter.started(@files)
26
+
27
+ execution_time = Benchmark.realtime do
28
+ @files.flat_map do |path|
29
+ run_context.process_file(file: path).tap do |offenses|
30
+ mark_progress(offenses: offenses, progress_formatter: @progress_formatter)
31
+ end
32
+ end
33
+ end
34
+
35
+ @progress_formatter.finished(execution_time)
36
+ calculate_result
37
+ end
38
+
39
+ private
40
+
41
+ def run_context
42
+ @run_context ||= Packwerk::RunContext.from_configuration(@configuration, reference_lister: reference_lister)
43
+ end
44
+
45
+ def reference_lister
46
+ @reference_lister ||= ::Packwerk::DetectStaleDeprecatedReferences.new(@configuration.root_path)
47
+ end
48
+
49
+ sig { returns(Result) }
50
+ def calculate_result
51
+ result_status = !reference_lister.stale_violations?
52
+ message = "There were stale violations found, please run `packwerk update-deprecations`"
53
+ if result_status
54
+ message = "No stale violations detected"
55
+ end
56
+ Result.new(message: message, status: result_status)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+ require "sorbet-runtime"
4
+ require "packwerk/formatters/progress_formatter"
5
+
6
+ module Packwerk
7
+ module OffenseProgressMarker
8
+ extend T::Sig
9
+
10
+ sig do
11
+ params(
12
+ offenses: T::Array[T.nilable(::Packwerk::Offense)],
13
+ progress_formatter: ::Packwerk::Formatters::ProgressFormatter
14
+ ).void
15
+ end
16
+ def mark_progress(offenses:, progress_formatter:)
17
+ if offenses.empty?
18
+ progress_formatter.mark_as_inspected
19
+ else
20
+ progress_formatter.mark_as_failed
21
+ end
22
+ end
23
+ end
24
+ end