visualize_packs 0.5.20 → 0.5.22

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8efefa896a6d002c7333dad53f2a8fa0be10d8c0004895682239c7a7f6a1105
4
- data.tar.gz: 0046a3a518c25de488b4b2e0d89c04ced6e45c1ff5d90e9e85d71d46b5256e89
3
+ metadata.gz: 4bf6ada5b7fe3dbfc435be39f2eb2e7d7053f8326c80fe56caa321b114aa2c06
4
+ data.tar.gz: ec7ec07be1e5c7b4b747c92a2f16067c74a163df8ccf2ac9f8d5656247268f45
5
5
  SHA512:
6
- metadata.gz: 5282d8a1af4103a3d6c38675c378adee512029eb4320a29874b91463c2fc4aa7380a76165306f8dc2d8163b67e60875b2496aeacca209b40ebdb09217744888c
7
- data.tar.gz: 99f84713ec95080f82668184bd69ce4e67dc30fbc739803f67efe8ebbe51728dbd4717d22eec946a2e24ce1128cd646d3cca47413a09a481718b76c029c47ae7
6
+ metadata.gz: '02108ec30cd93949952ef1fbcae5c0105158f466f01eeaa94b3490d3b0663509ebe1deac01c270a5cacbe448e263b13c942cdaa7a364df78d813bfe29f1df843'
7
+ data.tar.gz: c3c50c11a25725ce40aa028f522215c026b1a992ab18cfe5097e40c01be08b3e957e5eeeaa51a1f57e45e920b72c5d2045b3707cf8a519adf3066875e4e46a62
data/bin/visualize_packs CHANGED
@@ -1,54 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "pathname"
5
- require "optparse"
6
- require "ostruct"
7
-
8
4
  require_relative '../lib/visualize_packs'
9
5
 
