packwerk 3.2.2 → 3.2.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/packwerk/application_validator.rb +2 -1
  3. data/lib/packwerk/graph.rb +15 -56
  4. data/lib/packwerk/reference_checking/checkers/dependency_checker.rb +1 -2
  5. data/lib/packwerk/run_context.rb +5 -0
  6. data/lib/packwerk/validators/dependency_validator.rb +5 -4
  7. data/lib/packwerk/version.rb +1 -1
  8. data/sorbet/rbi/gems/{actionpack@7.0.3.1.rbi → actionpack@7.0.8.7.rbi} +1338 -1227
  9. data/sorbet/rbi/gems/{actionview@7.0.3.1.rbi → actionview@7.0.8.7.rbi} +548 -503
  10. data/sorbet/rbi/gems/{activesupport@7.0.3.1.rbi → activesupport@7.0.8.7.rbi} +714 -635
  11. data/sorbet/rbi/gems/{better_html@2.0.1.rbi → better_html@2.1.1.rbi} +21 -21
  12. data/sorbet/rbi/gems/{concurrent-ruby@1.1.10.rbi → concurrent-ruby@1.3.5.rbi} +1390 -1366
  13. data/sorbet/rbi/gems/{constant_resolver@0.2.0.rbi → constant_resolver@0.3.0.rbi} +22 -13
  14. data/sorbet/rbi/gems/{erubi@1.11.0.rbi → erubi@1.13.1.rbi} +28 -17
  15. data/sorbet/rbi/gems/{i18n@1.12.0.rbi → i18n@1.14.7.rbi} +234 -172
  16. data/sorbet/rbi/gems/{json@2.6.2.rbi → json@2.7.2.rbi} +94 -74
  17. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14237 -0
  18. data/sorbet/rbi/gems/{loofah@2.18.0.rbi → loofah@2.24.0.rbi} +470 -243
  19. data/sorbet/rbi/gems/{minitest@5.16.2.rbi → minitest@5.25.4.rbi} +577 -472
  20. data/sorbet/rbi/gems/{mocha@1.14.0.rbi → mocha@2.5.0.rbi} +468 -684
  21. data/sorbet/rbi/gems/{nokogiri@1.15.3.rbi → nokogiri@1.18.4.rbi} +1756 -869
  22. data/sorbet/rbi/gems/{parallel@1.24.0.rbi → parallel@1.25.1.rbi} +26 -20
  23. data/sorbet/rbi/gems/{racc@1.7.1.rbi → racc@1.8.1.rbi} +36 -36
  24. data/sorbet/rbi/gems/{rack-test@2.0.2.rbi → rack-test@2.2.0.rbi} +87 -114
  25. data/sorbet/rbi/gems/{rack@2.2.4.rbi → rack@2.2.13.rbi} +243 -195
  26. data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +754 -0
  27. data/sorbet/rbi/gems/rails-html-sanitizer@1.6.2.rbi +764 -0
  28. data/sorbet/rbi/gems/{railties@7.0.3.1.rbi → railties@7.0.8.7.rbi} +146 -140
  29. data/sorbet/rbi/gems/{regexp_parser@2.5.0.rbi → regexp_parser@2.9.2.rbi} +947 -542
  30. data/sorbet/rbi/gems/{rexml@3.2.5.rbi → rexml@3.3.9.rbi} +452 -312
  31. data/sorbet/rbi/gems/{rubocop-ast@1.21.0.rbi → rubocop-ast@1.31.3.rbi} +717 -588
  32. data/sorbet/rbi/gems/{rubocop@1.34.1.rbi → rubocop@1.64.1.rbi} +10916 -4406
  33. data/sorbet/rbi/gems/{ruby-progressbar@1.11.0.rbi → ruby-progressbar@1.13.0.rbi} +359 -281
  34. data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +8 -0
  35. data/sorbet/rbi/gems/{tzinfo@2.0.5.rbi → tzinfo@2.0.6.rbi} +144 -141
  36. data/sorbet/rbi/gems/{unicode-display_width@2.2.0.rbi → unicode-display_width@2.5.0.rbi} +24 -7
  37. metadata +36 -41
  38. data/sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi +0 -8
  39. data/sorbet/rbi/gems/prettier_print@0.1.0.rbi +0 -8
  40. data/sorbet/rbi/gems/rails-dom-testing@2.0.3.rbi +0 -455
  41. data/sorbet/rbi/gems/rails-html-sanitizer@1.4.3.rbi +0 -542
  42. data/sorbet/rbi/gems/ruby-lsp@0.2.3.rbi +0 -11
  43. data/sorbet/rbi/gems/syntax_tree@3.3.0.rbi +0 -8
  44. /data/sorbet/rbi/gems/{builder@3.2.4.rbi → builder@3.3.0.rbi} +0 -0
  45. /data/sorbet/rbi/gems/{parser@3.3.1.0.rbi → parser@3.3.3.0.rbi} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9172cfed0b1190af4ece801d73138cdaba7cd9aaad8fdb90537b2d6a03d597bb
