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 : [¶m_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
|