LCOV - code coverage report
Current view: top level - src/parser - Builder.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 99787a Lines: 389 415 93.7 %
Date: 2025-10-14 20:01:24 Functions: 24 26 92.3 %
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 "MooseUtils.h"
      11             : #include "InputParameters.h"
      12             : #include "ActionFactory.h"
      13             : #include "Action.h"
      14             : #include "Factory.h"
      15             : #include "Parser.h"
      16             : #include "MooseObjectAction.h"
      17             : #include "AddActionComponentAction.h"
      18             : #include "ActionWarehouse.h"
      19             : #include "EmptyAction.h"
      20             : #include "MooseApp.h"
      21             : #include "GlobalParamsAction.h"
      22             : #include "SyntaxTree.h"
      23             : #include "InputFileFormatter.h"
      24             : #include "YAMLFormatter.h"
      25             : #include "MooseTypes.h"
      26             : #include "CommandLine.h"
      27             : #include "JsonSyntaxTree.h"
      28             : #include "Syntax.h"
      29             : #include "ParameterRegistry.h"
      30             : 
      31             : #include "libmesh/parallel.h"
      32             : #include "libmesh/fparser.hh"
      33             : 
      34             : #include <string>
      35             : #include <fstream>
      36             : #include <iomanip>
      37             : #include <algorithm>
      38             : #include <cstdlib>
      39             : #include <filesystem>
      40             : 
      41             : namespace Moose
      42             : {
      43             : 
      44             : bool
      45     1272854 : isSectionActive(const hit::Node & node)
      46             : {
      47     1272854 :   const hit::Node * n = &node;
      48     4214257 :   while (n)
      49             :   {
      50     3039790 :     const auto section = n->parent();
      51     3039790 :     if (section)
      52             :     {
      53             :       // only check current level, not nested ones
      54     3730646 :       if (const auto active = section->find("active");
      55     1865323 :           active && active->type() == hit::NodeType::Field && active->parent() == section)
      56             :       {
      57      170908 :         const auto vars = active->param<std::vector<std::string>>();
      58       85454 :         return std::find_if(vars.begin(),
      59             :                             vars.end(),
      60      116120 :                             [&n](const auto & var)
      61      287028 :                             { return n->path() == hit::pathNorm(var); }) != vars.end();
      62       85454 :       }
      63             :       // only check current level, not nested ones
      64     3559738 :       if (const auto inactive = section->find("inactive");
      65     1779869 :           inactive && inactive->type() == hit::NodeType::Field && inactive->parent() == section)
      66             :       {
      67       25866 :         const auto vars = inactive->param<std::vector<std::string>>();
      68       12933 :         return std::find_if(vars.begin(),
      69             :                             vars.end(),
      70       17509 :                             [&n](const auto & var)
      71       43375 :                             { return n->path() == hit::pathNorm(var); }) == vars.end();
      72       12933 :       }
      73             :     }
      74     2941403 :     n = section;
      75             :   }
      76     1174467 :   return true;
      77             : }
      78             : 
      79             : std::vector<std::string>
      80         131 : findSimilar(const std::string & param, const std::vector<std::string> & options)
      81             : {
      82         131 :   std::vector<std::string> candidates;
      83         131 :   if (options.size() == 0)
      84          14 :     return candidates;
      85             : 
      86         117 :   int mindist = MooseUtils::levenshteinDist(options[0], param);
      87        4152 :   for (const auto & opt : options)
      88             :   {
      89        4035 :     const int dist = MooseUtils::levenshteinDist(opt, param);
      90             :     // magic number heuristics to get similarity distance cutoff
      91        4035 :     const int dist_cutoff = 1 + param.size() / 5;
      92        4035 :     if (dist > dist_cutoff || dist > mindist)
      93        4031 :       continue;
      94             : 
      95           4 :     if (dist < mindist)
      96             :     {
      97           4 :       mindist = dist;
      98           4 :       candidates.clear();
      99             :     }
     100           4 :     candidates.push_back(opt);
     101             :   }
     102         117 :   return candidates;
     103           0 : }
     104             : 
     105       69807 : Builder::Builder(MooseApp & app, ActionWarehouse & action_wh, Parser & parser)
     106             :   : ConsoleStreamInterface(app),
     107       69807 :     _app(app),
     108      139614 :     _factory(app.getFactory()),
     109       69807 :     _action_wh(action_wh),
     110       69807 :     _action_factory(app.getActionFactory()),
     111       69807 :     _syntax(_action_wh.syntax()),
     112       69807 :     _parser(parser),
     113       69807 :     _root(_parser.getRoot()),
     114      139614 :     _syntax_formatter(nullptr)
     115             : {
     116       69807 : }
     117             : 
     118       64107 : Builder::~Builder() {}
     119             : 
     120             : InputParameters
     121     8043891 : Builder::validParams()
     122             : {
     123     8043891 :   InputParameters params = emptyInputParameters();
     124             : 
     125             :   /**
     126             :    * Add the "active" and "inactive" parameters so that all blocks in the input file
     127             :    * can selectively create lists of active/inactive sub-blocks.
     128             :    */
     129    24131673 :   params.addParam<std::vector<std::string>>(
     130             :       "active",
     131    24131673 :       std::vector<std::string>({"__all__"}),
     132             :       "If specified only the blocks named will be visited and made active");
     133    16087782 :   params.addParam<std::vector<std::string>>(
     134             :       "inactive",
     135    16087782 :       std::vector<std::string>(),
     136             :       "If specified blocks matching these identifiers will be skipped.");
     137             : 
     138     8043891 :   return params;
     139    24131673 : }
     140             : 
     141             : std::vector<std::string>
     142         131 : Builder::listValidParams(std::string & section_name)
     143             : {
     144             :   bool dummy;
     145         131 :   std::string registered_identifier = _syntax.isAssociated(section_name, &dummy);
     146         131 :   auto iters = _syntax.getActions(registered_identifier);
     147             : 
     148         131 :   std::vector<std::string> paramlist;
     149         376 :   for (auto it = iters.first; it != iters.second; ++it)
     150             :   {
     151         245 :     auto params = _action_factory.getValidParams(it->second._action);
     152        4280 :     for (const auto & it : params)
     153        4035 :       paramlist.push_back(it.first);
     154         245 :   }
     155         262 :   return paramlist;
     156         131 : }
     157             : 
     158             : void
     159     2611090 : UnusedWalker::walk(const std::string & fullpath, const std::string & nodename, hit::Node * n)
     160             : {
     161             :   // the line() > 0 check allows us to skip nodes that were merged into this tree (i.e. CLI
     162             :   // args) because their unused params are checked+reported independently of the ones in the
     163             :   // main tree.
     164     2683141 :   if (!_used.count(fullpath) && nodename != "active" && nodename != "inactive" &&
     165     2683141 :       isSectionActive(*n) && n->line() > 0)
     166             :   {
     167         131 :     auto section_name = fullpath.substr(0, fullpath.rfind("/"));
     168         131 :     const auto paramlist = _builder.listValidParams(section_name);
     169         131 :     const auto candidates = findSimilar(nodename, paramlist);
     170         131 :     if (candidates.size() > 0)
     171           4 :       errors.emplace_back(
     172           8 :           "unused parameter '" + fullpath + "'; did you mean '" + candidates[0] + "'?", n);
     173             :     else
     174         127 :       errors.emplace_back("unused parameter '" + fullpath + "'", n);
     175         131 :   }
     176     2611090 : }
     177             : 
     178             : std::string
     179        2456 : Builder::getPrimaryFileName(bool strip_leading_path) const
     180             : {
     181        2456 :   const auto path = _parser.getLastInputFilePath();
     182        4912 :   return (strip_leading_path ? path.filename() : std::filesystem::absolute(path)).string();
     183        2456 : }
     184             : 
     185             : void
     186     1219183 : Builder::walkRaw(std::string /*fullpath*/, std::string /*nodepath*/, hit::Node * n)
     187             : {
     188     1219183 :   InputParameters active_list_params = Action::validParams();
     189     1219183 :   InputParameters params = EmptyAction::validParams();
     190             : 
     191     1219183 :   const std::string section_name = n->fullpath();
     192     1219183 :   const std::string curr_identifier = n->fullpath();
     193             : 
     194             :   // Before we retrieve any actions or build any objects, make sure that the section they are in
     195             :   // is active
     196     1219183 :   if (!isSectionActive(*n))
     197       15913 :     return;
     198             : 
     199             :   // Extract the block parameters before constructing the action
     200             :   // There may be more than one Action registered for a given section in which case we need to
     201             :   // build them all
     202             :   bool is_parent;
     203     1203270 :   std::string registered_identifier = _syntax.isAssociated(section_name, &is_parent);
     204             : 
     205             :   // Make sure at least one action is associated with the current identifier
     206     1203270 :   if (const auto [begin, end] = _syntax.getActions(registered_identifier); begin == end)
     207             :   {
     208           4 :     _errors.emplace_back(
     209           8 :         "section '[" + curr_identifier +
     210             :             "]' does not have an associated Action; you likely misspelled the Action/section name "
     211             :             "or the app you are running does not support this Action/syntax",
     212             :         n);
     213           4 :     return;
     214             :   }
     215             : 
     216             :   // The DynamicObjecRegistrationAction changes the action multimap and would invalidate the
     217             :   // iterators returned by _syntax.getActions, that's why we have to loop in this awkward way.
     218     1203266 :   std::set<const Syntax::ActionInfo *> processed_actions;
     219             :   while (true)
     220             :   {
     221             :     // search for an unprocessed action
     222     3100041 :     auto [begin, end] = _syntax.getActions(registered_identifier);
     223     3100041 :     auto it = begin;
     224     6297701 :     for (; it != end && processed_actions.count(&it->second); ++it)
     225             :       ;
     226             : 
     227             :     // no more unprocessed actions
     228     3100041 :     if (it == end)
     229     1203152 :       break;
     230             : 
     231             :     // mark action as processed
     232     1896889 :     processed_actions.insert(&it->second);
     233             : 
     234     1896889 :     if (is_parent)
     235      351025 :       continue;
     236     1545864 :     if (_syntax.isDeprecatedSyntax(registered_identifier))
     237           0 :       mooseDeprecated(
     238           0 :           hit::errormsg(n, _syntax.deprecatedActionSyntaxMessage(registered_identifier)));
     239             : 
     240     1545864 :     params = _action_factory.getValidParams(it->second._action);
     241     3091728 :     params.set<ActionWarehouse *>("awh") = &_action_wh;
     242     1545864 :     params.setHitNode(*n, {});
     243             : 
     244     1545864 :     extractParams(n, params);
     245             : 
     246             :     // Add the parsed syntax to the parameters object for consumption by the Action
     247     4637592 :     params.set<std::string>("task") = it->second._task;
     248     1545864 :     params.set<std::string>("registered_identifier") = registered_identifier;
     249             : 
     250     1545864 :     if (!(params.have_parameter<bool>("isObjectAction") && params.get<bool>("isObjectAction")))
     251     1541034 :       params.set<std::vector<std::string>>("control_tags")
     252      770517 :           .push_back(MooseUtils::baseName(curr_identifier));
     253             : 
     254             :     // Create the Action
     255             :     std::shared_ptr<Action> action_obj =
     256     1545864 :         _action_factory.create(it->second._action, curr_identifier, params);
     257             : 
     258             :     {
     259             :       // extract the MooseObject params if necessary
     260             :       std::shared_ptr<MooseObjectAction> object_action =
     261     1545754 :           std::dynamic_pointer_cast<MooseObjectAction>(action_obj);
     262     1545754 :       if (object_action)
     263             :       {
     264      775124 :         auto & object_params = object_action->getObjectParams();
     265      775124 :         object_params.setHitNode(*n, {});
     266      775124 :         extractParams(n, object_params);
     267     1550248 :         object_params.set<std::vector<std::string>>("control_tags")
     268      775124 :             .push_back(MooseUtils::baseName(curr_identifier));
     269             :       }
     270             :       // extract the Component params if necessary
     271             :       std::shared_ptr<AddActionComponentAction> component_action =
     272     1545754 :           std::dynamic_pointer_cast<AddActionComponentAction>(action_obj);
     273     1545754 :       if (component_action)
     274             :       {
     275         196 :         auto & component_params = component_action->getComponentParams();
     276         196 :         component_params.setHitNode(*n, {});
     277         196 :         extractParams(n, component_params);
     278         392 :         component_params.set<std::vector<std::string>>("control_tags")
     279         196 :             .push_back(MooseUtils::baseName(curr_identifier));
     280             :       }
     281     1545754 :     }
     282             : 
     283             :     // add it to the warehouse
     284     1545754 :     _action_wh.addActionBlock(action_obj);
     285     3442525 :   }
     286     1266824 : }
     287             : 
     288             : void
     289     1219180 : Builder::walk(const std::string & fullpath, const std::string & nodepath, hit::Node * n)
     290             : {
     291             :   // skip sections that were manually processed first.
     292     1219180 :   if (std::find(_secs_need_first.begin(), _secs_need_first.end(), nodepath) !=
     293     2438360 :       _secs_need_first.end())
     294       28988 :     return;
     295             : 
     296     1190192 :   walkRaw(fullpath, nodepath, n);
     297             : }
     298             : 
     299             : void
     300       69052 : Builder::build()
     301             : {
     302             :   // Pull in extracted variables from the parser (fparse stuff)
     303       69052 :   _extracted_vars = _parser.getExtractedVars();
     304             : 
     305             :   // There are a few order dependent actions that have to be built first in
     306             :   // order for the parser and application to function properly
     307      207156 :   const auto need_action_syntax_first = [this](const auto & action_name)
     308             :   {
     309      828624 :     const auto syntax = _syntax.getSyntaxByAction(action_name);
     310             :     mooseAssert(syntax.size(), "Empty syntax");
     311      207156 :     std::copy(syntax.begin(), syntax.end(), std::back_inserter(_secs_need_first));
     312      276208 :   };
     313             : 
     314             :   // SetupDebugAction: This action can contain an option for monitoring the
     315             :   // parser progress. It must be parsed first to capture all of the parsing
     316             :   // output progress.
     317       69052 :   need_action_syntax_first("SetupDebugAction");
     318             : 
     319             :   // GlobalParamsAction: This action is checked during the parameter extraction
     320             :   // routines of all subsequent blocks. It must be parsed early since it must
     321             :   // exist during subsequent parameter extraction.
     322       69052 :   need_action_syntax_first("GlobalParamsAction");
     323             : 
     324             :   // DynamicObjectRegistration: This action must be built before any MooseObjectActions
     325             :   // are built. This is because we retrieve valid parameters from the Factory
     326             :   // during parse time. Objects must be registered before validParameters can be retrieved.
     327       69052 :   need_action_syntax_first("DynamicObjectRegistrationAction");
     328             : 
     329             :   // Walk all the sections extracting paramters from each into InputParameters objects
     330      276208 :   for (const auto & sec : _secs_need_first)
     331      207156 :     if (auto n = _root.find(sec))
     332       28991 :       walkRaw(n->parent()->fullpath(), n->path(), n);
     333             : 
     334             :   // Walk for the remainder
     335       69052 :   _root.walk(this, hit::NodeType::Section);
     336             : 
     337             :   // Warn for all deprecated parameters together
     338       68938 :   if (_deprecated_params.size())
     339             :   {
     340         949 :     std::vector<std::string> messages;
     341        2061 :     for (const auto & key_message_pair : _deprecated_params)
     342        1112 :       messages.push_back(key_message_pair.second);
     343         949 :     const auto message = MooseUtils::stringJoin(messages, "\n\n");
     344             : 
     345         949 :     const auto current_show_trace = Moose::show_trace;
     346         949 :     Moose::show_trace = false;
     347         949 :     moose::internal::mooseDeprecatedStream(Moose::out, false, true, message + "\n\n");
     348         941 :     Moose::show_trace = current_show_trace;
     349         941 :   }
     350             : 
     351       68930 :   if (_errors.size())
     352          92 :     _parser.parseError(_errors);
     353       68838 : }
     354             : 
     355             : // Checks the input and the way it has been used and emits any errors/warnings.
     356             : // This has to be a separate function because for we don't know if some parameters were unused
     357             : // until all the multiapps/subapps have been fully initialized - which isn't complete until
     358             : // *after* all the other member functions on Parser have been run.  So this is here to be
     359             : // externally called at the right time.
     360             : void
     361       63911 : Builder::errorCheck(const Parallel::Communicator & comm, bool warn_unused, bool err_unused)
     362             : {
     363             :   // Nothing to do here
     364       63911 :   if (!warn_unused && !err_unused)
     365           0 :     return;
     366             : 
     367       63911 :   std::vector<hit::ErrorMessage> messages;
     368             : 
     369             :   {
     370       63911 :     UnusedWalker uw(_extracted_vars, *this);
     371       63911 :     _parser.getCommandLineRoot().walk(&uw);
     372       63911 :     Parser::appendErrorMessages(messages, uw.errors);
     373       63911 :   }
     374             : 
     375             :   {
     376       63911 :     UnusedWalker uw(_extracted_vars, *this);
     377       63911 :     _root.walk(&uw);
     378       63911 :     Parser::appendErrorMessages(messages, uw.errors);
     379       63911 :   }
     380             : 
     381       63915 :   for (const auto & arg : _app.commandLine()->unusedHitParams(comm))
     382       63915 :     messages.emplace_back("unused command line parameter '" + arg + "'");
     383             : 
     384       63911 :   if (messages.size())
     385             :   {
     386          90 :     const auto message = _parser.joinErrorMessages(messages);
     387          90 :     if (warn_unused)
     388          51 :       mooseUnused(message);
     389          90 :     if (err_unused)
     390             :     {
     391          39 :       if (_parser.getThrowOnError())
     392           0 :         _parser.parseError(messages);
     393             :       else
     394          39 :         mooseError(
     395          39 :             message +
     396             :             "\n\nAppend --allow-unused (or -w) on the command line to ignore unused parameters.");
     397             :     }
     398          51 :   }
     399       63872 : }
     400             : 
     401             : void
     402          20 : Builder::initSyntaxFormatter(SyntaxFormatterType type, bool dump_mode)
     403             : {
     404          20 :   switch (type)
     405             :   {
     406           0 :     case INPUT_FILE:
     407           0 :       _syntax_formatter = std::make_unique<InputFileFormatter>(dump_mode);
     408           0 :       break;
     409          20 :     case YAML:
     410          20 :       _syntax_formatter = std::make_unique<YAMLFormatter>(dump_mode);
     411          20 :       break;
     412           0 :     default:
     413           0 :       mooseError("Unrecognized Syntax Formatter requested");
     414             :       break;
     415             :   }
     416          20 : }
     417             : 
     418             : void
     419         183 : Builder::buildJsonSyntaxTree(JsonSyntaxTree & root) const
     420             : {
     421         183 :   std::vector<std::pair<std::string, Syntax::ActionInfo>> all_names;
     422             : 
     423        5049 :   for (const auto & iter : _syntax.getAssociatedTypes())
     424        4866 :     root.addSyntaxType(iter.first, iter.second);
     425             : 
     426             :   // Build a list of all the actions appearing in the syntax
     427       22353 :   for (const auto & iter : _syntax.getAssociatedActions())
     428             :   {
     429       22170 :     Syntax::ActionInfo act_info = iter.second;
     430             :     /**
     431             :      * If the task is nullptr that means we need to figure out which task goes with this syntax for
     432             :      * the purpose of building the Moose Object part of the tree. We will figure this out by asking
     433             :      * the ActionFactory for the registration info.
     434             :      */
     435       22170 :     if (act_info._task == "")
     436       17219 :       act_info._task = _action_factory.getTaskName(act_info._action);
     437             : 
     438       22170 :     all_names.push_back(std::make_pair(iter.first, act_info));
     439       22170 :   }
     440             : 
     441             :   // Add all the actions to the JSON tree, except for ActionComponents (below)
     442       22353 :   for (const auto & act_names : all_names)
     443             :   {
     444       22170 :     const auto & act_info = act_names.second;
     445       22170 :     const std::string & action = act_info._action;
     446       22170 :     const std::string & task = act_info._task;
     447       22170 :     const std::string syntax = act_names.first;
     448       22170 :     InputParameters action_obj_params = _action_factory.getValidParams(action);
     449       44340 :     bool params_added = root.addParameters("",
     450             :                                            syntax,
     451             :                                            false,
     452             :                                            action,
     453             :                                            true,
     454             :                                            &action_obj_params,
     455       88680 :                                            _syntax.getLineInfo(syntax, action, ""),
     456             :                                            "");
     457             : 
     458       22170 :     if (params_added)
     459             :     {
     460       19503 :       auto tasks = _action_factory.getTasksByAction(action);
     461       50184 :       for (auto & t : tasks)
     462             :       {
     463       30681 :         auto info = _action_factory.getLineInfo(action, t);
     464       30681 :         root.addActionTask(syntax, action, t, info);
     465       30681 :       }
     466       19503 :     }
     467             : 
     468             :     /**
     469             :      * We need to see if this action is inherited from MooseObjectAction. If it is, then we will
     470             :      * loop over all the Objects in MOOSE's Factory object to print them out if they have associated
     471             :      * bases matching the current task.
     472             :      */
     473       35457 :     if (action_obj_params.have_parameter<bool>("isObjectAction") &&
     474       35457 :         action_obj_params.get<bool>("isObjectAction"))
     475             :     {
     476    20625777 :       for (auto & [moose_obj_name, obj] : _factory.registeredObjects())
     477             :       {
     478    20612490 :         auto moose_obj_params = obj->buildParameters();
     479             :         // Now that we know that this is a MooseObjectAction we need to see if it has been
     480             :         // restricted
     481             :         // in any way by the user.
     482    20612490 :         const std::vector<std::string> & buildable_types = action_obj_params.getBuildableTypes();
     483             : 
     484             :         // See if the current Moose Object syntax belongs under this Action's block
     485    20612490 :         if ((buildable_types.empty() || // Not restricted
     486           0 :              std::find(buildable_types.begin(), buildable_types.end(), moose_obj_name) !=
     487           0 :                  buildable_types.end()) && // Restricted but found
     488    20612490 :             moose_obj_params.hasBase() &&  // Has a registered base
     489    20612490 :             _syntax.verifyMooseObjectTask(moose_obj_params.getBase(),
     490    41224980 :                                           task) &&          // and that base is associated
     491      472015 :             action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     492             :         )
     493             :         {
     494      472015 :           std::string name;
     495      472015 :           size_t pos = 0;
     496      472015 :           bool is_action_params = false;
     497      472015 :           bool is_type = false;
     498      472015 :           if (syntax[syntax.size() - 1] == '*')
     499             :           {
     500      418774 :             pos = syntax.size();
     501             : 
     502      418774 :             if (!action_obj_params.collapseSyntaxNesting())
     503      418774 :               name = syntax.substr(0, pos - 1) + moose_obj_name;
     504             :             else
     505             :             {
     506           0 :               name = syntax.substr(0, pos - 1) + "/<type>/" + moose_obj_name;
     507           0 :               is_action_params = true;
     508             :             }
     509             :           }
     510             :           else
     511             :           {
     512       53241 :             name = syntax + "/<type>/" + moose_obj_name;
     513       53241 :             is_type = true;
     514             :           }
     515      472015 :           moose_obj_params.set<std::string>("type") = moose_obj_name;
     516             : 
     517      472015 :           auto lineinfo = _factory.getLineInfo(moose_obj_name);
     518      472015 :           std::string classname = _factory.associatedClassName(moose_obj_name);
     519      472015 :           root.addParameters(syntax,
     520             :                              name,
     521             :                              is_type,
     522             :                              moose_obj_name,
     523             :                              is_action_params,
     524             :                              &moose_obj_params,
     525             :                              lineinfo,
     526             :                              classname);
     527      472015 :         }
     528    20612490 :       }
     529             : 
     530             :       // Same thing for ActionComponents, which, while they are not MooseObjects, should behave
     531             :       // similarly syntax-wise
     532       13287 :       if (syntax != "ActionComponents/*")
     533       13104 :         continue;
     534             : 
     535         366 :       auto iters = _action_factory.getActionsByTask("list_component");
     536             : 
     537         549 :       for (auto it = iters.first; it != iters.second; ++it)
     538             :       {
     539             :         // Get the name and parameters
     540         366 :         const auto component_name = it->second;
     541         366 :         auto component_params = _action_factory.getValidParams(component_name);
     542             : 
     543             :         // We currently do not have build-type restrictions on this action that adds
     544             :         // action-components
     545             : 
     546             :         // See if the current Moose Object syntax belongs under this Action's block
     547         366 :         if (action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     548             :         )
     549             :         {
     550             :           // The logic for Components is a little simpler here for now because syntax like
     551             :           // Executioner/TimeIntegrator/type= do not exist for components
     552         366 :           std::string name;
     553         366 :           if (syntax[syntax.size() - 1] == '*')
     554             :           {
     555         366 :             size_t pos = syntax.size();
     556         366 :             name = syntax.substr(0, pos - 1) + component_name;
     557             :           }
     558         366 :           component_params.set<std::string>("type") = component_name;
     559             : 
     560        1098 :           auto lineinfo = _action_factory.getLineInfo(component_name, "list_component");
     561             :           // We add the parameters as for an object, because we want to fit them to be
     562             :           // added to json["AddActionComponentAction"]["subblock_types"]
     563         366 :           root.addParameters(syntax,
     564             :                              /*syntax_path*/ name,
     565             :                              /*is_type*/ false,
     566             :                              "AddActionComponentAction",
     567             :                              /*is_action=*/false,
     568             :                              &component_params,
     569             :                              lineinfo,
     570             :                              component_name);
     571         366 :         }
     572         366 :       }
     573             :     }
     574       35274 :   }
     575         183 :   root.addGlobal();
     576         183 : }
     577             : 
     578             : void
     579          20 : Builder::buildFullTree(const std::string & search_string)
     580             : {
     581          20 :   std::vector<std::pair<std::string, Syntax::ActionInfo>> all_names;
     582             : 
     583        2456 :   for (const auto & iter : _syntax.getAssociatedActions())
     584             :   {
     585        2436 :     Syntax::ActionInfo act_info = iter.second;
     586             :     /**
     587             :      * If the task is nullptr that means we need to figure out which task goes with this syntax for
     588             :      * the purpose of building the Moose Object part of the tree. We will figure this out by asking
     589             :      * the ActionFactory for the registration info.
     590             :      */
     591        2436 :     if (act_info._task == "")
     592        1892 :       act_info._task = _action_factory.getTaskName(act_info._action);
     593             : 
     594        2436 :     all_names.push_back(std::pair<std::string, Syntax::ActionInfo>(iter.first, act_info));
     595        2436 :   }
     596             : 
     597        2456 :   for (const auto & act_names : all_names)
     598             :   {
     599        2436 :     InputParameters action_obj_params = _action_factory.getValidParams(act_names.second._action);
     600        4872 :     _syntax_formatter->insertNode(
     601        2436 :         act_names.first, act_names.second._action, true, &action_obj_params);
     602             : 
     603        2436 :     const std::string & task = act_names.second._task;
     604        2436 :     std::string act_name = act_names.first;
     605             : 
     606             :     /**
     607             :      * We need to see if this action is inherited from MooseObjectAction. If it is, then we will
     608             :      * loop over all the Objects in MOOSE's Factory object to print them out if they have associated
     609             :      * bases matching the current task.
     610             :      */
     611        3892 :     if (action_obj_params.have_parameter<bool>("isObjectAction") &&
     612        3892 :         action_obj_params.get<bool>("isObjectAction"))
     613             :     {
     614     2261568 :       for (const auto & [moose_obj_name, obj] : _factory.registeredObjects())
     615             :       {
     616     2260112 :         auto moose_obj_params = obj->buildParameters();
     617             :         /**
     618             :          * Now that we know that this is a MooseObjectAction we need to see if it has been
     619             :          * restricted in any way by the user.
     620             :          */
     621     2260112 :         const std::vector<std::string> & buildable_types = action_obj_params.getBuildableTypes();
     622             : 
     623             :         // See if the current Moose Object syntax belongs under this Action's block
     624     2260112 :         if ((buildable_types.empty() || // Not restricted
     625           0 :              std::find(buildable_types.begin(), buildable_types.end(), moose_obj_name) !=
     626           0 :                  buildable_types.end()) && // Restricted but found
     627     2260112 :             moose_obj_params.hasBase() &&  // Has a registered base
     628     2260112 :             _syntax.verifyMooseObjectTask(moose_obj_params.getBase(),
     629     4520224 :                                           task) &&          // and that base is associated
     630       51930 :             action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     631             :         )
     632             :         {
     633       51930 :           std::string name;
     634       51930 :           size_t pos = 0;
     635       51930 :           bool is_action_params = false;
     636       51930 :           if (act_name[act_name.size() - 1] == '*')
     637             :           {
     638       46106 :             pos = act_name.size();
     639             : 
     640       46106 :             if (!action_obj_params.collapseSyntaxNesting())
     641       46106 :               name = act_name.substr(0, pos - 1) + moose_obj_name;
     642             :             else
     643             :             {
     644           0 :               name = act_name.substr(0, pos - 1) + "/<type>/" + moose_obj_name;
     645           0 :               is_action_params = true;
     646             :             }
     647             :           }
     648             :           else
     649             :           {
     650        5824 :             name = act_name + "/<type>/" + moose_obj_name;
     651             :           }
     652             : 
     653       51930 :           moose_obj_params.set<std::string>("type") = moose_obj_name;
     654             : 
     655       51930 :           _syntax_formatter->insertNode(name, moose_obj_name, is_action_params, &moose_obj_params);
     656       51930 :         }
     657     2260112 :       }
     658             :     }
     659        2436 :   }
     660             : 
     661             :   // Do not change to _console, we need this printed to the stdout in all cases
     662          20 :   Moose::out << _syntax_formatter->print(search_string) << std::flush;
     663          20 : }
     664             : 
     665             : void
     666     2408350 : Builder::extractParams(const hit::Node * const section_node, InputParameters & p)
     667             : {
     668             :   if (section_node)
     669             :     mooseAssert(section_node->type() == hit::NodeType::Section, "Node type should be a section");
     670             : 
     671    68215852 :   for (const auto & [name, par_unique_ptr] : p)
     672             :   {
     673    65807502 :     if (p.shouldIgnore(name))
     674        2804 :       continue;
     675             : 
     676    65804698 :     const hit::Node * param_node = nullptr;
     677             : 
     678   129007226 :     for (const auto & param_name : p.paramAliases(name))
     679             :     {
     680             :       // Check for parameters under the given section, if a section
     681             :       // node was provided
     682    65983641 :       if (section_node)
     683             :       {
     684    63638302 :         if (const auto section_param_node = section_node->find(param_name);
     685    66355120 :             section_param_node && section_param_node->type() == hit::NodeType::Field &&
     686     2716818 :             section_param_node->parent() == section_node)
     687     2716818 :           param_node = section_param_node;
     688             :       }
     689             :       // No node found within the given section, check [GlobalParams]
     690    65983641 :       if (!param_node && queryGlobalParamsNode())
     691             :       {
     692     4670852 :         if (const auto global_node = queryGlobalParamsNode()->find(param_name);
     693     4735289 :             global_node && global_node->type() == hit::NodeType::Field &&
     694       64437 :             global_node->parent() == queryGlobalParamsNode())
     695             :         {
     696             :           mooseAssert(isGlobal(*global_node), "Could not detect global-ness");
     697       64437 :           param_node = global_node;
     698             :         }
     699             :       }
     700             : 
     701             :       // Found it
     702    65983641 :       if (param_node)
     703             :       {
     704     2781255 :         const auto fullpath = param_node->fullpath();
     705     2781255 :         p.setHitNode(param_name, *param_node, {});
     706     2781255 :         p.set_attributes(param_name, false);
     707     2781255 :         _extracted_vars.insert(fullpath);
     708             : 
     709     2781255 :         const auto global = isGlobal(*param_node);
     710             : 
     711             :         // Check for deprecated parameters if the parameter is not a global param
     712     2781255 :         if (!global)
     713     2716818 :           if (const auto deprecated_message = p.queryDeprecatedParamMessage(param_name))
     714             :           {
     715        1786 :             std::string key = "";
     716        1786 :             if (const auto object_type_ptr = p.queryObjectType())
     717        1786 :               key += *object_type_ptr + "_";
     718        1786 :             key += param_name;
     719        1786 :             _deprecated_params.emplace(key, *deprecated_message);
     720     2718604 :           }
     721             : 
     722             :         // Private parameter, don't set
     723     2781255 :         if (p.isPrivate(param_name))
     724             :         {
     725             :           // Error if it isn't global, just once
     726         158 :           if (!global && std::find_if(_errors.begin(),
     727             :                                       _errors.end(),
     728           0 :                                       [&param_node](const auto & err)
     729         158 :                                       { return err.node == param_node; }) == _errors.end())
     730           8 :             _errors.emplace_back("parameter '" + fullpath + "' is private and cannot be set",
     731             :                                  param_node);
     732         142 :           continue;
     733         142 :         }
     734             : 
     735             :         // Set the value, capturing errors
     736     2781113 :         const auto param_field = dynamic_cast<const hit::Field *>(param_node);
     737             :         mooseAssert(param_field, "Is not a field");
     738     2781113 :         bool set_param = false;
     739             :         try
     740             :         {
     741     2781113 :           ParameterRegistry::get().set(*par_unique_ptr, *param_field);
     742     2781085 :           set_param = true;
     743             :         }
     744          28 :         catch (hit::Error & e)
     745             :         {
     746           0 :           _errors.emplace_back(e.message, param_node);
     747           0 :         }
     748          28 :         catch (std::exception & e)
     749             :         {
     750          28 :           _errors.emplace_back(e.what(), param_node);
     751          28 :         }
     752             : 
     753             :         // Break if we failed here and don't perform extra checks
     754     2781113 :         if (!set_param)
     755          28 :           break;
     756             : 
     757             :         // Special setup for vector<VariableName>
     758     2781085 :         if (auto cast_par = dynamic_cast<InputParameters::Parameter<std::vector<VariableName>> *>(
     759     5562170 :                 par_unique_ptr.get()))
     760       79174 :           if (const auto error = p.setupVariableNames(cast_par->set(), *param_node, {}))
     761       79174 :             _errors.emplace_back(*error, param_node);
     762             : 
     763             :         // Possibly perform a range check if this parameter has one
     764     2781085 :         if (p.isRangeChecked(param_node->path()))
     765       14873 :           if (const auto error = p.parameterRangeCheck(
     766       14873 :                   *par_unique_ptr, param_node->fullpath(), param_node->path(), true))
     767       14873 :             _errors.emplace_back(error->second, param_node);
     768             : 
     769             :         // Don't check the other alises since we've found it
     770     2781085 :         break;
     771     2781255 :       }
     772    65804698 :     }
     773             : 
     774             :     // Special casing when the parameter was not found
     775    65804698 :     if (!param_node)
     776             :     {
     777             :       // In the case where we have OutFileName but it wasn't actually found in the input filename,
     778             :       // we will populate it with the actual parsed filename which is available here in the
     779             :       // parser.
     780    63023443 :       if (auto out_par_ptr =
     781    63023443 :               dynamic_cast<InputParameters::Parameter<OutFileBase> *>(par_unique_ptr.get()))
     782             :       {
     783           0 :         const auto input_file_name = getPrimaryFileName();
     784             :         mooseAssert(input_file_name.size(), "Input Filename is empty");
     785           0 :         const auto pos = input_file_name.find_last_of('.');
     786             :         mooseAssert(pos != std::string::npos, "Unable to determine suffix of input file name");
     787           0 :         out_par_ptr->set() = input_file_name.substr(0, pos) + "_out";
     788           0 :         p.set_attributes(name, false);
     789           0 :       }
     790             :     }
     791             :   }
     792             : 
     793             :   // See if there are any auto build vectors that need to be created
     794     2408352 :   for (const auto & [param_name, base_name_num_repeat_pair] : p.getAutoBuildVectors())
     795             :   {
     796           2 :     const auto & [base_name, num_repeat] = base_name_num_repeat_pair;
     797             :     // We'll autogenerate values iff the requested vector is not valid but both the base and
     798             :     // number are valid
     799           2 :     if (!p.isParamValid(param_name) && p.isParamValid(base_name) && p.isParamValid(num_repeat))
     800             :     {
     801           2 :       const auto vec_size = p.get<unsigned int>(num_repeat);
     802           2 :       const std::string & name = p.get<std::string>(base_name);
     803             : 
     804           2 :       std::vector<VariableName> variable_names(vec_size);
     805           6 :       for (const auto i : index_range(variable_names))
     806             :       {
     807           4 :         std::ostringstream oss;
     808           4 :         oss << name << i;
     809           4 :         variable_names[i] = oss.str();
     810           4 :       }
     811             : 
     812             :       // Finally set the autogenerated vector into the InputParameters object
     813           2 :       p.set<std::vector<VariableName>>(param_name) = variable_names;
     814           2 :     }
     815     2408350 :   }
     816     2408350 : }
     817             : 
     818             : void
     819       87166 : Builder::extractParams(const std::string & prefix, InputParameters & p)
     820             : {
     821       87166 :   const auto node = _root.find(prefix);
     822       87166 :   extractParams((node && node->type() == hit::NodeType::Section) ? node : nullptr, p);
     823       87166 : }
     824             : 
     825             : bool
     826     2781255 : Builder::isGlobal(const hit::Node & node) const
     827             : {
     828     2781255 :   const auto global_params_node = queryGlobalParamsNode();
     829     2781255 :   return global_params_node && node.parent() == global_params_node;
     830             : }
     831             : 
     832             : const hit::Node *
     833    70783367 : Builder::queryGlobalParamsNode() const
     834             : {
     835    70783367 :   if (!_global_params_node)
     836             :   {
     837      276216 :     const auto syntax = _syntax.getSyntaxByAction("GlobalParamsAction");
     838             :     mooseAssert(syntax.size() == 1, "Unexpected GlobalParamsAction syntax size");
     839       69054 :     _global_params_node = _root.find(syntax.front());
     840       69054 :   }
     841    70783367 :   return *_global_params_node;
     842             : }
     843             : 
     844             : } // end of namespace Moose

Generated by: LCOV version 1.14