4
- data.tar.gz: 946267b723dff18a00a2948d4f9d5c8766018ae815b50fa542ba450bdc29c718
3
+ metadata.gz: 9b01578e447c49b16c57f33b6bfb111f65f91046b12465a433da90c30d6d1f7e
4
+ data.tar.gz: 731840a1431c1ac5305a30489379cd36a8c345e52589282eed80d694d2cc9b9a
5
5
  SHA512:
6
- metadata.gz: a7ec7b0f03a55f713b24d9aec7e6cadfb7138087685ee698f7a35c64209638168d91ee7de44a174543271b4252173007d64a16b0bd5f00348dd0554a76c34bb1
7
- data.tar.gz: ccc7785fcef8f061923c72f122dbf7f7c9ebab1e7c4cc9d2e6c2a8a643ac0da8f7594c17c2823b2bcc7845dd255d886a6b85eabe0ce68176a8b1ff57097c7278
6
+ metadata.gz: 26ff296eba5296f6674ebd963d4a5a3868a3a18d2464420d6ca3523745f8b5bfe6652c193cd43e6aa0304fe53bbba642857a956e89ae7b94e893edd47e47fb95
7
+ data.tar.gz: 742bdcfab120757f90621cea4301b84036cfdf0747809d1116a972c9076cd448451723f7b8fa1f62baeebfe0e539be71c1e4fdb319925130c9103af22780d143
@@ -72,7 +72,8 @@ module Packwerk
72
72
  def check_application_structure(configuration)
73
73
  resolver = ConstantResolver.new(
74
74
  root_path: configuration.root_path.to_s,
75
- load_paths: configuration.load_paths
75
+ load_paths: configuration.load_paths,
76
+ exclude: configuration.exclude,
76
77
  )
77
78
 
78
79
  begin
@@ -1,82 +1,41 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "tsort"
5
+
4
6
  module Packwerk
5
7
  # A general implementation of a graph data structure with the ability to check for - and list - cycles.
6
8
  class Graph
9
+ include TSort
10
+
7
11
  extend T::Sig
8
12
  sig do
9
13
  params(
10
- # The edges of the graph; An edge being represented as an Array of two nodes.
11
- edges: T::Array[T::Array[T.any(String, Integer, NilClass)]]
14
+ # The edges of the graph; represented as an Hash of Arrays.
15
+ edges: T::Hash[T.any(String, Integer, NilClass), T::Array[T.any(String, Integer, NilClass)]]
12
16
  ).void
13
17
  end
14
18
  def initialize(edges)
15
- @edges = edges.uniq
16
- @cycles = Set.new
17
- process
19
+ @edges = edges
18
20
  end
19
21
 
20
22
  def cycles
21
- @cycles.dup
23
+ @cycles ||= strongly_connected_components.reject { _1.size == 1 }
22
24
  end
23
25
 
24
26
  def acyclic?
25
- @cycles.empty?
26
- end
27
-
28
- private
29
-
30
- def nodes
31
- @edges.flatten.uniq
32
- end
33
-
34
- def process
35
- # See https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
36
- @processed ||= begin
37
- nodes.each { |node| visit(node) }
38
- true
39
- end
40
- end
41
-
42
- def visit(node, visited_nodes: Set.new, path: [])
43
- # Already visited, short circuit to avoid unnecessary processing
44
- return if visited_nodes.include?(node)
45
-
46
- # We've returned to a node that we've already visited, so we've found a cycle!
47
- if path.include?(node)
48
- # Filter out the part of the path that isn't a cycle. For example, with the following path:
49
- #
50
- # a -> b -> c -> d -> b
51
- #
52
- # "a" isn't part of the cycle. The cycle should only appear once in the path, so we reject
53
- # everything from the beginning to the first instance of the current node.
54
- add_cycle(path.drop_while { |n| n != node })
55
- return
56
- end
57
-
58
- path << node
59
- neighbours(node).each do |neighbour|
60
- visit(neighbour, visited_nodes: visited_nodes, path: path)
61
- end
62
- path.pop
63
- ensure
64
- visited_nodes << node
27
+ cycles.empty?
65
28
  end
