packwerk 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -5
  3. data/.ruby-version +1 -1
  4. data/Gemfile +0 -1
  5. data/Gemfile.lock +5 -95
  6. data/README.md +2 -7
  7. data/TROUBLESHOOT.md +0 -22
  8. data/USAGE.md +141 -51
  9. data/dev.yml +1 -1
  10. data/exe/packwerk +1 -0
  11. data/gemfiles/Gemfile-rails-6-1 +1 -1
  12. data/lib/packwerk/application_validator.rb +54 -285
  13. data/lib/packwerk/association_inspector.rb +2 -0
  14. data/lib/packwerk/cache.rb +6 -5
  15. data/lib/packwerk/checker.rb +54 -0
  16. data/lib/packwerk/cli/result.rb +11 -0
  17. data/lib/packwerk/cli.rb +55 -40
  18. data/lib/packwerk/configuration.rb +61 -40
  19. data/lib/packwerk/const_node_inspector.rb +2 -0
  20. data/lib/packwerk/constant_context.rb +8 -0
  21. data/lib/packwerk/constant_discovery.rb +5 -6
  22. data/lib/packwerk/constant_name_inspector.rb +2 -0
  23. data/lib/packwerk/disable_sorbet.rb +41 -0
  24. data/lib/packwerk/extension_loader.rb +24 -0
  25. data/lib/packwerk/file_processor.rb +3 -1
  26. data/lib/packwerk/files_for_processing.rb +25 -12
  27. data/lib/packwerk/formatters/default_offenses_formatter.rb +77 -0
  28. data/lib/packwerk/formatters/progress_formatter.rb +31 -12
  29. data/lib/packwerk/generators/configuration_file.rb +7 -2
  30. data/lib/packwerk/generators/root_package.rb +5 -1
  31. data/lib/packwerk/generators/templates/package.yml +0 -10
  32. data/lib/packwerk/graph.rb +10 -2
  33. data/lib/packwerk/node.rb +1 -1
  34. data/lib/packwerk/node_helpers.rb +14 -7
  35. data/lib/packwerk/node_processor.rb +2 -0
  36. data/lib/packwerk/node_processor_factory.rb +6 -4
  37. data/lib/packwerk/node_visitor.rb +10 -1
  38. data/lib/packwerk/offense_collection.rb +26 -18
  39. data/lib/packwerk/offenses_formatter.rb +59 -2
  40. data/lib/packwerk/package.rb +7 -35
  41. data/lib/packwerk/package_set.rb +1 -1
  42. data/lib/packwerk/package_todo.rb +15 -9
  43. data/lib/packwerk/parse_run.rb +27 -34
  44. data/lib/packwerk/parsed_constant_definitions.rb +28 -5
  45. data/lib/packwerk/parsers/erb.rb +23 -4
  46. data/lib/packwerk/parsers/factory.rb +11 -2
  47. data/lib/packwerk/parsers/parser_interface.rb +1 -1
  48. data/lib/packwerk/parsers/ruby.rb +13 -3
  49. data/lib/packwerk/parsers.rb +6 -2
  50. data/lib/packwerk/{application_load_paths.rb → rails_load_paths.rb} +6 -4
  51. data/lib/packwerk/reference.rb +7 -1
  52. data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +29 -6
  53. data/lib/packwerk/reference_checking/reference_checker.rb +1 -1
  54. data/lib/packwerk/reference_extractor.rb +24 -12
  55. data/lib/packwerk/reference_offense.rb +2 -2
  56. data/lib/packwerk/run_context.rb +7 -10
  57. data/lib/packwerk/spring_command.rb +11 -2
  58. data/lib/packwerk/unresolved_reference.rb +9 -1
  59. data/lib/packwerk/validator/result.rb +18 -0
  60. data/lib/packwerk/validator.rb +90 -0
  61. data/lib/packwerk/validators/dependency_validator.rb +154 -0
  62. data/lib/packwerk/version.rb +1 -1
  63. data/lib/packwerk.rb +64 -26
  64. data/packwerk.gemspec +4 -2
  65. data/sorbet/rbi/gems/{zeitwerk@2.6.0.rbi → zeitwerk@2.6.4.rbi} +291 -228
  66. data/sorbet/rbi/shims/minitest/test.rb +8 -0
  67. data/sorbet/rbi/shims/packwerk/reference.rbi +33 -0
  68. data/sorbet/rbi/shims/packwerk/unresolved_reference.rbi +33 -0
  69. data/sorbet/rbi/shims/parser.rbi +13 -0
  70. metadata +34 -15
  71. data/lib/packwerk/formatters/offenses_formatter.rb +0 -52
  72. data/lib/packwerk/reference_checking/checkers/checker.rb +0 -34
  73. data/lib/packwerk/reference_checking/checkers/privacy_checker.rb +0 -76
  74. data/lib/packwerk/result.rb +0 -9
  75. data/lib/packwerk/sanity_checker.rb +0 -8
  76. data/lib/packwerk/violation_type.rb +0 -11
  77. data/sorbet/rbi/gems/html_tokenizer@0.0.7.rbi +0 -46
  78. data/sorbet/rbi/gems/mini_portile2@2.8.0.rbi +0 -8
