LCOV - code coverage report
Current view: top level - src/parser - Builder.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 388 413 93.9 %
Date: 2026-05-29 20:35:17 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     1214434 : isSectionActive(const hit::Node & node)
      46             : {
      47     1214434 :   const hit::Node * n = &node;
      48     4020053 :   while (n)
      49             :   {
      50     2900285 :     const auto section = n->parent();
      51     2900285 :     if (section)
      52             :     {
      53             :       // only check current level, not nested ones
      54     3561034 :       if (const auto active = section->find("active");
      55     1780517 :           active && active->type() == hit::NodeType::Field && active->parent() == section)
      56             :       {
      57      165884 :         const auto vars = active->param<std::vector<std::string>>();
      58       82942 :         return std::find_if(vars.begin(),
      59             :                             vars.end(),
      60      116718 :                             [&n](const auto & var)
      61      282602 :                             { return n->path() == hit::pathNorm(var); }) != vars.end();
      62       82942 :       }
      63             :       // only check current level, not nested ones
      64     3395150 :       if (const auto inactive = section->find("inactive");
      65     1697575 :           inactive && inactive->type() == hit::NodeType::Field && inactive->parent() == section)
      66             :       {
      67       23448 :         const auto vars = inactive->param<std::vector<std::string>>();
      68       11724 :         return std::find_if(vars.begin(),
      69             :                             vars.end(),
      70       15309 :                             [&n](const auto & var)
      71       38757 :                             { return n->path() == hit::pathNorm(var); }) == vars.end();
      72       11724 :       }
      73             :     }
      74     2805619 :     n = section;
      75             :   }
      76     1119768 :   return true;
      77             : }
      78             : 
      79             : std::vector<std::string>
      80         104 : findSimilar(const std::string & param, const std::vector<std::string> & options)
      81             : {
      82         104 :   std::vector<std::string> candidates;
      83         104 :   if (options.size() == 0)
      84          10 :     return candidates;
      85             : 
      86          94 :   int mindist = MooseUtils::levenshteinDist(options[0], param);
      87        3427 :   for (const auto & opt : options)
      88             :   {
      89        3333 :     const int dist = MooseUtils::levenshteinDist(opt, param);
      90             :     // magic number heuristics to get similarity distance cutoff
      91        3333 :     const int dist_cutoff = 1 + param.size() / 5;
      92        3333 :     if (dist > dist_cutoff || dist > mindist)
      93        3330 :       continue;
      94             : 
      95           3 :     if (dist < mindist)
      96             :     {
      97           3 :       mindist = dist;
      98           3 :       candidates.clear();
      99             :     }
     100           3 :     candidates.push_back(opt);
     101             :   }
     102          94 :   return candidates;
     103           0 : }
     104             : 
     105       66995 : Builder::Builder(MooseApp & app, ActionWarehouse & action_wh, Parser & parser)
     106             :   : ConsoleStreamInterface(app),
     107       66995 :     _app(app),
     108      133990 :     _factory(app.getFactory()),
     109       66995 :     _action_wh(action_wh),
     110       66995 :     _action_factory(app.getActionFactory()),
     111       66995 :     _syntax(_action_wh.syntax()),
     112       66995 :     _parser(parser),
     113       66995 :     _root(_parser.getRoot()),
     114      133990 :     _syntax_formatter(nullptr)
     115             : {
     116       66995 : }
     117             : 
     118       62876 : Builder::~Builder() {}
     119             : 
     120             : InputParameters
     121     9819197 : Builder::validParams()
     122             : {
     123     9819197 :   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    29457591 :   params.addParam<std::vector<std::string>>(
     130             :       "active",
     131    29457591 :       std::vector<std::string>({"__all__"}),
     132             :       "If specified only the blocks named will be visited and made active");
     133    19638394 :   params.addParam<std::vector<std::string>>(
     134             :       "inactive",
     135    19638394 :       std::vector<std::string>(),
     136             :       "If specified blocks matching these identifiers will be skipped.");
     137             : 
     138     9819197 :   return params;
     139    29457591 : }
     140             : 
     141             : std::vector<std::string>
     142         104 : Builder::listValidParams(std::string & section_name)
     143             : {
     144             :   bool dummy;
     145         104 :   std::string registered_identifier = _syntax.isAssociated(section_name, &dummy);
     146         104 :   auto iters = _syntax.getActions(registered_identifier);
     147             : 
     148         104 :   std::vector<std::string> paramlist;
     149         306 :   for (auto it = iters.first; it != iters.second; ++it)
     150             :   {
     151         202 :     auto params = _action_factory.getValidParams(it->second._action);
     152        3535 :     for (const auto & it : params)
     153        3333 :       paramlist.push_back(it.first);
     154         202 :   }
     155         208 :   return paramlist;
     156         104 : }
     157             : 
     158             : void
     159     2509840 : 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     2580108 :   if (!_used.count(fullpath) && nodename != "active" && nodename != "inactive" &&
     165     2580108 :       isSectionActive(*n) && n->line() > 0)
     166             :   {
     167         104 :     auto section_name = fullpath.substr(0, fullpath.rfind("/"));
     168         104 :     const auto paramlist = _builder.listValidParams(section_name);
     169         104 :     const auto candidates = findSimilar(nodename, paramlist);
     170         104 :     if (candidates.size() > 0)
     171           3 :       errors.emplace_back(
     172           6 :           "unused parameter '" + fullpath + "'; did you mean '" + candidates[0] + "'?", n);
     173             :     else
     174         101 :       errors.emplace_back("unused parameter '" + fullpath + "'", n);
     175         104 :   }
     176     2509840 : }
     177             : 
     178             : std::string
     179        2470 : Builder::getPrimaryFileName(bool strip_leading_path) const
     180             : {
     181        2470 :   const auto path = _parser.getLastInputFilePath();
     182        4940 :   return (strip_leading_path ? path.filename() : std::filesystem::absolute(path)).string();
     183        2470 : }
     184             : 
     185             : void
     186     1161308 : Builder::walkRaw(std::string /*fullpath*/, std::string /*nodepath*/, hit::Node * n)
     187             : {
     188     1161308 :   InputParameters active_list_params = Action::validParams();
     189     1161308 :   InputParameters params = EmptyAction::validParams();
     190             : 
     191     1161308 :   const std::string section_name = n->fullpath();
     192     1161308 :   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     1161308 :   if (!isSectionActive(*n))
     197       15221 :     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     1146087 :   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     1146087 :   if (const auto [begin, end] = _syntax.getActions(registered_identifier); begin == end)
     207             :   {
     208           5 :     _errors.emplace_back(
     209          10 :         "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           5 :     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     1146082 :   std::set<const Syntax::ActionInfo *> processed_actions;
     219             :   while (true)
     220             :   {
     221             :     // search for an unprocessed action
     222     2959162 :     auto [begin, end] = _syntax.getActions(registered_identifier);
     223     2959162 :     auto it = begin;
     224     6020973 :     for (; it != end && processed_actions.count(&it->second); ++it)
     225             :       ;
     226             : 
     227             :     // no more unprocessed actions
     228     2959162 :     if (it == end)
     229     1145989 :       break;
     230             : 
     231             :     // mark action as processed
     232     1813173 :     processed_actions.insert(&it->second);
     233             : 
     234     1813173 :     if (is_parent)
     235      334831 :       continue;
     236     1478342 :     if (_syntax.isDeprecatedSyntax(registered_identifier))
     237           0 :       mooseDeprecated(
     238           0 :           hit::errormsg(n, _syntax.deprecatedActionSyntaxMessage(registered_identifier)));
     239             : 
     240     1478342 :     params = _action_factory.getValidParams(it->second._action);
     241     2956684 :     params.set<ActionWarehouse *>("awh") = &_action_wh;
     242     1478342 :     params.setHitNode(*n, {});
     243             : 
     244     1478342 :     extractParams(n, params);
     245             : 
     246             :     // Add the parsed syntax to the parameters object for consumption by the Action
     247     4435026 :     params.set<std::string>("task") = it->second._task;
     248     1478342 :     params.set<std::string>("registered_identifier") = registered_identifier;
     249             : 
     250     1478342 :     if (!(params.have_parameter<bool>("isObjectAction") && params.get<bool>("isObjectAction")))
     251     1478840 :       params.set<std::vector<std::string>>("control_tags")
     252      739420 :           .push_back(MooseUtils::baseName(curr_identifier));
     253             : 
     254             :     // Create the Action
     255             :     std::shared_ptr<Action> action_obj =
     256     1478342 :         _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     1478252 :           std::dynamic_pointer_cast<MooseObjectAction>(action_obj);
     262     1478252 :       if (object_action)
     263             :       {
     264      738351 :         auto & object_params = object_action->getObjectParams();
     265      738351 :         object_params.setHitNode(*n, {});
     266      738351 :         extractParams(n, object_params);
     267     1476702 :         object_params.set<std::vector<std::string>>("control_tags")
     268      738351 :             .push_back(MooseUtils::baseName(curr_identifier));
     269             :       }
     270             :       // extract the Component params if necessary
     271             :       std::shared_ptr<AddActionComponentAction> component_action =
     272     1478252 :           std::dynamic_pointer_cast<AddActionComponentAction>(action_obj);
     273     1478252 :       if (component_action)
     274             :       {
     275         550 :         auto & component_params = component_action->getComponentParams();
     276         550 :         component_params.setHitNode(*n, {});
     277         550 :         extractParams(n, component_params);
     278        1100 :         component_params.set<std::vector<std::string>>("control_tags")
     279         550 :             .push_back(MooseUtils::baseName(curr_identifier));
     280             :       }
     281     1478252 :     }
     282             : 
     283             :     // add it to the warehouse
     284     1478252 :     _action_wh.addActionBlock(action_obj);
     285     3291329 :   }
     286     1206898 : }
     287             : 
     288             : void
     289     1161305 : Builder::walk(const std::string & fullpath, const std::string & nodepath, hit::Node * n)
     290             : {
     291             :   // skip sections that were manually processed first.
     292     1161305 :   if (std::find(_secs_need_first.begin(), _secs_need_first.end(), nodepath) !=
     293     2322610 :       _secs_need_first.end())
     294       28776 :     return;
     295             : 
     296     1132529 :   walkRaw(fullpath, nodepath, n);
     297             : }
     298             : 
     299             : void
     300       66116 : Builder::build()
     301             : {
     302             :   // Pull in extracted variables from the parser (fparse stuff)
     303       66116 :   _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      198348 :   const auto need_action_syntax_first = [this](const auto & action_name)
     308             :   {
     309      793392 :     const auto syntax = _syntax.getSyntaxByAction(action_name);
     310             :     mooseAssert(syntax.size(), "Empty syntax");
     311      198348 :     std::copy(syntax.begin(), syntax.end(), std::back_inserter(_secs_need_first));
     312      264464 :   };
     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       66116 :   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       66116 :   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       66116 :   need_action_syntax_first("DynamicObjectRegistrationAction");
     328             : 
     329             :   // Walk all the sections extracting paramters from each into InputParameters objects
     330      264464 :   for (const auto & sec : _secs_need_first)
     331      198348 :     if (auto n = _root.find(sec))
     332       28779 :       walkRaw(n->parent()->fullpath(), n->path(), n);
     333             : 
     334             :   // Walk for the remainder
     335       66116 :   _root.walk(this, hit::NodeType::Section);
     336             : 
     337             :   // Warn for all deprecated parameters together
     338       66023 :   if (_deprecated_params.size())
     339             :   {
     340         749 :     std::vector<std::string> messages;
     341        1643 :     for (const auto & key_message_pair : _deprecated_params)
     342         894 :       messages.push_back(key_message_pair.second);
     343         749 :     const auto message = MooseUtils::stringJoin(messages, "\n\n");
     344             : 
     345         749 :     moose::internal::mooseDeprecatedStream(Moose::out, false, true, false, message + "\n\n");
     346         743 :   }
     347             : 
     348       66017 :   if (_errors.size())
     349          73 :     _parser.parseError(_errors);
     350       65946 : }
     351             : 
     352             : // Checks the input and the way it has been used and emits any errors/warnings.
     353             : // This has to be a separate function because for we don't know if some parameters were unused
     354             : // until all the multiapps/subapps have been fully initialized - which isn't complete until
     355             : // *after* all the other member functions on Parser have been run.  So this is here to be
     356             : // externally called at the right time.
     357             : void
     358       62339 : Builder::errorCheck(const Parallel::Communicator & comm, bool warn_unused, bool err_unused)
     359             : {
     360             :   // Nothing to do here
     361       62339 :   if (!warn_unused && !err_unused)
     362           0 :     return;
     363             : 
     364       62339 :   std::vector<hit::ErrorMessage> messages;
     365             : 
     366       62339 :   if (_parser.queryCommandLineRoot())
     367             :   {
     368       62337 :     UnusedWalker uw(_extracted_vars, *this);
     369       62337 :     _parser.getCommandLineRoot().walk(&uw);
     370       62337 :     Parser::appendErrorMessages(messages, uw.errors);
     371       62337 :   }
     372             : 
     373             :   {
     374       62339 :     UnusedWalker uw(_extracted_vars, *this);
     375       62339 :     _root.walk(&uw);
     376       62339 :     Parser::appendErrorMessages(messages, uw.errors);
     377       62339 :   }
     378             : 
     379       62342 :   for (const auto & arg : _app.commandLine()->unusedHitParams(comm))
     380       62342 :     messages.emplace_back("unused command line parameter '" + arg + "'");
     381             : 
     382       62339 :   if (messages.size())
     383             :   {
     384          74 :     const auto message = _parser.joinErrorMessages(messages);
     385          74 :     if (warn_unused)
     386          44 :       mooseUnused(message);
     387          74 :     if (err_unused)
     388             :     {
     389          30 :       if (_parser.getThrowOnError())
     390           4 :         _parser.parseError(messages);
     391             :       else
     392          28 :         mooseError(
     393          28 :             message +
     394             :             "\n\nAppend --allow-unused (or -w) on the command line to ignore unused parameters.");
     395             :     }
     396          46 :   }
     397       62311 : }
     398             : 
     399             : void
     400          18 : Builder::initSyntaxFormatter(SyntaxFormatterType type, bool dump_mode)
     401             : {
     402          18 :   switch (type)
     403             :   {
     404           0 :     case INPUT_FILE:
     405           0 :       _syntax_formatter = std::make_unique<InputFileFormatter>(dump_mode);
     406           0 :       break;
     407          18 :     case YAML:
     408          18 :       _syntax_formatter = std::make_unique<YAMLFormatter>(dump_mode);
     409          18 :       break;
     410           0 :     default:
     411           0 :       mooseError("Unrecognized Syntax Formatter requested");
     412             :       break;
     413             :   }
     414          18 : }
     415             : 
     416             : void
     417          24 : Builder::buildJsonSyntaxTree(JsonSyntaxTree & root) const
     418             : {
     419          24 :   std::vector<std::pair<std::string, Syntax::ActionInfo>> all_names;
     420             : 
     421         672 :   for (const auto & iter : _syntax.getAssociatedTypes())
     422         648 :     root.addSyntaxType(iter.first, iter.second);
     423             : 
     424             :   // Build a list of all the actions appearing in the syntax
     425        2907 :   for (const auto & iter : _syntax.getAssociatedActions())
     426             :   {
     427        2883 :     Syntax::ActionInfo act_info = iter.second;
     428             :     /**
     429             :      * If the task is nullptr that means we need to figure out which task goes with this syntax for
     430             :      * the purpose of building the Moose Object part of the tree. We will figure this out by asking
     431             :      * the ActionFactory for the registration info.
     432             :      */
     433        2883 :     if (act_info._task == "")
     434        2241 :       act_info._task = _action_factory.getTaskName(act_info._action);
     435             : 
     436        2883 :     all_names.push_back(std::make_pair(iter.first, act_info));
     437        2883 :   }
     438             : 
     439             :   // Add all the actions to the JSON tree, except for ActionComponents (below)
     440        2907 :   for (const auto & act_names : all_names)
     441             :   {
     442        2883 :     const auto & act_info = act_names.second;
     443        2883 :     const std::string & action = act_info._action;
     444        2883 :     const std::string & task = act_info._task;
     445        2883 :     const std::string syntax = act_names.first;
     446        2883 :     InputParameters action_obj_params = _action_factory.getValidParams(action);
     447        5766 :     bool params_added = root.addParameters("",
     448             :                                            syntax,
     449             :                                            false,
     450             :                                            action,
     451             :                                            true,
     452             :                                            &action_obj_params,
     453       11532 :                                            _syntax.getLineInfo(syntax, action, ""),
     454             :                                            "");
     455             : 
     456        2883 :     if (params_added)
     457             :     {
     458        1746 :       auto tasks = _action_factory.getTasksByAction(action);
     459        4494 :       for (auto & t : tasks)
     460             :       {
     461        2748 :         auto info = _action_factory.getLineInfo(action, t);
     462        2748 :         root.addActionTask(syntax, action, t, info);
     463        2748 :       }
     464        1746 :     }
     465             : 
     466             :     /**
     467             :      * We need to see if this action is inherited from MooseObjectAction. If it is, then we will
     468             :      * loop over all the Objects in MOOSE's Factory object to print them out if they have associated
     469             :      * bases matching the current task.
     470             :      */
     471        4626 :     if (action_obj_params.have_parameter<bool>("isObjectAction") &&
     472        4626 :         action_obj_params.get<bool>("isObjectAction"))
     473             :     {
     474     2906688 :       for (auto & [moose_obj_name, obj] : _factory.registeredObjects())
     475             :       {
     476     2904945 :         auto moose_obj_params = obj->buildParameters();
     477             :         // Now that we know that this is a MooseObjectAction we need to see if it has been
     478             :         // restricted
     479             :         // in any way by the user.
     480     2904945 :         const std::vector<std::string> & buildable_types = action_obj_params.getBuildableTypes();
     481             : 
     482             :         // See if the current Moose Object syntax belongs under this Action's block
     483     2904945 :         if ((buildable_types.empty() || // Not restricted
     484           0 :              std::find(buildable_types.begin(), buildable_types.end(), moose_obj_name) !=
     485           0 :                  buildable_types.end()) && // Restricted but found
     486     2904945 :             moose_obj_params.hasBase() &&  // Has a registered base
     487     2904945 :             _syntax.verifyMooseObjectTask(moose_obj_params.getBase(),
     488     5809890 :                                           task) &&          // and that base is associated
     489       63401 :             action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     490             :         )
     491             :         {
     492       63401 :           std::string name;
     493       63401 :           size_t pos = 0;
     494       63401 :           bool is_action_params = false;
     495       63401 :           bool is_type = false;
     496       63401 :           if (syntax[syntax.size() - 1] == '*')
     497             :           {
     498       55897 :             pos = syntax.size();
     499             : 
     500       55897 :             if (!action_obj_params.collapseSyntaxNesting())
     501       55897 :               name = syntax.substr(0, pos - 1) + moose_obj_name;
     502             :             else
     503             :             {
     504           0 :               name = syntax.substr(0, pos - 1) + "/<type>/" + moose_obj_name;
     505           0 :               is_action_params = true;
     506             :             }
     507             :           }
     508             :           else
     509             :           {
     510        7504 :             name = syntax + "/<type>/" + moose_obj_name;
     511        7504 :             is_type = true;
     512             :           }
     513       63401 :           moose_obj_params.set<std::string>("type") = moose_obj_name;
     514             : 
     515       63401 :           auto lineinfo = _factory.getLineInfo(moose_obj_name);
     516       63401 :           std::string classname = _factory.associatedClassName(moose_obj_name);
     517       63401 :           root.addParameters(syntax,
     518             :                              name,
     519             :                              is_type,
     520             :                              moose_obj_name,
     521             :                              is_action_params,
     522             :                              &moose_obj_params,
     523             :                              lineinfo,
     524             :                              classname);
     525       63401 :         }
     526     2904945 :       }
     527             : 
     528             :       // Same thing for ActionComponents, which, while they are not MooseObjects, should behave
     529             :       // similarly syntax-wise
     530        1743 :       if (syntax != "ActionComponents/*")
     531        1719 :         continue;
     532             : 
     533          48 :       auto iters = _action_factory.getActionsByTask("list_component");
     534             : 
     535          96 :       for (auto it = iters.first; it != iters.second; ++it)
     536             :       {
     537             :         // Get the name and parameters
     538          72 :         const auto component_name = it->second;
     539          72 :         auto component_params = _action_factory.getValidParams(component_name);
     540             : 
     541             :         // We currently do not have build-type restrictions on this action that adds
     542             :         // action-components
     543             : 
     544             :         // See if the current Moose Object syntax belongs under this Action's block
     545          72 :         if (action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     546             :         )
     547             :         {
     548             :           // The logic for Components is a little simpler here for now because syntax like
     549             :           // Executioner/TimeIntegrator/type= do not exist for components
     550          72 :           std::string name;
     551          72 :           if (syntax[syntax.size() - 1] == '*')
     552             :           {
     553          72 :             size_t pos = syntax.size();
     554          72 :             name = syntax.substr(0, pos - 1) + component_name;
     555             :           }
     556          72 :           component_params.set<std::string>("type") = component_name;
     557             : 
     558         216 :           auto lineinfo = _action_factory.getLineInfo(component_name, "list_component");
     559             :           // We add the parameters as for an object, because we want to fit them to be
     560             :           // added to json["AddActionComponentAction"]["subblock_types"]
     561          72 :           root.addParameters(syntax,
     562             :                              /*syntax_path*/ name,
     563             :                              /*is_type*/ false,
     564             :                              "AddActionComponentAction",
     565             :                              /*is_action=*/false,
     566             :                              &component_params,
     567             :                              lineinfo,
     568             :                              component_name);
     569          72 :         }
     570          72 :       }
     571             :     }
     572        4602 :   }
     573          24 :   root.addGlobal();
     574          24 : }
     575             : 
     576             : void
     577          18 : Builder::buildFullTree(const std::string & search_string)
     578             : {
     579          18 :   std::vector<std::pair<std::string, Syntax::ActionInfo>> all_names;
     580             : 
     581        2214 :   for (const auto & iter : _syntax.getAssociatedActions())
     582             :   {
     583        2196 :     Syntax::ActionInfo act_info = iter.second;
     584             :     /**
     585             :      * If the task is nullptr that means we need to figure out which task goes with this syntax for
     586             :      * the purpose of building the Moose Object part of the tree. We will figure this out by asking
     587             :      * the ActionFactory for the registration info.
     588             :      */
     589        2196 :     if (act_info._task == "")
     590        1710 :       act_info._task = _action_factory.getTaskName(act_info._action);
     591             : 
     592        2196 :     all_names.push_back(std::pair<std::string, Syntax::ActionInfo>(iter.first, act_info));
     593        2196 :   }
     594             : 
     595        2214 :   for (const auto & act_names : all_names)
     596             :   {
     597        2196 :     InputParameters action_obj_params = _action_factory.getValidParams(act_names.second._action);
     598        4392 :     _syntax_formatter->insertNode(
     599        2196 :         act_names.first, act_names.second._action, true, &action_obj_params);
     600             : 
     601        2196 :     const std::string & task = act_names.second._task;
     602        2196 :     std::string act_name = act_names.first;
     603             : 
     604             :     /**
     605             :      * We need to see if this action is inherited from MooseObjectAction. If it is, then we will
     606             :      * loop over all the Objects in MOOSE's Factory object to print them out if they have associated
     607             :      * bases matching the current task.
     608             :      */
     609        3510 :     if (action_obj_params.have_parameter<bool>("isObjectAction") &&
     610        3510 :         action_obj_params.get<bool>("isObjectAction"))
     611             :     {
     612     2191248 :       for (const auto & [moose_obj_name, obj] : _factory.registeredObjects())
     613             :       {
     614     2189934 :         auto moose_obj_params = obj->buildParameters();
     615             :         /**
     616             :          * Now that we know that this is a MooseObjectAction we need to see if it has been
     617             :          * restricted in any way by the user.
     618             :          */
     619     2189934 :         const std::vector<std::string> & buildable_types = action_obj_params.getBuildableTypes();
     620             : 
     621             :         // See if the current Moose Object syntax belongs under this Action's block
     622     2189934 :         if ((buildable_types.empty() || // Not restricted
     623           0 :              std::find(buildable_types.begin(), buildable_types.end(), moose_obj_name) !=
     624           0 :                  buildable_types.end()) && // Restricted but found
     625     2189934 :             moose_obj_params.hasBase() &&  // Has a registered base
     626     2189934 :             _syntax.verifyMooseObjectTask(moose_obj_params.getBase(),
     627     4379868 :                                           task) &&          // and that base is associated
     628       48258 :             action_obj_params.mooseObjectSyntaxVisibility() // and the Action says it's visible
     629             :         )
     630             :         {
     631       48258 :           std::string name;
     632       48258 :           size_t pos = 0;
     633       48258 :           bool is_action_params = false;
     634       48258 :           if (act_name[act_name.size() - 1] == '*')
     635             :           {
     636       42630 :             pos = act_name.size();
     637             : 
     638       42630 :             if (!action_obj_params.collapseSyntaxNesting())
     639       42630 :               name = act_name.substr(0, pos - 1) + moose_obj_name;
     640             :             else
     641             :             {
     642           0 :               name = act_name.substr(0, pos - 1) + "/<type>/" + moose_obj_name;
     643           0 :               is_action_params = true;
     644             :             }
     645             :           }
     646             :           else
     647             :           {
     648        5628 :             name = act_name + "/<type>/" + moose_obj_name;
     649             :           }
     650             : 
     651       48258 :           moose_obj_params.set<std::string>("type") = moose_obj_name;
     652             : 
     653       48258 :           _syntax_formatter->insertNode(name, moose_obj_name, is_action_params, &moose_obj_params);
     654       48258 :         }
     655     2189934 :       }
     656             :     }
     657        2196 :   }
     658             : 
     659             :   // Do not change to _console, we need this printed to the stdout in all cases
     660          18 :   Moose::out << _syntax_formatter->print(search_string) << std::flush;
     661          18 : }
     662             : 
     663             : void
     664     2299057 : Builder::extractParams(const hit::Node * const section_node, InputParameters & p)
     665             : {
     666             :   if (section_node)
     667             :     mooseAssert(section_node->type() == hit::NodeType::Section, "Node type should be a section");
     668             : 
     669    64912259 :   for (const auto & [name, par_unique_ptr] : p)
     670             :   {
     671    62613202 :     if (p.shouldIgnore(name))
     672        2670 :       continue;
     673             : 
     674    62610532 :     const hit::Node * param_node = nullptr;
     675             : 
     676   122592281 :     for (const auto & param_name : p.paramAliases(name))
     677             :     {
     678             :       // Check for parameters under the given section, if a section
     679             :       // node was provided
     680    62615784 :       if (section_node)
     681             :       {
     682    60472947 :         if (const auto section_param_node = section_node->find(param_name);
     683    63050105 :             section_param_node && section_param_node->type() == hit::NodeType::Field &&
     684     2577158 :             section_param_node->parent() == section_node)
     685     2577158 :           param_node = section_param_node;
     686             :       }
     687             :       // No node found within the given section, check [GlobalParams]
     688    62615784 :       if (!param_node && queryGlobalParamsNode())
     689             :       {
     690     3956325 :         if (const auto global_node = queryGlobalParamsNode()->find(param_name);
     691     4013330 :             global_node && global_node->type() == hit::NodeType::Field &&
     692       57005 :             global_node->parent() == queryGlobalParamsNode())
     693             :         {
     694             :           mooseAssert(isGlobal(*global_node), "Could not detect global-ness");
     695       57005 :           param_node = global_node;
     696             :         }
     697             :       }
     698             : 
     699             :       // Found it
     700    62615784 :       if (param_node)
     701             :       {
     702     2634163 :         const auto fullpath = param_node->fullpath();
     703     2634163 :         p.setHitNode(param_name, *param_node, {});
     704     2634163 :         p.set_attributes(param_name, false);
     705     2634163 :         _extracted_vars.insert(fullpath);
     706             : 
     707     2634163 :         const auto global = isGlobal(*param_node);
     708             : 
     709             :         // Check for deprecated parameters if the parameter is not a global param
     710     2634163 :         if (!global)
     711     2577158 :           if (const auto deprecated_message = p.queryDeprecatedParamMessage(param_name))
     712             :           {
     713        1024 :             std::string key = "";
     714        1024 :             if (const auto object_type_ptr = p.queryObjectType())
     715        1024 :               key += *object_type_ptr + "_";
     716        1024 :             key += param_name;
     717        1024 :             _deprecated_params.emplace(key, *deprecated_message);
     718     2578182 :           }
     719             : 
     720             :         // Private parameter, don't set
     721     2634163 :         if (p.isPrivate(param_name))
     722             :         {
     723             :           // Error if it isn't global, just once
     724         140 :           if (!global && std::find_if(_errors.begin(),
     725             :                                       _errors.end(),
     726           0 :                                       [&param_node](const auto & err)
     727         140 :                                       { return err.node == param_node; }) == _errors.end())
     728           6 :             _errors.emplace_back("parameter '" + fullpath + "' is private and cannot be set",
     729             :                                  param_node);
     730         128 :           continue;
     731         128 :         }
     732             : 
     733             :         // Set the value, capturing errors
     734     2634035 :         const auto param_field = dynamic_cast<const hit::Field *>(param_node);
     735             :         mooseAssert(param_field, "Is not a field");
     736     2634035 :         bool set_param = false;
     737             :         try
     738             :         {
     739     2634035 :           ParameterRegistry::get().set(*par_unique_ptr, *param_field);
     740     2634014 :           set_param = true;
     741             :         }
     742          21 :         catch (hit::Error & e)
     743             :         {
     744           0 :           _errors.emplace_back(e.message, param_node);
     745           0 :         }
     746          21 :         catch (std::exception & e)
     747             :         {
     748          21 :           _errors.emplace_back(e.what(), param_node);
     749          21 :         }
     750             : 
     751             :         // Break if we failed here and don't perform extra checks
     752     2634035 :         if (!set_param)
     753          21 :           break;
     754             : 
     755             :         // Special setup for vector<VariableName>
     756     2634014 :         if (auto cast_par = dynamic_cast<InputParameters::Parameter<std::vector<VariableName>> *>(
     757     5268028 :                 par_unique_ptr.get()))
     758       77502 :           if (const auto error = p.setupVariableNames(cast_par->set(), *param_node, {}))
     759       77502 :             _errors.emplace_back(*error, param_node);
     760             : 
     761             :         // Possibly perform a range check if this parameter has one
     762     2634014 :         if (p.isRangeChecked(param_node->path()))
     763       16575 :           if (const auto error = p.parameterRangeCheck(
     764       16575 :                   *par_unique_ptr, param_node->fullpath(), param_node->path(), true))
     765       16575 :             _errors.emplace_back(error->second, param_node);
     766             : 
     767             :         // Don't check the other alises since we've found it
     768     2634014 :         break;
     769     2634163 :       }
     770    62610532 :     }
     771             : 
     772             :     // Special casing when the parameter was not found
     773    62610532 :     if (!param_node)
     774             :     {
     775             :       // In the case where we have OutFileName but it wasn't actually found in the input filename,
     776             :       // we will populate it with the actual parsed filename which is available here in the
     777             :       // parser.
     778    59976369 :       if (auto out_par_ptr =
     779    59976369 :               dynamic_cast<InputParameters::Parameter<OutFileBase> *>(par_unique_ptr.get()))
     780             :       {
     781           0 :         const auto input_file_name = getPrimaryFileName();
     782             :         mooseAssert(input_file_name.size(), "Input Filename is empty");
     783           0 :         const auto pos = input_file_name.find_last_of('.');
     784             :         mooseAssert(pos != std::string::npos, "Unable to determine suffix of input file name");
     785           0 :         out_par_ptr->set() = input_file_name.substr(0, pos) + "_out";
     786           0 :         p.set_attributes(name, false);
     787           0 :       }
     788             :     }
     789             :   }
     790             : 
     791             :   // See if there are any auto build vectors that need to be created
     792     2299059 :   for (const auto & [param_name, base_name_num_repeat_pair] : p.getAutoBuildVectors())
     793             :   {
     794           2 :     const auto & [base_name, num_repeat] = base_name_num_repeat_pair;
     795             :     // We'll autogenerate values iff the requested vector is not valid but both the base and
     796             :     // number are valid
     797           2 :     if (!p.isParamValid(param_name) && p.isParamValid(base_name) && p.isParamValid(num_repeat))
     798             :     {
     799           2 :       const auto vec_size = p.get<unsigned int>(num_repeat);
     800           2 :       const std::string & name = p.get<std::string>(base_name);
     801             : 
     802           2 :       std::vector<VariableName> variable_names(vec_size);
     803           6 :       for (const auto i : index_range(variable_names))
     804             :       {
     805           4 :         std::ostringstream oss;
     806           4 :         oss << name << i;
     807           4 :         variable_names[i] = oss.str();
     808           4 :       }
     809             : 
     810             :       // Finally set the autogenerated vector into the InputParameters object
     811           2 :       p.set<std::vector<VariableName>>(param_name) = variable_names;
     812           2 :     }
     813     2299057 :   }
     814     2299057 : }
     815             : 
     816             : void
     817       81814 : Builder::extractParams(const std::string & prefix, InputParameters & p)
     818             : {
     819       81814 :   const auto node = _root.find(prefix);
     820       81814 :   extractParams((node && node->type() == hit::NodeType::Section) ? node : nullptr, p);
     821       81814 : }
     822             : 
     823             : bool
     824     2634163 : Builder::isGlobal(const hit::Node & node) const
     825             : {
     826     2634163 :   const auto global_params_node = queryGlobalParamsNode();
     827     2634163 :   return global_params_node && node.parent() == global_params_node;
     828             : }
     829             : 
     830             : const hit::Node *
     831    66686119 : Builder::queryGlobalParamsNode() const
     832             : {
     833    66686119 :   if (!_global_params_node)
     834             :   {
     835      264496 :     const auto syntax = _syntax.getSyntaxByAction("GlobalParamsAction");
     836             :     mooseAssert(syntax.size() == 1, "Unexpected GlobalParamsAction syntax size");
     837       66124 :     _global_params_node = _root.find(syntax.front());
     838       66124 :   }
     839    66686119 :   return *_global_params_node;
     840             : }
     841             : 
     842             : } // end of namespace Moose

Generated by: LCOV version 1.14