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 62760 : Syntax::Syntax() : _actions_to_syntax_valid(false) {}
18 :
19 : void
20 8963991 : Syntax::registerTaskName(const std::string & task, bool should_auto_build)
21 : {
22 8963991 : if (_registered_tasks.count(task) > 0)
23 125508 : return;
24 8838483 : _tasks.addItem(task);
25 8838483 : _registered_tasks[task] = should_auto_build;
26 : }
27 :
28 : void
29 4111874 : Syntax::registerTaskName(const std::string & task,
30 : const std::string & moose_object_type,
31 : bool should_auto_build)
32 : {
33 4111874 : auto range = _moose_systems_to_tasks.equal_range(moose_object_type);
34 4841757 : for (auto it = range.first; it != range.second; ++it)
35 729883 : if (it->second == task)
36 0 : return;
37 :
38 4111874 : 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 4111872 : registerTaskName(task, should_auto_build);
42 4111872 : _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
43 : }
44 :
45 : void
46 832227 : Syntax::appendTaskName(const std::string & task,
47 : const std::string & moose_object_type,
48 : bool deprecated)
49 : {
50 832227 : if (_registered_tasks.find(task) == _registered_tasks.end())
51 1 : mooseError("A ", task, " is not a registered task name.");
52 :
53 832226 : if (!deprecated)
54 643964 : _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
55 : else
56 188262 : _deprecated_list_moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
57 832226 : }
58 :
59 : void
60 10909178 : Syntax::addDependency(const std::string & task, const std::string & pre_req)
61 : {
62 10909178 : if (_registered_tasks.find(task) == _registered_tasks.end())
63 1 : mooseError("A ", task, " is not a registered task name.");
64 :
65 10909177 : _tasks.insertDependency(task, pre_req);
66 10909177 : }
67 :
68 : void
69 62754 : Syntax::addDependencySets(const std::string & action_sets)
70 : {
71 62754 : std::vector<std::string> sets, prev_names, tasks;
72 62754 : MooseUtils::tokenize(action_sets, sets, 1, "()");
73 :
74 6149892 : for (unsigned int i = 0; i < sets.size(); ++i)
75 : {
76 6087138 : tasks.clear();
77 6087138 : MooseUtils::tokenize(sets[i], tasks, 0, ", ");
78 14182404 : for (unsigned int j = 0; j < tasks.size(); ++j)
79 : {
80 : // Each line should depend on each item in the previous line
81 18198660 : for (unsigned int k = 0; k < prev_names.size(); ++k)
82 10103394 : addDependency(tasks[j], prev_names[k]);
83 : }
84 : // Copy the the current items to the previous items for the next iteration
85 6087138 : std::swap(tasks, prev_names);
86 : }
87 62754 : }
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 61935 : Syntax::getSortedTask()
106 : {
107 : try
108 : {
109 61935 : return _tasks.getSortedValues();
110 : }
111 1 : catch (CyclicDependencyException<std::string> & e)
112 : {
113 1 : const auto & cycle = e.getCyclicDependencies();
114 4 : 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 4665771 : Syntax::hasTask(const std::string & task) const
126 : {
127 4665771 : 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 8722836 : Syntax::shouldAutoBuild(const std::string & task) const
139 : {
140 8722836 : auto map_pair = _registered_tasks.find(task);
141 : mooseAssert(map_pair != _registered_tasks.end(), std::string("Unregistered task: ") + task);
142 :
143 8722836 : return map_pair->second;
144 : }
145 :
146 : void
147 7497712 : 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 7497712 : auto range = _syntax_to_actions.equal_range(syntax);
154 9004004 : for (auto it = range.first; it != range.second; ++it)
155 1506292 : if (it->second._action == action && it->second._task == task)
156 0 : return;
157 :
158 7497712 : _syntax_to_actions.insert(std::make_pair(syntax, ActionInfo{action, task}));
159 7497712 : _syntax_to_line.addInfo(syntax, action, task, file, line);
160 7497712 : _actions_to_syntax_valid = false;
161 7497712 : }
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 1638865 : Syntax::isDeprecatedSyntax(const std::string & syntax) const
206 : {
207 1638865 : return _deprecated_syntax.find(syntax) != _deprecated_syntax.end();
208 : }
209 :
210 : std::vector<std::string>
211 487754 : 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 487754 : if (!_actions_to_syntax_valid)
215 : {
216 124368 : std::transform(_syntax_to_actions.begin(),
217 : _syntax_to_actions.end(),
218 62184 : std::inserter(_actions_to_syntax, _actions_to_syntax.begin()),
219 7432014 : [](const std::pair<std::string, ActionInfo> pair) {
220 7432014 : return std::make_pair(pair.second._action,
221 14864028 : std::make_pair(pair.first, pair.second._task));
222 : });
223 62184 : _actions_to_syntax_valid = true;
224 : }
225 :
226 487754 : std::vector<std::string> syntax;
227 487754 : auto it_pair = _actions_to_syntax.equal_range(action);
228 975562 : for (const auto & syntax_pair : as_range(it_pair))
229 : // If task is blank, return all syntax, otherwise filter by task
230 487808 : if (task == "" || syntax_pair.second.second == task)
231 487808 : syntax.emplace_back(syntax_pair.second.first);
232 :
233 975508 : return syntax;
234 0 : }
235 :
236 : std::vector<std::string>
237 250437 : Syntax::getNonDeprecatedSyntaxByAction(const std::string & action, const std::string & task)
238 : {
239 250437 : auto syntaxes = getSyntaxByAction(action, task);
240 500928 : for (auto syntax_it = begin(syntaxes); syntax_it != end(syntaxes);)
241 : {
242 250491 : if (isDeprecatedSyntax(*syntax_it))
243 0 : syntax_it = syntaxes.erase(syntax_it);
244 : else
245 250491 : ++syntax_it;
246 : }
247 250437 : return syntaxes;
248 0 : }
249 :
250 : std::string
251 3526568 : 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 3526568 : std::set<std::string> syntax_to_traverse;
257 3526568 : 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 3526561 : std::transform(_syntax_to_actions.begin(),
264 : _syntax_to_actions.end(),
265 : std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
266 421477716 : [](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 3526568 : 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 3526568 : std::vector<std::string> real_elements, reg_elements;
279 3526568 : std::string return_value;
280 :
281 3526568 : MooseUtils::tokenize(real_id, real_elements);
282 :
283 3526568 : *is_parent = false;
284 245847396 : for (auto it = syntax_to_traverse.rbegin(); it != syntax_to_traverse.rend(); ++it)
285 : {
286 244405805 : std::string reg_id = *it;
287 244405805 : if (reg_id == real_id)
288 : {
289 1069899 : *is_parent = false;
290 1069899 : return reg_id;
291 : }
292 243335906 : reg_elements.clear();
293 243335906 : MooseUtils::tokenize(reg_id, reg_elements);
294 243335906 : if (real_elements.size() <= reg_elements.size())
295 : {
296 230829995 : bool keep_going = true;
297 341218371 : for (unsigned int j = 0; keep_going && j < real_elements.size(); ++j)
298 : {
299 110388376 : if (real_elements[j] != reg_elements[j] && reg_elements[j] != std::string("*"))
300 102257993 : keep_going = false;
301 : }
302 230829995 : if (keep_going)
303 : {
304 128572002 : 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 2786735 : *is_parent = true;
309 2786735 : return_value = reg_id;
310 : }
311 125785267 : else if (real_elements.size() == reg_elements.size())
312 : {
313 1015078 : *is_parent = false;
314 1015078 : return reg_id;
315 : }
316 : }
317 : }
318 244405805 : }
319 :
320 1441591 : if (*is_parent)
321 1425921 : return return_value;
322 : else
323 15670 : return "";
324 3526568 : }
325 :
326 : std::pair<std::multimap<std::string, Syntax::ActionInfo>::const_iterator,
327 : std::multimap<std::string, Syntax::ActionInfo>::const_iterator>
328 3861447 : Syntax::getActions(const std::string & syntax) const
329 : {
330 3861447 : return _syntax_to_actions.equal_range(syntax);
331 : }
332 :
333 : bool
334 22343153 : Syntax::verifyMooseObjectTask(const std::string & base, const std::string & task) const
335 : {
336 22343153 : auto iters = _moose_systems_to_tasks.equal_range(base);
337 :
338 48420043 : for (const auto & task_it : as_range(iters))
339 27585573 : if (task == task_it.second)
340 1508683 : return true;
341 :
342 20834470 : iters = _deprecated_list_moose_systems_to_tasks.equal_range(base);
343 21372417 : for (const auto & task_it : as_range(iters))
344 548045 : if (task == task_it.second)
345 : {
346 10098 : std::string object_tasks = "";
347 20196 : for (const auto & other_task : as_range(_moose_systems_to_tasks.equal_range(base)))
348 10098 : object_tasks += (object_tasks == "" ? "" : " ") + other_task.second;
349 :
350 10098 : mooseDeprecated(
351 20196 : "Adding objects from system '" + base + "' through task '" + task +
352 20196 : "' 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 10098 : return true;
356 10098 : }
357 :
358 20824372 : return false;
359 : }
360 :
361 : void
362 1631604 : Syntax::registerSyntaxType(const std::string & syntax, const std::string & type)
363 : {
364 1631604 : _associated_types.insert(std::make_pair(syntax, type));
365 1631604 : }
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 : }
|