packwerk 2.2.0 → 2.2.2

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +29 -20
  3. data/.github/workflows/cla.yml +22 -0
  4. data/.rubocop.yml +48 -19
  5. data/Gemfile +7 -2
  6. data/Gemfile.lock +202 -175
  7. data/README.md +1 -1
  8. data/RESOLVING_VIOLATIONS.md +81 -0
  9. data/Rakefile +1 -1
  10. data/USAGE.md +14 -5
  11. data/bin/m +1 -1
  12. data/bin/rake +1 -1
  13. data/bin/rubocop +1 -1
  14. data/bin/srb +1 -1
  15. data/bin/tapioca +1 -1
  16. data/gemfiles/Gemfile-rails-6-0 +1 -1
  17. data/gemfiles/Gemfile-rails-6-1 +22 -0
  18. data/lib/packwerk/application_load_paths.rb +1 -1
  19. data/lib/packwerk/application_validator.rb +7 -6
  20. data/lib/packwerk/association_inspector.rb +17 -15
  21. data/lib/packwerk/cache.rb +36 -29
  22. data/lib/packwerk/cli.rb +24 -20
  23. data/lib/packwerk/const_node_inspector.rb +8 -7
  24. data/lib/packwerk/constant_name_inspector.rb +2 -2
  25. data/lib/packwerk/deprecated_references.rb +40 -20
  26. data/lib/packwerk/file_processor.rb +14 -14
  27. data/lib/packwerk/files_for_processing.rb +27 -31
  28. data/lib/packwerk/formatters/offenses_formatter.rb +3 -3
  29. data/lib/packwerk/formatters/progress_formatter.rb +2 -2
  30. data/lib/packwerk/node.rb +1 -294
  31. data/lib/packwerk/node_helpers.rb +335 -0
  32. data/lib/packwerk/node_processor.rb +6 -5
  33. data/lib/packwerk/node_processor_factory.rb +3 -3
  34. data/lib/packwerk/node_visitor.rb +1 -1
  35. data/lib/packwerk/offense_collection.rb +27 -8
  36. data/lib/packwerk/offenses_formatter.rb +2 -2
  37. data/lib/packwerk/package.rb +3 -0
  38. data/lib/packwerk/package_set.rb +2 -0
  39. data/lib/packwerk/parse_run.rb +29 -20
  40. data/lib/packwerk/parsed_constant_definitions.rb +23 -20
  41. data/lib/packwerk/parsers/erb.rb +3 -3
  42. data/lib/packwerk/reference_checking/checkers/checker.rb +16 -3
  43. data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +16 -0
  44. data/lib/packwerk/reference_checking/checkers/privacy_checker.rb +18 -0
  45. data/lib/packwerk/reference_checking/reference_checker.rb +3 -1
  46. data/lib/packwerk/reference_extractor.rb +51 -48
  47. data/lib/packwerk/reference_offense.rb +3 -27
  48. data/lib/packwerk/run_context.rb +9 -8
  49. data/lib/packwerk/spring_command.rb +1 -1
  50. data/lib/packwerk/version.rb +1 -1
  51. data/lib/packwerk.rb +1 -0
  52. data/packwerk.gemspec +5 -12
  53. data/sorbet/rbi/gems/actioncable@7.0.3.1.rbi +2754 -0
  54. data/sorbet/rbi/gems/actionmailbox@7.0.3.1.rbi +1496 -0
  55. data/sorbet/rbi/gems/actionmailer@7.0.3.1.rbi +2362 -0
  56. data/sorbet/rbi/gems/actionpack@7.0.3.1.rbi +19397 -0
  57. data/sorbet/rbi/gems/actiontext@7.0.3.1.rbi +1569 -0
  58. data/sorbet/rbi/gems/actionview@7.0.3.1.rbi +14907 -0
  59. data/sorbet/rbi/gems/activejob@7.0.3.1.rbi +2553 -0
  60. data/sorbet/rbi/gems/activemodel@7.0.3.1.rbi +5999 -0
  61. data/sorbet/rbi/gems/activerecord@7.0.3.1.rbi +37832 -0
  62. data/sorbet/rbi/gems/activestorage@7.0.3.1.rbi +2321 -0
  63. data/sorbet/rbi/gems/activesupport@7.0.3.1.rbi +18818 -0
  64. data/sorbet/rbi/gems/concurrent-ruby@1.1.10.rbi +11722 -0
  65. data/sorbet/rbi/gems/constant_resolver@0.2.0.rbi +90 -0
  66. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1079 -0
  67. data/sorbet/rbi/gems/digest@3.1.0.rbi +189 -0
  68. data/sorbet/rbi/gems/erubi@1.11.0.rbi +140 -0
  69. data/sorbet/rbi/gems/globalid@1.0.0.rbi +572 -0
  70. data/sorbet/rbi/gems/i18n@1.12.0.rbi +2296 -0
  71. data/sorbet/rbi/gems/json@2.6.2.rbi +1548 -0
  72. data/sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi +8 -0
  73. data/sorbet/rbi/gems/loofah@2.18.0.rbi +877 -0
  74. data/sorbet/rbi/gems/m@1.6.0.rbi +257 -0
  75. data/sorbet/rbi/gems/marcel@1.0.2.rbi +220 -0
  76. data/sorbet/rbi/gems/mini_mime@1.1.2.rbi +170 -0
  77. data/sorbet/rbi/gems/mini_portile2@2.8.0.rbi +8 -0
  78. data/sorbet/rbi/gems/minitest-focus@1.3.1.rbi +104 -0
  79. data/sorbet/rbi/gems/minitest@5.16.2.rbi +2136 -0
  80. data/sorbet/rbi/gems/mocha@1.14.0.rbi +4177 -0
  81. data/sorbet/rbi/gems/net-imap@0.2.3.rbi +2147 -0
  82. data/sorbet/rbi/gems/net-pop@0.1.1.rbi +926 -0
  83. data/sorbet/rbi/gems/net-protocol@0.1.3.rbi +11 -0
  84. data/sorbet/rbi/gems/net-smtp@0.3.1.rbi +1108 -0
  85. data/sorbet/rbi/gems/netrc@0.11.0.rbi +153 -0
  86. data/sorbet/rbi/gems/nio4r@2.5.8.rbi +292 -0
  87. data/sorbet/rbi/gems/nokogiri@1.13.8.rbi +6478 -0
  88. data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  89. data/sorbet/rbi/gems/parser@3.1.2.1.rbi +9029 -0
  90. data/sorbet/rbi/gems/prettier_print@0.1.0.rbi +8 -0
  91. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  92. data/sorbet/rbi/gems/racc@1.6.0.rbi +152 -0
  93. data/sorbet/rbi/gems/rack-test@2.0.2.rbi +953 -0
  94. data/sorbet/rbi/gems/rack@2.2.4.rbi +5636 -0
  95. data/sorbet/rbi/gems/rails-html-sanitizer@1.4.3.rbi +688 -0
  96. data/sorbet/rbi/gems/rails@7.0.3.1.rbi +8 -0
  97. data/sorbet/rbi/gems/railties@7.0.3.1.rbi +3507 -0
  98. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +392 -0
  99. data/sorbet/rbi/gems/rake@13.0.6.rbi +2924 -0
  100. data/sorbet/rbi/gems/rbi@0.0.15.rbi +3007 -0
  101. data/sorbet/rbi/gems/regexp_parser@2.5.0.rbi +3383 -0
  102. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4714 -0
  103. data/sorbet/rbi/gems/rubocop-ast@1.21.0.rbi +6961 -0
  104. data/sorbet/rbi/gems/rubocop-performance@1.14.3.rbi +2986 -0
  105. data/sorbet/rbi/gems/{rubocop-shopify@2.0.1.rbi → rubocop-shopify@2.9.0.rbi} +4 -4
  106. data/sorbet/rbi/gems/rubocop-sorbet@0.6.11.rbi +992 -0
  107. data/sorbet/rbi/gems/rubocop@1.34.1.rbi +51820 -0
  108. data/sorbet/rbi/gems/ruby-lsp@0.2.1.rbi +11 -0
  109. data/sorbet/rbi/gems/smart_properties@1.17.0.rbi +474 -0
  110. data/sorbet/rbi/gems/spoom@1.1.11.rbi +2181 -0
  111. data/sorbet/rbi/gems/spring@4.0.0.rbi +411 -0
  112. data/sorbet/rbi/gems/strscan@3.0.4.rbi +8 -0
  113. data/sorbet/rbi/gems/syntax_tree@3.3.0.rbi +8 -0
  114. data/sorbet/rbi/gems/tapioca@0.9.2.rbi +3181 -0
  115. data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
  116. data/sorbet/rbi/gems/timeout@0.3.0.rbi +142 -0
  117. data/sorbet/rbi/gems/tzinfo@2.0.5.rbi +5896 -0
  118. data/sorbet/rbi/gems/unicode-display_width@2.2.0.rbi +48 -0
  119. data/sorbet/rbi/gems/unparser@0.6.5.rbi +4529 -0
  120. data/sorbet/rbi/gems/webrick@1.7.0.rbi +2582 -0
  121. data/sorbet/rbi/gems/websocket-driver@0.7.5.rbi +993 -0
  122. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +388 -0
  123. data/sorbet/rbi/gems/yard@0.9.28.rbi +18242 -0
  124. data/sorbet/rbi/gems/zeitwerk@2.6.0.rbi +867 -0
  125. data/sorbet/rbi/shims/psych.rbi +5 -0
  126. data/sorbet/tapioca/require.rb +2 -3
  127. metadata +91 -146
  128. data/.github/probots.yml +0 -2
  129. data/library.yml +0 -6
  130. data/service.yml +0 -1
  131. data/sorbet/rbi/gems/actioncable@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -860
  132. data/sorbet/rbi/gems/actionmailbox@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -568
  133. data/sorbet/rbi/gems/actionmailer@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -587
  134. data/sorbet/rbi/gems/actionpack@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -5314
  135. data/sorbet/rbi/gems/actiontext@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -699
  136. data/sorbet/rbi/gems/actionview@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -2515
  137. data/sorbet/rbi/gems/activejob@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -624
  138. data/sorbet/rbi/gems/activemodel@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -1248
  139. data/sorbet/rbi/gems/activerecord@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -8363
  140. data/sorbet/rbi/gems/activestorage@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -876
  141. data/sorbet/rbi/gems/activesupport@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -3987
  142. data/sorbet/rbi/gems/colorize@0.8.1.rbi +0 -40
  143. data/sorbet/rbi/gems/commander@4.5.2.rbi +0 -8
  144. data/sorbet/rbi/gems/concurrent-ruby@1.1.8.rbi +0 -1969
  145. data/sorbet/rbi/gems/constant_resolver@0.1.5.rbi +0 -26
  146. data/sorbet/rbi/gems/erubi@1.10.0.rbi +0 -41
  147. data/sorbet/rbi/gems/globalid@0.4.2.rbi +0 -178
  148. data/sorbet/rbi/gems/highline@2.0.3.rbi +0 -8
  149. data/sorbet/rbi/gems/i18n@1.8.10.rbi +0 -600
  150. data/sorbet/rbi/gems/loofah@2.9.0.rbi +0 -274
  151. data/sorbet/rbi/gems/m@1.5.1.rbi +0 -108
  152. data/sorbet/rbi/gems/marcel@1.0.0.rbi +0 -70
  153. data/sorbet/rbi/gems/mini_mime@1.0.3.rbi +0 -71
  154. data/sorbet/rbi/gems/minitest-focus@1.2.1.rbi +0 -8
  155. data/sorbet/rbi/gems/minitest@5.14.4.rbi +0 -544
  156. data/sorbet/rbi/gems/mocha@1.12.0.rbi +0 -953
  157. data/sorbet/rbi/gems/nio4r@2.5.7.rbi +0 -90
  158. data/sorbet/rbi/gems/nokogiri@1.11.2.rbi +0 -1647
  159. data/sorbet/rbi/gems/parallel@1.20.1.rbi +0 -117
  160. data/sorbet/rbi/gems/parlour@6.0.0.rbi +0 -1272
  161. data/sorbet/rbi/gems/parser@3.0.0.0.rbi +0 -1745
  162. data/sorbet/rbi/gems/pry@0.14.0.rbi +0 -8
  163. data/sorbet/rbi/gems/psych@3.3.2.rbi +0 -24
  164. data/sorbet/rbi/gems/racc@1.5.2.rbi +0 -57
  165. data/sorbet/rbi/gems/rack-test@1.1.0.rbi +0 -335
  166. data/sorbet/rbi/gems/rack@2.2.3.rbi +0 -1718
  167. data/sorbet/rbi/gems/rails-html-sanitizer@1.3.0.rbi +0 -213
  168. data/sorbet/rbi/gems/rails@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -8
  169. data/sorbet/rbi/gems/railties@7.0.0.alpha-d612542336d9a61381311c95a27d801bb4094779.rbi +0 -880
  170. data/sorbet/rbi/gems/rainbow@3.0.0.rbi +0 -155
  171. data/sorbet/rbi/gems/rake@13.0.3.rbi +0 -837
  172. data/sorbet/rbi/gems/regexp_parser@2.1.1.rbi +0 -8
  173. data/sorbet/rbi/gems/rexml@3.2.4.rbi +0 -8
  174. data/sorbet/rbi/gems/rubocop-ast@1.4.1.rbi +0 -8
  175. data/sorbet/rbi/gems/rubocop-performance@1.10.2.rbi +0 -8
  176. data/sorbet/rbi/gems/rubocop-sorbet@0.6.1.rbi +0 -8
  177. data/sorbet/rbi/gems/rubocop@1.12.0.rbi +0 -8
  178. data/sorbet/rbi/gems/smart_properties@1.15.0.rbi +0 -168
  179. data/sorbet/rbi/gems/spoom@1.1.0.rbi +0 -1061
  180. data/sorbet/rbi/gems/spring@2.1.1.rbi +0 -160
  181. data/sorbet/rbi/gems/sprockets-rails@3.2.2.rbi +0 -451
  182. data/sorbet/rbi/gems/sprockets@4.0.2.rbi +0 -1133
  183. data/sorbet/rbi/gems/tapioca@0.4.19.rbi +0 -603
  184. data/sorbet/rbi/gems/thor@1.1.0.rbi +0 -893
  185. data/sorbet/rbi/gems/tzinfo@2.0.4.rbi +0 -566
  186. data/sorbet/rbi/gems/unicode-display_width@2.0.0.rbi +0 -8
  187. data/sorbet/rbi/gems/websocket-driver@0.7.3.rbi +0 -438
  188. data/sorbet/rbi/gems/zeitwerk@2.4.2.rbi +0 -177
