Class: Woods::RubyAnalyzer::MermaidRenderer
- Inherits:
-
Object
- Object
- Woods::RubyAnalyzer::MermaidRenderer
- Defined in:
- lib/woods/ruby_analyzer/mermaid_renderer.rb
Overview
Renders Mermaid-format diagrams from extracted units, dependency graphs, and graph analysis data.
Produces valid Mermaid markdown strings for call graphs, dependency maps, dataflow charts, and combined architecture documents.
Instance Method Summary collapse
-
#render_architecture(units, graph_data, analysis) ⇒ String
Render a combined architecture document with all three diagram types.
-
#render_call_graph(units) ⇒ String
Render a call graph from extracted units showing method call relationships.
-
#render_dataflow(units) ⇒ String
Render a dataflow diagram from units that have data_transformations metadata.
-
#render_dependency_map(graph_data) ⇒ String
Render a dependency map from graph data (as returned by DependencyGraph#to_h).
Instance Method Details
#render_architecture(units, graph_data, analysis) ⇒ String
Render a combined architecture document with all three diagram types.
Returns a markdown document with headers and fenced Mermaid code blocks for call graph, dependency map, and dataflow diagrams, plus a summary of graph analysis findings.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/woods/ruby_analyzer/mermaid_renderer.rb', line 159 def render_architecture(units, graph_data, analysis) sections = [] sections << '# Architecture Overview' sections << '' # Call graph sections << '## Call Graph' sections << '' sections << '```mermaid' sections << render_call_graph(units) sections << '```' sections << '' # Dependency map sections << '## Dependency Map' sections << '' sections << '```mermaid' sections << render_dependency_map(graph_data) sections << '```' sections << '' # Dataflow sections << '## Data Flow' sections << '' sections << '```mermaid' sections << render_dataflow(units) sections << '```' sections << '' # Analysis summary sections << '## Analysis Summary' sections << '' sections.concat(render_stats_section(analysis)) sections.join("\n") end |
#render_call_graph(units) ⇒ String
Render a call graph from extracted units showing method call relationships.
Each unit with dependencies produces edges to its targets. Nodes are styled by type (class, module, method).
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/woods/ruby_analyzer/mermaid_renderer.rb', line 26 def render_call_graph(units) lines = ['graph TD'] return lines.join("\n") if units.nil? || units.empty? seen_nodes = Set.new seen_edges = Set.new units.each do |unit| node_id = sanitize_id(unit.identifier) lines << " #{node_id}[\"#{escape_label(unit.identifier)}\"]" if seen_nodes.add?(node_id) (unit.dependencies || []).each do |dep| target = dep[:target] || dep['target'] next unless target target_id = sanitize_id(target) lines << " #{target_id}[\"#{escape_label(target)}\"]" if seen_nodes.add?(target_id) via = dep[:via] || dep['via'] edge_key = "#{node_id}->#{target_id}" next unless seen_edges.add?(edge_key) lines << if via " #{node_id} -->|#{via}| #{target_id}" else " #{node_id} --> #{target_id}" end end end lines.join("\n") end |
#render_dataflow(units) ⇒ String
Render a dataflow diagram from units that have data_transformations metadata.
Shows transformation chains: which units construct, serialize, or deserialize data, with edges flowing between them.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/woods/ruby_analyzer/mermaid_renderer.rb', line 115 def render_dataflow(units) lines = ['flowchart TD'] return lines.join("\n") if units.nil? || units.empty? seen_nodes = Set.new units.each do |unit| transformations = unit.[:data_transformations] || unit.['data_transformations'] next unless transformations.is_a?(Array) && transformations.any? node_id = sanitize_id(unit.identifier) if seen_nodes.add?(node_id) shape = dataflow_shape(transformations) lines << " #{node_id}#{shape}" end transformations.each do |t| receiver = t[:receiver] || t['receiver'] next unless receiver receiver_id = sanitize_id(receiver) category = (t[:category] || t['category'])&.to_s method_name = t[:method] || t['method'] lines << " #{receiver_id}[\"#{escape_label(receiver)}\"]" if seen_nodes.add?(receiver_id) label = [category, method_name].compact.join(': ') lines << " #{node_id} -->|#{label}| #{receiver_id}" end end lines.join("\n") end |
#render_dependency_map(graph_data) ⇒ String
Render a dependency map from graph data (as returned by DependencyGraph#to_h).
Shows nodes grouped by type with edges representing dependencies.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/woods/ruby_analyzer/mermaid_renderer.rb', line 65 def render_dependency_map(graph_data) lines = ['graph TD'] return lines.join("\n") unless graph_data nodes = graph_data[:nodes] || graph_data['nodes'] || {} edges = graph_data[:edges] || graph_data['edges'] || {} return lines.join("\n") if nodes.empty? # Group nodes by type for subgraph rendering by_type = {} nodes.each do |identifier, | type = ([:type] || ['type'])&.to_sym || :unknown by_type[type] ||= [] by_type[type] << identifier end # Render subgraphs per type by_type.each do |type, identifiers| lines << " subgraph #{type}" identifiers.each do |id| node_id = sanitize_id(id) lines << " #{node_id}[\"#{escape_label(id)}\"]" end lines << ' end' end # Render edges seen_edges = Set.new edges.each do |source, targets| Array(targets).each do |target| next unless nodes.key?(target) edge_key = "#{sanitize_id(source)}->#{sanitize_id(target)}" next unless seen_edges.add?(edge_key) lines << " #{sanitize_id(source)} --> #{sanitize_id(target)}" end end lines.join("\n") end |