@@ -0,0 +1,8 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Minitest
5
+ class Test
6
+ include StubConst
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ # typed: true
2
+
3
+ module Packwerk
4
+ class Reference
5
+ sig do
6
+ params(
7
+ package: Package,
8
+ relative_path: String,
9
+ constant: ConstantContext,
10
+ source_location: T.nilable(Node::Location),
11
+ ).void
12
+ end
13
+ def initialize(
14
+ package:,
15
+ relative_path:,
16
+ constant:,
17
+ source_location:
18
+ )
19
+ end
20
+
21
+ sig { returns(Package) }
22
+ attr_reader(:package)
23
+
24
+ sig { returns(T.nilable(String)) }
25
+ attr_reader(:relative_path)
26
+
27
+ sig { returns(ConstantContext) }
28
+ attr_reader(:constant)
29
+
30
+ sig { returns(T.nilable(Node::Location)) }
31
+ attr_reader(:source_location)
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ # typed: true
2
+
3
+ module Packwerk
4
+ class UnresolvedReference
5
+ sig do
6
+ params(
7
+ constant_name: String,
8
+ namespace_path: T.nilable(T::Array[String]),
9
+ relative_path: String,
10
+ source_location: T.nilable(Node::Location),
11
+ ).void
12
+ end
13
+ def initialize(
14
+ constant_name:,
15
+ namespace_path:,
16
+ relative_path:,
17
+ source_location:
18
+ )
19
+ end
20
+
21
+ sig { returns(String) }
22
+ attr_reader(:constant_name)
23
+
24
+ sig { returns(T.nilable(T::Array[String])) }
25
+ attr_reader(:namespace_path)
26
+
27
+ sig { returns(String) }
28
+ attr_reader(:relative_path)
29
+
30
+ sig { returns(T.nilable(Node::Location)) }
31
+ attr_reader(:source_location)
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+
3
+ class Parser::Base < ::Racc::Parser
4
+ # Parses a source buffer and returns the AST, or `nil` in case of a non fatal error.
5
+ #
6
+ # @api public
7
+ # @param source_buffer [Parser::Source::Buffer] The source buffer to parse.
8
+ # @return [Parser::AST::Node, nil]
9
+ #
10
+ # source://parser-3.1.2.1/lib/parser/base.rb:186
11
+ sig { params(source_buffer: Parser::Source::Buffer).returns(T.nilable(Parser::AST::Node)) }
12
+ def parse(source_buffer); end
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packwerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-21 00:00:00.000000000 Z
11
+ date: 2023-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5.2'
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5.2'
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: railties
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: |
140
154
  Sets package level boundaries between a specified set of ruby
141
155
  constants to minimize cross-boundary referencing and dependency.
@@ -179,18 +193,22 @@ files:
179
193
  - gemfiles/Gemfile-rails-6-0