@@ -49,8 +49,8 @@ module Packwerk
49
49
  )
50
50
  end
51
51
 
52
- def code_nodes(node)
53
- return enum_for(:code_nodes, node) unless block_given?
52
+ def code_nodes(node, &block)
53
+ return enum_for(:code_nodes, node) unless block
54
54
  return unless node.is_a?(::AST::Node)
55
55
 
56
56
  yield node if node.type == :code
@@ -62,7 +62,7 @@ module Packwerk
62
62
  end
63
63
 
64
64
  node.children.each do |child|
65
- code_nodes(child) { |n| yield n }
65
+ code_nodes(child, &block)
66
66
  end
67
67
  end
68
68
  end
@@ -8,13 +8,26 @@ module Packwerk
8
8
  extend T::Sig
9
9
  extend T::Helpers
10
10
 
11
- interface!
11
+ abstract!
12
12
 
13
- sig { returns(ViolationType).abstract }
13
+ sig { abstract.returns(ViolationType) }
14
14
  def violation_type; end
15
15
 
16
- sig { params(reference: Reference).returns(T::Boolean).abstract }
16
+ sig { abstract.params(reference: Reference).returns(T::Boolean) }
17
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
18
31
  end
19
32
  end
20
33
  end
@@ -23,8 +23,24 @@ module Packwerk
23
23
  return false unless reference.source_package
