packwerk 2.2.0 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
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")