LCOV - code coverage report
Current view: top level - src/outputs/formatters - JsonInputFileFormatter.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 122 122 100.0 %
Date: 2026-05-29 20:35:17 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           6 : JsonInputFileFormatter::JsonInputFileFormatter() : _spaces(2), _level(0) {}
      16             : 
      17             : std::string
      18           6 : JsonInputFileFormatter::toString(const nlohmann::json & root)
      19             : {
      20           6 :   _stream.clear();
      21          12 :   _stream.str("");
      22         233 :   for (auto && el : root["blocks"].items())
      23         233 :     addBlock(el.key(), el.value(), true);
      24           6 :   return _stream.str();
      25             : }
      26             : 
      27             : void
      28      475503 : JsonInputFileFormatter::addLine(const std::string & line,
      29             :                                 size_t max_line_len,
      30             :                                 const std::string & comment)
      31             : {
      32      475503 :   if (line.empty() && comment.empty())
      33             :   {
      34        8766 :     _stream << "\n";
      35       26298 :     return;
      36             :   }
      37             : 
      38      933474 :   std::string indent(_level * _spaces, ' ');
      39      466737 :   auto doc = MooseUtils::trim(comment);
      40      466737 :   if (doc.empty()) // Not comment so just print out the line normally
      41             :   {
      42       17532 :     _stream << indent << line << "\n";
      43       17532 :     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      449205 :   _stream << indent << line;
      49      449205 :   std::vector<std::string> elements;
      50             : 
      51             :   // if the line is empty we can just start the comment right away
      52      449205 :   int extra = 1;
      53      449205 :   if (line.empty())
      54      302154 :     extra = 0;
      55             : 
      56             :   // be careful of really long lines.
      57      449205 :   int len = 100 - max_line_len - indent.size();
      58      449205 :   if (len < 0)
      59        2667 :     len = 20;
      60             : 
      61      898410 :   MooseUtils::tokenize(doc, elements, len, " \t");
      62      449205 :   std::string first(max_line_len - line.size() + extra, ' ');
      63      449205 :   _stream << first << "# " << elements[0] << "\n";
      64      449205 :   std::string cindent(max_line_len + indent.size() + extra, ' ');
      65      831468 :   for (size_t i = 1; i < elements.size(); ++i)
      66      382263 :     _stream << cindent << "# " << elements[i] << "\n";
      67             : 
      68      449205 :   _stream << std::flush;
      69      484269 : }
      70             : 
      71             : void
      72        8556 : JsonInputFileFormatter::addBlock(const std::string & name,
      73             :                                  const nlohmann::json & block,
      74             :                                  bool toplevel)
      75             : {
      76       25668 :   addLine("");
      77        8556 :   if (toplevel)
      78         454 :     addLine("[" + name + "]");
      79             :   else
      80       16658 :     addLine("[./" + name + "]");
      81             : 
      82        8556 :   _level++;
      83        9060 :   std::string desc = block.contains("description") ? nlohmann::to_string(block["description"]) : "";
      84        8556 :   if (!desc.empty())
      85       16104 :     addLine("", 0, desc);
      86             : 
      87        8556 :   if (block.contains("parameters"))
      88        8052 :     addParameters(block["parameters"]);
      89             : 
      90        8556 :   if (block.contains("actions"))
      91             :   {
      92             :     // there could be duplicate parameters across actions, last one wins
      93         315 :     nlohmann::json all_params;
      94         315 :     auto & actions = block["actions"];
      95         669 :     for (auto && el : actions.items())
      96             :     {
      97         354 :       auto & params = el.value()["parameters"];
      98        2760 :       for (auto && param_el : params.items())
      99        2760 :         all_params[param_el.key()] = param_el.value();
     100         315 :     }
     101         315 :     addParameters(all_params);
     102         315 :   }
     103             : 
     104        8556 :   if (block.contains("star"))
     105         615 :     addBlock("*", block["star"]);
     106             : 
     107       17112 :   addTypes("subblock_types", block);
     108        8556 :   addTypes("types", block);
     109             : 
     110        8556 :   if (block.contains("subblocks"))
     111             :   {
     112          33 :     auto & subblocks = block["subblocks"];
     113          33 :     if (!subblocks.is_null())
     114         105 :       for (auto && el : subblocks.items())
     115         105 :         addBlock(el.key(), el.value());
     116             :   }
     117             : 
     118        8556 :   _level--;
     119        8556 :   if (toplevel)
     120         908 :     addLine("[]");
     121             :   else
     122       33316 :     addLine("[../]");
     123        8556 : }
     124             : 
     125             : void
     126       17112 : JsonInputFileFormatter::addTypes(const std::string & key, const nlohmann::json & block)
     127             : {
     128       17112 :   if (!block.contains(key))
     129       16797 :     return;
     130         315 :   auto & types = block[key];
     131         315 :   if (types.is_null())
     132         105 :     return;
     133             : 
     134         840 :   addLine("");
     135         630 :   addLine("[./<types>]");
     136         210 :   _level++;
     137        8262 :   for (auto && el : types.items())
     138        8262 :     addBlock("<" + el.key() + ">", el.value());
     139         210 :   _level--;
     140         840 :   addLine("[../]");
     141             : }
     142             : 
     143             : void
     144        8367 : JsonInputFileFormatter::addParameters(const nlohmann::json & params)
     145             : {
     146        8367 :   size_t max_name = 0;
     147      155418 :   for (auto & el : params.items())
     148      147051 :     if (el.key().size() > max_name)
     149       26897 :       max_name = el.key().size();
     150             : 
     151        8367 :   size_t max_len = 0;
     152        8367 :   std::map<std::string, std::string> lines;
     153      155418 :   for (auto && el : params.items())
     154             :   {
     155      147051 :     auto & name = el.key();
     156      147051 :     auto & param = el.value();
     157             :     auto def =
     158      341995 :         param.contains("default") ? MooseUtils::trim(nlohmann::to_string(param["default"])) : "";
     159      147051 :     if (!def.empty())
     160       99158 :       def = def.substr(1, def.size() - 2);
     161      147051 :     if (def.find(' ') != std::string::npos)
     162        2904 :       def = "'" + def + "'";
     163      147051 :     std::string indent(max_name - name.size(), ' ');
     164      147051 :     std::string required;
     165      147051 :     if (param["required"])
     166       14070 :       required = "(required)";
     167      147051 :     if (def.size() == 0 && required.size() == 0)
     168       48011 :       def = "(no_default)";
     169      147051 :     std::string l = name + indent + " = " + def + required;
     170      147051 :     if (l.size() > max_len)
     171       22109 :       max_len = l.size();
     172      147051 :     lines[name] = l;
     173      155418 :   }
     174      155418 :   for (auto & el : params.items())
     175             :   {
     176      147051 :     auto & name = el.key();
     177      147051 :     auto & param = el.value();
     178      147051 :     auto & l = lines[name];
     179      147051 :     auto desc = nlohmann::to_string(param["description"]);
     180      147051 :     addLine(l, max_len, desc);
     181             : 
     182      147051 :     const auto doc_unit = nlohmann::to_string(param["doc_unit"]);
     183      147051 :     if (!doc_unit.empty())
     184      294102 :       addLine("", max_len + 1,
     185      294102 :               "Unit: " + doc_unit); // a +1 to account for an empty line
     186             : 
     187      147051 :     const auto group = nlohmann::to_string(param["group_name"]);
     188      147051 :     if (!group.empty())
     189      294102 :       addLine("", max_len + 1,
     190      294102 :               "Group: " + group); // a +1 to account for an empty line
     191      155418 :   }
     192        8367 : }

Generated by: LCOV version 1.14