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