LCOV - code coverage report
Current view: top level - gcc/text-art - tree-widget.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.9 % 98 93
Test Date: 2026-02-28 14:20:25 Functions: 81.8 % 11 9
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Tree diagrams.
       2              :    Copyright (C) 2024-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #define INCLUDE_VECTOR
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "pretty-print.h"
      26              : #include "selftest.h"
      27              : #include "text-art/selftests.h"
      28              : #include "text-art/tree-widget.h"
      29              : #include "text-art/dump-widget-info.h"
      30              : 
      31              : using namespace text_art;
      32              : 
      33              : /* class text_art::tree_widget : public text_art::widget.  */
      34              : 
      35              : static const int margin_width = 3;
      36              : 
      37              : std::unique_ptr<tree_widget>
      38          120 : tree_widget::make (styled_string str, const theme &theme, style::id_t style_id)
      39              : {
      40          120 :   return std::make_unique <tree_widget>
      41          240 :     (std::make_unique <text_widget> (std::move (str)),
      42              :      theme,
      43          120 :      style_id);
      44              : }
      45              : 
      46              : std::unique_ptr<tree_widget>
      47            0 : tree_widget::make (const dump_widget_info &dwi, pretty_printer *pp)
      48              : {
      49            0 :   return tree_widget::make (styled_string (dwi.m_sm, pp_formatted_text (pp)),
      50              :                             dwi.m_theme,
      51            0 :                             dwi.get_tree_style_id ());
      52              : }
      53              : 
      54              : std::unique_ptr<tree_widget>
      55            8 : tree_widget::make (const dump_widget_info &dwi, const char *str)
      56              : {
      57            8 :   return tree_widget::make (styled_string (dwi.m_sm, str),
      58              :                             dwi.m_theme,
      59            8 :                             dwi.get_tree_style_id ());
      60              : }
      61              : 
      62              : std::unique_ptr<tree_widget>
      63          112 : tree_widget::from_fmt (const dump_widget_info &dwi,
      64              :                        printer_fn format_decoder,
      65              :                        const char *fmt, ...)
      66              : {
      67          112 :   va_list ap;
      68          112 :   va_start (ap, fmt);
      69          112 :   styled_string styled_str
      70          112 :     (styled_string::from_fmt_va (dwi.m_sm, format_decoder, fmt, &ap));
      71          112 :   va_end (ap);
      72          112 :   return make (std::move (styled_str), dwi.m_theme, dwi.get_tree_style_id ());
      73          112 : }
      74              : 
      75              : const char *
      76            0 : tree_widget::get_desc () const
      77              : {
      78            0 :   return "tree_widget";
      79              : }
      80              : 
      81              : canvas::size_t
      82          116 : tree_widget::calc_req_size ()
      83              : {
      84          116 :   canvas::size_t result (0, 0);
      85          116 :   if (m_node)
      86              :     {
      87          116 :       canvas::size_t node_req_size = m_node->get_req_size ();
      88          116 :       result.h += node_req_size.h;
      89          116 :       result.w = std::max (result.w, node_req_size.w);
      90              :     }
      91          220 :   for (auto &child : m_children)
      92              :     {
      93          104 :       canvas::size_t child_req_size = child->get_req_size ();
      94          104 :       result.h += child_req_size.h;
      95          104 :       result.w = std::max (result.w, child_req_size.w + margin_width);
      96              :     }
      97          116 :   return result;
      98              : }
      99              : 
     100              : void
     101          116 : tree_widget::update_child_alloc_rects ()
     102              : {
     103          116 :   const int x = get_min_x ();
     104          116 :   int y = get_min_y ();
     105          116 :   if (m_node)
     106              :     {
     107          116 :       m_node->set_alloc_rect
     108          116 :         (canvas::rect_t (canvas::coord_t (x, y),
     109              :                          canvas::size_t (get_alloc_w (),
     110          116 :                                          m_node->get_req_h ())));
     111          116 :       y += m_node->get_req_h ();
     112              :     }
     113          220 :   for (auto &child : m_children)
     114              :     {
     115          104 :       child->set_alloc_rect
     116          208 :         (canvas::rect_t (canvas::coord_t (x + margin_width, y),
     117          104 :                          canvas::size_t (get_alloc_w () - margin_width,
     118          104 :                                          child->get_req_h ())));
     119          104 :       y += child->get_req_h ();
     120              :     }
     121          116 : }
     122              : 
     123              : void
     124          116 : tree_widget::paint_to_canvas (canvas &canvas)
     125              : {
     126          116 :   if (m_node)
     127          116 :     m_node->paint_to_canvas (canvas);
     128          116 :   const int min_x = get_min_x ();
     129          116 :   const canvas::cell_t cell_child_non_final
     130          116 :     (m_theme.get_cell (theme::cell_kind::TREE_CHILD_NON_FINAL, m_style_id));
     131          116 :   const canvas::cell_t cell_child_final
     132          116 :     (m_theme.get_cell (theme::cell_kind::TREE_CHILD_FINAL, m_style_id));
     133          116 :   const canvas::cell_t cell_x_connector
     134          116 :     (m_theme.get_cell (theme::cell_kind::TREE_X_CONNECTOR, m_style_id));
     135          116 :   const canvas::cell_t cell_y_connector
     136          116 :     (m_theme.get_cell (theme::cell_kind::TREE_Y_CONNECTOR, m_style_id));
     137          116 :   size_t idx = 0;
     138          220 :   for (auto &child : m_children)
     139              :     {
     140          104 :       child->paint_to_canvas (canvas);
     141              : 
     142          104 :       const bool last_child = (++idx == m_children.size ());
     143          104 :       canvas.paint (canvas::coord_t (min_x + 1, child->get_min_y ()),
     144              :                     cell_x_connector);
     145          208 :       canvas.paint (canvas::coord_t (min_x, child->get_min_y ()),
     146              :                     last_child ? cell_child_final : cell_child_non_final);
     147          104 :       if (!last_child)
     148          112 :         for (int y = child->get_min_y () + 1; y <= child ->get_max_y (); y++)
     149           48 :           canvas.paint (canvas::coord_t (min_x, y), cell_y_connector);
     150              :     }
     151          116 : }
     152              : 
     153              : #if CHECKING_P
     154              : 
     155              : namespace selftest {
     156              : 
     157              : static std::unique_ptr<tree_widget>
     158            8 : make_test_tree_widget (const dump_widget_info &dwi)
     159              : {
     160            8 :   std::unique_ptr<tree_widget> w
     161            8 :     (tree_widget::from_fmt (dwi, nullptr, "Root"));
     162           32 :   for (int i = 0; i < 3; i++)
     163              :     {
     164           24 :       std::unique_ptr<tree_widget> c
     165           24 :         (tree_widget::from_fmt (dwi, nullptr, "Child %i", i));
     166           96 :       for (int j = 0; j < 3; j++)
     167          144 :         c->add_child (tree_widget::from_fmt (dwi, nullptr,
     168              :                                              "Grandchild %i %i", i, j));
     169           48 :       w->add_child (std::move (c));
     170           24 :     }
     171            8 :   return w;
     172              : }
     173              : 
     174              : static void
     175            4 : test_tree_widget ()
     176              : {
     177            4 :   style_manager sm;
     178              : 
     179            4 :   style::id_t default_style_id (sm.get_or_create_id (style ()));
     180              : 
     181            4 :   {
     182            4 :     ascii_theme theme;
     183            4 :     dump_widget_info dwi (sm, theme, default_style_id);
     184            4 :     canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
     185            4 :     ASSERT_CANVAS_STREQ
     186              :       (c, false,
     187              :        ("Root\n"
     188              :         "+- Child 0\n"
     189              :         "|  +- Grandchild 0 0\n"
     190              :         "|  +- Grandchild 0 1\n"
     191              :         "|  `- Grandchild 0 2\n"
     192              :         "+- Child 1\n"
     193              :         "|  +- Grandchild 1 0\n"
     194              :         "|  +- Grandchild 1 1\n"
     195              :         "|  `- Grandchild 1 2\n"
     196              :         "`- Child 2\n"
     197              :         "   +- Grandchild 2 0\n"
     198              :         "   +- Grandchild 2 1\n"
     199              :         "   `- Grandchild 2 2\n"));
     200            4 :   }
     201              : 
     202            4 :   {
     203            4 :     unicode_theme theme;
     204            4 :     dump_widget_info dwi (sm, theme, default_style_id);
     205            4 :     canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
     206            4 :     ASSERT_CANVAS_STREQ
     207              :       (c, false,
     208              :        ("Root\n"
     209              :         "├─ Child 0\n"
     210              :         "│  ├─ Grandchild 0 0\n"
     211              :         "│  ├─ Grandchild 0 1\n"
     212              :         "│  ╰─ Grandchild 0 2\n"
     213              :         "├─ Child 1\n"
     214              :         "│  ├─ Grandchild 1 0\n"
     215              :         "│  ├─ Grandchild 1 1\n"
     216              :         "│  ╰─ Grandchild 1 2\n"
     217              :         "╰─ Child 2\n"
     218              :         "   ├─ Grandchild 2 0\n"
     219              :         "   ├─ Grandchild 2 1\n"
     220              :         "   ╰─ Grandchild 2 2\n"));
     221            4 :   }
     222            4 : }
     223              : 
     224              : /* Run all selftests in this file.  */
     225              : 
     226              : void
     227            4 : text_art_tree_widget_cc_tests ()
     228              : {
     229            4 :   test_tree_widget ();
     230            4 : }
     231              : 
     232              : } // namespace selftest
     233              : 
     234              : 
     235              : #endif /* #if CHECKING_P */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.