LCOV - code coverage report
Current view: top level - src/outputs/formatters - JsonInputFileFormatter.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 122 122 100.0 %
Date: 2025-08-08 20:01:16 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "JsonInputFileFormatter.h"
      11             : #include "MooseUtils.h"
      12             : 
      13             : #include <vector>
      14             : 
      15          14 : JsonInputFileFormatter::JsonInputFileFormatter() : _spaces(2), _level(0) {}
      16             : 
      17             : std::string
      18          14 : JsonInputFileFormatter::toString(const nlohmann::json & root)
      19             : {
      20          14 :   _stream.clear();
      21          14 :   _stream.str("");
      22        1054 :   for (auto && el : root["blocks"].items())
      23         534 :     addBlock(el.key(), el.value(), true);
      24          14 :   return _stream.str();
      25             : }
      26             : 
      27             : void
      28      918218 : JsonInputFileFormatter::addLine(const std::string & line,
      29             :                                 size_t max_line_len,
      30             :                                 const std::string & comment)
      31             : {
      32      918218 :   if (line.empty() && comment.empty())
      33             :   {
      34       17221 :     _stream << "\n";
      35       51663 :     return;
      36             :   }
      37             : 
      38      900997 :   std::string indent(_level * _spaces, ' ');
      39      900997 :   auto doc = MooseUtils::trim(comment);
      40      900997 :   if (doc.empty()) // Not comment so just print out the line normally
      41             :   {
      42       34442 :     _stream << indent << line << "\n";
      43       34442 :     return;
      44             :   }
      45             : 
      46             :   // We have a comment so we need to break it up over multiple lines if necessary
      47             :   // and make sure that they all start at the same spot.
      48      866555 :   _stream << indent << line;
      49      866555 :   std::vector<std::string> elements;
      50             : 
      51             :   // if the line is empty we can just start the comment right away
      52      866555 :   int extra = 1;
      53      866555 :   if (line.empty())
      54      582904 :     extra = 0;
      55             : 
      56             :   // be careful of really long lines.
      57      866555 :   int len = 100 - max_line_len - indent.size();
      58      866555 :   if (len < 0)
      59        3136 :     len = 20;
      60             : 
      61      866555 :   MooseUtils::tokenize(doc, elements, len, " \t");
      62      866555 :   std::string first(max_line_len - line.size() + extra, ' ');
      63      866555 :   _stream << first << "# " << elements[0] << "\n";
      64      866555 :   std::string cindent(max_line_len + indent.size() + extra, ' ');
      65     1425955 :   for (size_t i = 1; i < elements.size(); ++i)
      66      559400 :     _stream << cindent << "# " << elements[i] << "\n";
      67             : 
      68      866555 :   _stream << std::flush;
      69      935439 : }
      70             : 
      71             : void
      72       16750 : JsonInputFileFormatter::addBlock(const std::string & name,
      73             :                                  const nlohmann::json & block,
      74             :                                  bool toplevel)
      75             : {
      76       16750 :   addLine("");
      77       16750 :   if (toplevel)
      78         520 :     addLine("[" + name + "]");
      79             :   else
      80       16230 :     addLine("[./" + name + "]");
      81             : 
      82       16750 :   _level++;
      83       16750 :   std::string desc = block.contains("description") ? nlohmann::to_string(block["description"]) : "";
      84       16750 :   if (!desc.empty())
      85       15602 :     addLine("", 0, desc);
      86             : 
      87       16750 :   if (block.contains("parameters"))
      88       15602 :     addParameters(block["parameters"]);
      89             : 
      90       16750 :   if (block.contains("actions"))
      91             :   {
      92             :     // there could be duplicate parameters across actions, last one wins
      93         716 :     nlohmann::json all_params;
      94         716 :     auto & actions = block["actions"];
      95        2330 :     for (auto && el : actions.items())
      96             :     {
      97         807 :       auto & params = el.value()["parameters"];
      98        6261 :       for (auto && param_el : params.items())
      99        6261 :         all_params[param_el.key()] = param_el.value();
     100         716 :     }
     101         716 :     addParameters(all_params);
     102         716 :   }
     103             : 
     104       16750 :   if (block.contains("star"))
     105         460 :     addBlock("*", block["star"]);
     106             : 
     107       16750 :   addTypes("subblock_types", block);
     108       16750 :   addTypes("types", block);
     109             : 
     110       16750 :   if (block.contains("subblocks"))
     111             :   {
     112          77 :     auto & subblocks = block["subblocks"];
     113          77 :     if (!subblocks.is_null())
     114         413 :       for (auto && el : subblocks.items())
     115         245 :         addBlock(el.key(), el.value());
     116             :   }
     117             : 
     118       16750 :   _level--;
     119       16750 :   if (toplevel)
     120         520 :     addLine("[]");
     121             :   else
     122       16230 :     addLine("[../]");
     123       16750 : }
     124             : 
     125             : void
     126       33500 : JsonInputFileFormatter::addTypes(const std::string & key, const nlohmann::json & block)
     127             : {
     128       33500 :   if (!block.contains(key))
     129       32784 :     return;
     130         716 :   auto & types = block[key];
     131         716 :   if (types.is_null())
     132         245 :     return;
     133             : 
     134         471 :   addLine("");
     135         471 :   addLine("[./<types>]");
     136         471 :   _level++;
     137       16073 :   for (auto && el : types.items())
     138       16073 :     addBlock("<" + el.key() + ">", el.value());
     139         471 :   _level--;
     140         471 :   addLine("[../]");
     141             : }
     142             : 
     143             : void
     144       16318 : JsonInputFileFormatter::addParameters(const nlohmann::json & params)
     145             : {
     146       16318 :   size_t max_name = 0;
     147      583620 :   for (auto & el : params.items())
     148      283651 :     if (el.key().size() > max_name)
     149       52516 :       max_name = el.key().size();
     150             : 
     151       16318 :   size_t max_len = 0;
     152       16318 :   std::map<std::string, std::string> lines;
     153      583620 :   for (auto && el : params.items())
     154             :   {
     155      283651 :     auto & name = el.key();
     156      283651 :     auto & param = el.value();
     157             :     auto def =
     158      283651 :         param.contains("default") ? MooseUtils::trim(nlohmann::to_string(param["default"])) : "";
     159      283651 :     if (!def.empty())
     160      191231 :       def = def.substr(1, def.size() - 2);
     161      283651 :     if (def.find(' ') != std::string::npos)
     162        5680 :       def = "'" + def + "'";
     163      283651 :     std::string indent(max_name - name.size(), ' ');
     164      283651 :     std::string required;
     165      283651 :     if (param["required"])
     166       27246 :       required = "(required)";
     167      283651 :     if (def.size() == 0 && required.size() == 0)
     168       93310 :       def = "(no_default)";
     169      283651 :     std::string l = name + indent + " = " + def + required;
     170      283651 :     if (l.size() > max_len)
     171       40705 :       max_len = l.size();
     172      283651 :     lines[name] = l;
     173      299969 :   }
     174      583620 :   for (auto & el : params.items())
     175             :   {
     176      283651 :     auto & name = el.key();
     177      283651 :     auto & param = el.value();
     178      283651 :     auto & l = lines[name];
     179      283651 :     auto desc = nlohmann::to_string(param["description"]);
     180      283651 :     addLine(l, max_len, desc);
     181             : 
     182      283651 :     const auto doc_unit = nlohmann::to_string(param["doc_unit"]);
     183      283651 :     if (!doc_unit.empty())
     184      283651 :       addLine("", max_len + 1,
     185      567302 :               "Unit: " + doc_unit); // a +1 to account for an empty line
     186             : 
     187      283651 :     const auto group = nlohmann::to_string(param["group_name"]);
     188      283651 :     if (!group.empty())
     189      283651 :       addLine("", max_len + 1,
     190      567302 :               "Group: " + group); // a +1 to account for an empty line
     191      299969 :   }
     192       16318 : }

Generated by: LCOV version 1.14