24
24
  return false unless reference.source_package.enforce_dependencies?
25
25
  return false if reference.source_package.dependency?(reference.constant.package)
26
+
26
27
  true
27
28
  end
29
+
30
+ sig do
31
+ override
32
+ .params(reference: Packwerk::Reference)
33
+ .returns(String)
34
+ end
35
+ def message(reference)
36
+ <<~EOS
37
+ Dependency violation: #{reference.constant.name} belongs to '#{reference.constant.package}', but '#{reference.source_package}' does not specify a dependency on '#{reference.constant.package}'.
38
+ Are we missing an abstraction?
39
+ Is the code making the reference, and the referenced constant, in the right packages?
40
+
41
+ #{standard_help_message(reference)}
42
+ EOS
43
+ end
28
44
  end
29
45
  end
30
46
  end
@@ -31,6 +31,24 @@ module Packwerk
31
31
  true
32
32
  end
33
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
+
34
52
  private
35
53
 
36
54
  sig do
@@ -19,10 +19,12 @@ module Packwerk
19
19
  def call(reference)
20
20
  @checkers.each_with_object([]) do |checker, violations|
21
21
  next unless checker.invalid_reference?(reference)
22
+
22
23
  offense = Packwerk::ReferenceOffense.new(
23
24
  location: reference.source_location,
24
25
  reference: reference,
25
- violation_type: checker.violation_type
26
+ violation_type: checker.violation_type,
27
+ message: checker.message(reference)
26
28
  )
