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 "Syntax.h"
11 : #include "MooseUtils.h"
12 :
13 : #include "libmesh/simple_range.h"
14 :
15 : #include <algorithm>
16 :
17 68503 : Syntax::Syntax() : _actions_to_syntax_valid(false) {}
18 :
19 : void
20 9931681 : Syntax::registerTaskName(const std::string & task, bool should_auto_build)
21 : {
22 9931681 : if (_registered_tasks.count(task) > 0)
23 136994 : return;
24 9794687 : _tasks.addItem(task);
25 9794687 : _registered_tasks[task] = should_auto_build;
26 : }
27 :
28 : void
29 4494987 : Syntax::registerTaskName(const std::string & task,
30 : const std::string & moose_object_type,
31 : bool should_auto_build)
32 : {
33 4494987 : auto range = _moose_systems_to_tasks.equal_range(moose_object_type);
34 5293369 : for (auto it = range.first; it != range.second; ++it)
35 798382 : if (it->second == task)
36 0 : return;
37 :
38 4494987 : if (_registered_tasks.find(task) != _registered_tasks.end())
39 2 : mooseError("A ", task, " is already registered. Do you need to use appendTaskName instead?");
40 :
41 4494985 : registerTaskName(task, should_auto_build);
42 4494985 : _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
43 : }
44 :
45 : void
46 911795 : Syntax::appendTaskName(const std::string & task,
47 : const std::string & moose_object_type,
48 : bool deprecated)
49 : {
50 911795 : if (_registered_tasks.find(task) == _registered_tasks.end())
51 1 : mooseError("A ", task, " is not a registered task name.");
52 :
53 911794 : if (!deprecated)
54 706303 : _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
55 : else
56 205491 : _deprecated_list_moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
57 911794 : }
58 :
59 : void
60 12050167 : Syntax::addDependency(const std::string & task, const std::string & pre_req)
61 : {
62 12050167 : if (_registered_tasks.find(task) == _registered_tasks.end())
63 1 : mooseError("A ", task, " is not a registered task name.");
64 :
65 12050166 : _tasks.insertDependency(task, pre_req);
66 12050166 : }
67 :
68 : void
69 68497 : Syntax::addDependencySets(const std::string & action_sets)
70 : {
71 68497 : std::vector<std::string> sets, prev_names, tasks;
72 68497 : MooseUtils::tokenize(action_sets, sets, 1, "()");
73 :
74 6849700 : for (unsigned int i = 0; i < sets.size(); ++i)
75 : {
76 6781203 : tasks.clear();
77 6781203 : MooseUtils::tokenize(sets[i], tasks, 0, ", ");
78 15754310 : for (unsigned int j = 0; j < tasks.size(); ++j)
79 : {
80 : // Each line should depend on each item in the previous line
81 20069621 : for (unsigned int k = 0; k < prev_names.size(); ++k)
82 11096514 : addDependency(tasks[j], prev_names[k]);
83 : }
84 : // Copy the the current items to the previous items for the next iteration
85 6781203 : std::swap(tasks, prev_names);
86 : }
87 68497 : }
88 :
89 : void
90 0 : Syntax::deleteTaskDependencies(const std::string & task)
91 : {
92 0 : if (_registered_tasks.find(task) == _registered_tasks.end())
93 0 : mooseError("A ", task, " is not a registered task name.");
94 :
95 0 : _tasks.deleteDependenciesOfKey(task);
96 0 : }
97 :
98 : void
99 0 : Syntax::clearTaskDependencies()
100 : {
101 0 : _tasks.clear();
102 0 : }
103 :
104 : const std::vector<std::string> &
105 67685 : Syntax::getSortedTask()
106 : {
107 : try
108 : {
109 67685 : return _tasks.getSortedValues();
110 : }
111 1 : catch (CyclicDependencyException<std::string> & e)
112 : {
113 1 : const auto & cycle = e.getCyclicDependencies();
114 3 : mooseError("Cyclic dependencies detected: ", MooseUtils::join(cycle, " <- "));
115 1 : }
116 : }
117 :
118 : const std::vector<std::vector<std::string>> &
119 20 : Syntax::getSortedTaskSet()
120 : {
121 20 : return _tasks.getSortedValuesSets();
122 : }
123 :
124 : bool
125 5196708 : Syntax::hasTask(const std::string & task) const
126 : {
127 5196708 : return (_registered_tasks.find(task) != _registered_tasks.end());
128 : }
129 :
130 : bool
131 0 : Syntax::isActionRequired(const std::string & task) const
132 : {
133 0 : mooseDeprecated("Syntax::isActionRequired is deprecated, use shouldAutoBuild() instead");
134 0 : return shouldAutoBuild(task);
135 : }
136 :
137 : bool
138 9678391 : Syntax::shouldAutoBuild(const std::string & task) const
139 : {
140 9678391 : auto map_pair = _registered_tasks.find(task);
141 : mooseAssert(map_pair != _registered_tasks.end(), std::string("Unregistered task: ") + task);
142 :
143 19356782 : return map_pair->second;
144 : }
145 :
146 : void
147 8190944 : Syntax::registerActionSyntax(const std::string & action,
148 : const std::string & syntax,
149 : const std::string & task,
150 : const std::string & file,
151 : int line)
152 : {
153 8190944 : auto range = _syntax_to_actions.equal_range(syntax);
154 9835023 : for (auto it = range.first; it != range.second; ++it)
155 1644079 : if (it->second._action == action && it->second._task == task)
156 0 : return;
157 :
158 8190944 : _syntax_to_actions.insert(std::make_pair(syntax, ActionInfo{action, task}));
159 8190944 : _syntax_to_line.addInfo(syntax, action, task, file, line);
160 8190944 : _actions_to_syntax_valid = false;
161 : }
162 :
163 : void
164 1 : Syntax::replaceActionSyntax(const std::string & action,
165 : const std::string & syntax,
166 : const std::string & task,
167 : const std::string & file,
168 : int line)
169 : {
170 1 : _syntax_to_actions.erase(syntax);
171 1 : registerActionSyntax(action, syntax, task, file, line);
172 1 : }
173 :
174 : void
175 1 : Syntax::removeAllActionsForSyntax(const std::string & syntax)
176 : {
177 1 : _syntax_to_actions.erase(syntax);
178 1 : }
179 :
180 : void
181 1 : Syntax::deprecateActionSyntax(const std::string & syntax)
182 : {
183 1 : const std::string message = "\"[" + syntax + "]\" is deprecated.";
184 1 : deprecateActionSyntax(syntax, message);
185 1 : }
186 :
187 : void
188 50 : Syntax::deprecateActionSyntax(const std::string & syntax, const std::string & message)
189 : {
190 50 : _deprecated_syntax.insert(std::make_pair(syntax, message));
191 50 : }
192 :
193 : std::string
194 2 : Syntax::deprecatedActionSyntaxMessage(const std::string syntax)
195 : {
196 2 : auto it = _deprecated_syntax.find(syntax);
197 :
198 2 : if (it != _deprecated_syntax.end())
199 4 : return it->second;
200 : else
201 0 : mooseError("The action syntax ", syntax, " is not deprecated");
202 : }
203 :
204 : bool
205 1795274 : Syntax::isDeprecatedSyntax(const std::string & syntax) const
206 : {
207 1795274 : return _deprecated_syntax.find(syntax) != _deprecated_syntax.end();
208 : }
209 :
210 : std::vector<std::string>
211 532943 : Syntax::getSyntaxByAction(const std::string & action, const std::string & task)
212 : {
213 : // See if the reverse multimap has been built yet, if not build it now
214 532943 : if (!_actions_to_syntax_valid)
215 : {
216 135876 : std::transform(_syntax_to_actions.begin(),
217 : _syntax_to_actions.end(),
218 67938 : std::inserter(_actions_to_syntax, _actions_to_syntax.begin()),
219 8126550 : [](const std::pair<std::string, ActionInfo> pair) {
220 8126550 : return std::make_pair(pair.second._action,
221 8126550 : std::make_pair(pair.first, pair.second._task));
222 : });
223 67938 : _actions_to_syntax_valid = true;
224 : }
225 :
226 532943 : std::vector<std::string> syntax;
227 532943 : auto it_pair = _actions_to_syntax.equal_range(action);
228 1065944 : for (const auto & syntax_pair : as_range(it_pair))
229 : // If task is blank, return all syntax, otherwise filter by task
230 533001 : if (task == "" || syntax_pair.second.second == task)
231 533001 : syntax.emplace_back(syntax_pair.second.first);
232 :
233 1065886 : return syntax;
234 0 : }
235 :
236 : std::vector<std::string>
237 273648 : Syntax::getNonDeprecatedSyntaxByAction(const std::string & action, const std::string & task)
238 : {
239 273648 : auto syntaxes = getSyntaxByAction(action, task);
240 821002 : for (auto syntax_it = begin(syntaxes); syntax_it != end(syntaxes);)
241 : {
242 273706 : if (isDeprecatedSyntax(*syntax_it))
243 0 : syntax_it = syntaxes.erase(syntax_it);
244 : else
245 273706 : ++syntax_it;
246 : }
247 273648 : return syntaxes;
248 0 : }
249 :
250 : std::string
251 3928603 : Syntax::isAssociated(const std::string & real_id,
252 : bool * is_parent,
253 : const std::map<std::string, std::set<std::string>> & alt_map) const
254 : {
255 : // if non-empty alt_map was provided then traverse its syntax instead of _syntax_to_actions
256 3928603 : std::set<std::string> syntax_to_traverse;
257 3928603 : if (!alt_map.empty())
258 7 : std::transform(alt_map.begin(),
259 : alt_map.end(),
260 : std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
261 437 : [](auto pair) { return pair.first; });
262 : else
263 3928596 : std::transform(_syntax_to_actions.begin(),
264 : _syntax_to_actions.end(),
265 : std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
266 469956669 : [](auto pair) { return pair.first; });
267 :
268 : /**
269 : * This implementation assumes that wildcards can occur in the place of an entire token but not as
270 : * part of a token (i.e. 'Variables/ * /InitialConditions' is valid but not 'Variables/Partial*
271 : * /InitialConditions'. Since maps are ordered, a reverse traversal through the registered list
272 : * will always select a more specific match before a wildcard match ('*' == char(42)).
273 : */
274 : bool local_is_parent;
275 3928603 : if (is_parent == nullptr)
276 6 : is_parent = &local_is_parent; // Just so we don't have to keep checking below when we want to
277 : // set the value
278 3928603 : std::vector<std::string> real_elements, reg_elements;
279 3928603 : std::string return_value;
280 :
281 3928603 : MooseUtils::tokenize(real_id, real_elements);
282 :
283 3928603 : *is_parent = false;
284 275935976 : for (auto it = syntax_to_traverse.rbegin(); it != syntax_to_traverse.rend(); ++it)
285 : {
286 274301672 : std::string reg_id = *it;
287 274301672 : if (reg_id == real_id)
288 : {
289 1176900 : *is_parent = false;
290 1176900 : return reg_id;
291 : }
292 273124772 : reg_elements.clear();
293 273124772 : MooseUtils::tokenize(reg_id, reg_elements);
294 273124772 : if (real_elements.size() <= reg_elements.size())
295 : {
296 259319181 : bool keep_going = true;
297 514282453 : for (unsigned int j = 0; keep_going && j < real_elements.size(); ++j)
298 : {
299 751184688 : if (real_elements[j] != reg_elements[j] && reg_elements[j] != std::string("*"))
300 246017579 : keep_going = false;
301 : }
302 259319181 : if (keep_going)
303 : {
304 13301602 : if (real_elements.size() < reg_elements.size() && !*is_parent)
305 : {
306 : // We found a parent, the longest parent in fact but we need to keep
307 : // looking to make sure that the real thing isn't registered
308 1838770 : *is_parent = true;
309 1838770 : return_value = reg_id;
310 : }
311 11462832 : else if (real_elements.size() == reg_elements.size())
312 : {
313 1117399 : *is_parent = false;
314 1117399 : return reg_id;
315 : }
316 : }
317 : }
318 274301672 : }
319 :
320 1634304 : if (*is_parent)
321 342517 : return return_value;
322 : else
323 2583574 : return "";
324 3928603 : }
325 :
326 : std::pair<std::multimap<std::string, Syntax::ActionInfo>::const_iterator,
327 : std::multimap<std::string, Syntax::ActionInfo>::const_iterator>
328 4235528 : Syntax::getActions(const std::string & syntax) const
329 : {
330 4235528 : return _syntax_to_actions.equal_range(syntax);
331 : }
332 :
333 : bool
334 22734909 : Syntax::verifyMooseObjectTask(const std::string & base, const std::string & task) const
335 : {
336 22734909 : auto iters = _moose_systems_to_tasks.equal_range(base);
337 :
338 49201567 : for (const auto & task_it : as_range(iters))
339 28084351 : if (task == task_it.second)
340 1617693 : return true;
341 :
342 21117216 : iters = _deprecated_list_moose_systems_to_tasks.equal_range(base);
343 21682881 : for (const auto & task_it : as_range(iters))
344 576289 : if (task == task_it.second)
345 : {
346 10624 : std::string object_tasks = "";
347 21248 : for (const auto & other_task : as_range(_moose_systems_to_tasks.equal_range(base)))
348 10624 : object_tasks += (object_tasks == "" ? "" : " ") + other_task.second;
349 :
350 10624 : mooseDeprecated(
351 21248 : "Adding objects from system '" + base + "' through task '" + task +
352 21248 : "' is deprecated. This object should only be added from task(s): " + object_tasks +
353 : ". This is likely caused by adding objects in a block they no longer belong to. For "
354 : "example, FunctorMaterials should no longer be added in the [Materials] block.");
355 10624 : return true;
356 10624 : }
357 :
358 21106592 : return false;
359 : }
360 :
361 : void
362 1780922 : Syntax::registerSyntaxType(const std::string & syntax, const std::string & type)
363 : {
364 1780922 : _associated_types.insert(std::make_pair(syntax, type));
365 1780922 : }
366 :
367 : const std::multimap<std::string, std::string> &
368 250 : Syntax::getAssociatedTypes() const
369 : {
370 250 : return _associated_types;
371 : }
372 :
373 : const std::multimap<std::string, Syntax::ActionInfo> &
374 205 : Syntax::getAssociatedActions() const
375 : {
376 205 : return _syntax_to_actions;
377 : }
378 :
379 : FileLineInfo
380 21738 : Syntax::getLineInfo(const std::string & syntax,
381 : const std::string & action,
382 : const std::string & task) const
383 : {
384 21738 : return _syntax_to_line.getInfo(syntax, action, task);
385 : }
|