visualize_packs 0.5.20 → 0.5.22

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