27
29
  violations << offense
28
30
  end
@@ -6,6 +6,49 @@ module Packwerk
6
6
  class ReferenceExtractor
7
7
  extend T::Sig
8
8
 
9
+ class << self
10
+ extend T::Sig
11
+
12
+ sig do
13
+ params(
14
+ unresolved_references: T::Array[UnresolvedReference],
15
+ context_provider: ConstantDiscovery
16
+ ).returns(T::Array[Reference])
17
+ end
18
+ def get_fully_qualified_references_from(unresolved_references, context_provider)
19
+ fully_qualified_references = T.let([], T::Array[Reference])
20
+
21
+ unresolved_references.each do |unresolved_references_or_offense|
22
+ unresolved_reference = unresolved_references_or_offense
23
+
24
+ constant =
25
+ context_provider.context_for(
26
+ unresolved_reference.constant_name,
27
+ current_namespace_path: unresolved_reference.namespace_path
28
+ )
29
+
30
+ next if constant.nil?
31
+
32
+ package_for_constant = constant.package
33
+
34
+ next if package_for_constant.nil?
35
+
36
+ source_package = context_provider.package_from_path(unresolved_reference.relative_path)
37
+
38
+ next if source_package == package_for_constant
39
+
40
+ fully_qualified_references << Reference.new(
41
+ source_package,
42
+ unresolved_reference.relative_path,
43
+ constant,
44
+ unresolved_reference.source_location
45
+ )
46
+ end
47
+
48
+ fully_qualified_references
49
+ end
50
+ end
51
+
9
52
  sig do