180
194
  - gemfiles/Gemfile-rails-6-1
181
195
  - lib/packwerk.rb
182
- - lib/packwerk/application_load_paths.rb
183
196
  - lib/packwerk/application_validator.rb
184
197
  - lib/packwerk/association_inspector.rb
185
198
  - lib/packwerk/cache.rb
199
+ - lib/packwerk/checker.rb
186
200
  - lib/packwerk/cli.rb
201
+ - lib/packwerk/cli/result.rb
187
202
  - lib/packwerk/configuration.rb
188
203
  - lib/packwerk/const_node_inspector.rb
204
+ - lib/packwerk/constant_context.rb
189
205
  - lib/packwerk/constant_discovery.rb
190
206
  - lib/packwerk/constant_name_inspector.rb
207
+ - lib/packwerk/disable_sorbet.rb
208
+ - lib/packwerk/extension_loader.rb
191
209
  - lib/packwerk/file_processor.rb
192
210
  - lib/packwerk/files_for_processing.rb
193
- - lib/packwerk/formatters/offenses_formatter.rb
211
+ - lib/packwerk/formatters/default_offenses_formatter.rb
194
212
  - lib/packwerk/formatters/progress_formatter.rb
195
213
  - lib/packwerk/generators/configuration_file.rb
196
214
  - lib/packwerk/generators/root_package.rb
@@ -218,20 +236,19 @@ files:
218
236
  - lib/packwerk/parsers/factory.rb
219
237
  - lib/packwerk/parsers/parser_interface.rb
220
238
  - lib/packwerk/parsers/ruby.rb
239
+ - lib/packwerk/rails_load_paths.rb
221
240
  - lib/packwerk/reference.rb
222
- - lib/packwerk/reference_checking/checkers/checker.rb
223
241
  - lib/packwerk/reference_checking/checkers/dependency_checker.rb
224
- - lib/packwerk/reference_checking/checkers/privacy_checker.rb
225
242
  - lib/packwerk/reference_checking/reference_checker.rb
226
243
  - lib/packwerk/reference_extractor.rb
227
244
  - lib/packwerk/reference_offense.rb
228
- - lib/packwerk/result.rb
229
245
  - lib/packwerk/run_context.rb
230
- - lib/packwerk/sanity_checker.rb
231
246
  - lib/packwerk/spring_command.rb
232
247
  - lib/packwerk/unresolved_reference.rb
248
+ - lib/packwerk/validator.rb
249
+ - lib/packwerk/validator/result.rb
250
+ - lib/packwerk/validators/dependency_validator.rb
233
251
  - lib/packwerk/version.rb
234
- - lib/packwerk/violation_type.rb
235
252
  - packwerk.gemspec
236
253
  - shipit.rubygems.yml
237
254
  - sorbet/config
@@ -258,7 +275,6 @@ files:
258
275
  - sorbet/rbi/gems/digest@3.1.0.rbi
259
276
  - sorbet/rbi/gems/erubi@1.11.0.rbi
260
277
  - sorbet/rbi/gems/globalid@1.0.0.rbi
261
- - sorbet/rbi/gems/html_tokenizer@0.0.7.rbi
262
278
  - sorbet/rbi/gems/i18n@1.12.0.rbi
263
279
  - sorbet/rbi/gems/json@2.6.2.rbi
264
280
  - sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi
@@ -268,7 +284,6 @@ files:
268
284
  - sorbet/rbi/gems/marcel@1.0.2.rbi
269
285
  - sorbet/rbi/gems/method_source@1.0.0.rbi
270
286
  - sorbet/rbi/gems/mini_mime@1.1.2.rbi
271
- - sorbet/rbi/gems/mini_portile2@2.8.0.rbi
272
287
  - sorbet/rbi/gems/minitest-focus@1.3.1.rbi
273
288
  - sorbet/rbi/gems/minitest@5.16.2.rbi
274
289
  - sorbet/rbi/gems/mocha@1.14.0.rbi