10
- options = Options.new
11
-
12
- OptionParser.new do |opt|
13
- opt.on('--no-legend', "Don't show legend") { |o| options.show_legend = false }
14
-
15
- opt.on('--no-dependency-arrows', "Don't show accepted dependency arrows") { |o| options.show_dependencies = false }
16
- opt.on('--no-privacy-boxes', "Don't show privacy enforcement box on a pack") { |o| options.show_privacy = false }
17
- opt.on('--no-layers', "Don't show architectural layers") { |o| options.show_layers = false }
18
- opt.on('--no-visibility-arrows', "Don't show visibility arrows") { |o| options.show_visibility = false }
19
-
20
- opt.on('--no-todo-arrows', "Don't show pack todos") { |o| options.show_todos = false }
21
- opt.on("--only-todo-types=STRING", "Show only the selected types of todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.only_todo_types = o.to_s.split(",").uniq.map { EdgeTodoTypes.deserialize(_1) } }
22
- opt.on("--use-todos-for-layout", "Show only the selected types of todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.use_todos_for_layout = true }
23
-
24
- opt.on('--no-teams', "Don't show team colors") { |o| options.show_teams = false }
25
-
26
- opt.on('--focus-pack=STRING', "Focus on a specific pack(s). Comma-separated list of packs. Wildcards supported: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
27
- opt.on('--focus-pack-edge-mode=STRING', "If focus-pack is set, this shows only between focussed packs (when set to none) or the edges into / out of / in and out of the focus packs to non-focus packs (which will be re-added to the graph). One of #{FocusPackEdgeDirection.values.map &:serialize}") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
28
- opt.on('--exclude-packs=', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
29
-
30
- opt.on('--roll-nested-into-parent-packs', "Don't show nested packs (not counting root). Connect edges to top-level pack instead") { |o| options.roll_nested_into_parent_packs = true }
31
- opt.on('--no-nesting-arrows', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
32
-
33
- opt.on('--remote-base-url=STRING', "Link pack packs to a URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
34
-
35
- opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
36
-
37
- opt.on('-V', '--version', "Show version") do
38
- spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
39
- spec = Gem::Specification::load(spec_path)
40
- puts "Version #{spec.version}"
41
- exit
42
- end
43
-
44
- opt.on_tail("-h", "--help", "Show this message") do
45
- puts opt
46
- exit
47
- end
48
- end.parse!
49
-
50
6
  puts VisualizePacks.package_graph!(
51
- options,
7
+ ARGV,
52
8
  ParsePackwerk::Configuration.fetch.raw,
53
9
  Packs.all.map { ParsePackwerk.find(_1.name) }
54
10
  )
data/lib/graph.dot.erb CHANGED
@@ -46,11 +46,18 @@ digraph package_diagram {
46
46
  <table border='0' cellborder='1' cellspacing='0' cellpadding='4'>
47
47
  <tr> <td port='private'> <%= package.name -%> </td> </tr>
48
48
  </table>
49
- </td></tr></table>
49
+ </td></tr>
50
+ <%- if options.show_node_todos && node_protection.(package.name) != "" -%>
51
+ <tr><td CELLPADDING='1' ALIGN='RIGHT'><%= node_protection.(package.name) %></td></tr>
52
+ <%- end -%>
53
+ </table>
50
54
  >
51
55
  <%- else -%><
52
56
  <table border='0' cellborder='1' cellspacing='0' cellpadding='4'>
53
57
  <tr> <td align='left'> <%= package.name -%> </td> </tr>
58
+ <%- if options.show_node_todos && node_protection.(package.name) != "" -%>
59
+ <tr><td CELLPADDING='1' ALIGN='RIGHT'><%= node_protection.(package.name) %></td></tr>
60
+ <%- end -%>
54
61
  </table>
55
62
  >
56
63
  <%- end -%>
@@ -79,16 +86,16 @@ digraph package_diagram {
79
86
  <%- end -%>
80
87
  <%- end -%>
81
88
  <%- end -%>
82
- <%- if options.show_todos -%>
89
+ <%- if options.show_relationship_todos -%>
83
90
  <%- all_packages.each do |package| -%>
84
- <%- filtered_todos = package.violations.select { options.only_todo_types.include?(EdgeTodoTypes.deserialize(_1.type)) } -%>
91
+ <%- filtered_todos = package.violations.select { options.relationship_todo_types.include?(EdgeTodoTypes.deserialize(_1.type)) } -%>
85
92
  <%- todos_by_package = filtered_todos.group_by(&:to_package_name) -%>
86
93
  <%- todos_by_package.keys.each do |todos_to_package| -%>
87
94
  <%- todo_types = todos_by_package[todos_to_package].group_by(&:type) -%>
88
95
  <%- todo_types.keys.each do |todo_type| -%>
89
96
  <%- if show_edge.call(package.name, todos_to_package) -%>
90
97
  "<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [
91
- <%- if !options.use_todos_for_layout -%>
98
+ <%- if !options.use_relationship_todos_for_layout -%>
92
99
  constraint=false
93
100
  <%- end -%>
94
101
  # headlabel="<%= todo_type -%>"
@@ -98,6 +105,8 @@ digraph package_diagram {
98
105
  <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>
99
106
  <%- elsif todo_type == 'visibility' -%>
100
107
  <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>
108
+ <%- elsif todo_type == 'folder_visibility' -%>
109
+ <%= VisualizePacks::ArrowHead::FolderVisibilityTodo.serialize %>
101
110
  <%- elsif todo_type == 'dependency' -%>
102
111
  <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>
103
112
  <%- end -%>
@@ -134,35 +143,40 @@ digraph package_diagram {
134
143
  A -> B [label="accepted dependency" <%= VisualizePacks::ArrowHead::ConfiguredDependency.serialize %>]
135
144
  <%- end -%>
136
145
  <%- if options.show_nested_relationships -%>
137
- K [ fontsize=12 shape=box label="package"]
138
- L [ fontsize=12 shape=box label="package"]
139
- K -> L [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
140
- <%- end -%>
141
- <%- if options.show_visibility -%>
142
146
  M [ fontsize=12 shape=box label="package"]
143
147
  N [ fontsize=12 shape=box label="package"]
144
- M -> N [label="visibile to" <%= VisualizePacks::ArrowHead::ConfiguredVisibileTo.serialize %>]
148
+ M -> N [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
145
149
  <%- end -%>
146
- <%- if options.show_todos -%>
147
- <%- if options.only_todo_types.include?(EdgeTodoTypes::Privacy) -%>
150
+ <%- if options.show_visibility -%>
151
+ O [ fontsize=12 shape=box label="package"]
152
+ P [ fontsize=12 shape=box label="package"]
153
+ O -> P [label="visibile to" <%= VisualizePacks::ArrowHead::ConfiguredVisibileTo.serialize %>]
154
+ <%- end -%>
155
+ <%- if options.show_relationship_todos -%>
156
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Privacy) -%>
148
157
  C [ fontsize=12 shape=box label="package"]
149
158
  D [ fontsize=12 shape=box label="package"]
150
159
  C -> D [label="privacy todo" <%= VisualizePacks::ArrowHead::PrivacyTodo.serialize %>]
151
160
  <%- end -%>
152
- <%- if options.only_todo_types.include?(EdgeTodoTypes::Architecture) -%>
161
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Architecture) -%>
153
162
  E [ fontsize=12 shape=box label="package"]
154
163
  F [ fontsize=12 shape=box label="package"]
155
164
  E -> F [label="architecture todo" <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>]
156
165
  <%- end -%>
157
- <%- if options.only_todo_types.include?(EdgeTodoTypes::Visibility) -%>
166
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Visibility) -%>
158
167
  G [ fontsize=12 shape=box label="package"]
159
168
  H [ fontsize=12 shape=box label="package"]
160
169
  G -> H [label="visibility todo" <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>]
161
170
  <%- end -%>
162
- <%- if options.only_todo_types.include?(EdgeTodoTypes::Dependency) -%>
171
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Folder_Visibility) -%>
163
172
  I [ fontsize=12 shape=box label="package"]
164
173
  J [ fontsize=12 shape=box label="package"]
165
- I -> J [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
174
+ I -> J [label="folder visibility todo" <%= VisualizePacks::ArrowHead::FolderVisibilityTodo.serialize %>]
175
+ <%- end -%>
176
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Dependency) -%>
177
+ K [ fontsize=12 shape=box label="package"]
178
+ L [ fontsize=12 shape=box label="package"]
179
+ K -> L [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
166
180
  <%- end -%>
167
181
  <%- end -%>
168
182
  LEGEND_NODE_1 [ label="" peripheries=0 height=0 width=0 style=invis ]
@@ -7,6 +7,7 @@ class EdgeTodoTypes < T::Enum
7
7
  Privacy = new
8
8
  Architecture = new
9
9
  Visibility = new
10
+ Folder_Visibility = new
10
11
  end
11
12
  end
12
13
 
@@ -30,11 +31,12 @@ class Options < T::Struct
30
31
  prop :show_layers, T::Boolean, default: true
31
32
  prop :show_visibility, T::Boolean, default: true
32
33
 
33
- prop :show_todos, T::Boolean, default: true
34
- prop :only_todo_types, T::Array[EdgeTodoTypes], default: EdgeTodoTypes.values
35
- prop :use_todos_for_layout, T::Boolean, default: false
34
+ prop :show_relationship_todos, T::Boolean, default: true
35
+ prop :relationship_todo_types, T::Array[EdgeTodoTypes], default: EdgeTodoTypes.values
36
+ prop :use_relationship_todos_for_layout, T::Boolean, default: false
36
37
 
37
38
  prop :show_teams, T::Boolean, default: true
39
+ prop :show_node_todos, T::Boolean, default: true
38
40
 
39
41
  prop :focus_pack, T.nilable(T::Array[String]), default: nil
40
42
  prop :show_only_edges_to_focus_pack, FocusPackEdgeDirection, default: FocusPackEdgeDirection::All
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ #typed: strict
3
+
4
+ require "optparse"
5
+
6
+ class OptionsParser
7
+ extend T::Sig
8
+
9
+ sig { params(args: T::Array[String]).returns(Options) }
10
+ def self.parse(args)
11
+ options = Options.new
12
+
13
+ OptionParser.new do |opt|
14
+ opt.on('--no-legend', "Don't show legend") { |o| options.show_legend = false }
15
+
16
+ opt.on('--no-dependency-arrows', "Don't show accepted dependency arrows") { |o| options.show_dependencies = false }
17
+ opt.on('--no-privacy-boxes', "Don't show privacy enforcement box on a pack") { |o| options.show_privacy = false }
18
+ opt.on('--no-layers', "Don't show architectural layers") { |o| options.show_layers = false }
19
+ opt.on('--no-visibility-arrows', "Don't show visibility arrows") { |o| options.show_visibility = false }
20
+
21
+ opt.on('--no-todo-edges', "Don't show todos for package relationships") { |o| options.show_relationship_todos = false }
22
+ opt.on("--edge-todo-types=STRING", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.relationship_todo_types = o.to_s.split(",").uniq.map { EdgeTodoTypes.deserialize(_1) } }
23
+ opt.on("--use-edge-todos-for-layout", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.use_relationship_todos_for_layout = true }
24
+
25
+ opt.on('--no-teams', "Don't show team colors") { |o| options.show_teams = false }
26
+ opt.on('--no-node-todos', "Don't show package-based todos") { |o| options.show_node_todos = false }
27
+
28
+ opt.on('--focus-pack=STRING', "Focus on a specific pack(s). Comma-separated list of packs. Wildcards supported: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
29
+ opt.on('--focus-pack-edge-mode=STRING', "If focus-pack is set, this shows only between focussed packs (when set to none) or the edges into / out of / in and out of the focus packs to non-focus packs (which will be re-added to the graph). One of #{FocusPackEdgeDirection.values.map &:serialize}") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
30
+ opt.on('--exclude-packs=', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
31
+
32
+ opt.on('--roll-nested-into-parent-packs', "Don't show nested packs (not counting root). Connect edges to top-level pack instead") { |o| options.roll_nested_into_parent_packs = true }
33
+ opt.on('--no-nesting-arrows', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
34
+
35
+ opt.on('--remote-base-url=STRING', "Link pack packs to a URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
36
+
37
+ opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
38
+
39
+ opt.on('-V', '--version', "Show version") do
40
+ spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
41
+ spec = Gem::Specification::load(spec_path)
42
+ puts "Version #{spec.version}"
43
+ exit
44
+ end
45
+
46
+ opt.on_tail("-h", "--help", "Show this message") do
47
+ puts opt
48
+ exit
49
+ end
50
+ end.parse(args)
51
+
52
+ options
53
+ end
54
+ end
55
+
@@ -7,6 +7,7 @@ require 'parse_packwerk'
7
7
  require 'digest/md5'
8
8
 
9
9
  require 'visualize_packs/options'
10
+ require 'visualize_packs/options_parser'
10
11
 
11
12
  module VisualizePacks
12
13
  extend T::Sig
@@ -17,23 +18,27 @@ module VisualizePacks
17
18
  PrivacyTodo = new('color=darkred style=dashed arrowhead=crow')
18
19
  ArchitectureTodo = new('color=darkred style=dashed arrowhead=obox')
19
20
  VisibilityTodo = new('color=darkred style=dashed arrowhead=tee')
21
+ FolderVisibilityTodo = new('color=darkred style=dashed arrowhead=odot')
20
22
  ConfiguredDependency = new('color=darkgreen')
21
23
  ConfiguredVisibileTo = new('color=blue')
22
24
  ConfiguredNested = new('color=purple')
23
25
  end
24
26
  end
25
27
 
26
- sig { params(options: Options, raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
27
- def self.package_graph!(options, raw_config, packages)
28
+ sig { params(args: T::Array[String], raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
29
+ def self.package_graph!(args, raw_config, packages)
30
+ options = OptionsParser.parse(args)
31
+
28
32
  all_packages = filtered(packages, options).compact.sort_by {|x| x.name }
29
33
  all_packages = remove_nested_packs(all_packages, options)
30
34
  all_package_names = all_packages.map &:name
31
35
 
32
36
  show_edge = show_edge_builder(options, all_package_names)
33
37
  node_color = node_color_builder()
38
+ node_protection = package_based_todos_text_maker()
34
39
  max_todo_count = max_todo_count(all_packages, show_edge, options)
35
40
 
36
- title = diagram_title(options, max_todo_count)
41
+ title = diagram_title(args, options, max_todo_count)
37
42
 
38
43
  architecture_layers = (raw_config['architecture_layers'] || []) + ["NotInLayer"]
39
44
  grouped_packages = architecture_layers.inject({}) do |result, key|
@@ -66,10 +71,24 @@ module VisualizePacks
66
71
  package.config.dig("metadata", "owner") || package.config["owner"]
67
72
  end
68
73
 
69
- sig { params(options: Options, max_todo_count: T.nilable(Integer)).returns(String) }
70
- def self.diagram_title(options, max_todo_count)
74
+ sig { params(args: T::Array[String], options: Options, max_todo_count: T.nilable(Integer)).returns(String) }
75
+ def self.diagram_title(args, options, max_todo_count)
71
76
  return "<<b>#{options.title}</b>>" if options.title
72
77
 
78
+ sub_title1_length = 0
79
+ options_to_display = args.inject('') do |result, item|
80
+ sub_title1_length += item.length
81
+ if sub_title1_length > 90
82
+ sub_title1_length = 0
83
+ result += "<br/>#{item}"
84
+ else
85
+ result += " #{item}"
86
+ end
87
+ result
88
+ end
89
+ sub_title1 = "<br/>#{options_to_display}"
90
+
91
+
73
92
  focus_info = if options.focus_pack
74
93
  "Focus on #{limited_sentence(options.focus_pack)} (Edge mode: #{options.show_only_edges_to_focus_pack.serialize})"
75
94
  else
@@ -80,25 +99,26 @@ module VisualizePacks
80
99
  options.show_legend ? nil : "legend",
81
100
  options.show_layers ? nil : "layers",
82
101
  options.show_dependencies ? nil : "dependencies",
83
- options.show_todos ? nil : "todos",
102
+ options.show_relationship_todos ? nil : "edge todos",
84
103
  options.show_privacy ? nil : "privacy",
85
104
  options.show_teams ? nil : "teams",
105
+ options.show_node_todos ? nil : "node todos",
86
106
  options.show_visibility ? nil : "visibility",
87
107
  options.roll_nested_into_parent_packs ? "nested packs" : nil,
88
108
  options.show_nested_relationships ? nil : "nested relationships",
89
109
  ].compact.join(', ').strip
90
110
  hidden_aspects_title = hidden_aspects != '' ? "Hiding #{hidden_aspects}" : nil
91
111
 
92
- todo_types = EdgeTodoTypes.values.size == options.only_todo_types.size ? nil : "Only #{options.only_todo_types.map &:serialize} todos",
112
+ todo_types = EdgeTodoTypes.values.size == options.relationship_todo_types.size ? nil : "Only #{options.relationship_todo_types.map &:serialize} todos",
93
113
 
94
114
  exclusions = options.exclude_packs.empty? ? nil : "Excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
95
115
 
96
116
  main_title = [focus_info, hidden_aspects_title, todo_types, exclusions].compact.join('. ')
97
117
 
98
- if options.show_todos && max_todo_count
99
- sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
118
+ if options.show_relationship_todos && max_todo_count
119
+ sub_title2 = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
100
120
  end
101
- "<<b>#{main_title}</b>#{sub_title}>"
121
+ "<<b>#{main_title}</b>#{sub_title1}#{sub_title2}>"
102
122
  end
103
123
 
104
124
  sig { params(list: T.nilable(T::Array[String])).returns(T.nilable(String)) }
@@ -150,13 +170,13 @@ module VisualizePacks
150
170
  sig { params(all_packages: T::Array[ParsePackwerk::Package], show_edge: T.proc.params(arg0: String, arg1: String).returns(T::Boolean), options: Options).returns(T.nilable(Integer)) }
151
171
  def self.max_todo_count(all_packages, show_edge, options)
152
172
  todo_counts = {}
153
- if options.show_todos
173
+ if options.show_relationship_todos
154
174
  all_packages.each do |package|
155
175
  todos_by_package = package.violations&.group_by(&:to_package_name)
156
176
  todos_by_package&.keys&.each do |todos_to_package|
157
177
  todo_types = todos_by_package&& todos_by_package[todos_to_package]&.group_by(&:type)
158
178
  todo_types&.keys&.each do |todo_type|
159
- if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo_type))
179
+ if options.relationship_todo_types.include?(EdgeTodoTypes.deserialize(todo_type))
160
180
  if show_edge.call(package.name, todos_to_package)
161
181
  key = "#{package.name}->#{todos_to_package}:#{todo_type}"
162
182
  todo_counts[key] = todo_types && todo_types[todo_type]&.count
@@ -215,8 +235,8 @@ module VisualizePacks
215
235
 
216
236
  dependents = options.show_dependencies ? dependents_on(packages, focus_pack_name) : []
217
237
  dependencies = options.show_dependencies ? dependencies_of(packages, focus_pack_name) : []
218
- todos_out = options.show_todos ? todos_out(packages, focus_pack_name, options) : []
219
- todos_in = options.show_todos ? todos_in(packages, focus_pack_name, options) : []
238
+ todos_out = options.show_relationship_todos ? todos_out(packages, focus_pack_name, options) : []
239
+ todos_in = options.show_relationship_todos ? todos_in(packages, focus_pack_name, options) : []
220
240
 
221
241
  case options.show_only_edges_to_focus_pack
222
242
  when FocusPackEdgeDirection::All, FocusPackEdgeDirection::InOut then
@@ -342,7 +362,7 @@ module VisualizePacks
342
362
  def self.todos_in(all_packages, focus_packs_names, options)
343
363
  all_packages.select do |p|
344
364
  (p.violations || []).inject([]) do |res, todo|
345
- res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
365
+ res << todo.to_package_name if options.relationship_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
346
366
  res
347
367
  end.any? { |v| focus_packs_names.include?(v) }
348
368
  end.map { |pack| pack.name }
@@ -352,9 +372,43 @@ module VisualizePacks
352
372
  def self.todos_out(all_packages, focus_packs_names, options)
353
373
  all_packages.inject([]) do |result, p|
354
374
  focus_packs_names.include?(p.name) && (p.violations || []).each do |todo|
355
- result << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
375
+ result << todo.to_package_name if options.relationship_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
356
376
  end
357
377
  result
358
378
  end
359
379
  end
380
+
381
+ sig { params(protection: String, package_name: String, rubocop_config: T.any(NilClass, T::Boolean, T::Hash[String, T.untyped]), rubocop_todo: T.any(NilClass, T::Boolean, T::Hash[String, T.untyped])).returns(T.nilable(Integer)) }
382
+ def self.package_based_todos_for(protection, package_name, rubocop_config, rubocop_todo)
383
+ rubocop_config = {} if rubocop_config.is_a?(TrueClass) || rubocop_config.is_a?(FalseClass) || rubocop_config.is_a?(NilClass)
384
+ rubocop_todo = {} if rubocop_todo.is_a?(TrueClass) || rubocop_todo.is_a?(FalseClass) || rubocop_todo.is_a?(NilClass)
385
+
386
+ raise ArgumentError unless ['Packs/ClassMethodsAsPublicApis', 'Packs/DocumentedPublicApis', 'Packs/RootNamespaceIsPackName', 'Packs/TypedPublicApis'].include?(protection)
387
+ return nil unless (rubocop_config.dig(protection)&.dig('Enabled'))
388
+
389
+ (rubocop_todo.dig(protection)&.dig('Exclude') || []).inject(0) do |result, todo|
390
+ result += 1 if todo.start_with?("#{package_name}/")
391
+ result
392
+ end
393
+ end
394
+
395
+ sig { returns(T.untyped) }
396
+ def self.package_based_todos_text_maker
397
+ ->(package_name) {
398
+ [
399
+ 'Packs/ClassMethodsAsPublicApis',
400
+ 'Packs/DocumentedPublicApis',
401
+ 'Packs/RootNamespaceIsPackName',
402
+ 'Packs/TypedPublicApis'
403
+ ].map do |protection|
404
+ rubocop_config = File.exist?("#{package_name}/.rubocop.yml") ? YAML.load_file("#{package_name}/.rubocop.yml") : {}
405
+ rubocop_todo = File.exist?(".rubocop_todo.yml") ? YAML.load_file(".rubocop_todo.yml") : {}
406
+
407
+ todo_value = package_based_todos_for(protection, package_name, rubocop_config, rubocop_todo)
408
+ abbreviation = T.must(protection.split('/')[1]).chars[0]
409
+
410
+ "#{abbreviation}: #{todo_value}" if todo_value
411
+ end.compact.join(", ")
412
+ }
413
+ end
360
414
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visualize_packs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.20
4
+ version: 0.5.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-17 00:00:00.000000000 Z
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,7 @@ files:
122
122
  - lib/graph.dot.erb
123
123
  - lib/visualize_packs.rb
124
124
  - lib/visualize_packs/options.rb
125
+ - lib/visualize_packs/options_parser.rb
125
126
  homepage: https://github.com/rubyatscale/visualize_packs
126
127
  licenses:
127
128
  - MIT