10
53
  params(
11
54
  constant_name_inspectors: T::Array[Packwerk::ConstantNameInspector],
@@ -27,10 +70,10 @@ module Packwerk
27
70
  params(
28
71
  node: Parser::AST::Node,
29
72
  ancestors: T::Array[Parser::AST::Node],
30
- absolute_file: String
73
+ relative_file: String
31
74
  ).returns(T.nilable(UnresolvedReference))
32
75
  end
33
- def reference_from_node(node, ancestors:, absolute_file:)
76
+ def reference_from_node(node, ancestors:, relative_file:)
34
77
  constant_name = T.let(nil, T.nilable(String))
35
78
 
36
79
  @constant_name_inspectors.each do |inspector|
@@ -44,50 +87,11 @@ module Packwerk
44
87
  constant_name,
45
88
  node: node,
46
89
  ancestors: ancestors,
47
- absolute_file: absolute_file
90
+ relative_file: relative_file
48
91
  )
49
92
  end
50
93
  end
51
94
 
52
- sig do
53
- params(
54
- unresolved_references: T::Array[UnresolvedReference],
55
- context_provider: ConstantDiscovery
56
- ).returns(T::Array[Reference])
57
- end
58
- def self.get_fully_qualified_references_from(unresolved_references, context_provider)
59
- fully_qualified_references = T.let([], T::Array[Reference])
60
-
61
- unresolved_references.each do |unresolved_references_or_offense|
62
- unresolved_reference = unresolved_references_or_offense
63
-
64
- constant =
65
- context_provider.context_for(
66
- unresolved_reference.constant_name,
67
- current_namespace_path: unresolved_reference.namespace_path
68
- )
69
-
70
- next if constant.nil?
71
-
72
- package_for_constant = constant.package
73
-
74
- next if package_for_constant.nil?
75
-
76
- source_package = context_provider.package_from_path(unresolved_reference.relative_path)
77
-
78
- next if source_package == package_for_constant
79
-
80
- fully_qualified_references << Reference.new(
81
- source_package,
82
- unresolved_reference.relative_path,
83
- constant,
84
- unresolved_reference.source_location
85
- )
86
- end
87
-
88
- fully_qualified_references
89
- end
90
-
91
95
  private