66
29
 
67
- def neighbours(node)
68
- @edges
69
- .lazy
70
- .select { |src, _dst| src == node }
71
- .map { |_src, dst| dst }
30
+ private def tsort_each_node(&block)
31
+ @edges.each_key(&block)
72
32
  end
73
33
 
74
- def add_cycle(cycle)
75
- # Ensure that the lexicographically smallest item is the first one labeled in a cycle
76
- min_node = cycle.min
77
- cycle.rotate! until cycle.first == min_node
34
+ EMPTY_ARRAY = [].freeze
35
+ private_constant :EMPTY_ARRAY
78
36
 
79
- @cycles << cycle
37
+ private def tsort_each_child(node, &block)
38
+ (@edges[node] || EMPTY_ARRAY).each(&block)
80
39
  end
81
40
  end
82
41
 
@@ -40,8 +40,7 @@ module Packwerk
40
40
 
41
41
  <<~EOS
42
42
  Dependency violation: #{const_name} belongs to '#{const_package}', but '#{ref_package}' does not specify a dependency on '#{const_package}'.
43
- Are we missing an abstraction?
44
- Is the code making the reference, and the referenced constant, in the right packages?
43
+ Are the constant and its references in the right packages?
45
44
 
46
45
  #{standard_help_message(reference)}
47
46
  EOS
@@ -22,6 +22,7 @@ module Packwerk
22
22
  inflector: ActiveSupport::Inflector,
23
23
  custom_associations: configuration.custom_associations,
24
24
  associations_exclude: configuration.associations_exclude,
25
+ exclude: configuration.exclude,
25
26
  cache_enabled: configuration.cache_enabled?,
26
27
  cache_directory: configuration.cache_directory,
27
28
  config_path: configuration.config_path,
@@ -39,6 +40,7 @@ module Packwerk
39
40
  package_paths: T.nilable(T.any(T::Array[String], String)),
40
41
  custom_associations: AssociationInspector::CustomAssociations,
41
42
  associations_exclude: T::Array[String],
43
+ exclude: T::Array[String],
42
44
  checkers: T::Array[Checker],
43
45
  cache_enabled: T::Boolean,
44
46
  ).void
@@ -52,6 +54,7 @@ module Packwerk
52
54
  package_paths: nil,
53
55
  custom_associations: [],
54
56
  associations_exclude: [],
57
+ exclude: [],
55
58
  checkers: Checker.all,
56
59
  cache_enabled: false
57
60
  )
@@ -65,6 +68,7 @@ module Packwerk
65
68
  @cache_enabled = cache_enabled
66
69
  @cache_directory = cache_directory
67
70
  @config_path = config_path
71
+ @exclude = exclude
68
72
 
69
73
  @file_processor = T.let(nil, T.nilable(FileProcessor))
70
74
  @context_provider = T.let(nil, T.nilable(ConstantDiscovery))
@@ -123,6 +127,7 @@ module Packwerk
123
127
  root_path: @root_path,
124
128
  load_paths: @load_paths,
125
129
  inflector: @inflector,
130
+ exclude: @exclude,
126
131
  )
127
132
  end
128
133
 
@@ -65,10 +65,11 @@ module Packwerk
65
65
 
66
66
  sig { params(package_set: PackageSet).returns(Validator::Result) }
67
67
  def check_acyclic_graph(package_set)
68
- edges = package_set.flat_map do |package|
69
- package.dependencies.map do |dependency|
70
- [package.name, package_set.fetch(dependency)&.name]
71
- end
68
+ edges = package_set.to_h do |package|
69
+ [
70
+ package.name,
71
+ package.dependencies.map { |dependency| package_set.fetch(dependency)&.name },
72
+ ]
72
73
  end
73
74
 
74
75
  dependency_graph = Graph.new(edges)
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Packwerk
5
- VERSION = "3.2.2"
5
+ VERSION = "3.2.3"
6
6
  end