@@ -318,7 +333,11 @@ files:
318
333
  - sorbet/rbi/gems/websocket-extensions@0.1.5.rbi
319
334
  - sorbet/rbi/gems/yard-sorbet@0.6.1.rbi
320
335
  - sorbet/rbi/gems/yard@0.9.28.rbi
321
- - sorbet/rbi/gems/zeitwerk@2.6.0.rbi
336
+ - sorbet/rbi/gems/zeitwerk@2.6.4.rbi
337
+ - sorbet/rbi/shims/minitest/test.rb
338
+ - sorbet/rbi/shims/packwerk/reference.rbi
339
+ - sorbet/rbi/shims/packwerk/unresolved_reference.rbi
340
+ - sorbet/rbi/shims/parser.rbi
322
341
  - sorbet/rbi/shims/psych.rbi
323
342
  - sorbet/tapioca/require.rb
324
343
  homepage: https://github.com/Shopify/packwerk
@@ -337,7 +356,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
337
356
  requirements:
338
357
  - - ">="
339
358
  - !ruby/object:Gem::Version
340
- version: '2.6'
359
+ version: '2.7'
341
360
  required_rubygems_version: !ruby/object:Gem::Requirement
342
361
  requirements:
343
362
  - - ">="
@@ -1,52 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module Formatters
6
- class OffensesFormatter
7
- include Packwerk::OffensesFormatter
8
-
9
- extend T::Sig
10
-
11
- sig { params(style: OutputStyle).void }
12
- def initialize(style: OutputStyles::Plain.new)
13
- @style = style
14
- end
15
-
16
- sig { override.params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
17
- def show_offenses(offenses)
18
- return "No offenses detected" if offenses.empty?
19
-
20
- <<~EOS
21
- #{offenses_list(offenses)}
22
- #{offenses_summary(offenses)}
23
- EOS
24
- end
25
-
26
- sig { override.params(offense_collection: Packwerk::OffenseCollection, fileset: T::Set[String]).returns(String) }
27
- def show_stale_violations(offense_collection, fileset)
28
- if offense_collection.stale_violations?(fileset)
29
- "There were stale violations found, please run `packwerk update-todo`"
30
- else
31
- "No stale violations detected"
32
- end
33
- end
34
-
35
- private
36
-
37
- sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
38
- def offenses_list(offenses)
39
- offenses
40
- .compact
41
- .map { |offense| offense.to_s(@style) }
42
- .join("\n")
43
- end
44
-
45
- sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
46
- def offenses_summary(offenses)
47
- offenses_string = "offense".pluralize(offenses.length)
48
- "#{offenses.length} #{offenses_string} detected"
49
- end
50
- end
51
- end
52
- end
@@ -1,34 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module ReferenceChecking
6
- module Checkers
7
- module Checker
8
- extend T::Sig
9
- extend T::Helpers
10
-
11
- abstract!
12
-
13
- sig { abstract.returns(ViolationType) }
14
- def violation_type; end
15
-
16
- sig { abstract.params(reference: Reference).returns(T::Boolean) }
17
- def invalid_reference?(reference); end
18
-
19
- sig { abstract.params(reference: Reference).returns(String) }
20
- def message(reference); end
21
-
22
- sig { params(reference: Reference).returns(String) }
23
- def standard_help_message(reference)
24
- standard_message = <<~EOS
25
- Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
26
- To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
27
- EOS
28
-
29
- standard_message.chomp
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,76 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- module ReferenceChecking
6
- module Checkers
7
- # Checks whether a given reference references a private constant of another package.
8
- class PrivacyChecker
9
- extend T::Sig
10
- include Checker
11
-
12
- sig { override.returns(Packwerk::ViolationType) }
13
- def violation_type
14
- ViolationType::Privacy
15
- end
16
-
17
- sig do
18
- override
19
- .params(reference: Packwerk::Reference)
20
- .returns(T::Boolean)
21
- end
22
- def invalid_reference?(reference)
23
- return false if reference.constant.public?
24
-
25
- privacy_option = reference.constant.package.enforce_privacy
26
- return false if enforcement_disabled?(privacy_option)
27
-
28
- return false unless privacy_option == true ||
29
- explicitly_private_constant?(reference.constant, explicitly_private_constants: privacy_option)
30
-
31
- true
32
- end
33
-
34
- sig do
35
- override
36
- .params(reference: Packwerk::Reference)
37
- .returns(String)
38
- end
39
- def message(reference)
40
- source_desc = "'#{reference.source_package}'"
41
-
42
- message = <<~EOS
43
- Privacy violation: '#{reference.constant.name}' is private to '#{reference.constant.package}' but referenced from #{source_desc}.
44
- Is there a public entrypoint in '#{reference.constant.package.public_path}' that you can use instead?
45
-
46
- #{standard_help_message(reference)}
47
- EOS
48
-
49
- message.chomp
50
- end
51
-
52
- private
53
-
54
- sig do
55
- params(
56
- constant: ConstantDiscovery::ConstantContext,
57
- explicitly_private_constants: T::Array[String]
58
- ).returns(T::Boolean)
59
- end
60
- def explicitly_private_constant?(constant, explicitly_private_constants:)
61
- explicitly_private_constants.include?(constant.name) ||
62
- # nested constants
63
- explicitly_private_constants.any? { |epc| constant.name.start_with?(epc + "::") }
64
- end
65
-
66
- sig do
67
- params(privacy_option: T.nilable(T.any(T::Boolean, T::Array[String])))
68
- .returns(T::Boolean)
69
- end
70
- def enforcement_disabled?(privacy_option)
71
- [false, nil].include?(privacy_option)
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,9 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- class Result < T::Struct
6
- const :message, String
7
- const :status, T::Boolean
8
- end
9
- end
@@ -1,8 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- # To do: This alias and file should be removed as it is deprecated
6
- warn("DEPRECATION WARNING: Packwerk::SanityChecker is deprecated, use Packwerk::ApplicationValidator instead.")
7
- SanityChecker = ApplicationValidator
8
- end
@@ -1,11 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Packwerk
5
- class ViolationType < T::Enum
6
- enums do
7
- Privacy = new
8
- Dependency = new
9
- end
10
- end
11
- end
@@ -1,46 +0,0 @@
1
- # DO NOT EDIT MANUALLY
2
- # This is an autogenerated file for types exported from the `html_tokenizer` gem.
3
- # Please instead update this file by running `dev typecheck update`.
4
-
5
- # typed: true
6
-
7
- module HtmlTokenizer
8
- end
9
-
10
- class HtmlTokenizer::Parser
11
- def initialize; end
12
-
13
- def append_placeholder(_); end
14
- def attribute_name; end
15
- def attribute_quoted?; end
16
- def attribute_value; end
17
- def cdata_text; end
18
- def closing_tag?; end
19
- def column_number; end
20
- def comment_text; end
21
- def context; end
22
- def document; end
23
- def document_length; end
24
- def errors; end
25
- def errors_count; end
26
- def line_number; end
27
- def parse(_); end
28
- def quote_character; end
29
- def rawtext_text; end
30
- def self_closing_tag?; end
31
- def tag_name; end
32
- end
33
-
34
- class HtmlTokenizer::ParserError < ::RuntimeError
35
- def initialize(message, position, line, column); end
36
-
37
- def column; end
38
- def line; end
39
- def position; end
40
- end
41
-
42
- class HtmlTokenizer::Tokenizer
43
- def initialize; end
44
-
45
- def tokenize(_); end
46
- end
@@ -1,8 +0,0 @@
1
- # typed: true
2
-
3
- # DO NOT EDIT MANUALLY
4
- # This is an autogenerated file for types exported from the `mini_portile2` gem.
5
- # Please instead update this file by running `bin/tapioca gem mini_portile2`.
6
-
7
- # THIS IS AN EMPTY RBI FILE.
8
- # see https://github.com/Shopify/tapioca/wiki/Manual-Gem-Requires