92
96
 
93
97
  sig do
@@ -95,16 +99,15 @@ module Packwerk
95
99
  constant_name: String,
96
100
  node: Parser::AST::Node,
97
101
  ancestors: T::Array[Parser::AST::Node],
98
- absolute_file: String
102
+ relative_file: String
99
103
  ).returns(T.nilable(UnresolvedReference))
100
104
  end
101
- def reference_from_constant(constant_name, node:, ancestors:, absolute_file:)
102
- namespace_path = Node.enclosing_namespace_path(node, ancestors: ancestors)
105
+ def reference_from_constant(constant_name, node:, ancestors:, relative_file:)
106
+ namespace_path = NodeHelpers.enclosing_namespace_path(node, ancestors: ancestors)
103
107
 
104
- return if local_reference?(constant_name, Node.name_location(node), namespace_path)
108
+ return if local_reference?(constant_name, NodeHelpers.name_location(node), namespace_path)
105
109
 
106
- relative_file = Pathname.new(absolute_file).relative_path_from(@root_path).to_s
107
- location = Node.location(node)
110
+ location = NodeHelpers.location(node)
108
111
 
109
112
  UnresolvedReference.new(
110
113
  constant_name,
@@ -17,39 +17,15 @@ module Packwerk
17
17
  params(
18
18
  reference: Packwerk::Reference,
19
19
  violation_type: Packwerk::ViolationType,
20
+ message: String,
20
21
  location: T.nilable(Node::Location)
21
22
  )
22
23
  .void
23
24
  end
24
- def initialize(reference:, violation_type:, location: nil)
25
- super(file: reference.relative_path, message: build_message(reference, violation_type), location: location)
25
+ def initialize(reference:, violation_type:, message:, location: nil)
26
+ super(file: reference.relative_path, message: message, location: location)
26
27
  @reference = reference
27
28
  @violation_type = violation_type
28
29
  end
29
-
30
- private
31
-
32
- sig { params(reference: Reference, violation_type: ViolationType).returns(String) }
33
- def build_message(reference, violation_type)
34
- violation_message = case violation_type
35
- when ViolationType::Privacy
36
- source_desc = "'#{reference.source_package}'"
37
- "Privacy violation: '#{reference.constant.name}' is private to '#{reference.constant.package}' but " \
38
- "referenced from #{source_desc}.\n" \
39
- "Is there a public entrypoint in '#{reference.constant.package.public_path}' that you can use instead?"
40
- when ViolationType::Dependency
41
- "Dependency violation: #{reference.constant.name} belongs to '#{reference.constant.package}', but " \
42
- "'#{reference.source_package}' does not specify a dependency on " \
43
- "'#{reference.constant.package}'.\n" \
44
- "Are we missing an abstraction?\n" \
45
- "Is the code making the reference, and the referenced constant, in the right packages?\n"
46
- end
47
-
48
- <<~EOS
49
- #{violation_message}
50
- Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
51
- To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
52
- EOS
53
- end
54
30
  end
55
31
  end
@@ -71,15 +71,16 @@ module Packwerk
71
71
 
72
72
  @file_processor = T.let(nil, T.nilable(FileProcessor))
73
73
  @context_provider = T.let(nil, T.nilable(ConstantDiscovery))
74
+ @package_set = T.let(nil, T.nilable(PackageSet))
74
75
  # We need to initialize this before we fork the process, see https://github.com/Shopify/packwerk/issues/182
75
76
  @cache = T.let(
76
77
  Cache.new(enable_cache: @cache_enabled, cache_directory: @cache_directory, config_path: @config_path), Cache
77
78
  )
78
79
  end
79
80
 
80
- sig { params(absolute_file: String).returns(T::Array[Packwerk::Offense]) }
81
- def process_file(absolute_file:)
82
- processed_file = file_processor.call(absolute_file)
81
+ sig { params(relative_file: String).returns(T::Array[Packwerk::Offense]) }
82
+ def process_file(relative_file:)
83
+ processed_file = file_processor.call(relative_file)
83
84
 
84
85
  references = ReferenceExtractor.get_fully_qualified_references_from(
85
86
  processed_file.unresolved_references,
@@ -90,6 +91,11 @@ module Packwerk
90
91
  processed_file.offenses + references.flat_map { |reference| reference_checker.call(reference) }
91
92
  end
92
93
 
94
+ sig { returns(PackageSet) }
95
+ def package_set
96
+ @package_set ||= ::Packwerk::PackageSet.load_all_from(@root_path, package_pathspec: @package_paths)
97
+ end
98
+
93
99
  private
94
100
 
95
101
  sig { returns(FileProcessor) }
@@ -123,11 +129,6 @@ module Packwerk
123
129
  )
124
130
  end
125
131
 
126
- sig { returns(PackageSet) }
127
- def package_set
128
- ::Packwerk::PackageSet.load_all_from(@root_path, package_pathspec: @package_paths)
129
- end
130
-
131
132
  sig { returns(T::Array[ConstantNameInspector]) }
132
133
  def constant_name_inspectors
133
134
  [
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
1
  # typed: true
2
+ # frozen_string_literal: true
3
3
 
4
4
  require "spring/commands"
5
5
 
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
5
- VERSION = "2.2.0"
5
+ VERSION = "2.2.2"
6
6
  end
data/lib/packwerk.rb CHANGED
@@ -26,6 +26,7 @@ module Packwerk
26
26
  autoload :FilesForProcessing
27
27
  autoload :Graph
28
28
  autoload :Node
29
+ autoload :NodeHelpers
29
30
  autoload :NodeProcessor
30
31
  autoload :NodeProcessorFactory
31
32
  autoload :NodeVisitor
data/packwerk.gemspec CHANGED
@@ -36,23 +36,16 @@ Gem::Specification.new do |spec|
36
36
  spec.files = Dir.chdir(__dir__) do
37
37
  %x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features|static)/}) }
38
38
  end
39
- spec.require_paths = %w(lib)
39
+ spec.require_paths = ["lib"]
40
40
 
41
41
  spec.required_ruby_version = ">= 2.6"
42
42
 
43
43
  spec.add_dependency("activesupport", ">= 5.2")
44
- spec.add_dependency("constant_resolver", ">=0.2.0")
45
- spec.add_dependency("parallel")
46
- spec.add_dependency("sorbet-runtime", ">=0.5.9914")
47
44
  spec.add_dependency("bundler")
48
- spec.add_dependency("digest")
49
-
50
- spec.add_development_dependency("rake")
51
- spec.add_development_dependency("sorbet")
52
- spec.add_development_dependency("m")
53
- # https://github.com/ruby/psych/pull/487
54
- spec.add_development_dependency("psych", "~> 3")
55
- spec.add_development_dependency("zeitwerk")
45
+ spec.add_dependency("constant_resolver", ">= 0.2.0")
46
+ spec.add_dependency("parallel")
47
+ spec.add_dependency("sorbet-runtime", ">= 0.5.9914")
48
+ spec.add_dependency("zeitwerk", ">= 2.6.1")
56
49
 
57
50
  # For Ruby parsing
58
51
  spec.add_dependency("ast")